diff --git a/src/webui/www/private/addpeers.html b/src/webui/www/private/addpeers.html index 4a23ace3d..a86673d14 100644 --- a/src/webui/www/private/addpeers.html +++ b/src/webui/www/private/addpeers.html @@ -14,11 +14,11 @@ defaultEventType: 'keydown', events: { 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -49,7 +49,7 @@ alert("QBT_TR(Unable to add peers. Please ensure you are adhering to the IP:port format.)QBT_TR[CONTEXT=HttpServer]"); }, onSuccess: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); }); @@ -62,7 +62,7 @@

QBT_TR(List of peers to add (one IP per line):)QBT_TR[CONTEXT=PeersAdditionDialog]

- +
diff --git a/src/webui/www/private/addtrackers.html b/src/webui/www/private/addtrackers.html index 5bf5670cf..e22cf078b 100644 --- a/src/webui/www/private/addtrackers.html +++ b/src/webui/www/private/addtrackers.html @@ -15,11 +15,11 @@ defaultEventType: 'keydown', events: { 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -37,7 +37,7 @@ urls: $('trackersUrls').value }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); }); diff --git a/src/webui/www/private/confirmdeletion.html b/src/webui/www/private/confirmdeletion.html index 2170d9b51..9c5038624 100644 --- a/src/webui/www/private/confirmdeletion.html +++ b/src/webui/www/private/confirmdeletion.html @@ -75,7 +75,7 @@ $('cancelBtn').focus(); $('cancelBtn').addEvent('click', function(e) { new Event(e).stop(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }); $('confirmBtn').addEvent('click', function(e) { parent.torrentsTable.deselectAll(); @@ -90,7 +90,7 @@ 'deleteFiles': deleteFiles }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); }); diff --git a/src/webui/www/private/confirmfeeddeletion.html b/src/webui/www/private/confirmfeeddeletion.html index dba355316..053cacc3d 100644 --- a/src/webui/www/private/confirmfeeddeletion.html +++ b/src/webui/www/private/confirmfeeddeletion.html @@ -15,7 +15,7 @@ $('cancelBtn').focus(); $('cancelBtn').addEvent('click', (e) => { new Event(e).stop(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }); $('confirmBtn').addEvent('click', (e) => { new Event(e).stop(); @@ -32,7 +32,7 @@ ++completionCount; if (completionCount === paths.length) { window.parent.qBittorrent.Rss.updateRssFeedList(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } } }).send(); diff --git a/src/webui/www/private/download.html b/src/webui/www/private/download.html index 913a10001..13caf8526 100644 --- a/src/webui/www/private/download.html +++ b/src/webui/www/private/download.html @@ -187,7 +187,7 @@ $('download_frame').addEventListener("load", function() { if (submitted) - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); });
diff --git a/src/webui/www/private/downloadlimit.html b/src/webui/www/private/downloadlimit.html index fa49266dd..35e127363 100644 --- a/src/webui/www/private/downloadlimit.html +++ b/src/webui/www/private/downloadlimit.html @@ -36,7 +36,7 @@ }, onComplete: function() { window.parent.updateMainData(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); } @@ -49,7 +49,7 @@ 'limit': limit }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); } @@ -67,11 +67,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } diff --git a/src/webui/www/private/edittracker.html b/src/webui/www/private/edittracker.html index 17d2a92d2..feb5f5766 100644 --- a/src/webui/www/private/edittracker.html +++ b/src/webui/www/private/edittracker.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -48,7 +48,7 @@ newUrl: $('trackerUrl').value }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); }); diff --git a/src/webui/www/private/newcategory.html b/src/webui/www/private/newcategory.html index 63186e013..8fa1986aa 100644 --- a/src/webui/www/private/newcategory.html +++ b/src/webui/www/private/newcategory.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -89,7 +89,7 @@ category: categoryName }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); }, @@ -111,7 +111,7 @@ savePath: savePath }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); break; @@ -124,7 +124,7 @@ savePath: savePath }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); break; diff --git a/src/webui/www/private/newfeed.html b/src/webui/www/private/newfeed.html index 4f6204a9d..496e68940 100644 --- a/src/webui/www/private/newfeed.html +++ b/src/webui/www/private/newfeed.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': (event) => { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': (event) => { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -52,7 +52,7 @@ }, onSuccess: (response) => { window.parent.qBittorrent.Rss.updateRssFeedList(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }, onFailure: (response) => { if (response.status === 409) diff --git a/src/webui/www/private/newfolder.html b/src/webui/www/private/newfolder.html index cc1259b8d..5429d2575 100644 --- a/src/webui/www/private/newfolder.html +++ b/src/webui/www/private/newfolder.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': (event) => { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': (event) => { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -51,7 +51,7 @@ }, onSuccess: (response) => { window.parent.qBittorrent.Rss.updateRssFeedList(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }, onFailure: (response) => { if (response.status === 409) diff --git a/src/webui/www/private/newtag.html b/src/webui/www/private/newtag.html index 16b779ce3..4e67beaf7 100644 --- a/src/webui/www/private/newtag.html +++ b/src/webui/www/private/newtag.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -66,7 +66,7 @@ tags: tagName, }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); break; @@ -82,7 +82,7 @@ tags: tagName, }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); break; diff --git a/src/webui/www/private/rename.html b/src/webui/www/private/rename.html index 1284812db..1775f0119 100644 --- a/src/webui/www/private/rename.html +++ b/src/webui/www/private/rename.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -53,7 +53,7 @@ name: name }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); } diff --git a/src/webui/www/private/rename_feed.html b/src/webui/www/private/rename_feed.html index 141e1a01f..4698c6e47 100644 --- a/src/webui/www/private/rename_feed.html +++ b/src/webui/www/private/rename_feed.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': (event) => { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': (event) => { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -61,7 +61,7 @@ }, onSuccess: (response) => { window.parent.qBittorrent.Rss.updateRssFeedList(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }, onFailure: (response) => { if (response.status === 409) { diff --git a/src/webui/www/private/rename_file.html b/src/webui/www/private/rename_file.html index 49cdbada8..b9ed1e99c 100644 --- a/src/webui/www/private/rename_file.html +++ b/src/webui/www/private/rename_file.html @@ -20,11 +20,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -70,7 +70,7 @@ newPath: newPath }, onSuccess: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }, onFailure: function() { alert('QBT_TR(Failed to update name)QBT_TR[CONTEXT=HttpServer]'); diff --git a/src/webui/www/private/rename_files.html b/src/webui/www/private/rename_files.html index 01ede024c..947aa8ed7 100644 --- a/src/webui/www/private/rename_files.html +++ b/src/webui/www/private/rename_files.html @@ -75,11 +75,11 @@ defaultEventType: 'keydown', events: { 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -298,7 +298,7 @@ $('renameButton').set('value', replaceOperation); }); $('closeButton').addEvent('click', function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }); // synchronize header scrolling to table body diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index ca86563b6..b02f655f1 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -1,5 +1,6 @@ /* * MIT License + * Copyright (C) 2024 Mike Tzou (Chocobo1) * Copyright (c) 2008 Ishan Arora , * Christophe Dumez * @@ -24,6 +25,48 @@ 'use strict'; +if (window.qBittorrent === undefined) { + window.qBittorrent = {}; +} + +window.qBittorrent.Client = (() => { + const exports = () => { + return { + closeWindows: closeWindows, + genHash: genHash, + getSyncMainDataInterval: getSyncMainDataInterval, + qbtVersion: qbtVersion + }; + }; + + const closeWindows = function() { + MochaUI.closeAll(); + }; + + const genHash = function(string) { + // origins: + // https://stackoverflow.com/a/8831937 + // https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0 + let hash = 0; + for (let i = 0; i < string.length; ++i) + hash = ((Math.imul(hash, 31) + string.charCodeAt(i)) | 0); + return hash; + }; + + const getSyncMainDataInterval = function() { + return customSyncMainDataInterval ? customSyncMainDataInterval : serverSyncMainDataInterval; + }; + + const qbtVersion = function() { + return LocalPreferences.get('qbtVersion', ''); + }; + + return exports(); +})(); +Object.freeze(window.qBittorrent.Client); + +// TODO: move global functions/variables into some namespace/scope + this.torrentsTable = new window.qBittorrent.DynamicTable.TorrentsTable(); let updatePropertiesPanel = function() {}; @@ -34,13 +77,6 @@ let queueing_enabled = true; let serverSyncMainDataInterval = 1500; let customSyncMainDataInterval = null; let useSubcategories = true; -let searchTabInitialized = false; -let rssTabInitialized = false; -let logTabInitialized = false; - -let syncRequestInProgress = false; - -let clipboardEvent; /* Categories filter */ const CATEGORIES_ALL = 1; @@ -66,7 +102,7 @@ const TRACKERS_TRACKERLESS = 2; const trackerList = new Map(); -let selectedTracker = TRACKERS_ALL; +let selectedTracker = LocalPreferences.get('selected_tracker', TRACKERS_ALL); let setTrackerFilter = function() {}; /* All filters */ @@ -74,61 +110,6 @@ let selected_filter = LocalPreferences.get('selected_filter', 'all'); let setFilter = function() {}; let toggleFilterDisplay = function() {}; -const loadSelectedTracker = function() { - selectedTracker = LocalPreferences.get('selected_tracker', TRACKERS_ALL); -}; -loadSelectedTracker(); - -const getShowFiltersSidebar = function() { - // Show Filters Sidebar is enabled by default - const show = LocalPreferences.get('show_filters_sidebar'); - return (show === null) || (show === 'true'); -}; - -// getHost emulate the GUI version `QString getHost(const QString &url)` -function getHost(url) { - // We want the hostname. - // If failed to parse the domain, original input should be returned - - if (!/^(?:https?|udp):/i.test(url)) { - return url; - } - - try { - // hack: URL can not get hostname from udp protocol - const parsedUrl = new URL(url.replace(/^udp:/i, 'https:')); - // host: "example.com:8443" - // hostname: "example.com" - const host = parsedUrl.hostname; - if (!host) { - return url; - } - - return host; - } - catch (error) { - return url; - } -} - -function genHash(string) { - // origins: - // https://stackoverflow.com/a/8831937 - // https://gist.github.com/hyamamoto/fd435505d29ebfa3d9716fd2be8d42f0 - let hash = 0; - for (let i = 0; i < string.length; ++i) - hash = ((Math.imul(hash, 31) + string.charCodeAt(i)) | 0); - return hash; -} - -function getSyncMainDataInterval() { - return customSyncMainDataInterval ? customSyncMainDataInterval : serverSyncMainDataInterval; -} - -const qbtVersion = function() { - return LocalPreferences.get('qbtVersion', ''); -}; - window.addEvent('load', function() { const saveColumnSizes = function() { const filters_width = $('Filters').getSize().x; @@ -305,6 +286,11 @@ window.addEvent('load', function() { $('desktopFooterWrapper').addClass('invisible'); } + const getShowFiltersSidebar = function() { + // Show Filters Sidebar is enabled by default + const show = LocalPreferences.get('show_filters_sidebar'); + return (show === null) || (show === 'true'); + }; const showFiltersSidebar = getShowFiltersSidebar(); if (!showFiltersSidebar) { $('showFiltersSidebarLink').firstChild.style.opacity = '0'; @@ -351,7 +337,7 @@ window.addEvent('load', function() { return true; } - const categoryHash = genHash(category); + const categoryHash = window.qBittorrent.Client.genHash(category); if (!category_list.has(categoryHash)) { // This should not happen category_list.set(categoryHash, { name: category, @@ -394,7 +380,7 @@ window.addEvent('load', function() { const tags = torrent['tags'].split(','); let added = false; for (let i = 0; i < tags.length; ++i) { - const tagHash = genHash(tags[i].trim()); + const tagHash = window.qBittorrent.Client.genHash(tags[i].trim()); if (!tagList.has(tagHash)) { // This should not happen tagList.set(tagHash, { name: tags, @@ -573,6 +559,32 @@ window.addEvent('load', function() { children[i].className = (Number(children[i].id) === selectedTag) ? "selectedFilter" : ""; }; + // getHost emulate the GUI version `QString getHost(const QString &url)` + const getHost = function(url) { + // We want the hostname. + // If failed to parse the domain, original input should be returned + + if (!/^(?:https?|udp):/i.test(url)) { + return url; + } + + try { + // hack: URL can not get hostname from udp protocol + const parsedUrl = new URL(url.replace(/^udp:/i, 'https:')); + // host: "example.com:8443" + // hostname: "example.com" + const host = parsedUrl.hostname; + if (!host) { + return url; + } + + return host; + } + catch (error) { + return url; + } + }; + const updateTrackerList = function() { const trackerFilterList = $('trackerFilterList'); if (trackerFilterList === null) @@ -625,7 +637,38 @@ window.addEvent('load', function() { child.className = (child.id === selectedTracker) ? "selectedFilter" : ""; }; + const setupCopyEventHandler = (function() { + let clipboardEvent; + + return () => { + if (clipboardEvent) + clipboardEvent.destroy(); + + clipboardEvent = new ClipboardJS('.copyToClipboard', { + text: function(trigger) { + switch (trigger.id) { + case "copyName": + return copyNameFN(); + case "copyInfohash1": + return copyInfohashFN(1); + case "copyInfohash2": + return copyInfohashFN(2); + case "copyMagnetLink": + return copyMagnetLinkFN(); + case "copyID": + return copyIdFN(); + case "copyComment": + return copyCommentFN(); + default: + return ""; + } + } + }); + }; + })(); + let syncMainDataTimer; + let syncRequestInProgress = false; const syncMainData = function() { const url = new URI('api/v2/sync/maindata'); url.setData('rid', syncMainDataLastResponseId); @@ -664,7 +707,7 @@ window.addEvent('load', function() { continue; const responseCategory = response['categories'][key]; - const categoryHash = genHash(key); + const categoryHash = window.qBittorrent.Client.genHash(key); const category = category_list.get(categoryHash); if (category !== undefined) { // only the save path can change for existing categories @@ -682,14 +725,14 @@ window.addEvent('load', function() { } if (response['categories_removed']) { response['categories_removed'].each(function(category) { - const categoryHash = genHash(category); + const categoryHash = window.qBittorrent.Client.genHash(category); category_list.delete(categoryHash); }); update_categories = true; } if (response['tags']) { for (const tag of response['tags']) { - const tagHash = genHash(tag); + const tagHash = window.qBittorrent.Client.genHash(tag); if (!tagList.has(tagHash)) { tagList.set(tagHash, { name: tag, @@ -701,7 +744,7 @@ window.addEvent('load', function() { } if (response['tags_removed']) { for (let i = 0; i < response['tags_removed'].length; ++i) { - const tagHash = genHash(response['tags_removed'][i]); + const tagHash = window.qBittorrent.Client.genHash(response['tags_removed'][i]); tagList.delete(tagHash); } updateTags = true; @@ -709,7 +752,7 @@ window.addEvent('load', function() { if (response['trackers']) { for (const tracker in response['trackers']) { const torrents = response['trackers'][tracker]; - const hash = genHash(getHost(tracker)); + const hash = window.qBittorrent.Client.genHash(getHost(tracker)); // the reason why we need the merge here is because the web ui api returned trackers may have different url for the same tracker host. // for example, some private trackers use diff urls for each torrent from the same tracker host. @@ -739,7 +782,7 @@ window.addEvent('load', function() { if (response['trackers_removed']) { for (let i = 0; i < response['trackers_removed'].length; ++i) { const tracker = response['trackers_removed'][i]; - const hash = genHash(getHost(tracker)); + const hash = window.qBittorrent.Client.genHash(getHost(tracker)); trackerList.delete(hash); } updateTrackers = true; @@ -796,7 +839,7 @@ window.addEvent('load', function() { torrentsTable.reselectRows(torrentsTableSelectedRows); } syncRequestInProgress = false; - syncData(getSyncMainDataInterval()); + syncData(window.qBittorrent.Client.getSyncMainDataInterval()); } }); syncRequestInProgress = true; @@ -827,11 +870,11 @@ window.addEvent('load', function() { transfer_info += " (" + window.qBittorrent.Misc.friendlyUnit(serverState.up_info_data, false) + ")"; $("UpInfos").set('html', transfer_info); if (speedInTitle) { - document.title = "QBT_TR([D: %1, U: %2] qBittorrent %3)QBT_TR[CONTEXT=MainWindow]".replace("%1", window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_speed, true)).replace("%2", window.qBittorrent.Misc.friendlyUnit(serverState.up_info_speed, true)).replace("%3", qbtVersion()); + document.title = "QBT_TR([D: %1, U: %2] qBittorrent %3)QBT_TR[CONTEXT=MainWindow]".replace("%1", window.qBittorrent.Misc.friendlyUnit(serverState.dl_info_speed, true)).replace("%2", window.qBittorrent.Misc.friendlyUnit(serverState.up_info_speed, true)).replace("%3", window.qBittorrent.Client.qbtVersion()); document.title += " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]"; } else - document.title = ("qBittorrent " + qbtVersion() + " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]"); + document.title = ("qBittorrent " + window.qBittorrent.Client.qbtVersion() + " QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]"); $('freeSpaceOnDisk').set('html', 'QBT_TR(Free space: %1)QBT_TR[CONTEXT=HttpServer]'.replace("%1", window.qBittorrent.Misc.friendlyUnit(serverState.free_space_on_disk))); $('DHTNodes').set('html', 'QBT_TR(DHT: %1 nodes)QBT_TR[CONTEXT=StatusBar]'.replace("%1", serverState.dht_nodes)); @@ -966,6 +1009,26 @@ window.addEvent('load', function() { MochaUI.Desktop.setDesktopSize(); }); + const registerMagnetHandler = function() { + if (typeof navigator.registerProtocolHandler !== 'function') { + if (window.location.protocol !== 'https:') + alert("QBT_TR(To use this feature, the WebUI needs to be accessed over HTTPS)QBT_TR[CONTEXT=MainWindow]"); + else + alert("QBT_TR(Your browser does not support this feature)QBT_TR[CONTEXT=MainWindow]"); + return; + } + + const hashString = location.hash ? location.hash.replace(/^#/, '') : ''; + const hashParams = new URLSearchParams(hashString); + hashParams.set('download', ''); + + const templateHashString = hashParams.toString().replace('download=', 'download=%s'); + const templateUrl = location.origin + location.pathname + + location.search + '#' + templateHashString; + + navigator.registerProtocolHandler('magnet', templateUrl, + 'qBittorrent WebUI magnet handler'); + }; $('registerMagnetHandlerLink').addEvent('click', function(e) { registerMagnetHandler(); }); @@ -1088,39 +1151,47 @@ window.addEvent('load', function() { MochaUI.Desktop.resizePanels(); }; - const showSearchTab = function() { - if (!searchTabInitialized) { - window.qBittorrent.Search.init(); - searchTabInitialized = true; - } + const showSearchTab = (function() { + let searchTabInitialized = false; - $("searchTabColumn").removeClass("invisible"); - customSyncMainDataInterval = 30000; - hideTransfersTab(); - hideRssTab(); - hideLogTab(); - }; + return () => { + if (!searchTabInitialized) { + window.qBittorrent.Search.init(); + searchTabInitialized = true; + } + + $("searchTabColumn").removeClass("invisible"); + customSyncMainDataInterval = 30000; + hideTransfersTab(); + hideRssTab(); + hideLogTab(); + }; + })(); const hideSearchTab = function() { $("searchTabColumn").addClass("invisible"); MochaUI.Desktop.resizePanels(); }; - const showRssTab = function() { - if (!rssTabInitialized) { - window.qBittorrent.Rss.init(); - rssTabInitialized = true; - } - else { - window.qBittorrent.Rss.load(); - } + const showRssTab = (function() { + let rssTabInitialized = false; - $("rssTabColumn").removeClass("invisible"); - customSyncMainDataInterval = 30000; - hideTransfersTab(); - hideSearchTab(); - hideLogTab(); - }; + return () => { + if (!rssTabInitialized) { + window.qBittorrent.Rss.init(); + rssTabInitialized = true; + } + else { + window.qBittorrent.Rss.load(); + } + + $("rssTabColumn").removeClass("invisible"); + customSyncMainDataInterval = 30000; + hideTransfersTab(); + hideSearchTab(); + hideLogTab(); + }; + })(); const hideRssTab = function() { $("rssTabColumn").addClass("invisible"); @@ -1128,21 +1199,25 @@ window.addEvent('load', function() { MochaUI.Desktop.resizePanels(); }; - const showLogTab = function() { - if (!logTabInitialized) { - window.qBittorrent.Log.init(); - logTabInitialized = true; - } - else { - window.qBittorrent.Log.load(); - } + const showLogTab = (function() { + let logTabInitialized = false; - $('logTabColumn').removeClass('invisible'); - customSyncMainDataInterval = 30000; - hideTransfersTab(); - hideSearchTab(); - hideRssTab(); - }; + return () => { + if (!logTabInitialized) { + window.qBittorrent.Log.init(); + logTabInitialized = true; + } + else { + window.qBittorrent.Log.load(); + } + + $('logTabColumn').removeClass('invisible'); + customSyncMainDataInterval = 30000; + hideTransfersTab(); + hideSearchTab(); + hideRssTab(); + }; + })(); const hideLogTab = function() { $('logTabColumn').addClass('invisible'); @@ -1224,6 +1299,18 @@ window.addEvent('load', function() { }); }; + const handleDownloadParam = function() { + // Extract torrent URL from download param in WebUI URL hash + const downloadHash = "#download="; + if (location.hash.indexOf(downloadHash) !== 0) + return; + + const url = decodeURIComponent(location.hash.substring(downloadHash.length)); + // Remove the processed hash from the URL + history.replaceState('', document.title, (location.pathname + location.search)); + showDownloadPage([url]); + }; + new MochaUI.Panel({ id: 'transferList', title: 'Panel', @@ -1459,6 +1546,36 @@ window.addEvent('load', function() { }; registerDragAndDrop(); + new Keyboard({ + defaultEventType: 'keydown', + events: { + 'ctrl+a': function(event) { + if (event.target.nodeName == "INPUT" || event.target.nodeName == "TEXTAREA") + return; + if (event.target.isContentEditable) + return; + torrentsTable.selectAll(); + event.preventDefault(); + }, + 'delete': function(event) { + if (event.target.nodeName == "INPUT" || event.target.nodeName == "TEXTAREA") + return; + if (event.target.isContentEditable) + return; + deleteFN(); + event.preventDefault(); + }, + 'shift+delete': (event) => { + if (event.target.nodeName == "INPUT" || event.target.nodeName == "TEXTAREA") + return; + if (event.target.isContentEditable) + return; + deleteFN(true); + event.preventDefault(); + } + } + }).activate(); + // fetch qbt version and store it locally new Request({ url: 'api/v2/app/version', @@ -1491,96 +1608,3 @@ window.addEvent('load', function() { } }).send(); }); - -function registerMagnetHandler() { - if (typeof navigator.registerProtocolHandler !== 'function') { - if (window.location.protocol !== 'https:') - alert("QBT_TR(To use this feature, the WebUI needs to be accessed over HTTPS)QBT_TR[CONTEXT=MainWindow]"); - else - alert("QBT_TR(Your browser does not support this feature)QBT_TR[CONTEXT=MainWindow]"); - return; - } - - const hashString = location.hash ? location.hash.replace(/^#/, '') : ''; - const hashParams = new URLSearchParams(hashString); - hashParams.set('download', ''); - - const templateHashString = hashParams.toString().replace('download=', 'download=%s'); - const templateUrl = location.origin + location.pathname - + location.search + '#' + templateHashString; - - navigator.registerProtocolHandler('magnet', templateUrl, - 'qBittorrent WebUI magnet handler'); -} - -function handleDownloadParam() { - // Extract torrent URL from download param in WebUI URL hash - const downloadHash = "#download="; - if (location.hash.indexOf(downloadHash) !== 0) - return; - - const url = decodeURIComponent(location.hash.substring(downloadHash.length)); - // Remove the processed hash from the URL - history.replaceState('', document.title, (location.pathname + location.search)); - showDownloadPage([url]); -} - -function closeWindows() { - MochaUI.closeAll(); -} - -function setupCopyEventHandler() { - if (clipboardEvent) - clipboardEvent.destroy(); - - clipboardEvent = new ClipboardJS('.copyToClipboard', { - text: function(trigger) { - switch (trigger.id) { - case "copyName": - return copyNameFN(); - case "copyInfohash1": - return copyInfohashFN(1); - case "copyInfohash2": - return copyInfohashFN(2); - case "copyMagnetLink": - return copyMagnetLinkFN(); - case "copyID": - return copyIdFN(); - case "copyComment": - return copyCommentFN(); - default: - return ""; - } - } - }); -} - -new Keyboard({ - defaultEventType: 'keydown', - events: { - 'ctrl+a': function(event) { - if (event.target.nodeName == "INPUT" || event.target.nodeName == "TEXTAREA") - return; - if (event.target.isContentEditable) - return; - torrentsTable.selectAll(); - event.preventDefault(); - }, - 'delete': function(event) { - if (event.target.nodeName == "INPUT" || event.target.nodeName == "TEXTAREA") - return; - if (event.target.isContentEditable) - return; - deleteFN(); - event.preventDefault(); - }, - 'shift+delete': (event) => { - if (event.target.nodeName == "INPUT" || event.target.nodeName == "TEXTAREA") - return; - if (event.target.isContentEditable) - return; - deleteFN(true); - event.preventDefault(); - } - } -}).activate(); diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index b3f03a212..e6b1e18e8 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -1395,7 +1395,7 @@ window.qBittorrent.DynamicTable = (function() { break; // do nothing default: if (!useSubcategories) { - if (categoryHash !== genHash(row['full_data'].category)) + if (categoryHash !== window.qBittorrent.Client.genHash(row['full_data'].category)) return false; } else { @@ -1417,7 +1417,7 @@ window.qBittorrent.DynamicTable = (function() { break; // do nothing default: { - const tagHashes = row['full_data'].tags.split(', ').map(tag => genHash(tag)); + const tagHashes = row['full_data'].tags.split(', ').map(tag => window.qBittorrent.Client.genHash(tag)); if (!tagHashes.contains(tagHash)) return false; break; diff --git a/src/webui/www/private/scripts/prop-peers.js b/src/webui/www/private/scripts/prop-peers.js index be5af9d91..660e6bb22 100644 --- a/src/webui/www/private/scripts/prop-peers.js +++ b/src/webui/www/private/scripts/prop-peers.js @@ -56,7 +56,7 @@ window.qBittorrent.PropPeers = (function() { syncTorrentPeersLastResponseId = 0; torrentPeersTable.clear(); clearTimeout(loadTorrentPeersTimer); - loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval()); + loadTorrentPeersTimer = loadTorrentPeersData.delay(window.qBittorrent.Client.getSyncMainDataInterval()); return; } const url = new URI('api/v2/sync/torrentPeers'); @@ -68,7 +68,7 @@ window.qBittorrent.PropPeers = (function() { method: 'get', onComplete: function() { clearTimeout(loadTorrentPeersTimer); - loadTorrentPeersTimer = loadTorrentPeersData.delay(getSyncMainDataInterval()); + loadTorrentPeersTimer = loadTorrentPeersData.delay(window.qBittorrent.Client.getSyncMainDataInterval()); }, onSuccess: function(response) { $('error_div').set('html', ''); diff --git a/src/webui/www/private/setlocation.html b/src/webui/www/private/setlocation.html index 36a2ee815..2f21fe7b3 100644 --- a/src/webui/www/private/setlocation.html +++ b/src/webui/www/private/setlocation.html @@ -19,11 +19,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -55,7 +55,7 @@ location: location }, onSuccess: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }, onFailure: function(xhr) { $('error_div').set('text', xhr.response); diff --git a/src/webui/www/private/shareratio.html b/src/webui/www/private/shareratio.html index 897f0cb01..9dc804ae6 100644 --- a/src/webui/www/private/shareratio.html +++ b/src/webui/www/private/shareratio.html @@ -22,11 +22,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } @@ -111,7 +111,7 @@ inactiveSeedingTimeLimit: inactiveSeedingTimeLimitValue }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); }); diff --git a/src/webui/www/private/upload.html b/src/webui/www/private/upload.html index b2e2b018c..e8fb925c7 100644 --- a/src/webui/www/private/upload.html +++ b/src/webui/www/private/upload.html @@ -164,7 +164,7 @@ $('upload_frame').addEventListener("load", function() { if (submitted) - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); }); if ((Browser.platform === 'ios') || ((Browser.platform === 'mac') && (navigator.maxTouchPoints > 1))) { diff --git a/src/webui/www/private/uploadlimit.html b/src/webui/www/private/uploadlimit.html index e6cb93ef6..b0dc4d800 100644 --- a/src/webui/www/private/uploadlimit.html +++ b/src/webui/www/private/uploadlimit.html @@ -36,7 +36,7 @@ }, onComplete: function() { window.parent.updateMainData(); - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); } @@ -49,7 +49,7 @@ 'limit': limit }, onComplete: function() { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); } }).send(); } @@ -67,11 +67,11 @@ event.preventDefault(); }, 'Escape': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); }, 'Esc': function(event) { - window.parent.closeWindows(); + window.parent.qBittorrent.Client.closeWindows(); event.preventDefault(); } } diff --git a/src/webui/www/private/views/about.html b/src/webui/www/private/views/about.html index c204b4354..c6276a0a5 100644 --- a/src/webui/www/private/views/about.html +++ b/src/webui/www/private/views/about.html @@ -843,7 +843,7 @@