From 1cae467acdcfd0ca0f635fca9c448494fc3e9980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isabella=20Sko=C5=99epov=C3=A1?= Date: Tue, 24 May 2022 06:55:33 +0200 Subject: [PATCH] add magnet link support to transmission web (#2874) --- web/assets/css/transmission-app.scss | 1 + web/src/open-dialog.js | 13 +++--- web/src/prefs-dialog.js | 65 ++++++++++++++++++++++++++++ web/src/transmission.js | 15 +++++++ 4 files changed, 89 insertions(+), 5 deletions(-) diff --git a/web/assets/css/transmission-app.scss b/web/assets/css/transmission-app.scss index c141462af..021eace75 100644 --- a/web/assets/css/transmission-app.scss +++ b/web/assets/css/transmission-app.scss @@ -785,6 +785,7 @@ $popup-top: 61px; // TODO: ugly that this is hardcoded .blocklist-size-label, .blocklist-update-button, + .register-handler-button, .port-status { grid-column: 2 / 3; } diff --git a/web/src/open-dialog.js b/web/src/open-dialog.js index daa001670..f7f02f6bc 100644 --- a/web/src/open-dialog.js +++ b/web/src/open-dialog.js @@ -8,13 +8,13 @@ import { Formatter } from './formatter.js'; import { createDialogContainer, makeUUID } from './utils.js'; export class OpenDialog extends EventTarget { - constructor(controller, remote) { + constructor(controller, remote, url = '') { super(); this.controller = controller; this.remote = remote; - this.elements = this._create(); + this.elements = this._create(url); this.elements.dismiss.addEventListener('click', () => this._onDismiss()); this.elements.confirm.addEventListener('click', () => this._onConfirm()); this._updateFreeSpaceInAddDialog(); @@ -43,8 +43,10 @@ export class OpenDialog extends EventTarget { _updateFreeSpaceInAddDialog() { const path = this.elements.folder_input.value; this.remote.getFreeSpace(path, (dir, bytes) => { - const string = bytes > 0 ? `${Formatter.size(bytes)} Free` : ''; - this.elements.freespace.textContent = string; + if (!this.closed) { + const string = bytes > 0 ? `${Formatter.size(bytes)} Free` : ''; + this.elements.freespace.textContent = string; + } }); } @@ -114,7 +116,7 @@ export class OpenDialog extends EventTarget { this._onDismiss(); } - _create() { + _create(url) { const elements = createDialogContainer(); const { confirm, root, heading, workarea } = elements; @@ -145,6 +147,7 @@ export class OpenDialog extends EventTarget { input = document.createElement('input'); input.type = 'url'; input.id = input_id; + input.value = url; workarea.append(input); elements.url_input = input; input.addEventListener('keyup', ({ key }) => { diff --git a/web/src/prefs-dialog.js b/web/src/prefs-dialog.js index 112fdca44..8b2597a6f 100644 --- a/web/src/prefs-dialog.js +++ b/web/src/prefs-dialog.js @@ -196,6 +196,53 @@ export class PrefsDialog extends EventTarget { callback(); } + static _getProtocolHandlerRegistered() { + return localStorage.getItem('protocol-handler-registered') === 'true'; + } + + static _updateProtocolHandlerButton(button) { + button.removeAttribute('disabled'); + button.removeAttribute('title'); + + if (PrefsDialog._getProtocolHandlerRegistered()) { + button.textContent = 'Remove Browser Handler'; + if (!('unregisterProtocolHandler' in navigator)) { + button.setAttribute( + 'title', + 'Your browser does not support removing protocol handlers. This button only allows you to re-register a handler.' + ); + } + } else { + button.textContent = 'Add Browser Handler'; + button.removeAttribute('title'); + if (!('registerProtocolHandler' in navigator)) { + button.setAttribute('disabled', true); + button.setAttribute( + 'title', + 'Your browser does not support protocol handlers' + ); + } + } + } + + static _toggleProtocolHandler(button) { + const handlerUrl = new URL(window.location.href); + handlerUrl.search = 'addtorrent=%s'; + if (this._getProtocolHandlerRegistered()) { + navigator.unregisterProtocolHandler?.('magnet', handlerUrl.toString()); + localStorage.removeItem('protocol-handler-registered'); + PrefsDialog._updateProtocolHandlerButton(button); + } else { + navigator.registerProtocolHandler( + 'magnet', + handlerUrl.toString(), + 'Transmission Web' + ); + localStorage.setItem('protocol-handler-registered', 'true'); + PrefsDialog._updateProtocolHandlerButton(button); + } + } + static _createTorrentsPage() { const root = document.createElement('div'); root.classList.add('prefs-torrents-page'); @@ -302,6 +349,17 @@ export class PrefsDialog extends EventTarget { PrefsDialog._enableIfChecked(input, cal.check); const stop_idle_input = input; + label = document.createElement('div'); + label.textContent = 'Magnet Protocol Handler'; + label.classList.add('section-label'); + root.append(label); + + const button = document.createElement('button'); + button.classList.add('register-handler-button'); + PrefsDialog._updateProtocolHandlerButton(button); + root.append(button); + const register_handler_button = button; + return { autostart_check, download_dir, @@ -309,6 +367,7 @@ export class PrefsDialog extends EventTarget { download_queue_input, incomplete_dir_check, incomplete_dir_input, + register_handler_button, root, stop_idle_check, stop_idle_input, @@ -723,6 +782,12 @@ export class PrefsDialog extends EventTarget { this._setBlocklistButtonEnabled(false); } ); + this.elements.torrents.register_handler_button.addEventListener( + 'click', + (event_) => { + PrefsDialog._toggleProtocolHandler(event_.currentTarget); + } + ); this.outside = new OutsideClickListener(this.elements.root); this.outside.addEventListener('click', () => this.close()); diff --git a/web/src/transmission.js b/web/src/transmission.js index 0beb81dbb..9eb33df12 100644 --- a/web/src/transmission.js +++ b/web/src/transmission.js @@ -260,9 +260,24 @@ export class Transmission extends EventTarget { } } + _openTorrentFromUrl() { + setTimeout(() => { + const addTorrent = new URLSearchParams(window.location.search).get( + 'addtorrent' + ); + if (addTorrent) { + this.setCurrentPopup(new OpenDialog(this, this.remote, addTorrent)); + const newUrl = new URL(window.location); + newUrl.search = ''; + window.history.pushState('', '', newUrl.toString()); + } + }, 0); + } + loadDaemonPrefs() { this.remote.loadDaemonPrefs((data) => { this.session_properties = data.arguments; + this._openTorrentFromUrl(); }); }