diff --git a/addon/chrome/content/minit/minit.js b/addon/chrome/content/minit/minit.js index a2722193..92c15866 100644 --- a/addon/chrome/content/minit/minit.js +++ b/addon/chrome/content/minit/minit.js @@ -63,6 +63,17 @@ var TMP_tabDNDObserver = { }); } + function tabmixHandleMoveString() { + const baseTest = 'this.getAttribute("orient") === "horizontal" && TabmixTabbar.widthFitTitle'; + if (Tabmix.isVersion(1300)) { + return `!this.verticalMode && ${baseTest}`; + } + if (Tabmix.isVersion({fp: "128.0.0"})) { + return `!verticalTabbarEnabled() && ${baseTest}`; + } + return baseTest; + } + // Determine what tab we're dragging over. // * In tabmix tabs can have different width // * Point of reference is the start of the dragged tab/tabs when @@ -71,8 +82,8 @@ var TMP_tabDNDObserver = { // the middle of a background tab, the dragged tab would take that // tab's position when dropped. const _animateTabMove = Tabmix.changeCode(tabBar, "gBrowser.tabContainer._animateTabMove")._replace( - 'let draggedTab', - `let tabmixHandleMove = this.getAttribute("orient") === "horizontal" && TabmixTabbar.widthFitTitle; + /(?:const|let) draggedTab/, + `let tabmixHandleMove = ${tabmixHandleMoveString()}; $&` )._replace( 'this.selectedItem = draggedTab;', @@ -85,7 +96,7 @@ var TMP_tabDNDObserver = { )._replace( `if (${Tabmix.isVersion(1300) ? "screen" : "screenX"} > ${Tabmix.isVersion(1330) ? "point" : "tabCenter"}) {`, `let midWidth = tabs[mid].getBoundingClientRect().width; - if (!this.verticalMode && tabmixHandleMove && referenceTabWidth > midWidth) { + if (tabmixHandleMove && referenceTabWidth > midWidth) { _screenX += midWidth / 2; if (_screenX > tabCenter + referenceTabWidth / 2) { high = mid - 1; @@ -140,22 +151,28 @@ var TMP_tabDNDObserver = { "this.#rtlMode", "this._rtlMode", {check: Tabmix.isVersion(1310), flags: "g"} ).toCode(); } else { + // helper function to get floorp strings for width in vertical mode + /** @param {string} vertical @param {string} horizontal */ + const getWidthString = (vertical, horizontal) => + (Tabmix.isVersion({fp: "128.0.0"}) ? + `(verticalTabbarEnabled() ? ${vertical} : ${horizontal})` : + horizontal); _animateTabMove._replace( - 'let shiftWidth = tabWidth * movingTabs.length;', - `let shiftWidth = Tabmix.getMovingTabsWidth(movingTabs); + /(?:const|let) shiftWidth = tabWidth \* movingTabs\.length;/, + `let shiftWidth = tabmixHandleMove ? Tabmix.getMovingTabsWidth(movingTabs) : tabWidth * movingTabs.length; draggedTab._dragData.shiftWidth = shiftWidth; let rightTabWidth = movingTabs[movingTabs.length - 1].getBoundingClientRect().width; let leftTabWidth = movingTabs[0].getBoundingClientRect().width; let referenceTabWidth = ltrMove ? rightTabWidth : leftTabWidth;` )._replace( '(rightMovingTabScreenX + tabWidth)', - `(rightMovingTabScreenX + rightTabWidth)`, + `(rightMovingTabScreenX + ${getWidthString("tabWidth", "rightTabWidth")})`, )._replace( - /let leftTabCenter =.*;/, - `let leftTabCenter = leftMovingTabScreenX + translateX + leftTabWidth / 2;` + /(?:const|let) leftTabCenter =.*;/, + `let leftTabCenter = leftMovingTabScreenX + translateX + ${getWidthString("tabWidth / 2", "leftTabWidth / 2")};` )._replace( - /let rightTabCenter =.*;/, - `let rightTabCenter = rightMovingTabScreenX + translateX + rightTabWidth / 2;` + /(?:const|let) rightTabCenter =.*;/, + `let rightTabCenter = rightMovingTabScreenX + translateX + ${getWidthString("tabWidth / 2", "rightTabWidth / 2")};` ).toCode(); } @@ -172,12 +189,12 @@ var TMP_tabDNDObserver = { 'var newMargin;', 'var newMargin, newMarginY = 0;' )._replace( - /let newIndex = this\._getDropIndex\(event.*\);/, + /(?:const|let) newIndex = this\._getDropIndex\(event.*\);/, 'let {newIndex, addWidth} = this._getDropIndex(event, {dragover: true, children: this.allTabs});' )._replace( - /let tabRect = children[^;]*;/g, + /(?:const|let) tabRect = children[^;]*;/g, `$& - newMarginY = TMP_tabDNDObserver.getDropIndicatorMarginY(ind, tabRect, rect);` + newMarginY = TMP_tabDNDObserver.getDropIndicatorMarginY(ind, tabRect, rect);`, )._replace( 'newMargin = rect.right - tabRect.right', '$& + (addWidth ? tabRect.width : 0)' @@ -206,8 +223,8 @@ var TMP_tabDNDObserver = { } $&` )._replace( - 'let newTab = gBrowser.duplicateTab(tab);', - 'let newTab = Tabmix.duplicateTab(tab);' + 'newTab = gBrowser.duplicateTab(tab);', + 'newTab = Tabmix.duplicateTab(tab);' )._replace( '} else if (draggedTab && draggedTab.container == this) {', `gBrowser.ensureTabIsVisible(draggedTabCopy); @@ -235,7 +252,7 @@ var TMP_tabDNDObserver = { } $&`.replace(/_newTranslateX/g, Tabmix.isVersion(1300) && !Tabmix.isVersion(1320) ? "newTranslate" : "newTranslateX"), )._replace( - 'let urls = links.map(link => link.url);', + /urls = links.map\(\(?link\)? => link.url\);/, `$& if (event.target.id === "tabmix-scrollbox") { if (event.originalTarget.id === "scrollbutton-up") newIndex = 0; diff --git a/addon/chrome/content/minit/tablib.js b/addon/chrome/content/minit/tablib.js index 4b74416b..0ad68f33 100644 --- a/addon/chrome/content/minit/tablib.js +++ b/addon/chrome/content/minit/tablib.js @@ -379,7 +379,12 @@ Tabmix.tablib = { let $LF = '\n '; const doPosition = Tabmix.isVersion(1300) ? "absPositionHorizontalTabs" : "doPosition"; + const floorpVerticalTabbar = Tabmix.isVersion({fp: "128.0.0"}) ? " && !verticalTabbarEnabled()" : ""; Tabmix.changeCode(tabBar, "gBrowser.tabContainer._positionPinnedTabs")._replace( + 'const doPosition =', + 'let doPosition =', + {check: Tabmix.isVersion({fp: "128.0.0"})} + )._replace( 'let layoutData = this._pinnedTabsLayoutCache;', 'if (typeof this.arrowScrollbox.resetFirstTabInRow == "function")\ this.arrowScrollbox.resetFirstTabInRow();\ @@ -388,13 +393,13 @@ Tabmix.tablib = { 'scrollStartOffset:', '$& TabmixTabbar.scrollButtonsMode != TabmixTabbar.SCROLL_BUTTONS_LEFT_RIGHT ? 0 :' )._replace( - `if (${doPosition})`, - `if (${doPosition} && TabmixTabbar.isMultiRow && + `if (${doPosition}${floorpVerticalTabbar})`, + `if (${doPosition}${floorpVerticalTabbar} && TabmixTabbar.isMultiRow && Tabmix.prefs.getBoolPref("pinnedTabScroll")) { ${doPosition} = false; this.toggleAttribute("positionpinnedtabs", false); } - if (${doPosition} && TabmixTabbar.isMultiRow) {` + $LF + + if (${doPosition}${floorpVerticalTabbar} && TabmixTabbar.isMultiRow) {` + $LF + (Tabmix.isVersion(1190) ? ' this.toggleAttribute("positionpinnedtabs", true)' : ' this.setAttribute("positionpinnedtabs", "true");') + $LF + ' let layoutData = this._pinnedTabsLayoutCache;' + $LF + diff --git a/addon/chrome/content/overlay/autoReload.xhtml b/addon/chrome/content/overlay/autoReload.xhtml index d12a6bdb..8b0cdcbf 100644 --- a/addon/chrome/content/overlay/autoReload.xhtml +++ b/addon/chrome/content/overlay/autoReload.xhtml @@ -49,7 +49,7 @@
-
diff --git a/addon/chrome/content/overlay/multirow.css b/addon/chrome/content/overlay/multirow.css index 3ae76742..bcb784f8 100644 --- a/addon/chrome/content/overlay/multirow.css +++ b/addon/chrome/content/overlay/multirow.css @@ -10,7 +10,7 @@ :root { --tab_min_width_mlt: 100px; --tab_max_width_mlt: 200px; - --tab-min-height_mlt: calc(var(--tab-min-height) + 2 * (var(--proton-tab-block-margin, 0px) + var(--tab-block-margin, 0px))); + --tab-min-height_mlt: calc(var(--tabmix-tab-min-height) + 2 * var(--tab-block-margin, 0px)) !important; --tabmix-scrollbutton-padding: calc(var(--toolbarbutton-inner-padding) + var(--toolbarbutton-outer-padding)); } diff --git a/addon/chrome/content/preferences/appearance.js b/addon/chrome/content/preferences/appearance.js index 879775a7..a0f837bd 100644 --- a/addon/chrome/content/preferences/appearance.js +++ b/addon/chrome/content/preferences/appearance.js @@ -8,9 +8,10 @@ var gAppearancePane = { var browserWindow = Tabmix.getTopWin(); // disable options for position the tabbar and scroll mode if TreeStyleTab extension installed if (browserWindow.Tabmix.tabsUtils.isVerticalTabBar) { + const floorpVerticalTabbar = Tabmix.isVersion({fp: "128.0.0"}); const description = document.getElementById("treeStyleTab.msg"); Tabmix.setItem(description, "hidden", null); - if (browserWindow.gBrowser.tabContainer.verticalMode) { + if (browserWindow.gBrowser.tabContainer.verticalMode || floorpVerticalTabbar) { description.innerHTML = "These preferences are not in use for vertical tabs."; description.style.width = "25em"; } @@ -23,7 +24,7 @@ var gAppearancePane = { Tabmix.setItem("scrollDelay", "disabled", true); Tabmix.setItem("smoothScroll", "disabled", true); - if (Tabmix.isVersion(1330)) { + if (Tabmix.isVersion(1330) || floorpVerticalTabbar) { const hideTabbar = $("hideTabbar"); Tabmix.setItem(hideTabbar, "disabled", true); Tabmix.setItem(hideTabbar.previousElementSibling, "disabled", true); diff --git a/addon/chrome/content/tab/tab.js b/addon/chrome/content/tab/tab.js index 6ad5a21e..1367f913 100644 --- a/addon/chrome/content/tab/tab.js +++ b/addon/chrome/content/tab/tab.js @@ -322,7 +322,6 @@ Tabmix.tabsUtils = { _inUpdateVerticalTabStrip: false, _keepLastTab: false, _show_newtabbutton: "aftertabs", - _tabmixPositionalTabs: {}, checkNewtabButtonVisibility: false, closeButtonsEnabled: false, initialized: false, @@ -403,14 +402,8 @@ Tabmix.tabsUtils = { this.tabBar.mCloseButtons = Tabmix.prefs.getIntPref("tabs.closeButtons"); this._keepLastTab = Tabmix.prefs.getBoolPref("keepLastTab"); this.closeButtonsEnabled = Tabmix.prefs.getBoolPref("tabs.closeButtons.enable"); - this._tabmixPositionalTabs = { - beforeSelectedTab: null, - afterSelectedTab: null, - beforeHoveredTab: null, - afterHoveredTab: null - }; - Tabmix.afterTabsButtonsWidth = [35]; + Tabmix.getAfterTabsButtonsWidth(); Tabmix.tabsNewtabButton = document.getElementById("tabs-newtab-button"); this._show_newtabbutton = "aftertabs"; @@ -463,7 +456,6 @@ Tabmix.tabsUtils = { if (!this.initialized) return; TMP_eventListener.toggleEventListener(this.tabBar, this.events, false, this); - this._tabmixPositionalTabs = {}; }, handleEvent(aEvent) { @@ -621,6 +613,11 @@ Tabmix.tabsUtils = { /** @param {number} width */ const setNewMinWidth = width => { if (width !== currentMinWidth) { + // since we prevent tab animation whe we change min/max width we need to remove closing tabs + // to avoid bug 608589 + for (let tab of gBrowser._removingTabs) { + gBrowser._endRemoveTab(tab); + } this.tabBar.setAttribute("no-animation", ""); gTMPprefObserver.dynamicRules.width.style.setProperty( "min-width", @@ -672,13 +669,13 @@ Tabmix.tabsUtils = { if (this._widthCache.minWidth !== newMinWidth) { this._widthCache.minWidth = newMinWidth; this._widthCache.maxWidth = newMinWidth; - this._widthCache[pinnedTabCount] = newMinWidth; + this._widthCache[0] = newMinWidth; } if (isFirstRowWithPinnedTabs && firstNonPinnedTab) { const stripWidthWithoutPinned = tabstripWidth - (firstNonPinnedTab.getBoundingClientRect().x - tsboX); const testNewMinWidth = calcMinWidth(stripWidthWithoutPinned, tabsButtonWidth, newMinWidth); - if (testNewMinWidth > newMinWidth) { + if (testNewMinWidth < newMinWidth) { const widthForeNonPinnedTabs = calcMinWidth(stripWidthWithoutPinned, tabsButtonWidth); this._widthCache[pinnedTabCount] = widthForeNonPinnedTabs; this._widthCache.maxWidth = Math.max(this._widthCache.maxWidth, widthForeNonPinnedTabs); @@ -699,13 +696,6 @@ Tabmix.tabsUtils = { return; } - // TabmixTabbar.widthFitTitle is false when mTabMinWidth === mTabMaxWidth - if (this.checkNewtabButtonVisibility && !TabmixTabbar.widthFitTitle) { - this.updateMinWidth(); - this.disAllowNewtabbutton = false; - return; - } - if (!this.checkNewtabButtonVisibility) { this.showNewTabButtonOnSide(this.overflow, "right-side"); return; @@ -713,8 +703,16 @@ Tabmix.tabsUtils = { // when Private-tab enabled/disabled we need to reset // tabsNewtabButton and afterTabsButtonsWidth - if (!Tabmix.tabsNewtabButton) + if (!Tabmix.tabsNewtabButton || !Tabmix.afterTabsButtonsWidthReady) { Tabmix.getAfterTabsButtonsWidth(); + } + + // TabmixTabbar.widthFitTitle is false when mTabMinWidth === mTabMaxWidth + if (this.checkNewtabButtonVisibility && !TabmixTabbar.widthFitTitle) { + this.updateMinWidth(); + this.disAllowNewtabbutton = false; + return; + } const lastTab = Tabmix.visibleTabs.last; const tsboRect = this.tabBar.arrowScrollbox.scrollbox.getBoundingClientRect(); @@ -1007,7 +1005,7 @@ Tabmix.tabsUtils = { gBrowser.tabContainer.getAttribute("orient") !== "vertical" && TabmixTabbar.visibleRows > 1; const margin = reduceMargin ? "1px" : ""; - document.documentElement.style.setProperty(this.protonValues.name, margin); + document.documentElement.style.setProperty(this.protonValues.name, margin, "important"); }, }; @@ -1879,6 +1877,14 @@ window.gTMPprefObserver = { ); } + this.insertRule(`:root { --tabmix-tab-min-height: var(--tab-min-height);}`, "tabMinHeight"); + if (Tabmix.isVersion({fp: "128.0.0"})) { + window.gFloorpObservePreference("floorp.browser.tabs.tabMinHeight", () => { + const height = Services.prefs.getIntPref("floorp.browser.tabs.tabMinHeight", 30); + this.dynamicRules.tabMinHeight.style.setProperty("--tabmix-tab-min-height", height + "px"); + }); + } + this.dynamicProtonRules(); this.toolbarbuttonTopMargin(); }, @@ -1896,6 +1902,14 @@ window.gTMPprefObserver = { }`); } + const padding = Tabmix.isVersion({fp: "128.0.0"}) ? { + block: "3.5px", + inline: "3.5px", + } : { + block: "calc(var(--toolbarbutton-inner-padding) - 3px)", + inline: "calc(var(--toolbarbutton-inner-padding) - 6px)", + }; + this.insertRule( `#tabmix-scrollbox::part(scrollbutton-up), #tabmix-scrollbox::part(scrollbutton-down) { @@ -1904,14 +1918,14 @@ window.gTMPprefObserver = { border: 4px solid transparent; border-radius: calc(var(--tab-border-radius) + 4px); margin: ${buttonsMarginBlock}; - padding: calc(var(--toolbarbutton-inner-padding) - 3px) calc(var(--toolbarbutton-inner-padding) - 6px); + padding: ${padding.block} ${padding.inline}; }` ); this.insertRule( `#tabmix-scrollbox[tabmix-flowing=multibar]::part(scrollbutton-up), #tabmix-scrollbox[tabmix-flowing=multibar]::part(scrollbutton-down) { - padding-inline: calc(var(--toolbarbutton-inner-padding) - 5px); + padding: ${padding.block}; }` ); diff --git a/addon/chrome/content/tabmix.js b/addon/chrome/content/tabmix.js index 97e9ca75..bf4fb06b 100644 --- a/addon/chrome/content/tabmix.js +++ b/addon/chrome/content/tabmix.js @@ -73,13 +73,15 @@ Tabmix.sessionInitialized = function() { } }; -Tabmix.getAfterTabsButtonsWidth = function TMP_getAfterTabsButtonsWidth() { - if (!this.afterTabsButtonsWidth) { - this.afterTabsButtonsWidth = []; - } +/** @this {typeof TabmixNS} */ // @ts-ignore +Tabmix.getAfterTabsButtonsWidth = function() { + this.afterTabsButtonsWidthReady = false; + this.afterTabsButtonsWidth = this.isVersion({fp: "128.0.0"}) ? [40] : [35]; + /** @type {number[]} */ + const buttonWidths = []; if (gBrowser.tabContainer.getAttribute("orient") == "horizontal") { const {toolbar, tabBar, collapsed, tabBarCollapsed, toolbarCollapsed} = - Tabmix.tabsUtils.getCollapsedState; + this.tabsUtils.getCollapsedState; let stripIsHidden = TabmixTabbar.hideMode !== 0 && collapsed; if (stripIsHidden) { toolbar.collapsed = false; @@ -88,7 +90,9 @@ Tabmix.getAfterTabsButtonsWidth = function TMP_getAfterTabsButtonsWidth() { // save tabsNewtabButton width this.tabsNewtabButton = document.getElementById("tabs-newtab-button"); this.tabsNewtabButton.setAttribute("force-display", true); - let openNewTabRect = Tabmix.getBoundsWithoutFlushing(this.tabsNewtabButton); + // don't use getBoundsWithoutFlushing here, it will get width zero if the button is hidden + // since we get here after the browser was painted we can use getBoundingClientRect + let openNewTabRect = this.tabsNewtabButton.getBoundingClientRect(); let style = window.getComputedStyle(this.tabsNewtabButton); let marginStart = style?.getPropertyValue("margin-left") ?? "0px"; // it doesn't work when marginEnd add to buttonWidth @@ -96,7 +100,7 @@ Tabmix.getAfterTabsButtonsWidth = function TMP_getAfterTabsButtonsWidth() { // let buttonWidth = openNewTabRect.width + parseFloat(marginStart) + parseFloat(marginEnd); let buttonWidth = openNewTabRect.width + parseFloat(marginStart); if (buttonWidth > 0) { - this.afterTabsButtonsWidth.push(buttonWidth); + buttonWidths.push(buttonWidth); } // when privateTab extension installed add its new tab button width @@ -104,8 +108,8 @@ Tabmix.getAfterTabsButtonsWidth = function TMP_getAfterTabsButtonsWidth() { // the right button let openNewPrivateTab = document.getElementById("privateTab-afterTabs-openNewPrivateTab"); if (openNewPrivateTab) { - let openNewPrivateTabRect = Tabmix.getBoundsWithoutFlushing(openNewPrivateTab); - this.afterTabsButtonsWidth.push(openNewPrivateTabRect.width); + let openNewPrivateTabRect = openNewPrivateTab.getBoundingClientRect(); + buttonWidths.push(openNewPrivateTabRect.width); if (openNewPrivateTabRect.right > openNewTabRect.right) this.tabsNewtabButton = openNewPrivateTab; } @@ -114,6 +118,11 @@ Tabmix.getAfterTabsButtonsWidth = function TMP_getAfterTabsButtonsWidth() { toolbar.collapsed = toolbarCollapsed; tabBar.collapsed = tabBarCollapsed; } + if (buttonWidths.length) { + this.tabsUtils._widthCache = {minWidth: 0, maxWidth: 0}; + this.afterTabsButtonsWidth = buttonWidths; + this.afterTabsButtonsWidthReady = true; + } } }; @@ -162,8 +171,6 @@ Tabmix.afterDelayedStartup = function() { TMP_extensionsCompatibility.onDelayedStartup(); - setTimeout(() => Tabmix.getAfterTabsButtonsWidth(), 100); - gTMPprefObserver.setMenuIcons(); TabmixTabbar.updateSettings(true); diff --git a/addon/modules/AutoReload.jsm b/addon/modules/AutoReload.jsm index e3815a91..c3ce01b4 100644 --- a/addon/modules/AutoReload.jsm +++ b/addon/modules/AutoReload.jsm @@ -426,7 +426,7 @@ function doReloadTab(window, browser, tab, data) { // Also reset DOS mitigations for the basic auth prompt on reload. delete browser.authPromptAbuseCounter; - if (TabmixSvc.version(1290) || TabmixSvc.version(1283, "esr")) { + if (TabmixSvc.version(1290) || TabmixSvc.version(1283, "esr") || TabmixSvc.version({fp: "128.0.0"})) { if (window.document.hasValidTransientUserGestureActivation) { loadFlags |= Ci.nsIWebNavigation.LOAD_FLAGS_USER_ACTIVATION; } diff --git a/addon/modules/Floorp.jsm b/addon/modules/Floorp.jsm new file mode 100644 index 00000000..75b1de87 --- /dev/null +++ b/addon/modules/Floorp.jsm @@ -0,0 +1,94 @@ +"use strict"; + +const EXPORTED_SYMBOLS = ["FloorpPrefsObserver"]; + +const lazy = {}; + +ChromeUtils.defineLazyGetter(lazy, "prefs", () => { + const {Preferences} = ChromeUtils.importESModule("resource://gre/modules/Preferences.sys.mjs"); + return new Preferences(""); +}); + +const PREFS = [ + "extensions.tabmix.tabBarMode", + "floorp.tabbar.style", + "userChrome.padding.tabbar_height", +]; + +const FloorpPrefsObserver = { + init() { + if (this._initialized) { + return; + } + this._initialized = true; + + PREFS.forEach(pref => this.onPrefChange(pref)); + PREFS.forEach(pref => Services.prefs.addObserver(pref, this)); + Services.obs.addObserver(this, "quit-application"); + }, + + observe(subject, topic, data) { + switch (topic) { + case "nsPref:changed": + this.onPrefChange(data); + break; + case "quit-application": + this.onQuitApplication(); + break; + } + }, + + onPrefChange(data) { + const prefValue = lazy.prefs.get(data); + + // when in vertical mode exit + if (Services.prefs.getIntPref("floorp.tabbar.style") === 2 && data !== "floorp.tabbar.style") { + return; + } + + switch (data) { + case "extensions.tabmix.tabBarMode": { + const pref = "userChrome.padding.tabbar_height"; + const backupPref = `${pref}._backup`; + if (prefValue === 2) { + Services.prefs.setBoolPref(backupPref, Services.prefs.getBoolPref(pref)); + Services.prefs.setBoolPref(pref, false); + Services.prefs.setIntPref("floorp.tabbar.style", 0); + } else if (Services.prefs.prefHasUserValue(backupPref)) { + Services.prefs.setBoolPref(pref, Services.prefs.getBoolPref(backupPref)); + Services.prefs.clearUserPref(backupPref); + } + break; + } + case "floorp.tabbar.style": { + const pref = "extensions.tabmix.tabBarMode"; + const backupPref = `${pref}._backup`; + const tabmixInMultiRow = Services.prefs.getIntPref(pref) === 2; + if (prefValue === 0 && Services.prefs.prefHasUserValue(backupPref)) { + Services.prefs.setIntPref(pref, Services.prefs.getIntPref(backupPref)); + Services.prefs.clearUserPref(backupPref); + } else if (prefValue === 1 && tabmixInMultiRow) { + Services.prefs.setIntPref(data, 0); + } else if (prefValue === 2 && tabmixInMultiRow) { + Services.prefs.setIntPref(backupPref, 2); + Services.prefs.setIntPref(pref, 1); + } + break; + } + case "userChrome.padding.tabbar_height": { + if ( + prefValue && + Services.prefs.getIntPref("extensions.tabmix.tabBarMode") === 2 + ) { + Services.prefs.setBoolPref(data, false); + } + break; + } + } + }, + + onQuitApplication() { + PREFS.forEach(pref => Services.prefs.removeObserver(pref, this)); + Services.obs.removeObserver(this, "quit-application"); + }, +}; diff --git a/addon/modules/TabmixSvc.jsm b/addon/modules/TabmixSvc.jsm index 4ad469e3..ebf9589d 100644 --- a/addon/modules/TabmixSvc.jsm +++ b/addon/modules/TabmixSvc.jsm @@ -15,12 +15,10 @@ ChromeUtils.defineModuleGetter(lazy, "SyncedTabs", ChromeUtils.defineModuleGetter(lazy, "isVersion", "chrome://tabmix-resource/content/BrowserVersion.jsm"); -// place holder for load default preferences function -// eslint-disable-next-line no-unused-vars -var pref; -let TabmixSvc; +ChromeUtils.defineModuleGetter(lazy, "FloorpPrefsObserver", + "chrome://tabmix-resource/content/Floorp.jsm"); -TabmixSvc = { +const TabmixSvc = { aboutBlank: "about:blank", aboutNewtab: "about:#".replace("#", "newtab"), newtabUrl: "browser.#.url".replace("#", "newtab"), @@ -180,6 +178,10 @@ TabmixSvc = { Services.prefs.lockPref("extensions.tabmix.tabBarPosition"); } + if (lazy.isVersion({fp: "128.0.0"})) { + lazy.FloorpPrefsObserver.init(); + } + aWindow.gTMPprefObserver.setLink_openPrefs(); }, diff --git a/types/addon.d.ts b/types/addon.d.ts index 0efccbb7..c80fd29c 100644 --- a/types/addon.d.ts +++ b/types/addon.d.ts @@ -156,6 +156,9 @@ interface Window { init: () => void; }; + /** Floorp */ + gFloorpObservePreference: (prefName: string, callback: () => void) => void; + /** @deprecated - removed from firefox on version 126 */ BrowserOpenTab: (options: {event: MouseEvent; url: string}) => void; } @@ -659,11 +662,6 @@ declare namespace TabmixTabbarNS { } declare namespace PrivateFunctionsNS { - namespace TabmixTabbar { - function _updateAtt(tab: Tab | null | undefined, type: keyof typeof TabsUtils._tabmixPositionalTabs, attrib: string, visible?: boolean): void; - function _getAttVal(val: boolean | null, hoverAttr?: boolean): "special" | boolean | null; - } - namespace UndocloseTabButtonObserver { function _removeTab(b: MockedGeckoTypes.TabBrowser, aTab: Tab): void; } diff --git a/types/extraTabmixUtils.d.ts b/types/extraTabmixUtils.d.ts index 30af3165..08bb03b3 100644 --- a/types/extraTabmixUtils.d.ts +++ b/types/extraTabmixUtils.d.ts @@ -66,6 +66,7 @@ declare namespace TabmixNS { let _lastTabOpenedTime: number; let _deferredInitialized: DeferredPromise; let afterTabsButtonsWidth: number[]; + let afterTabsButtonsWidthReady: boolean; let initialization: typeof TabmixInitialization; let isFirstWindow: boolean; let selectedTab: Tab | null; @@ -74,7 +75,7 @@ declare namespace TabmixNS { let userTypedValue: string; function afterDelayedStartup(): void; function beforeDelayedStartup(): void; - function getAfterTabsButtonsWidth(this: typeof TabmixNS): void; + function getAfterTabsButtonsWidth(): void; function sessionInitialized(): void; function startup(): void; // lazygetters for modules (jsm files) @@ -434,12 +435,6 @@ declare namespace TabsUtils { let closeButtonsEnabled: boolean; let initialized: boolean; - let _tabmixPositionalTabs: { - beforeSelectedTab?: Tab | null | undefined; - afterSelectedTab?: Tab | null | undefined; - beforeHoveredTab?: Tab | null | undefined; - afterHoveredTab?: Tab | null | undefined; - }; const tabBar: MockedGeckoTypes.TabContainer; const scrollClientRect: DOMRect; function getInnerbox(): HTMLElement; diff --git a/types/general.d.ts b/types/general.d.ts index 00bd2fc6..e3d1748b 100644 --- a/types/general.d.ts +++ b/types/general.d.ts @@ -304,7 +304,7 @@ declare namespace MockedGeckoTypes { visibleTab: BrowserTab; }; _blurTab: (tab: BrowserTab) => void; - readonly pinnedTabCount: number; + _endRemoveTab: (tab: BrowserTab) => void; /** @deprecated replaced with pinnedTabCount in Firefox version 133 */ readonly _numPinnedTabs: number; _lastRelatedTabMap: WeakMap; @@ -334,6 +334,7 @@ declare namespace MockedGeckoTypes { lastMultiSelectedTab: BrowserTab; moveTabTo: (tab: BrowserTab, index: number, keepRelatedTabs?: boolean) => void; pinTab: (tab: BrowserTab) => void; + readonly pinnedTabCount: number; preloadedBrowser?: ChromeBrowser; reloadTab: (tab: BrowserTab) => void; /// modified by Tab Mix Plus diff --git a/types/tabmix.d.ts b/types/tabmix.d.ts index e60d0b1b..6c0ea000 100644 --- a/types/tabmix.d.ts +++ b/types/tabmix.d.ts @@ -2,6 +2,8 @@ // Tabmix modules +type BrowserVersion = (aVersionNo: number | {ff?: number; wf?: string; fp?: string; updateChannel?: string}, updateChannel?: string) => boolean; + interface ChromeManifest { parse: (filename?: string, base?: string) => Promise; } @@ -25,7 +27,7 @@ interface CSSRule { readonly style: CSSStyleDeclaration; } -type RulesTYpes = "max-rows" | "visibleRows" | "width"; +type RulesTYpes = "max-rows" | "visibleRows" | "width" | "tabMinHeight"; interface gTMPprefObserver { _marginStart: string; _singleWindowUI_initialized: boolean; @@ -158,7 +160,7 @@ declare namespace TabmixNS { const prefs: nsIPrefBranchXpcom; const defaultPrefs: nsIPrefBranchXpcom; - function isVersion(aVersionNo: number | {ff?: number; wf?: string; bs?: string; updateChannel?: string}, updateChannel?: string): boolean; + const isVersion: BrowserVersion; function isAltKey(event: MouseEvent): boolean; function debug(aMessage: string, aShowCaller?: boolean): void; function showItem(aItemOrId: ItemOrId, aShow?: boolean): void; @@ -281,6 +283,7 @@ declare namespace TabmixModules { getSMString: (key: string) => string; i10IdMap: I10Map; isCyberfox: boolean; + isFloorp: boolean; isFixedGoogleUrl: (url: string) => boolean; isLinux: boolean; isMac: boolean; @@ -315,7 +318,7 @@ declare namespace TabmixModules { progressMeter: TabStyle & {text: false}; }; URILoadingHelperChanged: boolean; - version: (aVersionNo: number | {ff?: number; wf?: string; bs?: string; updateChannel?: string}, updateChannel?: string) => boolean; + version: BrowserVersion; whereToOpenLinkChanged: boolean; windowStartup: { _initialized: boolean;