From ead24028f170170a7cde57f10cfbced8dab0cb8e Mon Sep 17 00:00:00 2001 From: Anton Reshetov Date: Wed, 18 Jun 2025 10:42:17 +0300 Subject: [PATCH 1/2] feat: add snippet link via deep link --- src/main/index.ts | 89 +++++++++++++------ src/main/types/ipc.ts | 2 +- .../components/editor/markdown/Markdown.vue | 77 ++++++++-------- .../components/sidebar/folders/TreeNode.vue | 16 ++-- src/renderer/components/snippet/Item.vue | 23 ++++- src/renderer/composables/useApp.ts | 4 + src/renderer/ipc/index.ts | 2 + src/renderer/ipc/listeners/system.ts | 36 ++++++++ 8 files changed, 171 insertions(+), 78 deletions(-) create mode 100644 src/renderer/ipc/listeners/system.ts diff --git a/src/main/index.ts b/src/main/index.ts index e48c56aa..d0a5f1dd 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -11,10 +11,22 @@ import { store } from './store' process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true' // Отключаем security warnings const isDev = process.env.NODE_ENV === 'development' +const gotTheLock = app.requestSingleInstanceLock() let mainWindow: BrowserWindow let isQuitting = false +if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient('masscode', process.execPath, [ + path.resolve(process.argv[1]), + ]) + } +} +else { + app.setAsDefaultProtocolClient('masscode') +} + function createWindow() { const bounds = store.app.get('bounds') mainWindow = new BrowserWindow({ @@ -54,37 +66,60 @@ function createWindow() { }) } -app.whenReady().then(() => { - createWindow() - registerIPC() +if (!gotTheLock) { + app.quit() +} +else { + app.whenReady().then(() => { + createWindow() + registerIPC() - initApi() + initApi() - if (store.app.get('isAutoMigratedFromJson')) { - return - } + if (store.app.get('isAutoMigratedFromJson')) { + return + } - try { - const jsonDbPath = `${store.preferences.get('storagePath')}/db.json` - const jsonData = readFileSync(jsonDbPath, 'utf8') + try { + const jsonDbPath = `${store.preferences.get('storagePath')}/db.json` + const jsonData = readFileSync(jsonDbPath, 'utf8') - migrateJsonToSqlite(JSON.parse(jsonData)) - store.app.set('isAutoMigratedFromJson', true) - } - catch (err) { - console.error('Error on auto migration JSON to SQLite:', err) - } -}) + migrateJsonToSqlite(JSON.parse(jsonData)) + store.app.set('isAutoMigratedFromJson', true) + } + catch (err) { + console.error('Error on auto migration JSON to SQLite:', err) + } + }) -app.on('activate', () => { - mainWindow.show() -}) + app.on('activate', () => { + mainWindow.show() + }) + + app.on('before-quit', () => { + isQuitting = true + }) -app.on('before-quit', () => { - isQuitting = true -}) + app.on('window-all-closed', () => { + if (process.platform !== 'darwin') + app.quit() + }) + + app.on('second-instance', (_, argv) => { + if (mainWindow) { + mainWindow.isMinimized() ? mainWindow.restore() : mainWindow.focus() + } -app.on('window-all-closed', () => { - if (process.platform !== 'darwin') - app.quit() -}) + if (process.platform !== 'darwin') { + const url = argv.find(i => i.startsWith('masscode://')) + BrowserWindow.getFocusedWindow()?.webContents.send( + 'system:deep-link', + url, + ) + } + }) + + app.on('open-url', (_, url) => { + BrowserWindow.getFocusedWindow()?.webContents.send('system:deep-link', url) + }) +} diff --git a/src/main/types/ipc.ts b/src/main/types/ipc.ts index 41d0bc73..d0a9b0f6 100644 --- a/src/main/types/ipc.ts +++ b/src/main/types/ipc.ts @@ -22,7 +22,7 @@ type MainMenuAction = | 'presentation-mode' type DBAction = 'relaod' | 'move' | 'migrate' | 'clear' -type SystemAction = 'reload' | 'open-external' +type SystemAction = 'reload' | 'open-external' | 'deep-link' type PrettierAction = 'format' type FsAction = 'assets' diff --git a/src/renderer/components/editor/markdown/Markdown.vue b/src/renderer/components/editor/markdown/Markdown.vue index b5a17dc4..848d4bea 100644 --- a/src/renderer/components/editor/markdown/Markdown.vue +++ b/src/renderer/components/editor/markdown/Markdown.vue @@ -45,9 +45,8 @@ marked.use({ return `
` }, link({ href, text }) { - if (/^masscode:\/\/snippets/.test(href)) { - const id = href.split('/').pop() - return `${text}` + if (href.startsWith('masscode://')) { + return `${text}` } else { return `${text}` @@ -134,19 +133,10 @@ function onLinkClick(event: MouseEvent) { if (target.tagName === 'A') { const href = target.getAttribute('href') - if (href) { - if (target.classList.contains('snippet-link')) { - const snippetId = target.getAttribute('data-snippet-id') - if (snippetId) { - // TODO: Implement snippet link - - event.preventDefault() - } - } - else if (target.classList.contains('external')) { - ipc.invoke('system:open-external', href) - event.preventDefault() - } + + if (href && target.classList.contains('external')) { + ipc.invoke('system:open-external', href) + event.preventDefault() } } } @@ -176,33 +166,38 @@ watch(isDark, (value) => {