From 18b650a72e8c8ff2c01d8fd75a6df30087677ce1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=BF=E8=8F=9C=20Cai?= Date: Tue, 13 Feb 2024 22:20:29 +0800 Subject: [PATCH] feat(client): add file right-click menu to `*.md` and directly read file content (#717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: Only retain **始终按所有用户(每台计算机)安装** * feat(client): directly open files in Mac --- client/electron-builder.json5 | 14 +++-- client/electron/main/index.ts | 51 +++++++++++++++++-- client/electron/preload/menu/category/file.ts | 45 ++++++++++++---- client/electron/preload/menu/index.ts | 4 +- client/src/App.vue | 2 +- .../src/components/CherryMarkdown/index.vue | 22 ++++---- 6 files changed, 107 insertions(+), 31 deletions(-) diff --git a/client/electron-builder.json5 b/client/electron-builder.json5 index b57353a0..18b2fad6 100644 --- a/client/electron-builder.json5 +++ b/client/electron-builder.json5 @@ -2,7 +2,7 @@ * @see https://www.electron.build/configuration/configuration */ { - appId: 'com.electron.cherry-noted', + appId: 'cherry-noted', productName: 'Cherry Noted', asar: true, icon: 'public/favicon.ico', @@ -25,8 +25,16 @@ }, nsis: { oneClick: false, - perMachine: false, + "perMachine": true, allowToChangeInstallationDirectory: true, - deleteAppDataOnUninstall: false, }, + fileAssociations: [ + { + ext: ['md'], + name: 'Cherry Noted', + description: 'Cherry Noted file', + role: 'Editor', + icon: './public/favicon.ico', + }, + ], } diff --git a/client/electron/main/index.ts b/client/electron/main/index.ts index 289e539d..1372a62f 100644 --- a/client/electron/main/index.ts +++ b/client/electron/main/index.ts @@ -2,6 +2,7 @@ import { app, BrowserWindow, shell, ipcMain, Menu } from 'electron'; import { release } from 'node:os'; import { join } from 'node:path'; import { menuConfig } from '../preload/menu'; +import fs from 'fs'; // The built directory structure // @@ -65,9 +66,51 @@ async function createWindow() { win.loadFile(indexHtml); } - // Test actively push message to the Electron-Renderer win.webContents.on('did-finish-load', () => { - win?.webContents.send('main-process-message', new Date().toLocaleString()); + /** + * @description Windows 直接打开文件 + * @param status -1 读取文件失败; -2 取消读取; 0 读取成功 + * @param message 读取文件失败的原因 + * @param data 读取成功的文件内容 + * @param filePath 读取成功的文件路径 + */ + try { + if (process.argv.length > 1 && fs.statSync(process.argv[1]).isFile() && process.argv[1].endsWith('.md')) { + win?.webContents.send('open_file', { + status: 0, + message: 'success', + data: fs.readFileSync(process.argv[1]).toString(), + filePath: process.argv[1] + }); + } + } catch (error) { + win?.webContents.send('open_file', { + status: -1, + message: error.message, + data: '', + filePath: '' + }); + } + }); + + // mac 打开文件 + app.on('open-file', (event, path) => { + event.preventDefault(); + if (path.endsWith('.md')) { + win?.webContents.send('open_file', { + status: 0, + message: 'success', + data: fs.readFileSync(path).toString(), + filePath: path + }); + }else{ + win?.webContents.send('open_file', { + status: -1, + message: '文件格式不支持', + data: '', + filePath: '' + }); + } }); // Make all links open with the browser, not with the application @@ -80,7 +123,9 @@ async function createWindow() { Menu.setApplicationMenu(menu); } -app.whenReady().then(createWindow); +app.whenReady().then(() => { + createWindow(); +}); app.on('window-all-closed', () => { win = null; diff --git a/client/electron/preload/menu/category/file.ts b/client/electron/preload/menu/category/file.ts index 25ab5cbe..d025a202 100644 --- a/client/electron/preload/menu/category/file.ts +++ b/client/electron/preload/menu/category/file.ts @@ -1,7 +1,6 @@ import { BrowserWindow, dialog, ipcMain, Menu } from "electron" import fs from "node:fs" - /** * @description 新建文件 */ @@ -12,7 +11,10 @@ export const newFile = () => { /** * @description 打开文件 - * @param status -2 -1 读取文件失败; -3 取消读取; 1 读取成功 + * @param status -1 读取文件失败; -2 取消读取; 0 读取成功 + * @param message 读取文件失败的原因 + * @param data 读取成功的文件内容 + * @param filePath 读取成功的文件路径 */ export const openFile = () => { // 获取第一个窗口 @@ -24,26 +26,49 @@ export const openFile = () => { ], }).then(result => { if (result.canceled) { - win.webContents.send('open_file', { status: -3, message: 'open file canceled' }) + win.webContents.send('open_file', { + status: -2, + message: 'open file canceled', + data: '', + filePath: '' + }) return; }; let filePath = result.filePaths[0]; fs.readFile(filePath, 'utf-8', (err, data) => { if (err) { - win.webContents.send('open_file', { status: -1, message: err.message }) + win.webContents.send('open_file', { + status: -1, + message: err.message, + data: '', + filePath: '' + }) return; } - win.webContents.send('open_file', { status: 1, message: 'open file success', data: data, filePath: filePath }) + win.webContents.send('open_file', { + status: 0, + message: 'open file success', + data: data, + filePath: filePath + }) }); }).catch(err => { - win.webContents.send('open_file', { status: -2, message: err }) + win.webContents.send('open_file', { + status: -1, + message: err.message, + data: '', + filePath: '' + }) }); } /** * @description 另存为... - * @description status -2 -1 读取文件失败; 0 取消读取; 1 读取成功 + * @description status -2 -1 保存文件失败; 0 取消读取; 1 读取成功 + * @description message 保存文件失败的原因 + * @description filePath 保存文件成功的路径 + * */ export const saveFileAs = () => { const win = BrowserWindow.getAllWindows()[0]; @@ -63,7 +88,7 @@ ipcMain.on('save-file-as-info', async (event, arg: { data: string }) => { if (err) { event.reply('save-file-as-reply', { status: -1, message: err.message, filePath: '' }) } else { - event.reply('save-file-as-reply', { status: 1, message: 'save file as success', filePath: filePath }) + event.reply('save-file-as-reply', { status: 0, message: 'save file as success', filePath: filePath }) const menu = Menu.getApplicationMenu(); const saveFileBtn = menu.getMenuItemById('save-file'); saveFileBtn.enabled = false @@ -77,6 +102,8 @@ ipcMain.on('save-file-as-info', async (event, arg: { data: string }) => { /** * @description 保存文件 + * @description status 0 保存成功; -1 保存失败 + * @description message 保存失败的原因 */ export const saveFile = () => { // 询问是否有文件路径->如没有则调用另存为文件功能 @@ -91,7 +118,7 @@ ipcMain.on('sava-file-type', (event, arg: { filePath: string, data: string }) => event.reply('save-file-reply', { status: -1, message: err.message, }); } else { console.error('success'); - event.reply('save-file-reply', { status: 1, message: 'save file as success' }); + event.reply('save-file-reply', { status: 0, message: 'save file as success' }); const menu = Menu.getApplicationMenu(); const saveFileBtn = menu.getMenuItemById('save-file'); saveFileBtn.enabled = false diff --git a/client/electron/preload/menu/index.ts b/client/electron/preload/menu/index.ts index 162380cd..ce1308ff 100644 --- a/client/electron/preload/menu/index.ts +++ b/client/electron/preload/menu/index.ts @@ -95,8 +95,8 @@ const menuConfig: Array = [ ] }, ] - -isPackaged ? [] : menuConfig.push({ +// isPackaged ? [] : + menuConfig.push({ label: "打开DevTools", role: 'toggleDevTools' }) diff --git a/client/src/App.vue b/client/src/App.vue index a361ce49..911ea735 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -1,5 +1,5 @@