From 1bb5a07822673eda5fea855b22ef7d10d29fd194 Mon Sep 17 00:00:00 2001 From: Alex Kontos Date: Wed, 7 Jun 2023 11:21:47 +0100 Subject: [PATCH] refactor: waterfox ui customization --- waterfox/browser/components/WaterfoxGlue.jsm | 2 +- .../uicustomizations/UICustomizations.jsm | 230 -------------- .../uicustomizations/UICustomizations.sys.mjs | 296 ++++++++++++++++++ .../components/uicustomizations/moz.build | 2 +- .../test/browser/browser_uicustomizations.js | 6 +- .../uicustomizations/test/browser/head.js | 6 +- 6 files changed, 303 insertions(+), 239 deletions(-) delete mode 100644 waterfox/browser/components/uicustomizations/UICustomizations.jsm create mode 100644 waterfox/browser/components/uicustomizations/UICustomizations.sys.mjs diff --git a/waterfox/browser/components/WaterfoxGlue.jsm b/waterfox/browser/components/WaterfoxGlue.jsm index b7be572bca78..751002847419 100644 --- a/waterfox/browser/components/WaterfoxGlue.jsm +++ b/waterfox/browser/components/WaterfoxGlue.jsm @@ -23,7 +23,7 @@ XPCOMUtils.defineLazyModuleGetters(lazy, { PrivateTab: "resource:///modules/PrivateTab.sys.mjs", StatusBar: "resource:///modules/StatusBar.sys.mjs", TabFeatures: "resource:///modules/TabFeatures.sys.mjs", - UICustomizations: "resource:///modules/UICustomizations.jsm", + UICustomizations: "resource:///modules/UICustomizations.sys.mjs", }); XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]); diff --git a/waterfox/browser/components/uicustomizations/UICustomizations.jsm b/waterfox/browser/components/uicustomizations/UICustomizations.jsm deleted file mode 100644 index af4c237ddc82..000000000000 --- a/waterfox/browser/components/uicustomizations/UICustomizations.jsm +++ /dev/null @@ -1,230 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* global */ - -const EXPORTED_SYMBOLS = ["UICustomizations"]; - -const { PrefUtils } = ChromeUtils.import("resource:///modules/PrefUtils.jsm"); - -const { BrowserUtils } = ChromeUtils.import( - "resource:///modules/BrowserUtils.jsm" -); - -const UICustomizations = { - PREF_TOOLBARPOS: "browser.tabs.toolbarposition", - PREF_BOOKMARKPOS: "browser.bookmarks.toolbarposition", - PREF_DEFAULTTHEME: "browser.lepton.enabled", - PREF_ACTIVETHEME: "extensions.activeThemeID", - DEFAULT_THEMEID: "lepton@waterfox.net", - - init(window) { - this.styleButtonBox(window.document); - this.styleMenuBar(window.document, window); - this.moveTabBar(window); - this.moveBookmarksBar(window); - this.initListeners(window); - this.initPrefObservers(); - - // Make sure pref is aligned with active theme ID initially - let activeTheme = PrefUtils.get(this.PREF_ACTIVETHEME); - if ( - activeTheme != this.DEFAULT_THEMEID && - PrefUtils.get(this.PREF_DEFAULTTHEME) - ) { - this.setDefaultThemePref(activeTheme); - } - }, - - initPrefObservers() { - // Set Tab toolbar position - this.toolbarPositionListener = PrefUtils.addObserver( - this.PREF_TOOLBARPOS, - value => { - UICustomizations.executeInAllWindows(window => { - const { document } = window; - UICustomizations.moveTabBar(window, value); - UICustomizations.styleMenuBar(document, window); - }); - } - ); - // Set Bookmark bar position - this.bookmarkBarPositionListener = PrefUtils.addObserver( - this.PREF_BOOKMARKPOS, - value => { - UICustomizations.executeInAllWindows(window => { - UICustomizations.moveBookmarksBar(window, value); - }); - } - ); - - // If activeThemeID changes update default theme pref -> could expand to do more than just default or not - PrefUtils.addObserver(this.PREF_ACTIVETHEME, value => { - this.setDefaultThemePref(value); - }); - }, - - setDefaultThemePref(prefValue) { - PrefUtils.set( - this.PREF_DEFAULTTHEME, - prefValue === this.DEFAULT_THEMEID // Currently, only lepton displays icons - ); - }, - - initListeners(aWindow) { - // Hide tabs toolbar buttonbox if menubar displayed - if (aWindow.document) { - let menuBar = aWindow.document.getElementById("toolbar-menubar"); - var observer = new aWindow.MutationObserver(mutations => { - mutations.forEach(mutation => { - if ( - mutation.type === "attributes" && - mutation.attributeName == "autohide" - ) { - UICustomizations.styleButtonBox(aWindow.document); - UICustomizations.styleMenuBar(aWindow.document, aWindow); - } - }); - }); - - observer.observe(menuBar, { - attributes: true, //configure it to listen to attribute changes - }); - } - // Ensure menu bar/ nav bar not cut off when maximized in Windows - aWindow.addEventListener( - "sizemodechange", - function updateTitleBarStyling() { - UICustomizations.styleMenuBar(aWindow.document, aWindow); - } - ); - }, - - styleButtonBox(doc) { - let menuBar = doc.getElementById("toolbar-menubar"); - let buttonBox = doc.querySelector( - "#TabsToolbar .titlebar-buttonbox-container" - ); - menuBar.getAttribute("autohide") == "false" - ? (buttonBox.style.display = "none") - : (buttonBox.style.display = "-moz-box"); - }, - - styleMenuBar(doc, win) { - let menuBar = doc.getElementById("toolbar-menubar"); - let titleBar = doc.getElementById("titlebar"); - // Appearance should be none if windowed and menu-bar not displaying, - // should be none with padding-top: 6px if fullscreen and menu-bar not displaying, - // else should be "" - let fullscreen = win.windowState == win.STATE_MAXIMIZED; - if ( - PrefUtils.get(this.PREF_TOOLBARPOS) != "topabove" && - menuBar.getAttribute("autohide") == "true" - ) { - if (fullscreen) { - titleBar.setAttribute("style", "appearance: none; padding-top: 6px;"); - } else { - titleBar.setAttribute("style", "appearance: none;"); - } - } else { - titleBar.setAttribute("style", ""); - } - }, - - moveTabBar(aWindow, aValue) { - let bottomBookmarksBar = aWindow.document.querySelector( - "#browser-bottombox #PersonalToolbar" - ); - let bottomBox = aWindow.document.querySelector("#browser-bottombox"); - let tabsToolbar = aWindow.document.querySelector("#TabsToolbar"); - let titlebar = aWindow.document.querySelector("#titlebar"); - - if (!aValue) { - aValue = PrefUtils.get(this.PREF_TOOLBARPOS); - } - switch (aValue) { - case "topabove": - titlebar.insertAdjacentElement("beforeend", tabsToolbar); - aWindow.gBrowser.setTabTitle( - aWindow.document.querySelector(".tabbrowser-tab[first-visible-tab]") - ); - break; - case "topbelow": - aWindow.document - .querySelector("#navigator-toolbox") - .appendChild(tabsToolbar); - aWindow.gBrowser.setTabTitle( - aWindow.document.querySelector(".tabbrowser-tab[first-visible-tab]") - ); - break; - case "bottomabove": - // Above status bar - bottomBox.collapsed = false; - if (bottomBookmarksBar) { - bottomBookmarksBar.insertAdjacentElement("afterend", tabsToolbar); - } else { - bottomBox.insertAdjacentElement("afterbegin", tabsToolbar); - } - aWindow.gBrowser.setTabTitle( - aWindow.document.querySelector(".tabbrowser-tab[first-visible-tab]") - ); - break; - case "bottombelow": - // Below status bar - bottomBox.collapsed = false; - bottomBox.insertAdjacentElement("beforeend", tabsToolbar); - aWindow.gBrowser.setTabTitle( - aWindow.document.querySelector(".tabbrowser-tab[first-visible-tab]") - ); - break; - } - - // Set title on top bar when title bar is disabled and tab bar position is different than default - const topBar = aWindow.document.querySelector("#toolbar-menubar-pagetitle"); - const activeTab = aWindow.document.querySelector('tab[selected="true"]'); - if (topBar && activeTab) { - topBar.textContent = activeTab.getAttribute("label"); - } - }, - - moveBookmarksBar(aWindow, aValue) { - let bottomTabs = aWindow.document.querySelector( - "#browser-bottombox #TabsToolbar" - ); - let bookmarksBar = aWindow.document.querySelector("#PersonalToolbar"); - - if (!aValue) { - aValue = PrefUtils.get(this.PREF_BOOKMARKPOS, "top"); - } - // Don't move if already in correct position - if ( - (aValue == "top" && - bookmarksBar.parentElement.id == "navigator-toolbox") || - (aValue == "bottom" && - bookmarksBar.parentElement.id == "browser-bottombox") - ) { - return; - } - - switch (aValue) { - case "top": - aWindow.document - .querySelector("#nav-bar") - .insertAdjacentElement("afterend", bookmarksBar); - break; - case "bottom": - if (bottomTabs) { - bottomTabs.insertAdjacentElement("beforebegin", bookmarksBar); - } else { - aWindow.document - .querySelector("#browser-bottombox") - .insertAdjacentElement("afterbegin", bookmarksBar); - } - break; - } - }, -}; - -// Inherited props -UICustomizations.executeInAllWindows = BrowserUtils.executeInAllWindows; diff --git a/waterfox/browser/components/uicustomizations/UICustomizations.sys.mjs b/waterfox/browser/components/uicustomizations/UICustomizations.sys.mjs new file mode 100644 index 000000000000..dceed7c48149 --- /dev/null +++ b/waterfox/browser/components/uicustomizations/UICustomizations.sys.mjs @@ -0,0 +1,296 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import { BrowserUtils } from "resource:///modules/BrowserUtils.sys.mjs"; +import { PrefUtils } from "resource:///modules/PrefUtils.sys.mjs"; + +export const UICustomizations = { + PREF_TOOLBARPOS: "browser.tabs.toolbarposition", + PREF_BOOKMARKPOS: "browser.bookmarks.toolbarposition", + + init(window) { + this.styleButtonBox(window.document); + this.styleMenuBar(window.document, window); + this.moveTabBar(window); + this.moveBookmarksBar(window); + this.initListeners(window); + this.initPrefObservers(); + }, + + initPrefObservers() { + // Set Tab toolbar position + this.toolbarPositionListener = PrefUtils.addObserver( + this.PREF_TOOLBARPOS, + (value) => { + UICustomizations.executeInAllWindows((window) => { + const { document } = window; + UICustomizations.moveTabBar(window, value); + UICustomizations.styleMenuBar(document, window); + }); + } + ); + // Set Bookmark bar position + this.bookmarkBarPositionListener = PrefUtils.addObserver( + this.PREF_BOOKMARKPOS, + (value) => { + UICustomizations.executeInAllWindows((window) => { + UICustomizations.moveBookmarksBar(window, value); + }); + } + ); + }, + + initListeners(aWindow) { + // Hide tabs toolbar buttonbox if menubar displayed + if (aWindow.document) { + const menuBar = aWindow.document.getElementById("toolbar-menubar"); + const observer = new aWindow.MutationObserver((mutations) => { + for (const mutation of mutations) { + if ( + mutation.type === "attributes" && + mutation.attributeName === "autohide" + ) { + UICustomizations.styleButtonBox(aWindow.document); + UICustomizations.styleMenuBar(aWindow.document, aWindow); + } + } + }); + + observer.observe(menuBar, { + attributes: true, //configure it to listen to attribute changes + }); + } + // Ensure menu bar/ nav bar not cut off when maximized in Windows + aWindow.addEventListener( + "sizemodechange", + function updateTitleBarStyling() { + UICustomizations.styleMenuBar(aWindow.document, aWindow); + } + ); + }, + + styleButtonBox(doc) { + const menuBar = doc.getElementById("toolbar-menubar"); + const buttonBox = doc.querySelector( + "#TabsToolbar .titlebar-buttonbox-container" + ); + + // If menuBar is not found, we cannot get its "autohide" attribute. + if (!menuBar) { + console.warn( + "UICustomizations.sys.mjs: #toolbar-menubar element not found in styleButtonBox. Cannot determine button box visibility." + ); + return; + } + + // If buttonBox is not found, we cannot style it. + if (!buttonBox) { + console.warn( + "UICustomizations.sys.mjs: #TabsToolbar .titlebar-buttonbox-container element not found in styleButtonBox. Cannot style button box." + ); + return; + } + + if (menuBar.getAttribute("autohide") === "false") { + buttonBox.style.display = "none"; + } else { + buttonBox.style.display = "-moz-box"; + } + }, + + styleMenuBar(doc, win) { + const menuBar = doc.getElementById("toolbar-menubar"); + // If menuBar (toolbar-menubar) doesn't exist, we can't proceed with its styling. + if (!menuBar) { + console.warn( + "UICustomizations.sys.mjs: toolbar-menubar element not found. Cannot apply custom menubar styling." + ); + return; + } + + // The original code used a 'titleBar' element which has been removed in recent changes. + // We will now apply the conditional styling directly to the 'menuBar' element itself. + + const fullscreen = win.windowState === win.STATE_MAXIMIZED; + if ( + PrefUtils.get(this.PREF_TOOLBARPOS) !== "topabove" && + menuBar.getAttribute("autohide") === "true" + ) { + if (fullscreen) { + menuBar.setAttribute("style", "appearance: none; padding-top: 6px;"); + } else { + menuBar.setAttribute("style", "appearance: none;"); + } + } else { + // If conditions are not met, clear any inline style from menuBar. + menuBar.setAttribute("style", ""); + } + }, + + moveTabBar(aWindow, aValue) { + const doc = aWindow.document; // Use a shorthand for document + + // Get elements used in various cases, check them early if crucial. + const tabsToolbar = doc.querySelector("#TabsToolbar"); + if (!tabsToolbar) { + console.warn( + "UICustomizations.sys.mjs: #TabsToolbar not found. Cannot move tab bar." + ); + return; + } + + const navigatorToolbox = doc.querySelector("#navigator-toolbox"); + const bottomBox = doc.querySelector("#browser-bottombox"); + // bottomBookmarksBar is queried specifically in the 'bottomabove' case. + + let effectiveValue = aValue; + if (!effectiveValue) { + effectiveValue = PrefUtils.get(this.PREF_TOOLBARPOS); + } + + switch (effectiveValue) { + case "topabove": { + // Original logic used 'titlebar'. #titlebar is removed. + // #titlebar used to contain #toolbar-menubar then #TabsToolbar. + // So, "beforeend" of #titlebar meant #TabsToolbar came after #toolbar-menubar. + const menuBar = doc.querySelector("#toolbar-menubar"); + // Ensure menuBar exists and is a child of navigatorToolbox for sensible placement. + if (menuBar && menuBar.parentElement === navigatorToolbox) { + menuBar.insertAdjacentElement("afterend", tabsToolbar); + } else if (navigatorToolbox) { + // Fallback: if menubar isn't suitable/found, place tabs at the start of navigator-toolbox. + navigatorToolbox.insertAdjacentElement("afterbegin", tabsToolbar); + } else { + console.warn( + "UICustomizations.sys.mjs: Could not place TabsToolbar 'topabove'. #navigator-toolbox or #toolbar-menubar not suitable." + ); + } + break; + } + case "topbelow": + if (navigatorToolbox) { + navigatorToolbox.appendChild(tabsToolbar); + } else { + console.warn( + "UICustomizations.sys.mjs: #navigator-toolbox not found. Cannot move tab bar to 'topbelow'." + ); + } + break; + case "bottomabove": { + // Above status bar + if (!bottomBox) { + console.warn( + "UICustomizations.sys.mjs: #browser-bottombox not found for 'bottomabove'." + ); + break; + } + bottomBox.collapsed = false; + const bottomBookmarksBar = doc.querySelector( + "#browser-bottombox #PersonalToolbar" + ); + if (bottomBookmarksBar) { + bottomBookmarksBar.insertAdjacentElement("afterend", tabsToolbar); + } else { + bottomBox.insertAdjacentElement("afterbegin", tabsToolbar); + } + break; + } + case "bottombelow": + // Below status bar + if (!bottomBox) { + console.warn( + "UICustomizations.sys.mjs: #browser-bottombox not found for 'bottombelow'." + ); + break; + } + bottomBox.collapsed = false; + bottomBox.insertAdjacentElement("beforeend", tabsToolbar); + break; + } + + // This call was common to all cases, so move it after the switch. + // Also, ensure the first tab exists before trying to set its title. + const firstTab = doc.querySelector(".tabbrowser-tab:first-child"); + if (firstTab && aWindow.gBrowser) { + aWindow.gBrowser.setTabTitle(firstTab); + } + + // Set title on top bar when title bar is disabled and tab bar position is different than default + const topBar = doc.querySelector("#toolbar-menubar-pagetitle"); + const activeTab = doc.querySelector('tab[selected="true"]'); + if (topBar && activeTab) { + topBar.textContent = activeTab.getAttribute("label"); + } + }, + + moveBookmarksBar(aWindow, aValue) { + const doc = aWindow.document; + const bottomTabs = doc.querySelector("#browser-bottombox #TabsToolbar"); + const bookmarksBar = doc.querySelector("#PersonalToolbar"); + + let effectiveValue = aValue; + if (!effectiveValue) { + effectiveValue = PrefUtils.get(this.PREF_BOOKMARKPOS, "top"); + } + // Don't move if already in correct position + // Note: The original code has a potential null pointer issue here if bookmarksBar is null + // and bookmarksBar.parentElement is accessed. This change only addresses the + // "parameter reassignment" diagnostic and does not alter that specific behavior. + if ( + bookmarksBar?.parentElement && // Added a guard for parentElement before accessing its id + ((effectiveValue === "top" && + bookmarksBar.parentElement.id === "navigator-toolbox") || + (effectiveValue === "bottom" && + bookmarksBar.parentElement.id === "browser-bottombox")) + ) { + return; + } + + switch (effectiveValue) { + case "top": { + const navBar = doc.querySelector("#nav-bar"); + if (navBar && bookmarksBar) { + navBar.insertAdjacentElement("afterend", bookmarksBar); + } else { + if (!bookmarksBar) { + console.warn( + "UICustomizations.sys.mjs: #PersonalToolbar not found. Cannot move bookmarks bar." + ); + } + // Ensure this warning is only logged if navBar is indeed the missing element, + // and not because bookmarksBar was also missing (though the above handles that). + if (!navBar && bookmarksBar) { + console.warn( + "UICustomizations.sys.mjs: #nav-bar not found. Cannot move bookmarks bar to top." + ); + } + } + break; + } + case "bottom": + if (!bookmarksBar) { + console.warn( + "UICustomizations.sys.mjs: #PersonalToolbar not found. Cannot move bookmarks bar." + ); + break; + } + if (bottomTabs) { + bottomTabs.insertAdjacentElement("beforebegin", bookmarksBar); + } else { + const bottomBox = doc.querySelector("#browser-bottombox"); + if (bottomBox) { + bottomBox.insertAdjacentElement("afterbegin", bookmarksBar); + } else { + console.warn( + "UICustomizations.sys.mjs: #browser-bottombox not found. Cannot move bookmarks bar to bottom." + ); + } + } + break; + } + }, +}; + +// Inherited props +UICustomizations.executeInAllWindows = BrowserUtils.executeInAllWindows; diff --git a/waterfox/browser/components/uicustomizations/moz.build b/waterfox/browser/components/uicustomizations/moz.build index c05999409840..db5ea8ceb3b9 100644 --- a/waterfox/browser/components/uicustomizations/moz.build +++ b/waterfox/browser/components/uicustomizations/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXTRA_JS_MODULES += [ - "UICustomizations.jsm", + "UICustomizations.sys.mjs", ] BROWSER_CHROME_MANIFESTS += [ diff --git a/waterfox/browser/components/uicustomizations/test/browser/browser_uicustomizations.js b/waterfox/browser/components/uicustomizations/test/browser/browser_uicustomizations.js index 26643d11112a..57890a4d5e2b 100644 --- a/waterfox/browser/components/uicustomizations/test/browser/browser_uicustomizations.js +++ b/waterfox/browser/components/uicustomizations/test/browser/browser_uicustomizations.js @@ -1,7 +1,7 @@ add_task(async function testMoveTabBar() { // Test default (topabove) - let el = document.querySelector("#TabsToolbar"); - let bottomBox = document.querySelector("#browser-bottombox"); + const el = document.querySelector("#TabsToolbar"); + const bottomBox = document.querySelector("#browser-bottombox"); is(el.parentElement.id, "titlebar", "Tab toolbar is below menu bar"); // Test topbelow Services.prefs.setCharPref(TABBAR_POSITION_PREF, "topbelow"); @@ -28,7 +28,7 @@ add_task(async function testMoveTabBar() { add_task(async function testMoveBookmarksBar() { // Test default (top) - let el = document.querySelector("#PersonalToolbar"); + const el = document.querySelector("#PersonalToolbar"); is( el.parentElement.id, "navigator-toolbox", diff --git a/waterfox/browser/components/uicustomizations/test/browser/head.js b/waterfox/browser/components/uicustomizations/test/browser/head.js index 4e68ab27570f..4e5c332fdf55 100644 --- a/waterfox/browser/components/uicustomizations/test/browser/head.js +++ b/waterfox/browser/components/uicustomizations/test/browser/head.js @@ -1,4 +1,2 @@ -"use strict"; - -const TABBAR_POSITION_PREF = "browser.tabs.toolbarposition"; -const BOOKMARKBAR_POSITION_PREF = "browser.bookmarks.toolbarposition"; +const _TABBAR_POSITION_PREF = "browser.tabs.toolbarposition"; +const _BOOKMARKBAR_POSITION_PREF = "browser.bookmarks.toolbarposition";