From 821a649224531d34fd75b4b9cb4537add52101c2 Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Sat, 10 Feb 2024 03:48:14 +0800 Subject: [PATCH 001/210] fix: improve platform recognition then fix icon display in visionos --- src/ext/background/main.js | 14 +++++++++++++- xcode/Shared/Utilities.swift | 29 +++++++++++++++++++---------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/ext/background/main.js b/src/ext/background/main.js index 2d90f256..1c51e2c4 100644 --- a/src/ext/background/main.js +++ b/src/ext/background/main.js @@ -72,9 +72,21 @@ function setClipboard(data, type = "text/plain") { } async function setBadgeCount() { - const clearBadge = () => browser.browserAction.setBadgeText({ text: "" }); + const clearBadge = () => { + if (import.meta.env.SAFARI_VERSION < 16.4) { + browser.browserAction.setBadgeText({ text: "" }); + } else { + browser.browserAction.setBadgeText({ text: null }); + } + }; // @todo until better introduce in ios, only set badge on macOS const platform = await getPlatform(); + // set a text badge or an empty string in visionOS will cause the extension's icon to no longer be displayed + // set it to null to fix already affected users + if (platform === "visionos") { + browser.browserAction.setBadgeText({ text: null }); + return; + } if (platform !== "macos") return clearBadge(); // @todo settingsStorage.get("global_exclude_match") const settings = await settingsStorage.get([ diff --git a/xcode/Shared/Utilities.swift b/xcode/Shared/Utilities.swift index c64c2fc6..8e3f0949 100644 --- a/xcode/Shared/Utilities.swift +++ b/xcode/Shared/Utilities.swift @@ -28,16 +28,25 @@ func directoryExists(path: String) -> Bool { } func getPlatform() -> String { - var platform:String -#if os(iOS) - if UIDevice.current.userInterfaceIdiom == .pad { - platform = "ipados" +#if os(macOS) + return "macos" +#elseif os(iOS) + // https://developer.apple.com/documentation/uikit/uiuserinterfaceidiom + switch UIDevice.current.userInterfaceIdiom { + case .phone: + return "ios" + case .pad, .mac: + return "ipados" + case .vision: + return "visionos" + case .tv: + return "tvos" + case .carPlay: + return "carplay" + case .unspecified: + return "unspecified" + @unknown default: + return "unknown" } - else { - platform = "ios" - } -#elseif os(macOS) - platform = "macos" #endif - return platform } From 54da240a7a1637f11468f2483e0623bdb9c8a2b5 Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Sat, 10 Feb 2024 03:50:53 +0800 Subject: [PATCH 002/210] refactor: solve the unpleasant bounce of loader icon --- src/ext/shared/Components/Loader.svelte | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ext/shared/Components/Loader.svelte b/src/ext/shared/Components/Loader.svelte index d35782e2..666ae404 100644 --- a/src/ext/shared/Components/Loader.svelte +++ b/src/ext/shared/Components/Loader.svelte @@ -5,12 +5,24 @@ export let abort = false; export let abortClick = () => {}; export let backgroundColor = "var(--color-bg-secondary)"; + + /** + * Avoid icon bouncing due to viewport height changes or banner insertion + * @type {import('svelte/action').Action} + */ + function lockIconTopPosition(node) { + const icon = node.querySelector("svg"); + const rect = icon.getBoundingClientRect(); + icon.style.top = rect.top.toString(); + icon.style.position = "fixed"; + }
{@html iconLoader} From b660a36d06e34e1e02234315795f63a63190326d Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Sat, 10 Feb 2024 11:21:03 +0800 Subject: [PATCH 003/210] refactor: improve basic popup view structure resolve popup open size adaptation resolve height and safe area adaptation avoid some unpleasant height changes and bounces --- src/ext/action-popup/App.svelte | 286 ++++++++---------- src/ext/action-popup/Components/View.svelte | 10 +- .../Components/Views/InstallView.svelte | 5 - src/ext/action-popup/app.css | 54 ++-- src/ext/shared/utils.js | 1 + 5 files changed, 160 insertions(+), 196 deletions(-) diff --git a/src/ext/action-popup/App.svelte b/src/ext/action-popup/App.svelte index be597bf1..b3d36250 100644 --- a/src/ext/action-popup/App.svelte +++ b/src/ext/action-popup/App.svelte @@ -29,7 +29,6 @@ let platform; let initError; let firstGuide; - let windowHeight = 0; let header; let warn; let err; @@ -50,13 +49,10 @@ let installViewUserscriptError; let showAll; let allItems = []; - let resizeTimer; let abort = false; $: list = items.sort((a, b) => a.name.localeCompare(b.name)); - $: if (platform) document.body.classList.add(platform); - function getItemBackgroundColor(elements, index) { if (elements.length < 2) return null; if (elements.length % 2 === 0 && index % 2 === 0) return "light"; @@ -264,9 +260,6 @@ // set toggle state active = await settingsStorage.get("global_active"); - // set popup height - resize(); - // get matches const currentTab = await browser.tabs.getCurrent(); const url = currentTab.url; @@ -361,34 +354,15 @@ window.location.reload(); } - async function resize() { - if (!platform || platform === "macos") return; - clearTimeout(resizeTimer); - resizeTimer = setTimeout(async () => { - if (platform === "ipados") { - if (window.matchMedia("(max-width: 360px)").matches) { - // the popup window is no greater than 360px - // ensure body & main element have no leftover styling - main.removeAttribute("style"); - document.body.removeAttribute("style"); - return; - } - main.style.maxHeight = "unset"; - document.body.style.width = "100vw"; - } - // on ios and ipados (split view) programmatically set the height of the scrollable container - // first get the header height - const headerHeight = header.offsetHeight; - // then check if a warning or error is visible (ie. taking up height) - let addHeight = 0; - // if warn or error elements visible, also subtract that from applied height - if (warn) addHeight += warn.offsetHeight; - if (err) addHeight += err.offsetHeight; - windowHeight = window.outerHeight - (headerHeight + addHeight); - main.style.height = `${windowHeight}px`; - main.style.paddingBottom = `${headerHeight + addHeight}px`; - }, 25); - } + /** @type {import("svelte/elements").UIEventHandler} */ + // async function resizeHandler(event) { + // if (platform !== "macos") { + // const viewport = event.currentTarget.visualViewport; + // console.debug(platform, viewport); + // // add max limits after the window size has been rendered + // // avoid display overflow when window shrinks dynamically + // } + // } /** * Check if the current page contains a user script @@ -497,8 +471,6 @@ onMount(async () => { await initialize(); - // run resize again for good measure - resize(); }); // handle native app messages @@ -522,114 +494,6 @@ let showBetaNews = true; - -
- - (showUpdates = true)} - title={"Show updates"} - {disabled} - /> - - -
-{#if !active} - -{/if} -{#if showBetaNews && platform !== "macos"} -
- NEW: is - now available on iOS! - (showBetaNews = false)} - title={"Close"} - /> -
-{/if} -{#if showInstallPrompt} -
- Userscript - {#if scriptChecking} - {showInstallPrompt} - {:else} - {scriptInstalled ? "Installed" : "Detected"}: - - {/if} -
-{/if} -{#if errorNotification} -
- {errorNotification} - (errorNotification = undefined)} - title={"Clear error"} - /> -
-{/if} -
- {#if loading} - - {:else if inactive} -
Popup inactive on extension page
- {:else if firstGuide} -
-

Welcome, first use please: 

- -

to complete the initialization

-
- {:else if initError} -
- Something went wrong:  - -
- {:else if items.length < 1} -
No matched userscripts
- {:else} -
- {#each list as item, i (item.filename)} - toggleItem(item)} - /> - {/each} -
- {/if} -
-{#if !inactive && platform === "macos"} - -{/if} {#if showUpdates} +{:else} +
+
+ + (showUpdates = true)} + title={"Show updates"} + {disabled} + /> + + +
+ {#if !active} + + {/if} + {#if showBetaNews && platform !== "macos"} +
+ NEW: + is now available! + (showBetaNews = false)} + title={"Close"} + /> +
+ {/if} + {#if showInstallPrompt} +
+ Userscript + {#if scriptChecking} + {showInstallPrompt} + {:else} + {scriptInstalled ? "Installed" : "Detected"}: + + {/if} +
+ {/if} + {#if errorNotification} +
+ {errorNotification} + (errorNotification = undefined)} + title={"Clear error"} + /> +
+ {/if} +
+
+ {#if loading} + + {:else if inactive} +
Popup inactive on extension page
+ {:else if firstGuide} +
+

Welcome, first use please: 

+ +

to complete the initialization

+
+ {:else if initError} +
+ Something went wrong:  + +
+ {:else if items.length < 1} +
No matched userscripts
+ {:else} +
+ {#each list as item, i (item.filename)} + toggleItem(item)} + /> + {/each} +
+ {/if} +
+ {#if !inactive && platform === "macos"} + + {/if} {/if} diff --git a/src/ext/action-popup/Components/Views/InstallView.svelte b/src/ext/action-popup/Components/Views/InstallView.svelte index fe3a3152..d4d23d2b 100644 --- a/src/ext/action-popup/Components/Views/InstallView.svelte +++ b/src/ext/action-popup/Components/Views/InstallView.svelte @@ -76,11 +76,6 @@ padding: 0 1rem; } - :global(body.ios) .view--install, - :global(body.ipados) .view--install { - padding-bottom: calc(39px + 1rem); - } - .install__error { color: var(--text-color-disabled); font-weight: 600; diff --git a/src/ext/action-popup/app.css b/src/ext/action-popup/app.css index 2d2feca2..e0a88c6e 100644 --- a/src/ext/action-popup/app.css +++ b/src/ext/action-popup/app.css @@ -8,55 +8,45 @@ body { color: var(--text-color-primary); font: var(--text-medium); letter-spacing: var(--letter-spacing-medium); - position: relative; text-rendering: optimizelegibility; - width: 18rem; -webkit-font-smoothing: antialiased; + position: relative; + width: 18rem; + height: 26rem; } -/* attempts to detect iOS */ -@media (hover: none) { +/* ios */ +@supports (-webkit-touch-callout: none) { html { font-size: 125%; + overflow: visible; + overscroll-behavior: none; } body { - width: 100vw; + width: auto; + min-width: 16rem; + height: auto; } -} -@media screen and (width >= 481px) and (orientation: portrait) and (hover: none) { - body { - width: 18rem; + /* non-fixed width need to stretch */ + @media (width < 320px) { + body { + width: 18rem; + min-height: 16rem; + } } } -@media screen and (width >= 1024px) and (orientation: landscape) and (hover: none) { - body { - width: 18rem; - } -} - -body.ipados { - width: 18rem; - height: 100vh; -} - -body.ipados #app { - height: 100%; -} - -body.ios { - height: 100vh; - width: 100vw; +noscript { + display: block; } -body.ios #app { +#app { + display: flex; + flex-direction: column; height: 100%; -} - -noscript { - display: block; + justify-content: space-between; } button { diff --git a/src/ext/shared/utils.js b/src/ext/shared/utils.js index 96b76af3..63875afd 100644 --- a/src/ext/shared/utils.js +++ b/src/ext/shared/utils.js @@ -374,6 +374,7 @@ export async function openExtensionPage() { const tab = tabs.find((e) => e.url.startsWith(url)); if (!tab) return browser.tabs.create({ url }); await browser.tabs.update(tab.id, { active: true }); + if (!browser.windows.update) return; await browser.windows.update(tab.windowId, { focused: true }); } From af2954f17a66384945d4bd6e1429cd4e7d24236e Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Sat, 10 Feb 2024 14:04:29 +0800 Subject: [PATCH 004/210] fix: think of visionos always as ios There is currently no effective way to detect visionOS in Apple Vision (Designed for iPad) mode. So it can only always be treated as ios to handle any surprises. setBadgeText `null` value tested working on Safari 15.6.1 (macOS 12.6). --- src/ext/background/main.js | 15 ++------------- xcode/Shared/Utilities.swift | 1 + 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/ext/background/main.js b/src/ext/background/main.js index 1c51e2c4..135661bb 100644 --- a/src/ext/background/main.js +++ b/src/ext/background/main.js @@ -72,21 +72,10 @@ function setClipboard(data, type = "text/plain") { } async function setBadgeCount() { - const clearBadge = () => { - if (import.meta.env.SAFARI_VERSION < 16.4) { - browser.browserAction.setBadgeText({ text: "" }); - } else { - browser.browserAction.setBadgeText({ text: null }); - } - }; + const clearBadge = () => browser.browserAction.setBadgeText({ text: null }); // @todo until better introduce in ios, only set badge on macOS - const platform = await getPlatform(); // set a text badge or an empty string in visionOS will cause the extension's icon to no longer be displayed - // set it to null to fix already affected users - if (platform === "visionos") { - browser.browserAction.setBadgeText({ text: null }); - return; - } + const platform = await getPlatform(); if (platform !== "macos") return clearBadge(); // @todo settingsStorage.get("global_exclude_match") const settings = await settingsStorage.get([ diff --git a/xcode/Shared/Utilities.swift b/xcode/Shared/Utilities.swift index 8e3f0949..dfb00425 100644 --- a/xcode/Shared/Utilities.swift +++ b/xcode/Shared/Utilities.swift @@ -32,6 +32,7 @@ func getPlatform() -> String { return "macos" #elseif os(iOS) // https://developer.apple.com/documentation/uikit/uiuserinterfaceidiom + // There is no reliable way to detect visionOS for now, will match `.phone` in Apple Vision (Designed for iPad) mode switch UIDevice.current.userInterfaceIdiom { case .phone: return "ios" From 8d9b7a2a96ac06dcd46aa3975df400c27e2b0c55 Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Mon, 12 Feb 2024 12:36:44 +0800 Subject: [PATCH 005/210] fix: revert view height and scrolling for macos --- src/ext/action-popup/Components/View.svelte | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ext/action-popup/Components/View.svelte b/src/ext/action-popup/Components/View.svelte index 4a7564e7..805b5f16 100644 --- a/src/ext/action-popup/Components/View.svelte +++ b/src/ext/action-popup/Components/View.svelte @@ -40,11 +40,12 @@ background-color: var(--color-bg-secondary); display: flex; flex-direction: column; - left: 0; position: absolute; text-align: center; top: 0; + left: 0; width: 100%; + height: 100%; z-index: 3; } @@ -71,6 +72,18 @@ .view__body { flex-grow: 1; + overflow-y: auto; position: relative; } + + /* ios */ + @supports (-webkit-touch-callout: none) { + .view { + height: auto; + } + + .view__body { + overflow-y: visible; + } + } From 9d25dafcf58164bbd29e4a90e3cf36ffdf4aaaf3 Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Mon, 12 Feb 2024 12:56:36 +0800 Subject: [PATCH 006/210] fix: make the subview none style consistent --- .../action-popup/Components/Views/AllItemsView.svelte | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ext/action-popup/Components/Views/AllItemsView.svelte b/src/ext/action-popup/Components/Views/AllItemsView.svelte index b5457123..2c5484bb 100644 --- a/src/ext/action-popup/Components/Views/AllItemsView.svelte +++ b/src/ext/action-popup/Components/Views/AllItemsView.svelte @@ -47,12 +47,10 @@ } .none { - align-items: center; - color: var(--text-color-disabled); - display: flex; font-weight: 600; - justify-content: center; - inset: 0; - position: absolute; + color: var(--text-color-disabled); + text-align: center; + padding: 3rem 0; + line-height: 2.5; } From 9bf39f3c291550b07a4bf89f6d07e914c0ebeffc Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Tue, 20 Feb 2024 10:17:47 +0800 Subject: [PATCH 007/210] build: v4.5.0(86), v1.5.0(60) --- xcode/xcconfig/Userscripts-Release.xcconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xcode/xcconfig/Userscripts-Release.xcconfig b/xcode/xcconfig/Userscripts-Release.xcconfig index 9de57ebb..ff3971b8 100644 --- a/xcode/xcconfig/Userscripts-Release.xcconfig +++ b/xcode/xcconfig/Userscripts-Release.xcconfig @@ -1,9 +1,9 @@ #include "Userscripts-Base.xcconfig" INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2018–2023 Justin Wasack. All rights reserved. -IOS_APP_BUILD = 59 +IOS_APP_BUILD = 60 IOS_APP_VERSION = 1.5.0 -MAC_APP_BUILD = 85 +MAC_APP_BUILD = 86 MAC_APP_VERSION = 4.5.0 // Development From 3f16a24a4c2f981afb21a5a897aef3fbaa6188cc Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:07:34 +0800 Subject: [PATCH 008/210] build: v4.5.0(87), v1.5.0(60) --- xcode/xcconfig/Userscripts-Release.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcode/xcconfig/Userscripts-Release.xcconfig b/xcode/xcconfig/Userscripts-Release.xcconfig index ff3971b8..e6fe5df0 100644 --- a/xcode/xcconfig/Userscripts-Release.xcconfig +++ b/xcode/xcconfig/Userscripts-Release.xcconfig @@ -3,7 +3,7 @@ INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2018–2023 Justin Wasack. All rights reserved. IOS_APP_BUILD = 60 IOS_APP_VERSION = 1.5.0 -MAC_APP_BUILD = 86 +MAC_APP_BUILD = 87 MAC_APP_VERSION = 4.5.0 // Development From d138ec0456e9cc75c604752e2ce55c1668e804aa Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Tue, 20 Feb 2024 20:24:04 +0800 Subject: [PATCH 009/210] feat: support ios dynamic type to improve a11y --- src/app/variables.css | 3 +-- src/ext/action-popup/app.css | 21 +++++++++++++++++++++ src/ext/extension-page/app.css | 21 +++++++++++++++++++++ src/ext/shared/variables.css | 3 +-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/app/variables.css b/src/app/variables.css index 0c641d23..04ab9458 100644 --- a/src/app/variables.css +++ b/src/app/variables.css @@ -18,8 +18,7 @@ --text-color-primary: rgb(255 255 255); --text-color-secondary: rgb(255 255 255 / 0.65); --text-color-disabled: rgb(255 255 255 / 0.4); - --font-family: system-ui, -apple-system, "Helvetica Neue", "Helvetica", - sans-serif; + --font-family: -apple-system, "Helvetica Neue", "Helvetica", sans-serif; --text-default: 1rem/1.5rem var(--font-family); --text-large: 1.25rem/1.5rem var(--font-family); --text-medium: 0.875rem/1.313rem var(--font-family); diff --git a/src/ext/action-popup/app.css b/src/ext/action-popup/app.css index e0a88c6e..9ecba94e 100644 --- a/src/ext/action-popup/app.css +++ b/src/ext/action-popup/app.css @@ -23,6 +23,20 @@ body { overscroll-behavior: none; } + /** + * Dynamic Type + * https://support.apple.com/102453 + * https://webkit.org/blog/3709/using-the-system-font-in-web-content/ + * https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_7_0.html#//apple_ref/doc/uid/TP40014305-CH5-SW10 + * https://github.com/w3c/csswg-drafts/issues/3708 + */ + @supports (font: -apple-system-body) { + html { + /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ + font: -apple-system-title3; /* default 20px */ + } + } + body { width: auto; min-width: 16rem; @@ -36,6 +50,13 @@ body { min-height: 16rem; } } + + /* Avoid page zoom */ + input, + textarea, + select { + font-size: max(1rem, 16px); + } } noscript { diff --git a/src/ext/extension-page/app.css b/src/ext/extension-page/app.css index 61b9195a..4ae66302 100644 --- a/src/ext/extension-page/app.css +++ b/src/ext/extension-page/app.css @@ -12,6 +12,27 @@ html { height: auto; overflow: visible; } + + /** + * Dynamic Type + * https://support.apple.com/102453 + * https://webkit.org/blog/3709/using-the-system-font-in-web-content/ + * https://developer.apple.com/library/archive/releasenotes/General/WhatsNewInSafari/Articles/Safari_7_0.html#//apple_ref/doc/uid/TP40014305-CH5-SW10 + * https://github.com/w3c/csswg-drafts/issues/3708 + */ + @supports (font: -apple-system-body) { + html { + /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */ + font: -apple-system-body; /* default 17px */ + } + } + + /* Avoid page zoom */ + input, + textarea, + select { + font-size: max(1rem, 16px); + } } body { diff --git a/src/ext/shared/variables.css b/src/ext/shared/variables.css index 0c641d23..04ab9458 100644 --- a/src/ext/shared/variables.css +++ b/src/ext/shared/variables.css @@ -18,8 +18,7 @@ --text-color-primary: rgb(255 255 255); --text-color-secondary: rgb(255 255 255 / 0.65); --text-color-disabled: rgb(255 255 255 / 0.4); - --font-family: system-ui, -apple-system, "Helvetica Neue", "Helvetica", - sans-serif; + --font-family: -apple-system, "Helvetica Neue", "Helvetica", sans-serif; --text-default: 1rem/1.5rem var(--font-family); --text-large: 1.25rem/1.5rem var(--font-family); --text-medium: 0.875rem/1.313rem var(--font-family); From 04395d2b6688743f03fcc1205f6d7d0dda6ed9c8 Mon Sep 17 00:00:00 2001 From: ACTCD <101378590+ACTCD@users.noreply.github.com> Date: Fri, 22 Mar 2024 06:50:25 +0800 Subject: [PATCH 010/210] refactor: improve settings interface layout adaptability --- .../Components/ModalWrapper.svelte | 1 + .../extension-page/Components/Settings.svelte | 426 ++++++++++-------- 2 files changed, 236 insertions(+), 191 deletions(-) diff --git a/src/ext/extension-page/Components/ModalWrapper.svelte b/src/ext/extension-page/Components/ModalWrapper.svelte index 826d5141..e1077a3d 100644 --- a/src/ext/extension-page/Components/ModalWrapper.svelte +++ b/src/ext/extension-page/Components/ModalWrapper.svelte @@ -100,6 +100,7 @@ } .scroll { + border-radius: var(--border-radius); max-height: calc(100svh - 5rem); overflow-y: auto; overscroll-behavior: none; diff --git a/src/ext/extension-page/Components/Settings.svelte b/src/ext/extension-page/Components/Settings.svelte index 084472ae..50b5abf9 100644 --- a/src/ext/extension-page/Components/Settings.svelte +++ b/src/ext/extension-page/Components/Settings.svelte @@ -237,10 +237,10 @@ {#each groups as group}
-
{gl(`settings_section_${group}`)}
+
{gl(`settings_section_${group}`)}
{#if indicators.resetting} -
- {gl(`settings_${item.name}`)} -
- {#if item.nodeType === "Toggle"} - - settings.updateSingleSetting(item.name, !$settings[item.name])} - /> - {/if} - {#if item.nodeType === "select"} - - {/if} - {#if indicators.resetting && !indicators.saving[item.name] && !item.protect && (item.name !== "global_exclude_match" || !gemFocused)} - - {/if} + {gl(`settings_${item.name}`)} +
+
+ {gl(`settings_${item.name}_desc`)} +
+
+ {#if item.nodeType === "Toggle"} + + settings.updateSingleSetting( + item.name, + !$settings[item.name], + )} + /> + {/if} + {#if item.nodeType === "select"} + + {/if} +
+
+ {#if indicators.resetting && !indicators.saving[item.name] && !item.protect && (item.name !== "global_exclude_match" || !gemFocused)} + + {/if} + {#if item.nodeType === "textarea"} + {#if indicators.saving[item.name]} +
+ + {@html iconLoader} + {gl(`settings_${item.name}_saving`)} +
+ {/if} + {#if gemFocused} + + + {/if} + {/if} +
+
{#if item.nodeType === "textarea" && item.name === "global_exclude_match"} - {#if indicators.saving[item.name]} - - {@html iconLoader} - {gl(`settings_${item.name}_saving`)} - {/if} - {#if gemFocused} - - - {/if}