diff --git a/README.md b/README.md index 5d2db41..9a2cdab 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,11 @@ When using firefox, use the following: You can enable or disabled for which hosts the extension should redirect. +### Per-site disables + +The popup shows the current website at the top. Press **Configure this site** to disable specific hosts (or all of them) for the current site only — useful when a site uses multiple hosts and you only want to bypass a few, or when a host misbehaves on a particular site. +All per-site disables are listed here and can be edited or removed. + ### ff2mpv [ff2mpv](https://github.com/woodruffw/ff2mpv) allows you to play streams directly in [mpv](https://mpv.io/) instead of the browser. diff --git a/src/entrypoints/popup/App.svelte b/src/entrypoints/popup/App.svelte index 194af18..43065a9 100644 --- a/src/entrypoints/popup/App.svelte +++ b/src/entrypoints/popup/App.svelte @@ -5,13 +5,14 @@ import Toast from '@/entrypoints/popup/components/Toast.svelte'; import Main from '@/entrypoints/popup/pages/main/Main.svelte'; import Settings from '@/entrypoints/popup/pages/settings/Settings.svelte'; + import SiteConfig from '@/entrypoints/popup/pages/site-config/SiteConfig.svelte'; import { isMobile } from '@/entrypoints/popup/state.js'; /* state init */ browser.runtime.getPlatformInfo().then((info) => ($isMobile = info.os === 'android')); /* types */ - type Page = 'main' | 'settings'; + type Page = 'main' | 'settings' | 'site-config'; /* states */ let activePage = $state('main'); @@ -21,7 +22,10 @@ {#if activePage === 'main'}
-
(activePage = 'settings')} /> +
(activePage = 'settings')} + onSiteConfigOpenRequest={() => (activePage = 'site-config')} + />
{:else if activePage === 'settings'}
(activePage = 'main')} />
+ {:else if activePage === 'site-config'} +
+ (activePage = 'main')} /> +
{/if} diff --git a/src/entrypoints/popup/components/HostRow.svelte b/src/entrypoints/popup/components/HostRow.svelte index ab1824c..4d38cd9 100644 --- a/src/entrypoints/popup/components/HostRow.svelte +++ b/src/entrypoints/popup/components/HostRow.svelte @@ -6,12 +6,13 @@ interface Props { host: Host; enabled?: boolean; + badge?: string; onclick?: () => void; actions: Snippet; } /* states */ - let { host, enabled, onclick, actions }: Props = $props(); + let { host, enabled, badge, onclick, actions }: Props = $props(); let rowClass = $derived( `flex items-center gap-3 px-3 py-2 rounded-md transition-colors ${onclick ? 'hover:bg-gray-800/40 cursor-pointer' : ''}` @@ -40,10 +41,18 @@ class:bg-linux-mint-green={enabled === true} class:bg-gray-500={enabled === false} class:bg-transparent={enabled === undefined} - aria-hidden="true" >
-

{host.name}

+
+

{host.name}

+ {#if badge} + + {badge} + + {/if} +

{host.domains.join(', ')}

diff --git a/src/entrypoints/popup/components/Notice.svelte b/src/entrypoints/popup/components/Notice.svelte new file mode 100644 index 0000000..b71fc90 --- /dev/null +++ b/src/entrypoints/popup/components/Notice.svelte @@ -0,0 +1,39 @@ + + +
+ +
+ {#if title} +

{title}

+ {/if} + {#if description} +

{description}

+ {/if} +
+
diff --git a/src/entrypoints/popup/components/SearchInput.svelte b/src/entrypoints/popup/components/SearchInput.svelte index 0dfd6f8..42be77c 100644 --- a/src/entrypoints/popup/components/SearchInput.svelte +++ b/src/entrypoints/popup/components/SearchInput.svelte @@ -20,14 +20,12 @@ type="text" bind:value {placeholder} - aria-label="Filter hosts" class="flex-1 bg-transparent text-sm text-gray-100 placeholder:text-gray-500 outline-none min-w-0" /> {#if value} +
diff --git a/src/entrypoints/popup/pages/main/Main.svelte b/src/entrypoints/popup/pages/main/Main.svelte index 2804bff..54c2eff 100644 --- a/src/entrypoints/popup/pages/main/Main.svelte +++ b/src/entrypoints/popup/pages/main/Main.svelte @@ -3,11 +3,11 @@ import { onDestroy } from 'svelte'; import Divider from '@/entrypoints/popup/components/Divider.svelte'; - import AllDisabled from '@/entrypoints/popup/pages/main/AllDisabled.svelte'; + import Notice from '@/entrypoints/popup/components/Notice.svelte'; import CopyMatch from '@/entrypoints/popup/pages/main/CopyMatch.svelte'; + import CurrentSite from '@/entrypoints/popup/pages/main/CurrentSite.svelte'; import Header from '@/entrypoints/popup/pages/main/Header.svelte'; import Match from '@/entrypoints/popup/pages/main/Match.svelte'; - import NoMatch from '@/entrypoints/popup/pages/main/NoMatch.svelte'; import { listenMessages, MessageType, sendMessageToActiveTab } from '@/lib/communication'; import { hosts, type Host } from '@/lib/host'; import { HostSettings } from '@/lib/settings'; @@ -15,11 +15,13 @@ /* types */ interface Props { onSettingsOpenRequest: () => void; + onSiteConfigOpenRequest: () => void; } /* states */ - let { onSettingsOpenRequest }: Props = $props(); + let { onSettingsOpenRequest, onSiteConfigOpenRequest }: Props = $props(); let currentMatch = $state<{ host: Host; url: string; domain: string } | null>(null); + let currentDomain = $state(null); let allHostsDisabled = $state(false); HostSettings.getAllHostsDisabled().then((val) => (allHostsDisabled = val)); @@ -27,35 +29,73 @@ /* lifecycle */ const cancel = listenMessages((type, data) => { if (type !== MessageType.NotifyActiveMatch) return; - currentMatch = { + const match = { host: hosts.find((host) => host.id === data.id)!, url: data.url, domain: data.domain }; + currentMatch = match; + currentDomain = match.domain; }); sendMessageToActiveTab(MessageType.RequestActiveMatch, undefined); + browser.tabs + .query({ active: true, currentWindow: true }) + .then((tabs) => { + if (currentDomain) return; + const url = tabs[0]?.url; + if (!url) return; + try { + currentDomain = new URL(url).hostname; + } catch { + /* ignore */ + } + }) + .catch(() => {}); + onDestroy(cancel); -
+
-
- {#if allHostsDisabled} - - {:else if !currentMatch} - - {:else} -
- -
-
+
+
+ {#if currentDomain} + + {/if} +
+ +
+ {#if allHostsDisabled} + + {:else if currentMatch} +
+ +
+
-
- {/if} + {:else} +
+ +
+ {/if} +
+ +
+

+ Suggestions or bugs can be submitted here +

+