diff --git a/src/webui/www/private/index.html b/src/webui/www/private/index.html index b5877abc4..fce081cf9 100644 --- a/src/webui/www/private/index.html +++ b/src/webui/www/private/index.html @@ -29,6 +29,7 @@ + diff --git a/src/webui/www/private/scripts/addtorrent.js b/src/webui/www/private/scripts/addtorrent.js index 3decbf73a..4660862e7 100644 --- a/src/webui/www/private/scripts/addtorrent.js +++ b/src/webui/www/private/scripts/addtorrent.js @@ -44,9 +44,10 @@ window.qBittorrent.AddTorrent ??= (() => { let source = ""; const LocalPreferences = new window.qBittorrent.LocalPreferences.LocalPreferences(); + const clientData = window.parent.qBittorrent.ClientData; const getCategories = () => { - const defaultCategory = LocalPreferences.get("add_torrent_default_category", ""); + const defaultCategory = clientData.getCached("add_torrent_default_category") ?? ""; const categorySelect = document.getElementById("categorySelect"); for (const name of window.parent.qBittorrent.Client.categoryMap.keys()) { const option = document.createElement("option"); @@ -311,10 +312,7 @@ window.qBittorrent.AddTorrent ??= (() => { if (document.getElementById("setDefaultCategory").checked) { const category = document.getElementById("category").value.trim(); - if (category.length === 0) - LocalPreferences.remove("add_torrent_default_category"); - else - LocalPreferences.set("add_torrent_default_category", category); + clientData.set({ add_torrent_default_category: category.length > 0 ? category : null }); } }; diff --git a/src/webui/www/private/scripts/client-data.js b/src/webui/www/private/scripts/client-data.js new file mode 100644 index 000000000..4857e2cf4 --- /dev/null +++ b/src/webui/www/private/scripts/client-data.js @@ -0,0 +1,128 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2025 Thomas Piccirello + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +"use strict"; + +window.qBittorrent ??= {}; +window.qBittorrent.ClientData ??= (() => { + const exports = () => { + return { + getCached: (...args) => instance.getCached(...args), + get: (...args) => instance.get(...args), + set: (...args) => instance.set(...args), + }; + }; + + // this is exposed as a singleton + class ClientData { + /** + * @type Map + */ + #cache = new Map(); + + /** + * @param {string[]} keys + * @returns {Record} + */ + async #fetch(keys) { + return await fetch("api/v2/app/clientData", { + method: "POST", + body: new URLSearchParams({ + keys: JSON.stringify(keys) + }) + }) + .then(async (response) => { + if (!response.ok) + return; + + return await response.json(); + }); + } + + /** + * @param {Record} data + */ + async #set(data) { + await fetch("api/v2/app/setClientData", { + method: "POST", + body: new URLSearchParams({ + data: JSON.stringify(data) + }) + }) + .then((response) => { + if (!response.ok) + throw new Error("Failed to store client data"); + }); + } + + /** + * @param {string} key + * @returns {any} + */ + getCached(key) { + return this.#cache.get(key); + } + + /** + * @param {string[]} keys + * @returns {Record} + */ + async get(keys = []) { + const keysToFetch = keys.filter((key) => !this.#cache.has(key)); + if (keysToFetch.length > 0) { + const fetchedData = await this.#fetch(keysToFetch); + for (const [key, value] of Object.entries(fetchedData)) + this.#cache.set(key, value); + } + + return Object.fromEntries(keys.map((key) => ([key, this.#cache.get(key)]))); + } + + /** + * @param {Record} data + */ + async set(data) { + try { + await this.#set(data); + } + catch (err) { + console.error(err); + return; + } + + // update cache + for (const [key, value] of Object.entries(data)) + this.#cache.set(key, value); + } + } + + const instance = new ClientData(); + + return exports(); +})(); +Object.freeze(window.qBittorrent.ClientData); diff --git a/src/webui/www/private/scripts/client.js b/src/webui/www/private/scripts/client.js index 4c17cb5b1..eb09b777b 100644 --- a/src/webui/www/private/scripts/client.js +++ b/src/webui/www/private/scripts/client.js @@ -31,6 +31,7 @@ window.qBittorrent.Client ??= (() => { return { setup: setup, initializeCaches: initializeCaches, + initializeClientData: initializeClientData, closeWindow: closeWindow, closeFrameWindow: closeFrameWindow, getSyncMainDataInterval: getSyncMainDataInterval, @@ -56,15 +57,47 @@ window.qBittorrent.Client ??= (() => { const tagMap = new Map(); let cacheAllSettled; + let clientDataPromise; const setup = () => { // fetch various data and store it in memory + clientDataPromise = window.qBittorrent.ClientData.get([ + "show_search_engine", + "show_rss_reader", + "show_log_viewer", + "speed_in_browser_title_bar", + "show_top_toolbar", + "show_status_bar", + "show_filters_sidebar", + "hide_zero_status_filters", + "color_scheme", + "full_url_tracker_column", + "use_alt_row_colors", + "use_virtual_list", + "dblclick_complete", + "dblclick_download", + "dblclick_filter", + "search_in_filter", + "qbt_selected_log_levels", + "add_torrent_default_category", + ]); + cacheAllSettled = Promise.allSettled([ window.qBittorrent.Cache.buildInfo.init(), window.qBittorrent.Cache.preferences.init(), - window.qBittorrent.Cache.qbtVersion.init() + window.qBittorrent.Cache.qbtVersion.init(), + clientDataPromise, ]); }; + const initializeClientData = async () => { + try { + await clientDataPromise; + } + catch (error) { + console.error(`Failed to initialize client data. Reason: "${error}".`); + } + }; + const initializeCaches = async () => { const results = await cacheAllSettled; for (const [idx, result] of results.entries()) { @@ -224,8 +257,8 @@ let queueing_enabled = true; let serverSyncMainDataInterval = 1500; let customSyncMainDataInterval = null; let useSubcategories = true; -const useAutoHideZeroStatusFilters = LocalPreferences.get("hide_zero_status_filters", "false") === "true"; -const displayFullURLTrackerColumn = LocalPreferences.get("full_url_tracker_column", "false") === "true"; +let useAutoHideZeroStatusFilters = false; +let displayFullURLTrackerColumn = false; /* Categories filter */ const CATEGORIES_ALL = "b4af0e4c-e76d-4bac-a392-46cbc18d9655"; @@ -251,6 +284,8 @@ const TRACKERS_WARNING = "82a702c5-210c-412b-829f-97632d7557e9"; // Map> const trackerMap = new Map(); +const clientData = window.qBittorrent.ClientData; + let selectedTracker = LocalPreferences.get("selected_tracker", TRACKERS_ALL); let setTrackerFilter = () => {}; @@ -259,7 +294,13 @@ let selectedStatus = LocalPreferences.get("selected_filter", "all"); let setStatusFilter = () => {}; let toggleFilterDisplay = () => {}; -window.addEventListener("DOMContentLoaded", (event) => { +window.addEventListener("DOMContentLoaded", async (event) => { + await window.qBittorrent.Client.initializeClientData(); + window.qBittorrent.ColorScheme.update(); + + useAutoHideZeroStatusFilters = clientData.getCached("hide_zero_status_filters") === true; + displayFullURLTrackerColumn = clientData.getCached("full_url_tracker_column") === true; + window.qBittorrent.LocalPreferences.upgrade(); let isSearchPanelLoaded = false; @@ -406,6 +447,13 @@ window.addEventListener("DOMContentLoaded", (event) => { LocalPreferences.set(`filter_${filterListID.replace("FilterList", "")}_collapsed`, filterList.classList.toggle("invisible").toString()); }; + const highlightSelectedStatus = () => { + const statusFilter = document.getElementById("statusFilterList"); + const filterID = `${selectedStatus}_filter`; + for (const status of statusFilter.children) + status.classList.toggle("selectedFilter", (status.id === filterID)); + }; + new MochaUI.Panel({ id: "Filters", title: "Panel", @@ -427,35 +475,35 @@ window.addEventListener("DOMContentLoaded", (event) => { initializeWindows(); // Show Top Toolbar is enabled by default - let showTopToolbar = LocalPreferences.get("show_top_toolbar", "true") === "true"; + let showTopToolbar = clientData.getCached("show_top_toolbar") !== false; if (!showTopToolbar) { document.getElementById("showTopToolbarLink").firstElementChild.style.opacity = "0"; document.getElementById("mochaToolbar").classList.add("invisible"); } // Show Status Bar is enabled by default - let showStatusBar = LocalPreferences.get("show_status_bar", "true") === "true"; + let showStatusBar = clientData.getCached("show_status_bar") !== false; if (!showStatusBar) { document.getElementById("showStatusBarLink").firstElementChild.style.opacity = "0"; document.getElementById("desktopFooterWrapper").classList.add("invisible"); } // Show Filters Sidebar is enabled by default - let showFiltersSidebar = LocalPreferences.get("show_filters_sidebar", "true") === "true"; + let showFiltersSidebar = clientData.getCached("show_filters_sidebar") !== false; if (!showFiltersSidebar) { document.getElementById("showFiltersSidebarLink").firstElementChild.style.opacity = "0"; document.getElementById("filtersColumn").classList.add("invisible"); document.getElementById("filtersColumn_handle").classList.add("invisible"); } - let speedInTitle = LocalPreferences.get("speed_in_browser_title_bar") === "true"; + let speedInTitle = clientData.getCached("speed_in_browser_title_bar") === true; if (!speedInTitle) document.getElementById("speedInBrowserTitleBarLink").firstElementChild.style.opacity = "0"; // After showing/hiding the toolbar + status bar - window.qBittorrent.Client.showSearchEngine(LocalPreferences.get("show_search_engine") !== "false"); - window.qBittorrent.Client.showRssReader(LocalPreferences.get("show_rss_reader") !== "false"); - window.qBittorrent.Client.showLogViewer(LocalPreferences.get("show_log_viewer") === "true"); + window.qBittorrent.Client.showSearchEngine(clientData.getCached("show_search_engine") !== false); + window.qBittorrent.Client.showRssReader(clientData.getCached("show_rss_reader") !== false); + window.qBittorrent.Client.showLogViewer(clientData.getCached("show_log_viewer") === true); // After Show Top Toolbar MochaUI.Desktop.setDesktopSize(); @@ -572,13 +620,6 @@ window.addEventListener("DOMContentLoaded", (event) => { window.qBittorrent.Filters.clearStatusFilter(); }; - const highlightSelectedStatus = () => { - const statusFilter = document.getElementById("statusFilterList"); - const filterID = `${selectedStatus}_filter`; - for (const status of statusFilter.children) - status.classList.toggle("selectedFilter", (status.id === filterID)); - }; - const updateCategoryList = () => { const categoryList = document.getElementById("categoryFilterList"); if (!categoryList) @@ -1221,7 +1262,7 @@ window.addEventListener("DOMContentLoaded", (event) => { document.getElementById("showTopToolbarLink").addEventListener("click", (e) => { showTopToolbar = !showTopToolbar; - LocalPreferences.set("show_top_toolbar", showTopToolbar.toString()); + clientData.set({ show_top_toolbar: showTopToolbar }); if (showTopToolbar) { document.getElementById("showTopToolbarLink").firstElementChild.style.opacity = "1"; document.getElementById("mochaToolbar").classList.remove("invisible"); @@ -1235,7 +1276,7 @@ window.addEventListener("DOMContentLoaded", (event) => { document.getElementById("showStatusBarLink").addEventListener("click", (e) => { showStatusBar = !showStatusBar; - LocalPreferences.set("show_status_bar", showStatusBar.toString()); + clientData.set({ show_status_bar: showStatusBar }); if (showStatusBar) { document.getElementById("showStatusBarLink").firstElementChild.style.opacity = "1"; document.getElementById("desktopFooterWrapper").classList.remove("invisible"); @@ -1272,7 +1313,7 @@ window.addEventListener("DOMContentLoaded", (event) => { document.getElementById("showFiltersSidebarLink").addEventListener("click", (e) => { showFiltersSidebar = !showFiltersSidebar; - LocalPreferences.set("show_filters_sidebar", showFiltersSidebar.toString()); + clientData.set({ show_filters_sidebar: showFiltersSidebar }); if (showFiltersSidebar) { document.getElementById("showFiltersSidebarLink").firstElementChild.style.opacity = "1"; document.getElementById("filtersColumn").classList.remove("invisible"); @@ -1288,7 +1329,7 @@ window.addEventListener("DOMContentLoaded", (event) => { document.getElementById("speedInBrowserTitleBarLink").addEventListener("click", (e) => { speedInTitle = !speedInTitle; - LocalPreferences.set("speed_in_browser_title_bar", speedInTitle.toString()); + LocalPreferences.set("speed_in_browser_title_bar", speedInTitle); if (speedInTitle) document.getElementById("speedInBrowserTitleBarLink").firstElementChild.style.opacity = "1"; else @@ -1298,19 +1339,19 @@ window.addEventListener("DOMContentLoaded", (event) => { document.getElementById("showSearchEngineLink").addEventListener("click", (e) => { window.qBittorrent.Client.showSearchEngine(!window.qBittorrent.Client.isShowSearchEngine()); - LocalPreferences.set("show_search_engine", window.qBittorrent.Client.isShowSearchEngine().toString()); + clientData.set({ show_search_engine: window.qBittorrent.Client.isShowSearchEngine() }); updateTabDisplay(); }); document.getElementById("showRssReaderLink").addEventListener("click", (e) => { window.qBittorrent.Client.showRssReader(!window.qBittorrent.Client.isShowRssReader()); - LocalPreferences.set("show_rss_reader", window.qBittorrent.Client.isShowRssReader().toString()); + clientData.set({ show_rss_reader: window.qBittorrent.Client.isShowRssReader() }); updateTabDisplay(); }); document.getElementById("showLogViewerLink").addEventListener("click", (e) => { window.qBittorrent.Client.showLogViewer(!window.qBittorrent.Client.isShowLogViewer()); - LocalPreferences.set("show_log_viewer", window.qBittorrent.Client.isShowLogViewer().toString()); + clientData.set({ show_log_viewer: window.qBittorrent.Client.isShowLogViewer() }); updateTabDisplay(); }); @@ -1367,7 +1408,7 @@ window.addEventListener("DOMContentLoaded", (event) => { // main window tabs const showTransfersTab = () => { - const showFiltersSidebar = LocalPreferences.get("show_filters_sidebar", "true") === "true"; + const showFiltersSidebar = clientData.getCached("show_filters_sidebar") !== false; if (showFiltersSidebar) { document.getElementById("filtersColumn").classList.remove("invisible"); document.getElementById("filtersColumn_handle").classList.remove("invisible"); diff --git a/src/webui/www/private/scripts/color-scheme.js b/src/webui/www/private/scripts/color-scheme.js index d02fce243..c35779a41 100644 --- a/src/webui/www/private/scripts/color-scheme.js +++ b/src/webui/www/private/scripts/color-scheme.js @@ -36,12 +36,12 @@ window.qBittorrent.ColorScheme ??= (() => { }; }; - const LocalPreferences = new window.qBittorrent.LocalPreferences.LocalPreferences(); const colorSchemeQuery = window.matchMedia("(prefers-color-scheme: dark)"); + const clientData = window.parent.qBittorrent.ClientData; const update = () => { const root = document.documentElement; - const colorScheme = LocalPreferences.get("color_scheme"); + const colorScheme = clientData.getCached("color_scheme"); const validScheme = (colorScheme === "light") || (colorScheme === "dark"); const isDark = colorSchemeQuery.matches; root.classList.toggle("dark", ((!validScheme && isDark) || (colorScheme === "dark"))); @@ -52,5 +52,3 @@ window.qBittorrent.ColorScheme ??= (() => { return exports(); })(); Object.freeze(window.qBittorrent.ColorScheme); - -window.qBittorrent.ColorScheme.update(); diff --git a/src/webui/www/private/scripts/dynamicTable.js b/src/webui/www/private/scripts/dynamicTable.js index aacdb5f5d..826f87386 100644 --- a/src/webui/www/private/scripts/dynamicTable.js +++ b/src/webui/www/private/scripts/dynamicTable.js @@ -65,6 +65,7 @@ window.qBittorrent.DynamicTable ??= (() => { return 0; }; + const clientData = window.qBittorrent.ClientData ?? window.parent.qBittorrent.ClientData; let DynamicTableHeaderContextMenuClass = null; if (typeof LocalPreferences === "undefined") @@ -75,7 +76,7 @@ window.qBittorrent.DynamicTable ??= (() => { this.dynamicTableDivId = dynamicTableDivId; this.dynamicTableFixedHeaderDivId = dynamicTableFixedHeaderDivId; this.dynamicTableDiv = document.getElementById(dynamicTableDivId); - this.useVirtualList = useVirtualList && (LocalPreferences.get("use_virtual_list", "false") === "true"); + this.useVirtualList = useVirtualList && (clientData.getCached("use_virtual_list") === true); this.fixedTableHeader = document.querySelector(`#${dynamicTableFixedHeaderDivId} thead tr`); this.hiddenTableHeader = this.dynamicTableDiv.querySelector("thead tr"); this.table = this.dynamicTableDiv.querySelector("table"); @@ -730,7 +731,7 @@ window.qBittorrent.DynamicTable ??= (() => { } setupAltRow() { - const useAltRowColors = (LocalPreferences.get("use_alt_row_colors", "true") === "true"); + const useAltRowColors = clientData.getCached("use_alt_row_colors") !== false; if (useAltRowColors) document.getElementById(this.dynamicTableDivId).classList.add("altRowColors"); } @@ -1805,7 +1806,7 @@ window.qBittorrent.DynamicTable ??= (() => { ? "dblclick_download" : "dblclick_complete"; - if (LocalPreferences.get(prefKey, "1") !== "1") + if (clientData.getCached(prefKey) === "0") return true; if (state.includes("stopped")) diff --git a/src/webui/www/private/scripts/search.js b/src/webui/www/private/scripts/search.js index a8367255b..f13693694 100644 --- a/src/webui/www/private/scripts/search.js +++ b/src/webui/www/private/scripts/search.js @@ -107,8 +107,7 @@ window.qBittorrent.Search ??= (() => { }); const init = () => { - // load "Search in" preference from local storage - document.getElementById("searchInTorrentName").value = (LocalPreferences.get("search_in_filter") === "names") ? "names" : "everywhere"; + document.getElementById("searchInTorrentName").value = (window.qBittorrent.ClientData.getCached("search_in_filter") === "names") ? "names" : "everywhere"; const searchResultsTableContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({ targets: "#searchResultsTableDiv tbody tr", menu: "searchResultsTableMenu", @@ -804,7 +803,8 @@ window.qBittorrent.Search ??= (() => { }; const searchInTorrentName = () => { - LocalPreferences.set("search_in_filter", getSearchInTorrentName()); + // don't await this + window.qBittorrent.ClientData.set({ search_in_filter: getSearchInTorrentName() }); searchFilterChanged(); }; diff --git a/src/webui/www/private/views/confirmdeletion.html b/src/webui/www/private/views/confirmdeletion.html index 215e80fef..4eff7f27d 100644 --- a/src/webui/www/private/views/confirmdeletion.html +++ b/src/webui/www/private/views/confirmdeletion.html @@ -58,11 +58,11 @@ // Set current "Delete files" choice as the default rememberButton.addEventListener("click", (e) => { window.qBittorrent.Cache.preferences.set({ - delete_torrent_content_files: deleteCB.checked - }).then(() => { - prefDeleteContentFiles = deleteCB.checked; - setRememberBtnEnabled(false); - }); + delete_torrent_content_files: deleteCB.checked + }).then(() => { + prefDeleteContentFiles = deleteCB.checked; + setRememberBtnEnabled(false); + }); }); cancelButton.focus(); diff --git a/src/webui/www/private/views/createtorrent.html b/src/webui/www/private/views/createtorrent.html index a85e5a57d..23ef59cf5 100644 --- a/src/webui/www/private/views/createtorrent.html +++ b/src/webui/www/private/views/createtorrent.html @@ -138,7 +138,7 @@ return option; }; - const init = () => { + const init = async () => { const pieceSizeSelect = document.getElementById("pieceSize"); pieceSizeSelect.appendChild(createSizeOption(0)); for (let i = 4; i <= 17; ++i) @@ -163,7 +163,7 @@ submit(); }); - loadPreference(); + await loadPreference(); window.qBittorrent.pathAutofill.attachPathAutofill(); }; @@ -207,11 +207,13 @@ comments: document.getElementById("comments").value, source: document.getElementById("source").value, }; - LocalPreferences.set("torrent_creator", JSON.stringify(preference)); + window.parent.qBittorrent.ClientData.set({ torrent_creator: preference }); }; - const loadPreference = () => { - const preference = JSON.parse(LocalPreferences.get("torrent_creator") ?? "{}"); + const loadPreference = async () => { + const clientData = await window.parent.qBittorrent.ClientData.get(["torrent_creator"]); + const preference = clientData.torrent_creator ?? {}; + document.getElementById("sourcePath").value = preference.sourcePath ?? ""; document.getElementById("torrentFormat").value = preference.torrentFormat ?? "hybrid"; document.getElementById("pieceSize").value = preference.pieceSize ?? 0; diff --git a/src/webui/www/private/views/filters.html b/src/webui/www/private/views/filters.html index 623990c1a..1c66100ca 100644 --- a/src/webui/www/private/views/filters.html +++ b/src/webui/www/private/views/filters.html @@ -261,7 +261,7 @@ }); document.getElementById("Filters_pad").addEventListener("dblclick", (event) => { - if (LocalPreferences.get("dblclick_filter", "1") !== "1") + if (window.qBittorrent.ClientData.getCached("dblclick_filter") === "0") return; const filterItem = event.target.closest("li"); diff --git a/src/webui/www/private/views/log.html b/src/webui/www/private/views/log.html index a1fc55472..cdbb6fe34 100644 --- a/src/webui/www/private/views/log.html +++ b/src/webui/www/private/views/log.html @@ -185,7 +185,7 @@ let logFilterTimer = -1; let inputtedFilterText = ""; let selectBox; - let selectedLogLevels = JSON.parse(LocalPreferences.get("qbt_selected_log_levels")) || ["1", "2", "4", "8"]; + let selectedLogLevels = window.qBittorrent.ClientData.getCached("qbt_selected_log_levels") ?? ["1", "2", "4", "8"]; const init = () => { for (const option of document.getElementById("logLevelSelect").options) @@ -276,7 +276,8 @@ if (selectedLogLevels !== value) { tableInfo[currentSelectedTab].last_id = -1; selectedLogLevels = value; - LocalPreferences.set("qbt_selected_log_levels", JSON.stringify(selectedLogLevels)); + // don't await this + window.qBittorrent.ClientData.set({ qbt_selected_log_levels: selectedLogLevels }); logFilterChanged(); } }; diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html index 80b089459..f05fca02f 100644 --- a/src/webui/www/private/views/preferences.html +++ b/src/webui/www/private/views/preferences.html @@ -2215,10 +2215,8 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD document.getElementById("locale_select").value = selected; }; - const updateColoSchemeSelect = () => { + const updateColoSchemeSelect = (colorScheme) => { const combobox = document.getElementById("colorSchemeSelect"); - const colorScheme = LocalPreferences.get("color_scheme"); - if (colorScheme === "light") combobox.options[1].selected = true; else if (colorScheme === "dark") @@ -2230,20 +2228,31 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD const loadPreferences = () => { window.parent.qBittorrent.Cache.preferences.init() .then((pref) => { + const clientData = window.parent.qBittorrent.ClientData; + const colorScheme = clientData.getCached("color_scheme"); + const fullUrlTrackerColumn = clientData.getCached("full_url_tracker_column"); + const useVirtualList = clientData.getCached("use_virtual_list"); + const hideZeroStatusFilters = clientData.getCached("hide_zero_status_filters"); + const dblclickDownload = clientData.getCached("dblclick_download"); + const dblclickComplete = clientData.getCached("dblclick_complete"); + const dblclickFilter = clientData.getCached("dblclick_filter"); + const useAltRowColors = clientData.getCached("use_alt_row_colors"); + // Behavior tab // Language updateWebuiLocaleSelect(pref.locale); - updateColoSchemeSelect(); + updateColoSchemeSelect(colorScheme); + document.getElementById("statusBarExternalIP").checked = pref.status_bar_external_ip; document.getElementById("performanceWarning").checked = pref.performance_warning; - document.getElementById("displayFullURLTrackerColumn").checked = (LocalPreferences.get("full_url_tracker_column", "false") === "true"); - document.getElementById("useVirtualList").checked = (LocalPreferences.get("use_virtual_list", "false") === "true"); - document.getElementById("hideZeroFiltersCheckbox").checked = (LocalPreferences.get("hide_zero_status_filters", "false") === "true"); - document.getElementById("dblclickDownloadSelect").value = LocalPreferences.get("dblclick_download", "1"); - document.getElementById("dblclickCompleteSelect").value = LocalPreferences.get("dblclick_complete", "1"); - document.getElementById("dblclickFiltersSelect").value = LocalPreferences.get("dblclick_filter", "1"); + document.getElementById("displayFullURLTrackerColumn").checked = fullUrlTrackerColumn === true; + document.getElementById("useVirtualList").checked = useVirtualList === true; + document.getElementById("hideZeroFiltersCheckbox").checked = hideZeroStatusFilters === true; + document.getElementById("dblclickDownloadSelect").value = dblclickDownload ?? "1"; + document.getElementById("dblclickCompleteSelect").value = dblclickComplete ?? "1"; + document.getElementById("dblclickFiltersSelect").value = dblclickFilter ?? "1"; document.getElementById("confirmTorrentDeletion").checked = pref.confirm_torrent_deletion; - document.getElementById("useAltRowColorsInput").checked = (LocalPreferences.get("use_alt_row_colors", "true") === "true"); + document.getElementById("useAltRowColorsInput").checked = useAltRowColors !== false; document.getElementById("filelog_checkbox").checked = pref.file_log_enabled; document.getElementById("filelog_save_path_input").value = pref.file_log_path; document.getElementById("filelog_backup_checkbox").checked = pref.file_log_backup_enabled; @@ -2658,6 +2667,7 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD const applyPreferences = () => { const settings = {}; + const clientData = {}; // Validate form data // Behavior tab @@ -2665,21 +2675,21 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD settings["locale"] = document.getElementById("locale_select").value; const colorScheme = Number(document.getElementById("colorSchemeSelect").value); if (colorScheme === 0) - LocalPreferences.remove("color_scheme"); + clientData.color_scheme = null; else if (colorScheme === 1) - LocalPreferences.set("color_scheme", "light"); + clientData.color_scheme = "light"; else - LocalPreferences.set("color_scheme", "dark"); + clientData.color_scheme = "dark"; settings["status_bar_external_ip"] = document.getElementById("statusBarExternalIP").checked; settings["performance_warning"] = document.getElementById("performanceWarning").checked; - LocalPreferences.set("full_url_tracker_column", document.getElementById("displayFullURLTrackerColumn").checked.toString()); - LocalPreferences.set("use_virtual_list", document.getElementById("useVirtualList").checked.toString()); - LocalPreferences.set("hide_zero_status_filters", document.getElementById("hideZeroFiltersCheckbox").checked.toString()); - LocalPreferences.set("dblclick_download", document.getElementById("dblclickDownloadSelect").value); - LocalPreferences.set("dblclick_complete", document.getElementById("dblclickCompleteSelect").value); - LocalPreferences.set("dblclick_filter", document.getElementById("dblclickFiltersSelect").value); + clientData.full_url_tracker_column = document.getElementById("displayFullURLTrackerColumn").checked; + clientData.use_virtual_list = document.getElementById("useVirtualList").checked; + clientData.hide_zero_status_filters = document.getElementById("hideZeroFiltersCheckbox").checked; + clientData.dblclick_download = document.getElementById("dblclickDownloadSelect").value; + clientData.dblclick_complete = document.getElementById("dblclickCompleteSelect").value; + clientData.dblclick_filter = document.getElementById("dblclickFiltersSelect").value; settings["confirm_torrent_deletion"] = document.getElementById("confirmTorrentDeletion").checked; - LocalPreferences.set("use_alt_row_colors", document.getElementById("useAltRowColorsInput").checked.toString()); + clientData.use_alt_row_colors = document.getElementById("useAltRowColorsInput").checked; settings["file_log_enabled"] = document.getElementById("filelog_checkbox").checked; settings["file_log_path"] = document.getElementById("filelog_save_path_input").value; settings["file_log_backup_enabled"] = document.getElementById("filelog_backup_checkbox").checked; @@ -3170,6 +3180,11 @@ Use ';' to split multiple entries. Can use wildcard '*'.)QBT_TR[CONTEXT=OptionsD settings["i2p_inbound_length"] = Number(document.getElementById("i2pInboundLength").value); settings["i2p_outbound_length"] = Number(document.getElementById("i2pOutboundLength").value); + window.parent.qBittorrent.ClientData.set(clientData) + .catch((error) => { + alert("QBT_TR(Unable to save web client preferences, qBittorrent is probably unreachable.)QBT_TR[CONTEXT=HttpServer]"); + }); + // Send it to qBT window.parent.qBittorrent.Cache.preferences.set(settings) .then(() => { diff --git a/src/webui/www/webui.qrc b/src/webui/www/webui.qrc index f17da4d50..cc0af3384 100644 --- a/src/webui/www/webui.qrc +++ b/src/webui/www/webui.qrc @@ -390,6 +390,7 @@ private/scripts/addtorrent.js private/scripts/cache.js private/scripts/client.js + private/scripts/client-data.js private/scripts/color-scheme.js private/scripts/contextmenu.js private/scripts/dynamicTable.js