const { app, BrowserWindow, dialog, ipcMain, Menu, nativeImage } = require('electron'); const path = require('path'); const fs = require('fs'); let mainWindow = null; let currentFilePath = null; function createWindow() { // Create the browser window mainWindow = new BrowserWindow({ width: 1200, height: 800, minWidth: 800, minHeight: 600, icon: path.join(__dirname, 'assets', 'icon.ico'), webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, nodeIntegration: false }, titleBarStyle: 'default', show: false }); // Load the index.html mainWindow.loadFile(path.join(__dirname, 'renderer', 'index.html')); // Show window when ready mainWindow.once('ready-to-show', () => { mainWindow.show(); }); // Build menu buildMenu(); mainWindow.on('closed', () => { mainWindow = null; }); } function buildMenu() { const template = [ { label: '文件', submenu: [ { label: '打开文件', accelerator: 'CmdOrCtrl+O', click: () => handleOpenFile() }, { label: '保存', accelerator: 'CmdOrCtrl+S', click: () => mainWindow.webContents.send('menu:save') }, { label: '另存为', accelerator: 'CmdOrCtrl+Shift+S', click: () => mainWindow.webContents.send('menu:saveAs') }, { type: 'separator' }, { label: '退出', accelerator: 'CmdOrCtrl+Q', click: () => app.quit() } ] }, { label: '视图', submenu: [ { label: '编辑 + 预览', accelerator: 'CmdOrCtrl+1', click: () => mainWindow.webContents.send('menu:viewMode', 'split') }, { label: '纯编辑', accelerator: 'CmdOrCtrl+2', click: () => mainWindow.webContents.send('menu:viewMode', 'editor') }, { label: '纯预览', accelerator: 'CmdOrCtrl+3', click: () => mainWindow.webContents.send('menu:viewMode', 'preview') }, { type: 'separator' }, { label: '开发者工具', accelerator: 'F12', click: () => mainWindow.webContents.toggleDevTools() }, { type: 'separator' }, { label: '重新加载', accelerator: 'CmdOrCtrl+R', click: () => mainWindow.webContents.reload() } ] }, { label: '帮助', submenu: [ { label: '关于 MarkLite', click: () => { dialog.showMessageBox(mainWindow, { type: 'info', title: '关于 MarkLite', message: 'MarkLite v1.0.0', detail: '一款轻量级的 Markdown 阅读器。\n\n技术栈:Electron + marked.js + highlight.js' }); } } ] } ]; const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu); } async function handleOpenFile() { const result = await dialog.showOpenDialog(mainWindow, { properties: ['openFile'], filters: [ { name: 'Markdown 文件', extensions: ['md', 'markdown', 'txt'] }, { name: '所有文件', extensions: ['*'] } ] }); if (!result.canceled && result.filePaths.length > 0) { openFile(result.filePaths[0]); } } function openFile(filePath) { try { const content = fs.readFileSync(filePath, 'utf-8'); currentFilePath = filePath; mainWindow.setTitle(`MarkLite - ${path.basename(filePath)}`); mainWindow.webContents.send('file:opened', { filePath, content }); } catch (err) { dialog.showErrorBox('错误', `无法读取文件: ${err.message}`); } } // IPC Handlers ipcMain.handle('dialog:openFile', async () => { const result = await dialog.showOpenDialog(mainWindow, { properties: ['openFile'], filters: [ { name: 'Markdown 文件', extensions: ['md', 'markdown', 'txt'] }, { name: '所有文件', extensions: ['*'] } ] }); if (!result.canceled && result.filePaths.length > 0) { const filePath = result.filePaths[0]; const content = fs.readFileSync(filePath, 'utf-8'); currentFilePath = filePath; mainWindow.setTitle(`MarkLite - ${path.basename(filePath)}`); return { filePath, content }; } return null; }); ipcMain.handle('file:read', async (event, filePath) => { try { const content = fs.readFileSync(filePath, 'utf-8'); return { success: true, content }; } catch (err) { return { success: false, error: err.message }; } }); ipcMain.handle('file:save', async (event, { filePath, content }) => { try { if (filePath) { fs.writeFileSync(filePath, content, 'utf-8'); currentFilePath = filePath; mainWindow.setTitle(`MarkLite - ${path.basename(filePath)}`); return { success: true, filePath }; } else { // No file path, do save as const result = await dialog.showSaveDialog(mainWindow, { filters: [ { name: 'Markdown 文件', extensions: ['md'] }, { name: '文本文件', extensions: ['txt'] } ] }); if (!result.canceled) { fs.writeFileSync(result.filePath, content, 'utf-8'); currentFilePath = result.filePath; mainWindow.setTitle(`MarkLite - ${path.basename(result.filePath)}`); return { success: true, filePath: result.filePath }; } return { success: false, canceled: true }; } } catch (err) { return { success: false, error: err.message }; } }); ipcMain.handle('file:saveAs', async (event, { content }) => { try { const result = await dialog.showSaveDialog(mainWindow, { filters: [ { name: 'Markdown 文件', extensions: ['md'] }, { name: '文本文件', extensions: ['txt'] } ] }); if (!result.canceled) { fs.writeFileSync(result.filePath, content, 'utf-8'); currentFilePath = result.filePath; mainWindow.setTitle(`MarkLite - ${path.basename(result.filePath)}`); return { success: true, filePath: result.filePath }; } return { success: false, canceled: true }; } catch (err) { return { success: false, error: err.message }; } }); ipcMain.handle('file:getCurrentPath', () => { return currentFilePath; }); // Handle file open from command line or file association function handleFileOpen() { const args = process.argv.slice(1); if (args.length > 0 && !args[0].startsWith('--')) { const filePath = args[0]; if (fs.existsSync(filePath)) { return filePath; } } return null; } // App lifecycle app.whenReady().then(() => { createWindow(); // Check for file passed via command line const fileToOpen = handleFileOpen(); if (fileToOpen) { // Wait for window to be ready mainWindow.webContents.on('did-finish-load', () => { openFile(fileToOpen); }); } // Handle macOS open-file event app.on('open-file', (event, filePath) => { event.preventDefault(); if (mainWindow) { openFile(filePath); } }); }); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } });