From 8730513340574d03d0b48abcd6b8c1a0627251aa Mon Sep 17 00:00:00 2001 From: FatttSnake Date: Tue, 19 Mar 2024 16:54:36 +0800 Subject: [PATCH] Feat: all - support URL protocol --- package.json | 11 ++++++-- src/main/global.d.ts | 13 +++++++++ src/main/index.ts | 51 ++++++++++++++++++++++++++++++++-- src/preload/index.ts | 6 ++-- src/renderer/src/AuthRoute.tsx | 7 +++++ src/renderer/src/electron.d.ts | 8 ++++++ src/renderer/src/global.d.ts | 7 +++++ 7 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 src/main/global.d.ts create mode 100644 src/renderer/src/electron.d.ts diff --git a/package.json b/package.json index 9d9037f..c157f01 100644 --- a/package.json +++ b/package.json @@ -6,17 +6,22 @@ "author": "example.com", "homepage": "https://electron-vite.org", "scripts": { - "dev": "electron-vite dev", + "dev": "electron-vite dev --sourcemap --remote-debugging-port=9000", "format": "prettier --write .", "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix", "typecheck": "tsc", "start": "electron-vite preview", "build": "electron-vite build && npm run typecheck", + "build-test": "electron-vite build --mode testing && npm run typecheck", "postinstall": "electron-builder install-app-deps", "build:unpack": "npm run build && electron-builder --dir", + "build-test:unpack": "npm run build-test && electron-builder --dir", "build:win": "npm run build && electron-builder --win", - "build:mac": "electron-vite build && electron-builder --mac", - "build:linux": "electron-vite build && electron-builder --linux" + "build-test:win": "npm run build-test && electron-builder --win", + "build:mac": "npm run build && electron-builder --mac", + "build-test:mac": "npm run build-test && electron-builder --mac", + "build:linux": "npm run build && electron-builder --linux", + "build-test:linux": "npm run build-test && electron-builder --linux" }, "dependencies": { "@electron-toolkit/preload": "^3.0.0", diff --git a/src/main/global.d.ts b/src/main/global.d.ts new file mode 100644 index 0000000..3c22eaa --- /dev/null +++ b/src/main/global.d.ts @@ -0,0 +1,13 @@ +type Platform = 'WEB' | 'DESKTOP' | 'ANDROID' + +interface ImportMetaEnv { + readonly VITE_PLATFORM: Platform + readonly VITE_PROTOCOL: string + readonly VITE_API_URL: string + readonly VITE_API_TOKEN_URL: string + readonly VITE_TURNSTILE_SITE_KEY: string +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} diff --git a/src/main/index.ts b/src/main/index.ts index 9f762a8..c953f1a 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,11 +1,58 @@ -import { app, shell, BrowserWindow, ipcMain } from 'electron' +import { app, shell, BrowserWindow, ipcMain, webContents } from 'electron' import { join } from 'path' import { electronApp, optimizer, is } from '@electron-toolkit/utils' import icon from '../../resources/logo.ico?asset' +import * as path from 'node:path' + +let mainWindow: BrowserWindow + +// Application singleton execution +if (!app.requestSingleInstanceLock()) { + app.quit() +} + +// Register protocol client +const args: string[] = [] +if (!app.isPackaged) { + args.push(path.resolve(process.argv[1])) +} +args.push('--') +app.setAsDefaultProtocolClient(import.meta.env.VITE_PROTOCOL, process.execPath, args) + +const handleArgv = (argv: string[]) => { + const prefix = `${import.meta.env.VITE_PROTOCOL}:` + const offset = app.isPackaged ? 1 : 2 + const url = argv.find((arg, index) => index >= offset && arg.startsWith(prefix)) + if (url) { + handleUrl(url) + } +} + +const handleUrl = (url: string) => { + const { hostname, pathname } = new URL(url) + if (hostname === 'openurl') { + webContents.getAllWebContents().forEach((webContent) => { + webContent.send('open-url', pathname) + }) + } +} + +// Windows +handleArgv(process.argv) +app.on('second-instance', (_, argv) => { + if (process.platform === 'win32') { + handleArgv(argv) + } +}) + +// macOS +app.on('open-url', (_, argv) => { + handleUrl(argv) +}) function createWindow(): void { // Create the browser window. - const mainWindow = new BrowserWindow({ + mainWindow = new BrowserWindow({ width: 900, height: 670, show: false, diff --git a/src/preload/index.ts b/src/preload/index.ts index 3e89029..f4c7828 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -9,15 +9,15 @@ const api = {} // just add to the DOM global. if (process.contextIsolated) { try { - contextBridge.exposeInMainWorld('electron', electronAPI) + contextBridge.exposeInMainWorld('electronAPI', electronAPI) contextBridge.exposeInMainWorld('api', api) - contextBridge.exposeInMainWorld('notification', Notification) + contextBridge.exposeInMainWorld('Notification', Notification) } catch (error) { console.error(error) } } else { // @ts-expect-error (define in dts) - window.electron = electronAPI + window.electronAPI = electronAPI // @ts-expect-error (define in dts) window.api = api // @ts-expect-error (define in dts) diff --git a/src/renderer/src/AuthRoute.tsx b/src/renderer/src/AuthRoute.tsx index 0336fd1..81e81fa 100644 --- a/src/renderer/src/AuthRoute.tsx +++ b/src/renderer/src/AuthRoute.tsx @@ -3,6 +3,7 @@ import { getRedirectUrl } from '@/util/route' import { getLoginStatus, getVerifyStatus_async } from '@/util/auth' const AuthRoute = () => { + const navigate = useNavigate() const [searchParams] = useSearchParams() const matches = useMatches() const lastMatch = matches.reduce((_, second) => second) @@ -12,6 +13,12 @@ const AuthRoute = () => { const isLogin = getLoginStatus() const isVerify = getVerifyStatus_async() + useEffect(() => { + window.electronAPI.ipcRenderer.on('open-url', (_, url: string) => { + navigate(url) + }) + }, []) + return useMemo(() => { document.title = `${handle?.titlePrefix ?? ''}${ handle?.title ? handle?.title : PRODUCTION_NAME diff --git a/src/renderer/src/electron.d.ts b/src/renderer/src/electron.d.ts new file mode 100644 index 0000000..c8c1689 --- /dev/null +++ b/src/renderer/src/electron.d.ts @@ -0,0 +1,8 @@ +import { ElectronAPI } from "@electron-toolkit/preload"; +import { Notification } from "electron"; + +declare global { + type _ElectronAPI = ElectronAPI + + class _Notification extends Notification {} +} diff --git a/src/renderer/src/global.d.ts b/src/renderer/src/global.d.ts index e67e298..1296c5e 100644 --- a/src/renderer/src/global.d.ts +++ b/src/renderer/src/global.d.ts @@ -1,10 +1,12 @@ /// +/// /// type Platform = 'WEB' | 'DESKTOP' | 'ANDROID' interface ImportMetaEnv { readonly VITE_PLATFORM: Platform + readonly VITE_PROTOCOL: string readonly VITE_API_URL: string readonly VITE_API_TOKEN_URL: string readonly VITE_TURNSTILE_SITE_KEY: string @@ -14,6 +16,11 @@ interface ImportMeta { readonly env: ImportMetaEnv } +interface Window { + electronAPI: _ElectronAPI + Notification: typeof _Notification +} + interface RouteJsonObject { path: string absolutePath: string