diff --git a/electron-builder.yml b/electron-builder.yml index f120f673..a6e23d39 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -22,6 +22,10 @@ mac: fileAssociations: ext: torrent icon: resources/file-moose.icns +protocols: + name: open-magnet + schemes: + - magnet dmg: # https://kilianvalkhof:com/2019/electron/notarizing-your-electron-application/: sign: false diff --git a/main/background.ts b/main/background.ts index 3f6dc98b..3961eb54 100644 --- a/main/background.ts +++ b/main/background.ts @@ -24,6 +24,7 @@ app.commandLine.appendSwitch("enable-experimental-web-platform-features"); app.name = name; let win: BrowserWindow; let path: string; +let magnetUri: string; if (app.isPackaged) { unhandled(); @@ -67,6 +68,9 @@ async function _createWindow() { if (path) { params.append("path", encodeURI(path)); } + if (magnetUri) { + params.append("magnet", encodeURI(magnetUri)); + } const query = params.toString(); if (app.isPackaged) { @@ -119,3 +123,12 @@ app.on("open-file", (_e, _path) => { path = _path; } }); + +app.setAsDefaultProtocolClient("magnet"); +app.on("open-url", (e, url) => { + if (app.isReady()) { + win.webContents.send("magnet-opened", url); + } else { + magnetUri = url; + } +}); diff --git a/renderer/components/Container/Container.tsx b/renderer/components/Container/Container.tsx index 54159573..4d18da6e 100644 --- a/renderer/components/Container/Container.tsx +++ b/renderer/components/Container/Container.tsx @@ -9,13 +9,16 @@ import { DownloadingTorrent } from "../../../types/DownloadingTorrent"; import { ipcRenderer, remote } from "electron"; import { Message } from "@components/Message"; import { SelectedCastContext } from "@contexts/SelectedCast"; -import { Toast } from "@components/Toast"; +import { showToast, Toast } from "@components/Toast"; import { getDefaultColor } from "@utils/theme"; import { parseFileInfo } from "@utils/parseFileInfo"; import fs from "fs"; +import MagnetUri from "magnet-uri"; +import ParseTorrent from "parse-torrent"; const { searchParams } = new URL(window.location.href); const path = decodeURI(searchParams.get("path")); +const magnetUri = decodeURI(searchParams.get("magnet")); export default function () { const [selectedTorrent, setSelectedTorrent] = useState( @@ -74,15 +77,15 @@ export default function () { [store] ); - const loadFile = useCallback((path: string) => { - if (!path) return; - fs.readFile(path, async (err, data) => { - if (err) return; - onFileSelect(await parseFileInfo(data)); - }); - }, []); - useEffect(() => { + function loadFile(path: string) { + if (!path) return; + fs.readFile(path, async (err, data) => { + if (err) return; + onFileSelect(await parseFileInfo(data)); + }); + } + loadFile(path); function loadFileWhenAppIsOpen(e, path: string) { @@ -93,7 +96,29 @@ export default function () { return () => { ipcRenderer.off("file-opened", loadFileWhenAppIsOpen); }; - }, [loadFile]); + }, []); + + useEffect(() => { + function loadMagnetUri(_magnetUri: string) { + if (!_magnetUri) return; + try { + const { name, infoHash }: MagnetUri.Instance = ParseTorrent(_magnetUri); + onFileSelect({ name: name as string, magnet: _magnetUri, infoHash }); + } catch (e) { + showToast(`${_magnetUri} is an invalid magnet url.`); + } + } + + loadMagnetUri(magnetUri); + function loadMagnetWhenAppIsOpen(e, url: string) { + loadMagnetUri(url); + } + ipcRenderer.on("magnet-opened", loadMagnetWhenAppIsOpen); + + return () => { + ipcRenderer.off("magnet-opened", loadMagnetWhenAppIsOpen); + }; + }, []); useEffect(() => { store.set("torrents", downloads);