diff --git a/addon/bootstrap.js b/addon/bootstrap.js index 4e1414e5..27627a99 100644 --- a/addon/bootstrap.js +++ b/addon/bootstrap.js @@ -35,8 +35,6 @@ const options = { abi: appinfo.XPCOMABI }; -const isVersion119 = Services.vc.compare(appinfo.version, "119.0a1"); - const man = ` overlay chrome://browser/content/browser.xhtml chrome://tabmixplus/content/tabmix.xhtml overlay about:addons chrome://tabmixplus/content/preferences/overlay/aboutaddons.xhtml @@ -115,28 +113,41 @@ function showRestartNotification(verb, window) { ); } -/** @type {Bootstarp.install} */ -async function install(data) { - const addon = await AddonManager.getAddonByID(data.id); +/** @param {string} id */ +async function updateAddon(id) { + const addon = await AddonManager.getAddonByID(id); if (addon?.__AddonInternal__) { addon.__AddonInternal__.signedState = AddonManager.SIGNEDSTATE_NOT_REQUIRED; + if (Services.appinfo.name === "Zen") { + addon.__AddonInternal__.matchingTargetApplication.minVersion = "1.0"; + addon.__AddonInternal__.updateURL = "https://raw.githubusercontent.com/onemen/TabMixPlus/main/config/zen_updates.json"; + } } } +/** @type {Bootstarp.install} */ +async function install(data) { + await updateAddon(data.id); +} + function uninstall() { } /** @type {Bootstarp.startup} */ async function startup(data, reason) { + /** @type {any} */ + const lazy = {}; + + TabmixChromeUtils.defineLazyModuleGetters(lazy, { + isVersion: "chrome://tabmix-resource/content/BrowserVersion.jsm", + SingleWindowModeUtils: "chrome://tabmix-resource/content/SingleWindowModeUtils.jsm" + }); + const chromeManifest = new ChromeManifest(() => { return man; }, options); await chromeManifest.parse(); - AddonManager.getAddonByID(data.id).then(addon => { - if (addon?.__AddonInternal__) { - addon.__AddonInternal__.signedState = AddonManager.SIGNEDSTATE_NOT_REQUIRED; - } - }); + updateAddon(data.id); PreferencesLoader.loadDefaultPreferences(); TabmixWidgets.create(); @@ -147,10 +158,9 @@ async function startup(data, reason) { return; } - const {name, version} = Services.appinfo; /** @type {MockedGeckoTypes.PlacesUIUtils["openTabset"]} */ let _tabmix_PlacesUIUtils_openTabset = () => {}; - if (name === 'Waterfox' && Services.vc.compare(version, '115.9.0') >= 0) { + if (lazy.isVersion({wf: "115.9.0"})) { const {PlacesUIUtils} = ChromeUtils.importESModule("resource:///modules/PlacesUIUtils.sys.mjs"); _tabmix_PlacesUIUtils_openTabset = PlacesUIUtils.openTabset; } @@ -162,7 +172,7 @@ async function startup(data, reason) { const document = win.document; if (document.documentElement) { const isBrowser = document.documentElement.getAttribute("windowtype") === "navigator:browser"; - const isOverflow = isVersion119 ? + const isOverflow = lazy.isVersion(1190) ? isBrowser && win.gBrowser.tabContainer.hasAttribute("overflow") : isBrowser && win.gBrowser.tabContainer.getAttribute("overflow") === "true"; const promiseOverlayLoaded = Overlays.load(chromeManifest, win); @@ -177,14 +187,6 @@ async function startup(data, reason) { } } - /** @type {any} */ - const lazy = {}; - - TabmixChromeUtils.defineLazyModuleGetters(lazy, { - // - SingleWindowModeUtils: "chrome://tabmix-resource/content/SingleWindowModeUtils.jsm" - }); - /** @type {DocumentObserver} */ const documentObserver = { observe(document) { diff --git a/addon/chrome.manifest b/addon/chrome.manifest index 07b2d7b0..cd1ed890 100644 --- a/addon/chrome.manifest +++ b/addon/chrome.manifest @@ -36,8 +36,8 @@ locale tabmixplus zh-TW chrome/locale/zh-TW/ skin tabmixplus classic/1.0 chrome/skin/ -skin tabmix-version tabmixplus chrome/skin/app_version/91/ appversion>=91 -skin tabmix-version tabmixplus chrome/skin/app_version/119/ appversion>=119 +skin tabmix-version tabmixplus chrome/skin/app_version/91/ platformversion>=91 +skin tabmix-version tabmixplus chrome/skin/app_version/119/ platformversion>=119 skin tabmix-os classic/1.0 chrome://tabmix-version/skin/win/ os=WINNT skin tabmix-os classic/1.0 chrome://tabmix-version/skin/mac/ os=Darwin skin tabmix-os classic/1.0 chrome://tabmix-version/skin/linux/ os=Linux diff --git a/addon/chrome/content/click/click.js b/addon/chrome/content/click/click.js index 8ec1446e..10a7ad40 100644 --- a/addon/chrome/content/click/click.js +++ b/addon/chrome/content/click/click.js @@ -952,7 +952,7 @@ var TabmixContext = { Tabmix.allTabs = { init() { const allTabsButton = document.getElementById("alltabs-button"); - allTabsButton.addEventListener("click", function onClick(event) { + allTabsButton?.addEventListener("click", function onClick(event) { if (event.button === 0 && event.detail === 1) { allTabsButton.removeEventListener("click", onClick); setTimeout(Tabmix.allTabs.insertSortButton, 0); diff --git a/addon/chrome/content/preferences/overlay/aboutaddons.js b/addon/chrome/content/preferences/overlay/aboutaddons.js index 1a24638c..41c0586e 100644 --- a/addon/chrome/content/preferences/overlay/aboutaddons.js +++ b/addon/chrome/content/preferences/overlay/aboutaddons.js @@ -4,12 +4,23 @@ const ID = "{dc572301-7619-498c-a57d-39143191b318}"; -// update gViewController.commands.cmd_showItemPreferences to open Tabmix -// options in dialog window -function updateShowItemPreferences() { +function updateAddonCard() { const htmlBrowser = window.docShell.chromeEventHandler; const tabmixItem = htmlBrowser.contentDocument .querySelector(`addon-card[addon-id="${ID}"]`); + + // hide compatibility error message + const messageBar = tabmixItem?.querySelector(".addon-card-message"); + if (messageBar) { + const supportedVersion = Services.vc.compare(Services.appinfo.platformVersion, "115.0") >= 0; + const incompatibleMessage = messageBar?.getAttribute("data-l10n-id")?.includes("incompatible"); + if (incompatibleMessage && supportedVersion) { + messageBar.remove(); + } + } + + // update gViewController.commands.cmd_showItemPreferences to open Tabmix + // options in dialog window. const panelItem = tabmixItem?.querySelector(`panel-item[action="preferences"]`); if (panelItem) { const optionsButton = panelItem.button; @@ -31,7 +42,7 @@ function updateShowItemPreferences() { window.addEventListener("load", () => { try { - updateShowItemPreferences(); + updateAddonCard(); } catch (ex) { console.error(ex); } @@ -49,7 +60,7 @@ window.addEventListener("load", () => { // @ts-expect-error - it is ok, querySelector exist if (isAddonList && (node.querySelector(`addon-card[addon-id="${ID}"]`) || node.getAttribute('addon-id') == ID)) { try { - updateShowItemPreferences(); + updateAddonCard(); break; } catch (ex) { console.error(ex); diff --git a/addon/chrome/content/tab/tab.js b/addon/chrome/content/tab/tab.js index f6185c7a..6e6693dc 100644 --- a/addon/chrome/content/tab/tab.js +++ b/addon/chrome/content/tab/tab.js @@ -2439,16 +2439,13 @@ window.gTMPprefObserver = { Services.prefs.setIntPref("toolkit.scrollbox.clickToScroll.scrollDelay", val); } // 2012-03-21 - var _loadOnNewTab = true, _replaceLastTabWith = true; if (Tabmix.prefs.prefHasUserValue("loadOnNewTab")) { let val = getPrefByType("extensions.tabmix.loadOnNewTab", 4, "IntPref"); Tabmix.prefs.setIntPref("loadOnNewTab.type", val); - _loadOnNewTab = false; } if (Tabmix.prefs.prefHasUserValue("replaceLastTabWith")) { let val = getPrefByType("extensions.tabmix.replaceLastTabWith", 4, "IntPref"); Tabmix.prefs.setIntPref("replaceLastTabWith.type", val); - _replaceLastTabWith = false; } // Changing our preference to use New Tab Page as default starting from Firefox 12 /** @type {TabmixprefObserverNS._setNewTabUrl} */ @@ -2610,16 +2607,6 @@ window.gTMPprefObserver = { /** @type {TabmixprefObserverNS._getVersion} */ let getVersion = function _getVersion(currentVersion, shouldAutoUpdate) { let oldVersion = TabmixSvc.prefs.get("extensions.tabmix.version", ""); - - // @ts-expect-error - let vCompare = (a, b) => Services.vc.compare(a, b) <= 0; - if (oldVersion) { - // 2013-08-18 - if (vCompare(oldVersion, "0.4.1.1pre.130817a") && - Services.prefs.prefHasUserValue("browser.tabs.loadDivertedInBackground")) - Tabmix.prefs.setBoolPref("loadExternalInBackground", true); - } - let showNewVersionTab; if (currentVersion != oldVersion) { // reset current preference in case it is not a string @@ -2644,13 +2631,9 @@ window.gTMPprefObserver = { if (showNewVersionTab) { // open Tabmix page in a new tab window.setTimeout(() => { - let defaultChanged = ""; - let showComment = oldVersion ? Services.vc.compare(oldVersion, "0.4.0.2pre.120330a") <= 0 : false; - if (showComment && (_loadOnNewTab || _replaceLastTabWith)) - defaultChanged = "&newtabpage"; let b = Tabmix.getTopWin().gBrowser; b.selectedTab = b.addTrustedTab("https://onemen.github.io/tabmixplus-docs/version_update?version=" + - currentVersion + defaultChanged); + currentVersion); b.selectedTab.loadOnStartup = true; }, 1000); // noting more to do at the moment diff --git a/addon/chrome/skin/app_version/all/preferences-proton.css b/addon/chrome/skin/app_version/all/preferences-proton.css index 153865e5..5c2aba0b 100644 --- a/addon/chrome/skin/app_version/all/preferences-proton.css +++ b/addon/chrome/skin/app_version/all/preferences-proton.css @@ -16,6 +16,22 @@ --combined-element-outline: 1px solid var(--in-content-focus-outline-color); } +/* for Zen browser */ +@media not (prefers-contrast) { + :root:not([lwtheme]) { + --color-accent-primary: light-dark(rgb(0, 97, 224), rgb(0, 221, 255)) !important; + --in-content-button-background: color-mix(in srgb, currentColor 7%, transparent) !important; + --in-content-button-background-hover: color-mix(in srgb, currentColor 14%, transparent) !important; + --in-content-button-background-active: color-mix(in srgb, currentColor 21%, transparent) !important; + --in-content-primary-button-text-color: rgb(251,251,254) !important; + --in-content-primary-button-text-color-hover: var(--in-content-primary-button-text-color) !important; + --in-content-primary-button-text-color-active: var(--in-content-primary-button-text-color) !important; + --in-content-primary-button-background: #0061e0 !important; + --in-content-primary-button-background-hover: #0250bb !important; + --in-content-primary-button-background-active: #053e94 !important; + } +} + .paneSelector > radio { border-top-right-radius: 4px; border-top-left-radius: 4px; diff --git a/addon/modules/BrowserVersion.jsm b/addon/modules/BrowserVersion.jsm index 43447209..67b34b94 100644 --- a/addon/modules/BrowserVersion.jsm +++ b/addon/modules/BrowserVersion.jsm @@ -16,6 +16,10 @@ ChromeUtils.defineLazyGetter(lazy, "isFloorp", () => { return Services.appinfo.name == "Floorp"; }); +ChromeUtils.defineLazyGetter(lazy, "isZen", () => { + return Services.appinfo.name == "Zen"; +}); + const _versions = {}; function isVersion(aVersionNo, updateChannel) { let firefox, waterfox, floorp, prefix = ""; @@ -56,12 +60,11 @@ function isVersion(aVersionNo, updateChannel) { if (typeof _versions[prefix + aVersionNo] == "boolean") return _versions[prefix + aVersionNo]; - let v = Services.appinfo.version; + let v = isLibrewolf || lazy.isZen ? Services.appinfo.platformVersion : Services.appinfo.version; if (lazy.isWaterfox && waterfox || lazy.isFloorp && floorp) { return (_versions[prefix + aVersionNo] = Services.vc.compare(v, aVersionNo) >= 0); } - const suffix = isLibrewolf ? `.${v.split('.')[1] ?? "0-1"}` : ".0a1"; - return (_versions[aVersionNo] = Services.vc.compare(v, aVersionNo / 10 + suffix) >= 0); + return (_versions[aVersionNo] = Services.vc.compare(v, aVersionNo / 10 + ".0a1") >= 0); } diff --git a/addon/modules/ChromeUtils.jsm b/addon/modules/ChromeUtils.jsm index 9bcd579f..7900733f 100644 --- a/addon/modules/ChromeUtils.jsm +++ b/addon/modules/ChromeUtils.jsm @@ -2,6 +2,11 @@ const EXPORTED_SYMBOLS = ["TabmixChromeUtils"]; +const localLazy = {}; + +ChromeUtils.defineModuleGetter(localLazy, "isVersion", + "chrome://tabmix-resource/content/BrowserVersion.jsm"); + /** * Note: If you rename this identifier, also update getModulesMap function in * eslint-plugin-tabmix use-mjs-modules.js. @@ -14,14 +19,6 @@ const modulesMap = { "resource:///modules/OpenInTabsUtils.jsm": [1160, "resource:///modules/OpenInTabsUtils.sys.mjs"], }; -const _versions = {}; -function isVersion(aVersionNo) { - if (typeof _versions[aVersionNo] == "boolean") return _versions[aVersionNo]; - - let v = Services.appinfo.version; - return (_versions[aVersionNo] = Services.vc.compare(v, aVersionNo / 10 + ".0a1") >= 0); -} - var TabmixChromeUtils = { get XPCOMUtils() { delete this.XPCOMUtils; @@ -33,7 +30,7 @@ var TabmixChromeUtils = { return module; } const [varsion, modulePath] = modulesMap[module] ?? []; - if (varsion && isVersion(varsion)) { + if (varsion && localLazy.isVersion(varsion)) { return modulePath; } return null; diff --git a/addon/modules/bootstrap/Overlays.jsm b/addon/modules/bootstrap/Overlays.jsm index 79fbfcb4..32b4063a 100644 --- a/addon/modules/bootstrap/Overlays.jsm +++ b/addon/modules/bootstrap/Overlays.jsm @@ -14,9 +14,8 @@ ChromeUtils.defineESModuleGetters(lazy, { setTimeout: "resource://gre/modules/Timer.sys.mjs", }); -function isVersion(versionNo) { - return Services.vc.compare(Services.appinfo.version, versionNo / 10 + ".0a1") >= 0; -} +ChromeUtils.defineModuleGetter(lazy, "isVersion", + "chrome://tabmix-resource/content/BrowserVersion.jsm"); /** * The overlays class, providing support for loading overlays like they used to work. This class @@ -262,7 +261,7 @@ class Overlays { */ _update(url, doc) { if (url === "chrome://tabmixplus/content/tabmix.xhtml") { - if (!isVersion(1160)) { + if (!lazy.isVersion(1160)) { const menu = doc.getElementById("tm-content-undoCloseTab"); menu.setAttribute("key", "key_undoCloseTab"); } diff --git a/addon/modules/bootstrap/ScriptsLoader.jsm b/addon/modules/bootstrap/ScriptsLoader.jsm index d3a4c0a9..510286d0 100644 --- a/addon/modules/bootstrap/ScriptsLoader.jsm +++ b/addon/modules/bootstrap/ScriptsLoader.jsm @@ -17,21 +17,15 @@ ChromeUtils.defineESModuleGetters(lazy, { }); TabmixChromeUtils.defineLazyModuleGetters(lazy, { - // + isVersion: "chrome://tabmix-resource/content/BrowserVersion.jsm", Overlays: "chrome://tabmix-resource/content/bootstrap/Overlays.jsm", }); -function isVersion(versionNo) { - return Services.vc.compare(Services.appinfo.version, versionNo / 10 + ".0a1") >= 0; -} - -const isVersion119 = isVersion(1190); - /** * stylesheets and scripts for navigator:browser */ const CSS_URLS = [ - isVersion119 ? "chrome://tabmixplus/content/overlay/browser.css" : "chrome://tabmixplus/content/overlay/browser_before_119.css", + lazy.isVersion(1190) ? "chrome://tabmixplus/content/overlay/browser.css" : "chrome://tabmixplus/content/overlay/browser_before_119.css", "chrome://tabmixplus/content/overlay/multirow.css", "chrome://tabmixplus/skin/general.css", "chrome://tabmixplus/skin/tab.css", diff --git a/config/zen_updates.json b/config/zen_updates.json new file mode 100644 index 00000000..f515c926 --- /dev/null +++ b/config/zen_updates.json @@ -0,0 +1,15 @@ +{ + "addons": { + "{dc572301-7619-498c-a57d-39143191b318}": { + "updates": [ + { + "version": "1.26.0", + "update_link": "https://bitbucket.org/onemen/tabmixplus-for-firefox/downloads/tab_mix_plus-1.26.0a.xpi", + "browser_specific_settings": { + "gecko": {"strict_min_version": "1.0"} + } + } + ] + } + } +} diff --git a/types/bootstrap.d.ts b/types/bootstrap.d.ts index 27095cc7..105e9201 100644 --- a/types/bootstrap.d.ts +++ b/types/bootstrap.d.ts @@ -43,7 +43,13 @@ interface Addon { setEnabled(value: boolean): Promise; uninstall(): Promise; __AddonInternal__: { + matchingTargetApplication: { + id: string; + minVersion: string; + maxVersion: string; + }; signedState?: number; + updateURL: string; }; }