diff --git a/src/components/main/Main.tsx b/src/components/main/Main.tsx index 2682cfa73..a87ac770d 100644 --- a/src/components/main/Main.tsx +++ b/src/components/main/Main.tsx @@ -394,6 +394,12 @@ const Main: FC = ({ } }, []); + useEffect(() => { + return window.electron?.on(ElectronEvent.DEEPLINK, (link: string) => { + processDeepLink(decodeURIComponent(link)); + }); + }, []); + useEffect(() => { const parsedLocationHash = parseLocationHash(); if (!parsedLocationHash) return; diff --git a/src/electron/config.yml b/src/electron/config.yml index 295612395..b6265c36c 100644 --- a/src/electron/config.yml +++ b/src/electron/config.yml @@ -1,9 +1,9 @@ -productName: "Telegram A" -artifactName: "${productName}-${arch}.${ext}" -appId: "org.telegram.TelegramA" +productName: Telegram A +artifactName: ${productName}-${arch}.${ext} +appId: org.telegram.TelegramA extraMetadata: - main: "./dist/electron.js" - productName: "Telegram A" + main: ./dist/electron.js + productName: Telegram A files: - "dist" - "package.json" @@ -14,40 +14,47 @@ files: - "!dist/get" - "!node_modules" directories: - buildResources: "./public" - output: "./dist-electron" + buildResources: ./public + output: ./dist-electron +protocols: + - name: Tg + schemes: + - tg publish: - provider: "github" - owner: "Ajaxy" - repo: "telegram-tt" - releaseType: "draft" + provider: github + owner: Ajaxy + repo: telegram-tt + releaseType: draft win: - target: "nsis" - icon: "public/icon-electron-windows.ico" + target: nsis + icon: public/icon-electron-windows.ico nsis: oneClick: false createDesktopShortcut: true createStartMenuShortcut: true mac: target: - target: "default" - arch: ["x64", "arm64"] - entitlements: "public/electron-entitlements.mac.plist" - icon: "public/icon-electron-macos.icns" + target: default + arch: + - x64 + - arm64 + entitlements: public/electron-entitlements.mac.plist + icon: public/icon-electron-macos.icns notarize: - teamId: "Y54Z4K69Z9" + teamId: Y54Z4K69Z9 dmg: - title: "Telegram A installer" - background: "public/background-electron-dmg.tiff" + title: Telegram A installer + background: public/background-electron-dmg.tiff iconSize: 100 contents: - x: 138 y: 225 - type: "file" + type: file - x: 402 y: 225 - type: "link" + type: link path: "/Applications" linux: - category: "Community" - target: ["AppImage"] + category: Community + target: + - AppImage diff --git a/src/electron/deeplink.ts b/src/electron/deeplink.ts new file mode 100644 index 000000000..af3f3e38c --- /dev/null +++ b/src/electron/deeplink.ts @@ -0,0 +1,78 @@ +import { app } from 'electron'; +import path from 'path'; + +import { ElectronEvent } from '../types/electron'; + +import { + IS_LINUX, IS_MAC_OS, IS_WINDOWS, windows, +} from './utils'; + +const TG_PROTOCOL = 'tg'; + +let deeplinkUrl: string | undefined; + +export function initDeeplink() { + const currentWindow = Array.from(windows).pop(); + + if (process.defaultApp) { + if (process.argv.length >= 2) { + app.setAsDefaultProtocolClient(TG_PROTOCOL, process.execPath, [path.resolve(process.argv[1])]); + } + } else { + app.setAsDefaultProtocolClient(TG_PROTOCOL); + } + + const gotTheLock = app.requestSingleInstanceLock(); + + if (!gotTheLock) { + app.quit(); + + return; + } + + app.on('will-finish-launching', () => { + app.on('open-url', (event: Event, url: string) => { + event.preventDefault(); + deeplinkUrl = url; + processDeeplink(); + }); + }); + + if (IS_WINDOWS || IS_LINUX) { + deeplinkUrl = findDeeplink(process.argv); + } + + app.on('second-instance', (_, argv: string[]) => { + if (IS_MAC_OS) { + deeplinkUrl = argv[0]; + } else { + deeplinkUrl = findDeeplink(argv); + } + + processDeeplink(); + + if (currentWindow) { + if (currentWindow.isMinimized()) { + currentWindow.restore(); + } + + currentWindow.focus(); + } + }); +} + +export function processDeeplink() { + const currentWindow = Array.from(windows).pop(); + + if (!currentWindow || !deeplinkUrl) { + return; + } + + currentWindow.webContents.send(ElectronEvent.DEEPLINK, deeplinkUrl); + + deeplinkUrl = undefined; +} + +function findDeeplink(args: string[]) { + return args.find((arg) => arg.startsWith(`${TG_PROTOCOL}://`)); +} diff --git a/src/electron/main.ts b/src/electron/main.ts index 9c3c033f0..babf27778 100644 --- a/src/electron/main.ts +++ b/src/electron/main.ts @@ -4,9 +4,12 @@ import { app, nativeImage } from 'electron'; import contextMenu from 'electron-context-menu'; import path from 'path'; +import { initDeeplink } from './deeplink'; import { createWindow, setupCloseHandlers, setupElectronActionHandlers } from './window'; import { IS_MAC_OS, IS_WINDOWS } from './utils'; +initDeeplink(); + contextMenu({ showLearnSpelling: false, showLookUpSelection: false, diff --git a/src/electron/window.ts b/src/electron/window.ts index dab5415ed..d7cedf3db 100644 --- a/src/electron/window.ts +++ b/src/electron/window.ts @@ -7,6 +7,7 @@ import path from 'path'; import { ElectronAction, ElectronEvent } from '../types/electron'; import type { TrafficLightPosition } from '../types/electron'; import setupAutoUpdates from './autoUpdates'; +import { processDeeplink } from './deeplink'; import { forceQuit, getAppTitle, IS_MAC_OS, TRAFFIC_LIGHT_POSITION, windows, } from './utils'; @@ -123,6 +124,7 @@ export function createWindow(url?: string) { window.webContents.once('dom-ready', () => { window.show(); + processDeeplink(); if (process.env.APP_ENV === 'production') { setupAutoUpdates(window, windowState); diff --git a/src/types/electron.ts b/src/types/electron.ts index 517ba14e6..cd443153f 100644 --- a/src/types/electron.ts +++ b/src/types/electron.ts @@ -2,6 +2,7 @@ export enum ElectronEvent { FULLSCREEN_CHANGE = 'fullscreen-change', UPDATE_ERROR = 'update-error', UPDATE_DOWNLOADED = 'update-downloaded', + DEEPLINK = 'deeplink', } export enum ElectronAction {