diff --git a/release-notes.md b/release-notes.md index e8fbfba..2a59032 100644 --- a/release-notes.md +++ b/release-notes.md @@ -1,17 +1,12 @@ -# 2.0.0 (26071) -[feature release] +# 2.0.1 (26072) +[bugfix release] ## Release Notes -- Refreshed the icons to reflect the new branding. -- Added support for OpenTubeX, Invidious and Piped, with the option to choose between them or FreeTube as the default redirection target. -- Added an optional keyboard shortcut to redirect the current tab, configurable to replace the tab or open a new one. -- Refined the options, popup, and introduction layouts with shared component styles. -- Added a direct Options button to the introduction screen and social links in the popup footer. -- Added Finnish (by Ricky-Tigg) localization and refreshed Estonian and Dutch strings for the updated URL rules UI. -- Improved YouTube URL and embed detection to correctly match subdomains instead of relying on substring checks. -- Made context menu redirects, icon updates, and URL rule loading more reliable on startup. -- Hardened the iframe placeholder against unsafe HTML in replacement text. +- Fixed the toolbar icon to update per tab instead of globally, so switching between YouTube and other tabs now immediately shows the correct allowed/blocked state. +- Fixed the RedirectTube-branded color icon option in Settings not saving due to a conflicting element ID with the FreeTube color icon. +- Reorganized the keyboard shortcut settings in Options and the introduction screen into a clearer, connected group with a proper label on the behavior dropdown. +- Corrected the Polish translation of the keyboard shortcut label. > [!WARNING] > For Firefox, the `-unsigned.xpi` artifact will most likely not install. Use the signed version (`-signed.xpi`) or download from the [Firefox Add-ons](https://addons.mozilla.org/firefox/addon/redirecttube/). For Chromium-based browsers, download the `-chromium-unsigned.zip` and load it unpacked in Developer Mode or download from the [Chrome Web Store](https://chromewebstore.google.com/detail/jpbaggklodpddjcadlebabhiopjkjfjh/). diff --git a/src/browser/background.js b/src/browser/background.js index 4c9d24e..616590a 100644 --- a/src/browser/background.js +++ b/src/browser/background.js @@ -14,6 +14,7 @@ let isDarkThemePreferred = false; let currentMenuLang = null; let urlRulesConfig = getDefaultUrlRulesConfig(); let urlRulesConfigLoaded = false; +const tabAllowedState = new Map(); extensionApi.runtime.onInstalled.addListener((details) => { if (details.reason === "install") { @@ -74,27 +75,49 @@ extensionApi.runtime.onStartup.addListener(() => { createContextMenu(); }); -extensionApi.runtime.onMessage.addListener((request) => { +extensionApi.runtime.onMessage.addListener((request, sender) => { + const tabId = sender && sender.tab && typeof sender.tab.id === "number" + ? sender.tab.id + : undefined; + if (request.message === RUNTIME_MESSAGES.currentUrlChanged && request.url) { // Ensure urlRulesConfig is loaded before evaluating the URL (avoid race with startup) if (!urlRulesConfigLoaded) { extensionApi.storage.local.get(STORAGE_KEYS.urlRulesConfig, (result = {}) => { urlRulesConfig = normalizeUrlRulesConfig(result[STORAGE_KEYS.urlRulesConfig]); urlRulesConfigLoaded = true; - handleUrlChange(request.url); + handleUrlChange(request.url, tabId); }); } else { - handleUrlChange(request.url); + handleUrlChange(request.url, tabId); } return; } if (request.message === RUNTIME_MESSAGES.redirecttubeTheme) { isDarkThemePreferred = Boolean(request.isDark); - updateActionIcon(); + updateActionIcon(tabId); } }); +extensionApi.tabs.onActivated.addListener(({ tabId }) => { + if (tabAllowedState.has(tabId)) { + updateActionIcon(tabId); + return; + } + extensionApi.tabs.get(tabId, (tab) => { + if (extensionApi.runtime.lastError || !tab || !tab.url) { + return; + } + tabAllowedState.set(tabId, isRedirectableYoutubeUrl(tab.url, urlRulesConfig)); + updateActionIcon(tabId); + }); +}); + +extensionApi.tabs.onRemoved.addListener((tabId) => { + tabAllowedState.delete(tabId); +}); + extensionApi.storage.onChanged.addListener((changes, areaName) => { if (areaName !== "local") { return; @@ -106,6 +129,7 @@ extensionApi.storage.onChanged.addListener((changes, areaName) => { if (changes[STORAGE_KEYS.extensionIcon]) { cachedExtensionIcon = changes[STORAGE_KEYS.extensionIcon].newValue || "redirecttube-color"; updateActionIcon(); + tabAllowedState.forEach((_isAllowed, tabId) => updateActionIcon(tabId)); } if (changes[STORAGE_KEYS.selectedPlayer]) { @@ -166,18 +190,26 @@ extensionApi.commands.onCommand.addListener((command) => { }); }); -function handleUrlChange(url) { +function handleUrlChange(url, tabId) { if (!url) { return; } - lastUrlAllowed = isRedirectableYoutubeUrl(url, urlRulesConfig); - updateActionIcon(); + const isAllowed = isRedirectableYoutubeUrl(url, urlRulesConfig); + lastUrlAllowed = isAllowed; + if (typeof tabId === "number") { + tabAllowedState.set(tabId, isAllowed); + } + updateActionIcon(tabId); } -function updateActionIcon() { +function updateActionIcon(tabId) { + const isAllowed = + typeof tabId === "number" && tabAllowedState.has(tabId) + ? tabAllowedState.get(tabId) + : lastUrlAllowed; const path = getIconPath( cachedExtensionIcon, - lastUrlAllowed, + isAllowed, isDarkThemePreferred ); try { @@ -185,9 +217,13 @@ function updateActionIcon() { extensionApi && extensionApi.runtime && typeof extensionApi.runtime.getURL === "function" ? extensionApi.runtime.getURL(path) : path; - extensionApi.action.setIcon({ path: resolvedPath }); + const details = { path: resolvedPath }; + if (typeof tabId === "number") { + details.tabId = tabId; + } + extensionApi.action.setIcon(details); } catch (err) { - console.error("Failed to set action icon:", err, { path }); + console.error("Failed to set action icon:", err, { path, tabId }); } } diff --git a/src/browser/i18n/locales/pl.json b/src/browser/i18n/locales/pl.json index 138e1ac..c3dd566 100644 --- a/src/browser/i18n/locales/pl.json +++ b/src/browser/i18n/locales/pl.json @@ -148,8 +148,8 @@ "behaviorLabel": "Działanie skrótu klawiaturowego", "replaceTab": "Zastąp bieżącą kartę", "newTab": "Otwórz w nowej karcie", - "changeLabel": "Skrót klawiszowy", - "change": "Zmień skrót klawiszowy…", + "changeLabel": "Skrót klawiaturowy", + "change": "Zmień skrót klawiaturowy…", "firefoxHint": "Otwórz menu przeglądarki Firefox (☰) → „Rozszerzenia i motywy”, a następnie kliknij ikonę koła zębatego (⚙) i wybierz opcję „Zarządzaj skrótami rozszerzeń”." } }, diff --git a/src/browser/introduction.css b/src/browser/introduction.css index a91eb0f..b9469d4 100644 --- a/src/browser/introduction.css +++ b/src/browser/introduction.css @@ -157,6 +157,27 @@ body { margin: 0; } +.flex-row { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + cursor: pointer; +} + +#shortcutOptions { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + gap: 10px; +} + +#shortcutOptions select, +#shortcutOptions button { + width: min(100%, 320px); +} + .instance-row { display: flex; flex-wrap: wrap; diff --git a/src/browser/introduction.html b/src/browser/introduction.html index 8e1d84c..25d854c 100644 --- a/src/browser/introduction.html +++ b/src/browser/introduction.html @@ -123,17 +123,20 @@

OpenTubeX requires the deskto