first commit
This commit is contained in:
141
electron/main.js
Normal file
141
electron/main.js
Normal file
@@ -0,0 +1,141 @@
|
||||
import { app, BrowserWindow, dialog, ipcMain } from 'electron'
|
||||
import { join } from 'path'
|
||||
import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'fs'
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
const CONFIG_DIR = join(app.getPath('userData'), '.tunji')
|
||||
const CONFIG_FILE = join(CONFIG_DIR, 'config.json')
|
||||
|
||||
function ensureConfigDir() {
|
||||
if (!existsSync(CONFIG_DIR)) {
|
||||
mkdirSync(CONFIG_DIR, { recursive: true })
|
||||
}
|
||||
}
|
||||
|
||||
function loadConfig() {
|
||||
ensureConfigDir()
|
||||
if (existsSync(CONFIG_FILE)) {
|
||||
try {
|
||||
return JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'))
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
function saveConfig(config) {
|
||||
ensureConfigDir()
|
||||
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8')
|
||||
}
|
||||
|
||||
function createWindow() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
minWidth: 800,
|
||||
minHeight: 600,
|
||||
webPreferences: {
|
||||
preload: join(__dirname, 'preload.js'),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
},
|
||||
})
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
mainWindow.loadURL(process.env.VITE_DEV_SERVER_URL)
|
||||
mainWindow.webContents.openDevTools()
|
||||
} else {
|
||||
mainWindow.loadFile(join(__dirname, '../dist/index.html'))
|
||||
}
|
||||
}
|
||||
|
||||
// IPC Handlers
|
||||
ipcMain.handle('workspace:select', async () => {
|
||||
const result = await dialog.showOpenDialog(mainWindow, {
|
||||
properties: ['openDirectory'],
|
||||
title: '选择工作目录',
|
||||
})
|
||||
if (result.canceled) return null
|
||||
const workspacePath = result.filePaths[0]
|
||||
const config = loadConfig()
|
||||
config.workspace = workspacePath
|
||||
saveConfig(config)
|
||||
return workspacePath
|
||||
})
|
||||
|
||||
ipcMain.handle('workspace:get', () => {
|
||||
const config = loadConfig()
|
||||
return config.workspace || null
|
||||
})
|
||||
|
||||
ipcMain.handle('workspace:set', (_event, path) => {
|
||||
const config = loadConfig()
|
||||
config.workspace = path
|
||||
saveConfig(config)
|
||||
})
|
||||
|
||||
ipcMain.handle('workspace:ensure-structure', (_event, workspacePath) => {
|
||||
const tunjiDir = join(workspacePath, '.tunji')
|
||||
if (!existsSync(tunjiDir)) {
|
||||
mkdirSync(tunjiDir, { recursive: true })
|
||||
}
|
||||
const configPath = join(tunjiDir, 'config.json')
|
||||
if (!existsSync(configPath)) {
|
||||
writeFileSync(configPath, JSON.stringify({ theme: 'light' }, null, 2), 'utf-8')
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('file:read', (_event, filePath) => {
|
||||
try {
|
||||
return readFileSync(filePath, 'utf-8')
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('file:write', (_event, filePath, content) => {
|
||||
writeFileSync(filePath, content, 'utf-8')
|
||||
})
|
||||
|
||||
ipcMain.handle('file:mkdir', (_event, dirPath) => {
|
||||
try {
|
||||
if (!existsSync(dirPath)) {
|
||||
mkdirSync(dirPath, { recursive: true })
|
||||
}
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.handle('file:list', (_event, dirPath) => {
|
||||
try {
|
||||
const entries = readdirSync(dirPath, { withFileTypes: true })
|
||||
return entries
|
||||
.filter(e => !e.name.startsWith('.'))
|
||||
.map(e => ({
|
||||
name: e.name,
|
||||
path: join(dirPath, e.name),
|
||||
isDirectory: e.isDirectory(),
|
||||
isFile: e.isFile(),
|
||||
}))
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
})
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
16
electron/preload.js
Normal file
16
electron/preload.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('tunjiAPI', {
|
||||
workspace: {
|
||||
select: () => ipcRenderer.invoke('workspace:select'),
|
||||
get: () => ipcRenderer.invoke('workspace:get'),
|
||||
set: (path) => ipcRenderer.invoke('workspace:set', path),
|
||||
ensureStructure: (path) => ipcRenderer.invoke('workspace:ensure-structure', path),
|
||||
},
|
||||
file: {
|
||||
read: (filePath) => ipcRenderer.invoke('file:read', filePath),
|
||||
write: (filePath, content) => ipcRenderer.invoke('file:write', filePath, content),
|
||||
list: (dirPath) => ipcRenderer.invoke('file:list', dirPath),
|
||||
mkdir: (dirPath) => ipcRenderer.invoke('file:mkdir', dirPath),
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user