diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23fd845d..0b2394da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,7 +45,6 @@ jobs: - name: Install Dependencies run: | - npm install -G node-gyp@11.1.0 npm install - name: Build Release Files diff --git a/electron/main/deeplink.ts b/electron/main/deeplink.ts new file mode 100644 index 00000000..dbf57746 --- /dev/null +++ b/electron/main/deeplink.ts @@ -0,0 +1,91 @@ +import { app } from "electron"; +type Query = Record; +export type Listener = (query: Query) => any; + +class ListenersMap { + private map: Map> = new Map(); + + add(action: string, listener: Listener) { + if (!this.map.has(action)) { + this.map.set(action, new Set()); + } + this.map.get(action)!.add(listener); + + return this.map.get(action)!.size; + } + + remove(action: string, listener: Listener) { + const listeners = this.map.get(action); + if (!listeners) return 0; + + listeners.delete(listener); + + if (listeners.size === 0) { + this.map.delete(action); + return 0; + } + + return listeners.size; + } + + emit(action: string, query: Query) { + const actionListeners = this.map.get(action); + if (!actionListeners) return 0; + + actionListeners.forEach((listener) => listener(query)); + + return actionListeners.size; + } +} + +const protocols = ["apmstore"]; +const listeners = new ListenersMap(); + +export const deepLink = { + on: (event: string, listener: Listener) => { + const count = listeners.add(event, listener); + console.log( + `Deep link: listener added for event ${event}. Total event listeners: ${count}` + ); + }, + off: (event: string, listener: Listener) => { + const count = listeners.remove(event, listener); + console.log( + `Deep link: listener removed for event ${event}. Total event listeners: ${count}` + ); + }, + once: (event: string, listener: Listener) => { + const onceListener: Listener = (query) => { + deepLink.off(event, onceListener); + listener(query); + }; + deepLink.on(event, onceListener); + }, +}; + +app.on("second-instance", (_e, commandLine) => { + const target = commandLine.find((arg) => + protocols.some((protocol) => arg.startsWith(protocol + "://")) + ); + if (!target) return; + + console.log(`Deep link: protocol link got: ${target}`); + + try { + const url = new URL(target); + + const action = url.hostname; + console.log(`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)}`); + + const emitCount = listeners.emit(action, query); + console.log(`Deep link: emitted for ${emitCount} listeners`); + } catch (error) { + console.error(`Deep link: error parsing URL: ${error}`); + } +}); diff --git a/electron/main/handle-url-scheme.ts b/electron/main/handle-url-scheme.ts index 485cd4a5..af5fd875 100644 --- a/electron/main/handle-url-scheme.ts +++ b/electron/main/handle-url-scheme.ts @@ -1,5 +1,6 @@ import { dialog } from 'electron' +import { deepLink } from './deeplink'; -export async function handleUrlScheme(requestUrl: string) { - console.log('Handling URL scheme request:', requestUrl); -} \ No newline at end of file +deepLink.on("event", (query) => { + console.log(`Deep link: event "event" fired with query: ${JSON.stringify(query)}`); +}); \ No newline at end of file diff --git a/electron/main/index.ts b/electron/main/index.ts index f8551c42..a4b3c2cd 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -3,14 +3,15 @@ import { createRequire } from 'node:module' import { fileURLToPath } from 'node:url' import path from 'node:path' import os from 'node:os' -import { electronAppUniversalProtocolClient } from 'electron-app-universal-protocol-client' -import { handleUrlScheme } from './handle-url-scheme.js' +import './handle-url-scheme.js' +// Assure single instance application if (!app.requestSingleInstanceLock()) { app.exit(0); } + const require = createRequire(import.meta.url) const __dirname = path.dirname(fileURLToPath(import.meta.url)) @@ -83,17 +84,6 @@ async function createWindow() { return { action: 'deny' } }) // win.webContents.on('will-navigate', (event, url) => { }) #344 - - // Initialize universal protocol client - electronAppUniversalProtocolClient.on( - 'request', - handleUrlScheme - ); - - await electronAppUniversalProtocolClient.initialize({ - protocol: 'apmstore', - mode: 'development', // Make sure to use 'production' when script is executed in bundled app - }); } app.whenReady().then(createWindow) diff --git a/package.json b/package.json index 83aec514..4dbc667f 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@dotenvx/dotenvx": "^1.51.4", "@vitejs/plugin-vue": "^5.0.4", "electron": "^39.2.7", - "electron-app-universal-protocol-client": "^2.1.1", + "electron-app-universal-protocol-client": "github:witcher112/electron-app-universal-protocol-client", "electron-builder": "^24.13.3", "typescript": "^5.4.2", "vite": "^5.1.5",