mirror of
https://gitee.com/spark-store-project/spark-store
synced 2026-04-26 09:20:18 +08:00
fix: deep link handling at electron startup
This commit is contained in:
2
electron/global.ts
Normal file
2
electron/global.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import { ref } from 'vue';
|
||||||
|
export let isLoaded = ref(false);
|
||||||
@@ -4,7 +4,7 @@ import readline from 'node:readline';
|
|||||||
import { promisify } from 'node:util';
|
import { promisify } from 'node:util';
|
||||||
import pino from 'pino';
|
import pino from 'pino';
|
||||||
|
|
||||||
const logger = pino({ 'name': 'download-manager' });
|
const logger = pino({ 'name': 'install-manager' });
|
||||||
|
|
||||||
type InstallTask = {
|
type InstallTask = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
* Author: juxnpxblo@github
|
* Author: juxnpxblo@github
|
||||||
*/
|
*/
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
|
import pino from "pino";
|
||||||
|
|
||||||
|
const logger = pino({ 'name': 'deeplink.ts' });
|
||||||
type Query = Record<string, string>;
|
type Query = Record<string, string>;
|
||||||
export type Listener = (query: Query) => any;
|
export type Listener = (query: Query) => any;
|
||||||
|
|
||||||
@@ -48,13 +51,13 @@ const listeners = new ListenersMap();
|
|||||||
export const deepLink = {
|
export const deepLink = {
|
||||||
on: (event: string, listener: Listener) => {
|
on: (event: string, listener: Listener) => {
|
||||||
const count = listeners.add(event, listener);
|
const count = listeners.add(event, listener);
|
||||||
console.log(
|
logger.info(
|
||||||
`Deep link: listener added for event ${event}. Total event listeners: ${count}`
|
`Deep link: listener added for event ${event}. Total event listeners: ${count}`
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
off: (event: string, listener: Listener) => {
|
off: (event: string, listener: Listener) => {
|
||||||
const count = listeners.remove(event, listener);
|
const count = listeners.remove(event, listener);
|
||||||
console.log(
|
logger.info(
|
||||||
`Deep link: listener removed for event ${event}. Total event listeners: ${count}`
|
`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) =>
|
const target = commandLine.find((arg) =>
|
||||||
protocols.some((protocol) => arg.startsWith(protocol + "://"))
|
protocols.some((protocol) => arg.startsWith(protocol + "://"))
|
||||||
);
|
);
|
||||||
if (!target) return;
|
if (!target) return;
|
||||||
|
|
||||||
console.log(`Deep link: protocol link got: ${target}`);
|
logger.info(`Deep link: protocol link got: ${target}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url = new URL(target);
|
const url = new URL(target);
|
||||||
|
|
||||||
const action = url.hostname;
|
const action = url.hostname;
|
||||||
console.log(`Deep link: action found: ${action}`);
|
logger.info(`Deep link: action found: ${action}`);
|
||||||
|
|
||||||
const query: Query = {};
|
const query: Query = {};
|
||||||
url.searchParams.forEach((value, key) => {
|
url.searchParams.forEach((value, key) => {
|
||||||
query[key] = value;
|
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);
|
const emitCount = listeners.emit(action, query);
|
||||||
console.log(`Deep link: emitted for ${emitCount} listeners`);
|
logger.info(`Deep link: emitted for ${emitCount} listeners`);
|
||||||
} catch (error) {
|
} 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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,36 @@
|
|||||||
import { BrowserWindow } from 'electron';
|
import { BrowserWindow } from 'electron';
|
||||||
import { deepLink } from './deeplink';
|
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<void>((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) => {
|
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) => {
|
deepLink.on("action", (query) => {
|
||||||
console.log(`Deep link: event "action" fired with query: ${JSON.stringify(query)}`);
|
logger.info(`Deep link: event "action" fired with query: ${JSON.stringify(query)}`);
|
||||||
|
|
||||||
|
const action = () => {
|
||||||
const win = BrowserWindow.getAllWindows()[0];
|
const win = BrowserWindow.getAllWindows()[0];
|
||||||
if (!win) return;
|
if (!win) return;
|
||||||
|
|
||||||
@@ -19,10 +43,21 @@ deepLink.on("action", (query) => {
|
|||||||
if (win.isMinimized()) win.restore();
|
if (win.isMinimized()) win.restore();
|
||||||
win.focus();
|
win.focus();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
logger.info(`isLoaded: ${isLoaded.value}`);
|
||||||
|
|
||||||
|
if (isLoaded.value) {
|
||||||
|
action();
|
||||||
|
} else {
|
||||||
|
pendingActions.push(action);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
deepLink.on("install", (query) => {
|
deepLink.on("install", (query) => {
|
||||||
console.log(`Deep link: event "install" fired with query: ${JSON.stringify(query)}`);
|
logger.info(`Deep link: event "install" fired with query: ${JSON.stringify(query)}`);
|
||||||
|
|
||||||
|
const action = () => {
|
||||||
const win = BrowserWindow.getAllWindows()[0];
|
const win = BrowserWindow.getAllWindows()[0];
|
||||||
if (!win) return;
|
if (!win) return;
|
||||||
|
|
||||||
@@ -31,4 +66,11 @@ deepLink.on("install", (query) => {
|
|||||||
if (win.isMinimized()) win.restore();
|
if (win.isMinimized()) win.restore();
|
||||||
win.focus();
|
win.focus();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isLoaded.value) {
|
||||||
|
action();
|
||||||
|
} else {
|
||||||
|
pendingActions.push(action);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
import { app, BrowserWindow, shell } from 'electron'
|
import { app, BrowserWindow, ipcMain, shell } from 'electron'
|
||||||
import { createRequire } from 'node:module'
|
import { createRequire } from 'node:module'
|
||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
import os from 'node:os'
|
import os from 'node:os'
|
||||||
|
import pino from 'pino'
|
||||||
|
import { handleCommandLine } from './deeplink.js'
|
||||||
|
import { isLoaded } from '../global.js'
|
||||||
|
|
||||||
|
|
||||||
// Assure single instance application
|
// Assure single instance application
|
||||||
if (!app.requestSingleInstanceLock()) {
|
if (!app.requestSingleInstanceLock()) {
|
||||||
app.exit(0);
|
app.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
import './handle-url-scheme.js'
|
|
||||||
import './backend/install-manager.js'
|
import './backend/install-manager.js'
|
||||||
|
import './handle-url-scheme.js'
|
||||||
|
|
||||||
|
const logger = pino({ 'name': 'index.ts' });
|
||||||
const require = createRequire(import.meta.url)
|
const require = createRequire(import.meta.url)
|
||||||
const __dirname = path.dirname(fileURLToPath(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
|
// Test actively push message to the Electron-Renderer
|
||||||
win.webContents.on('did-finish-load', () => {
|
win.webContents.on('did-finish-load', () => {
|
||||||
win?.webContents.send('main-process-message', new Date().toLocaleString())
|
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
|
// 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
|
// 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', () => {
|
app.on('window-all-closed', () => {
|
||||||
win = null
|
win = null
|
||||||
|
|||||||
@@ -588,6 +588,9 @@ onMounted(async () => {
|
|||||||
tryOpen();
|
tryOpen();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
window.ipcRenderer.send('renderer-ready', { status: true });
|
||||||
|
logger.info('Renderer process is ready!');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 观察器
|
// 观察器
|
||||||
|
|||||||
Reference in New Issue
Block a user