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/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; } 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/background/main.js b/src/ext/background/main.js index 2d90f256..135661bb 100644 --- a/src/ext/background/main.js +++ b/src/ext/background/main.js @@ -72,8 +72,9 @@ function setClipboard(data, type = "text/plain") { } async function setBadgeCount() { - const clearBadge = () => browser.browserAction.setBadgeText({ text: "" }); + const clearBadge = () => browser.browserAction.setBadgeText({ text: null }); // @todo until better introduce in ios, only set badge on macOS + // set a text badge or an empty string in visionOS will cause the extension's icon to no longer be displayed const platform = await getPlatform(); if (platform !== "macos") return clearBadge(); // @todo settingsStorage.get("global_exclude_match") 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} 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 }); } diff --git a/xcode/Shared/Utilities.swift b/xcode/Shared/Utilities.swift index c64c2fc6..dfb00425 100644 --- a/xcode/Shared/Utilities.swift +++ b/xcode/Shared/Utilities.swift @@ -28,16 +28,26 @@ 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 + // 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" + 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 }