From 0ed7f64a218e0a26b384810b1a0ac8ae314c2501 Mon Sep 17 00:00:00 2001 From: Elysia Date: Sat, 31 Jan 2026 16:07:15 +0800 Subject: [PATCH] fix: deep link handling at electron startup --- electron/global.ts | 2 + electron/main/backend/install-manager.ts | 2 +- electron/main/deeplink.ts | 23 ++++--- electron/main/handle-url-scheme.ts | 80 ++++++++++++++++++------ electron/main/index.ts | 21 ++++++- src/App.vue | 3 + 6 files changed, 100 insertions(+), 31 deletions(-) create mode 100644 electron/global.ts diff --git a/electron/global.ts b/electron/global.ts new file mode 100644 index 00000000..0cedfbc1 --- /dev/null +++ b/electron/global.ts @@ -0,0 +1,2 @@ +import { ref } from 'vue'; +export let isLoaded = ref(false); \ No newline at end of file diff --git a/electron/main/backend/install-manager.ts b/electron/main/backend/install-manager.ts index 6229cb4e..60a4fe41 100644 --- a/electron/main/backend/install-manager.ts +++ b/electron/main/backend/install-manager.ts @@ -4,7 +4,7 @@ import readline from 'node:readline'; import { promisify } from 'node:util'; import pino from 'pino'; -const logger = pino({ 'name': 'download-manager' }); +const logger = pino({ 'name': 'install-manager' }); type InstallTask = { id: number; diff --git a/electron/main/deeplink.ts b/electron/main/deeplink.ts index e3b36e95..2f941ba1 100644 --- a/electron/main/deeplink.ts +++ b/electron/main/deeplink.ts @@ -3,6 +3,9 @@ * Author: juxnpxblo@github */ import { app } from "electron"; +import pino from "pino"; + +const logger = pino({ 'name': 'deeplink.ts' }); type Query = Record; export type Listener = (query: Query) => any; @@ -48,13 +51,13 @@ const listeners = new ListenersMap(); export const deepLink = { on: (event: string, listener: Listener) => { const count = listeners.add(event, listener); - console.log( + logger.info( `Deep link: listener added for event ${event}. Total event listeners: ${count}` ); }, off: (event: string, listener: Listener) => { const count = listeners.remove(event, listener); - console.log( + logger.info( `Deep link: listener removed for event ${event}. Total event listeners: ${count}` ); }, @@ -67,29 +70,33 @@ export const deepLink = { }, }; -app.on("second-instance", (_e, commandLine) => { +export function handleCommandLine(commandLine: string[]) { const target = commandLine.find((arg) => protocols.some((protocol) => arg.startsWith(protocol + "://")) ); if (!target) return; - console.log(`Deep link: protocol link got: ${target}`); + logger.info(`Deep link: protocol link got: ${target}`); try { const url = new URL(target); const action = url.hostname; - console.log(`Deep link: action found: ${action}`); + logger.info(`Deep link: action found: ${action}`); const query: Query = {}; url.searchParams.forEach((value, key) => { query[key] = value; }); - console.log(`Deep link: query found: ${JSON.stringify(query)}`); + logger.info(`Deep link: query found: ${JSON.stringify(query)}`); const emitCount = listeners.emit(action, query); - console.log(`Deep link: emitted for ${emitCount} listeners`); + logger.info(`Deep link: emitted for ${emitCount} listeners`); } catch (error) { - console.error(`Deep link: error parsing URL: ${error}`); + logger.error(`Deep link: error parsing URL: ${error}`); } +} + +app.on("second-instance", (_e, commandLine) => { + handleCommandLine(commandLine); }); diff --git a/electron/main/handle-url-scheme.ts b/electron/main/handle-url-scheme.ts index f3e40b41..b468d75d 100644 --- a/electron/main/handle-url-scheme.ts +++ b/electron/main/handle-url-scheme.ts @@ -1,34 +1,76 @@ import { BrowserWindow } from 'electron'; import { deepLink } from './deeplink'; +import { isLoaded } from '../global'; +import pino from 'pino'; + +const logger = pino({ 'name': 'handle-url-scheme.ts' }); + +const pendingActions: Array<() => void> = []; + +new Promise((resolve) => { + const checkLoaded = () => { + if (isLoaded.value) { + resolve(); + } else { + setTimeout(checkLoaded, 100); + } + }; + checkLoaded(); +}).then(() => { + while (pendingActions.length > 0) { + const action = pendingActions.shift(); + if (action) action(); + } +}); deepLink.on("event", (query) => { - console.log(`Deep link: event "event" fired with query: ${JSON.stringify(query)}`); + logger.info(`Deep link: event "event" fired with query: ${JSON.stringify(query)}`); }); deepLink.on("action", (query) => { - console.log(`Deep link: event "action" fired with query: ${JSON.stringify(query)}`); - const win = BrowserWindow.getAllWindows()[0]; - if (!win) return; + logger.info(`Deep link: event "action" fired with query: ${JSON.stringify(query)}`); + + const action = () => { + const win = BrowserWindow.getAllWindows()[0]; + if (!win) return; - if (query.cmd === 'update') { - win.webContents.send('deep-link-update'); - if (win.isMinimized()) win.restore(); - win.focus(); - } else if (query.cmd === 'list') { - win.webContents.send('deep-link-installed'); - if (win.isMinimized()) win.restore(); - win.focus(); + if (query.cmd === 'update') { + win.webContents.send('deep-link-update'); + if (win.isMinimized()) win.restore(); + win.focus(); + } else if (query.cmd === 'list') { + win.webContents.send('deep-link-installed'); + if (win.isMinimized()) win.restore(); + win.focus(); + } + }; + + logger.info(`isLoaded: ${isLoaded.value}`); + + if (isLoaded.value) { + action(); + } else { + pendingActions.push(action); } }); deepLink.on("install", (query) => { - console.log(`Deep link: event "install" fired with query: ${JSON.stringify(query)}`); - const win = BrowserWindow.getAllWindows()[0]; - if (!win) return; + logger.info(`Deep link: event "install" fired with query: ${JSON.stringify(query)}`); + + const action = () => { + const win = BrowserWindow.getAllWindows()[0]; + if (!win) return; - if (query.pkg) { - win.webContents.send('deep-link-install', query.pkg); - if (win.isMinimized()) win.restore(); - win.focus(); + if (query.pkg) { + win.webContents.send('deep-link-install', query.pkg); + if (win.isMinimized()) win.restore(); + win.focus(); + } + }; + + if (isLoaded.value) { + action(); + } else { + pendingActions.push(action); } }); diff --git a/electron/main/index.ts b/electron/main/index.ts index 00c2dd79..32cc2e54 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -1,17 +1,22 @@ -import { app, BrowserWindow, shell } from 'electron' +import { app, BrowserWindow, ipcMain, shell } from 'electron' import { createRequire } from 'node:module' import { fileURLToPath } from 'node:url' import path from 'node:path' import os from 'node:os' +import pino from 'pino' +import { handleCommandLine } from './deeplink.js' +import { isLoaded } from '../global.js' + // Assure single instance application if (!app.requestSingleInstanceLock()) { app.exit(0); } -import './handle-url-scheme.js' import './backend/install-manager.js' +import './handle-url-scheme.js' +const logger = pino({ 'name': 'index.ts' }); const require = createRequire(import.meta.url) const __dirname = path.dirname(fileURLToPath(import.meta.url)) @@ -79,6 +84,7 @@ async function createWindow() { // Test actively push message to the Electron-Renderer win.webContents.on('did-finish-load', () => { win?.webContents.send('main-process-message', new Date().toLocaleString()) + logger.info('Renderer process is ready.'); }) // Make all links open with the browser, not with the application @@ -89,7 +95,16 @@ async function createWindow() { // win.webContents.on('will-navigate', (event, url) => { }) #344 } -app.whenReady().then(createWindow) +ipcMain.on('renderer-ready', (event, args) => { + logger.info('Received renderer-ready event with args: ' + JSON.stringify(args)); + isLoaded.value = args.status; + logger.info(`isLoaded set to: ${isLoaded.value}`); +}) + +app.whenReady().then(() => { + createWindow() + handleCommandLine(process.argv) +}) app.on('window-all-closed', () => { win = null diff --git a/src/App.vue b/src/App.vue index 0f7171f0..eceff507 100644 --- a/src/App.vue +++ b/src/App.vue @@ -588,6 +588,9 @@ onMounted(async () => { tryOpen(); } }); + + window.ipcRenderer.send('renderer-ready', { status: true }); + logger.info('Renderer process is ready!'); }); // 观察器