From e197d4eebd938a3a4624b745b060bc8910febe05 Mon Sep 17 00:00:00 2001 From: Vinty Date: Tue, 3 Dec 2024 19:06:42 -0500 Subject: [PATCH 1/5] Add toggle to disable new tab on double click --- src/browser/app/profile/zen-browser.js | 567 ++--- .../components/preferences/zen-settings.js | 2153 +++++++++-------- .../preferences/zenLooksAndFeel.inc.xhtml | 687 +++--- .../tabbrowser/content/tabs-js.patch | 59 +- 4 files changed, 1753 insertions(+), 1713 deletions(-) diff --git a/src/browser/app/profile/zen-browser.js b/src/browser/app/profile/zen-browser.js index 78b7c6d4a..0e9f9609a 100644 --- a/src/browser/app/profile/zen-browser.js +++ b/src/browser/app/profile/zen-browser.js @@ -1,283 +1,284 @@ -// 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/. - -#ifdef XP_UNIX - #ifndef XP_MACOSX - #define UNIX_BUT_NOT_MAC - #endif -#endif - -pref("browser.tabs.cardPreview.enabled", true); -pref("browser.tabs.hoverPreview.enabled", true); -pref("browser.tabs.cardPreview.delayMs", 100); - -#ifdef MOZ_UPDATE_CHANNEL -pref("devtools.debugger.prompt-connection", true); -#endif - -// Dont download the multilingual dictionary -pref("intl.multilingual.downloadEnabled", false); - -// Restore session on startup -pref("browser.startup.page", 3); - -// Theme -pref('toolkit.legacyUserProfileCustomizations.stylesheets', true); -pref('browser.compactmode.show', true); - -pref('browser.newtabpage.activity-stream.newtabWallpapers.enabled', true); -pref('browser.newtabpage.activity-stream.newtabWallpapers.v2.enabled', true); -pref('browser.translations.newSettingsUI.enable', true); - -pref('privacy.userContext.enabled', true); -pref('privacy.userContext.ui.enabled', true); - -pref("browser.urlbar.trimHttps", true); -pref("browser.urlbar.untrimOnUserInteraction.featureGate", true); - -// Url bar -pref('browser.urlbar.unitConversion.enabled', true); -pref('browser.urlbar.trending.featureGate', false); -pref('browser.urlbar.weather.featureGate', true); -pref('browser.urlbar.quickactions.enabled', true); -pref('browser.urlbar.clipboard.featureGate', true); - -// new tab page -pref('browser.newtabpage.activity-stream.feeds.topsites', false); -pref('browser.newtabpage.activity-stream.feeds.section.topstories', false); -pref("browser.topsites.contile.enabled", true); - -// Pdf -pref('browser.download.open_pdf_attachments_inline', true); -pref('pdfjs.enableHighlightEditor', true); -pref('pdfjs.enableHighlightFloatingButton', true); - -pref("alerts.showFavicons", true); - -pref("browser.tabs.loadBookmarksInTabs", false); -pref('browser.toolbars.bookmarks.visibility', 'never'); - -// Enable Do Not Track and GPC by default. -pref("privacy.donottrackheader.enabled", false); -pref("privacy.globalprivacycontrol.enabled", true); -// Disable more telemetry -pref("toolkit.telemetry.enabled", false); -pref("browser.ping-centre.telemetry", false); -pref("browser.attribution.enabled", false); -pref("toolkit.telemetry.pioneer-new-studies-available", false); - -pref("app.update.checkInstallTime.days", 6); - -// CUSTOM ZEN PREFS - -pref('zen.welcomeScreen.enabled', true); -pref('zen.welcomeScreen.seen', false); - -pref('zen.tabs.vertical', true); -pref('zen.tabs.vertical.right-side', false); -pref('zen.theme.accent-color', "#ffb787"); -pref('zen.theme.content-element-separation', 6); // In pixels -pref('zen.theme.pill-button', false); -pref('zen.theme.gradient', true); - -pref('zen.tabs.show-newtab-vertical', true); -pref('zen.view.show-newtab-button-border-top', true); -pref('zen.view.show-newtab-button-top', false); - -#ifdef XP_MACOSX -pref('zen.theme.border-radius', 10); // In pixels -#else -#ifdef XP_WIN -pref('zen.theme.border-radius', 6); // In pixels -#else -pref('zen.theme.border-radius', 8); // In pixels -#endif -#endif - -pref('zen.theme.color-prefs.use-workspace-colors', true); -pref('zen.theme.color-prefs.amoled', false); -pref('zen.theme.color-prefs.colorful', false); - -pref('zen.view.compact', false); -pref('zen.view.compact.hide-tabbar', true); -pref('zen.view.compact.hide-toolbar', false); -pref('zen.view.compact.toolbar-flash-popup', true); -pref('zen.view.compact.toolbar-flash-popup.duration', 800); -pref('zen.view.compact.toolbar-hide-after-hover.duration', 1000); -pref('zen.view.compact.color-toolbar', true); -pref('zen.view.compact.color-sidebar', true); - -pref('zen.glance.enabled', true); -pref('zen.glance.hold-duration', 300); // in ms - -pref('zen.glance.activation-method', 'alt'); // ctrl, alt, shift, none, hold - -pref('zen.view.sidebar-height-throttle', 200); // in ms -pref('zen.view.sidebar-expanded.max-width', 400); - -pref('zen.view.show-bottom-border', false); -pref('zen.view.use-single-toolbar', true); -pref('zen.view.sidebar-expanded', true); -pref('zen.view.sidebar-collapsed.hide-mute-button', true); - -#ifndef XP_MACOSX -pref('zen.view.hide-window-controls', true); -#endif - -pref('zen.tabs.dim-pending', true); -pref('zen.tabs.newtab-on-middle-click', true); - -pref('zen.keyboard.shortcuts.enabled', true); -pref('zen.keyboard.shortcuts.version', 0); // Empty string means default shortcuts -pref('zen.keyboard.shortcuts.disable-mainkeyset-clear', false); // for debugging - -pref('zen.themes.updated-value-observer', false); - -pref('zen.tab-unloader.enabled', true); -pref('zen.tab-unloader.timeout-minutes', 20); -pref('zen.tab-unloader.excluded-urls', "example.com,example.org"); - -pref('zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', false); -pref('zen.pinned-tab-manager.close-shortcut-behavior', 'switch'); - -// Pref to enable the new profiles (TODO: Check this out!) -//pref("browser.profiles.enabled", true); - -// Zen Sidebar -pref('zen.sidebar.data', "{\"data\":\n {\"p1\":{\n \"url\":\"https://www.wikipedia.org/\"\n },\n\"p2\":{\n \"url\":\"https://m.twitter.com/\",\n\"ua\": true\n },\n\"p3\": {\n \"url\": \"https://www.youtube.com/\",\n\"ua\": true\n},\n\"p4\": {\n \"url\": \"https://translate.google.com/\",\n\"ua\": true\n},\n\"p5\": {\n \"url\": \"https://todoist.com/\",\n\"ua\": true\n}},\n\"index\":[\"p1\",\"p2\",\"p3\",\"p4\",\"p5\"]}"); -pref('zen.sidebar.enabled', true); -pref('zen.sidebar.close-on-blur', true); -pref('zen.sidebar.max-webpanels', 8); - -// Zen Split View -pref('zen.splitView.working', false); -pref('zen.splitView.min-resize-width', 7); -pref('zen.splitView.change-on-hover', false); -pref('zen.splitView.rearrange-hover-size', 24); - -// Zen Workspaces -pref('zen.workspaces.enabled', true); -pref('zen.workspaces.hide-deactivated-workspaces', false); -pref('zen.workspaces.hide-default-container-indicator', true); -pref('zen.workspaces.individual-pinned-tabs', true); -pref('zen.workspaces.show-icon-strip', true); -pref('zen.workspaces.force-container-workspace', false); -pref('zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', true); -pref('zen.workspaces.show-workspace-indicator', true); -pref('zen.workspaces.swipe-actions', true); -pref('zen.workspaces.icons', '["⌚","⌛","⏪","⏫","⏬","⏰","⏳","⚽","⚾","⛄","⛅","⛎","⛔","⛪","⛲","⛳","⛵","⛺","⛽","✅","✊","✋","✨","❌","❎","❓","⭐","⭕","🀄","🃏","🆎","🆑","🆒","🆓","🆔","🆕","🆖","🆗","🆘","🆙","🆚","🈁","🈚","🈯","🈲","🈳","🈴","🈵","🈶","🈸","🈹","🈺","🉐","🉑","🌀","🌁","🌂","🌃","🌄","🌅","🌆","🌇","🌈","🌉","🌊","🌋","🌌","🌍","🌎","🌏","🌐","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚","🌛","🌜","🌝","🌞","🌟","🌠","🌭","🌮","🌯","🌰","🌱","🌲","🌳","🌴","🌵","🌷","🌸","🌹","🌺","🌻","🌼","🌽","🌾","🌿","🍀","🍁","🍂","🍃","🍄","🍅","🍆","🍇","🍈","🍉","🍊","🍋","🍌","🍍","🍎","🍏","🍐","🍑","🍒","🍓","🍔","🍕","🍖","🍗","🍘","🍙","🍚","🍛","🍜","🍝","🍞","🍟","🍠","🍡","🍢","🍣","🍤","🍥","🍦","🍧","🍨","🍩","🍪","🍫","🍬","🍭","🍮","🍯","🍰","🍱","🍲","🍳","🍴","🍵","🍶","🍷","🍸","🍹","🍺","🍻","🍼","🍾","🍿","🎀","🎁","🎂","🎃","🎄","🎅","🎆","🎇","🎈","🎉","🎊","🎋","🎌","🎍","🎎","🎏","🎐","🎑","🎒","🎓","🎠","🎡","🎢","🎣","🎤","🎥","🎦","🎧","🎨","🎩","🎪","🎫","🎬","🎭","🎮","🎯","🎰","🎱","🎲","🎳","🎴","🎵","🎶","🎷","🎸","🎹","🎺","🎻","🎼","🎽","🎾","🎿","🏀","🏁","🏂","🏃","🏄","🏅","🏆","🏇","🏈","🏉","🏊","🏏","🏐","🏑","🏒","🏓","🏠","🏡","🏢","🏣","🏤","🏥","🏦","🏧","🏨","🏩","🏪","🏫","🏬","🏭","🏮","🏯","🏰","🏴","🏸","🏹","🏺","🏻","🏼","🏽","🏾","🏿","🐀","🐁","🐂","🐃","🐄","🐅","🐆","🐇","🐈","🐉","🐊","🐋","🐌","🐍","🐎","🐏","🐐","🐑","🐒","🐓","🐔","🐕","🐖","🐗","🐘","🐙","🐚","🐛","🐜","🐝","🐞","🐟","🐠","🐡","🐢","🐣","🐤","🐥","🐦","🐧","🐨","🐩","🐪","🐫","🐬","🐭","🐮","🐯","🐰","🐱","🐲","🐳","🐴","🐵","🐶","🐷","🐸","🐹","🐺","🐻","🐼","🐽","🐾","👀","👂","👃","👄","👅","👆","👇","👈","👉","👊","👋","👌","👍","👎","👏","👐","👑","👒","👓","👔","👕","👖","👗","👘","👙","👚","👛","👜","👝","👞","👟","👠","👡","👢","👣","👤","👥","👦","👧","👨","👩","👪","👫","👬","👭","👮","👯","👰","👱","👲","👳","👴","👵","👶","👷","👸","👹","👺","👻","👼","👽","👾","👿","💀","💁","💂","💃","💄","💅","💆","💇","💈","💉","💊","💋","💌","💍","💎","💏","💐","💑","💒","💓","💔","💕","💖","💗","💘","💙","💚","💛","💜","💝","💞","💟","💠","💡","💢","💣","💤","💥","💦","💧","💨","💩","💪","💫","💬","💭","💮","💯","💰","💱","💲","💳","💴","💵","💶","💷","💸","💹","💺","💻","💼","💽","💾","💿","📀","📁","📂","📃","📄","📅","📆","📇","📈","📉","📊","📋","📌","📍","📎","📏","📐","📑","📒","📓","📔","📕","📖","📗","📘","📙","📚","📛","📜","📝","📞","📟","📠","📡","📢","📣","📤","📥","📦","📧","📨","📩","📪","📫","📬","📭","📮","📯","📰","📱","📲","📳","📴","📵","📶","📷","📸","📹","📺","📻","📼","📿","🔀","🔁","🔂","🔃","🔄","🔅","🔆","🔇","🔈","🔉","🔊","🔋","🔌","🔍","🔎","🔏","🔐","🔑","🔒","🔓","🔔","🔕","🔖","🔗","🔘","🔙","🔚","🔛","🔜","🔝","🔞","🔟","🔠","🔡","🔢","🔣","🔤","🔥","🔦","🔧","🔨","🔩","🔪","🔫","🔬","🔭","🔮","🔯","🔰","🔱","🔲","🔳","🔴","🔵","🔶","🔷","🔸","🔹","🔺","🔻","🔼","🔽","🕋","🕌","🕍","🕎","🕐","🕑","🕒","🕓","🕔","🕕","🕖","🕗","🕘","🕙","🕚","🕛","🕜","🕝","🕞","🕟","🕠","🕡","🕢","🕣","🕤","🕥","🕦","🕧","🖕","🖖","🗻","🗼","🗽","🗾","🗿","😀","😁","😂","😃","😄","😅","😆","😇","😈","😉","😊","😋","😌","😍","😎","😏","😐","😑","😒","😓","😔","😕","😖","😗","😘","😙","😚","😛","😜","😝","😞","😟","😠","😡","😢","😣","😤","😥","😦","😧","😨","😩","😪","😫","😬","😭","😮","😯","😰","😱","😲","😳","😴","😵","😶","😷","😸","😹","😺","😻","😼","😽","😾","😿","🙀","🙁","🙂","🙃","🙄","🙅","🙆","🙇","🙈","🙉","🙊","🙋","🙌","🙍","🙎","🙏","🚀","🚁","🚂","🚃","🚄","🚅","🚆","🚇","🚈","🚉","🚊","🚋","🚌","🚍","🚎","🚏","🚐","🚑","🚒","🚓","🚔","🚕","🚖","🚗","🚘","🚙","🚚","🚛","🚜","🚝","🚞","🚟","🚠","🚡","🚢","🚣","🚤","🚥","🚦","🚧","🚨","🚩","🚪","🚫","🚬","🚭","🚮","🚯","🚰","🚱","🚲","🚳","🚴","🚵","🚶","🚷","🚸","🚹","🚺","🚻","🚼","🚽","🚾","🚿","🛀","🛁","🛂","🛃","🛄","🛅","🛌","🛐","🛫","🛬","🤐","🤑","🤒","🤓","🤔","🤕","🤖","🤗","🤘","🦀","🦁","🦂","🦃","🦄","🧀","🇦🇨","🇦🇩","🇦🇪","🇦🇫","🇦🇬","🇦🇮","🇦🇱","🇦🇲","🇦🇴","🇦🇶","🇦🇷","🇦🇸","🇦🇹","🇦🇺","🇦🇼","🇦🇽","🇦🇿","🇧🇦","🇧🇧","🇧🇩","🇧🇪","🇧🇫","🇧🇬","🇧🇭","🇧🇮","🇧🇯","🇧🇱","🇧🇲","🇧🇳","🇧🇴","🇧🇶","🇧🇷","🇧🇸","🇧🇹","🇧🇻","🇧🇼","🇧🇾","🇧🇿","🇨🇦","🇨🇨","🇨🇩","🇨🇫","🇨🇬","🇨🇭","🇨🇮","🇨🇰","🇨🇱","🇨🇲","🇨🇳","🇨🇴","🇨🇵","🇨🇷","🇨🇺","🇨🇻","🇨🇼","🇨🇽","🇨🇾","🇨🇿","🇩🇪","🇩🇬","🇩🇯","🇩🇰","🇩🇲","🇩🇴","🇩🇿","🇪🇦","🇪🇨","🇪🇪","🇪🇬","🇪🇭","🇪🇷","🇪🇸","🇪🇹","🇪🇺","🇫🇮","🇫🇯","🇫🇰","🇫🇲","🇫🇴","🇫🇷","🇬🇦","🇬🇧","🇬🇩","🇬🇪","🇬🇫","🇬🇬","🇬🇭","🇬🇮","🇬🇱","🇬🇲","🇬🇳","🇬🇵","🇬🇶","🇬🇷","🇬🇸","🇬🇹","🇬🇺","🇬🇼","🇬🇾","🇭🇰","🇭🇲","🇭🇳","🇭🇷","🇭🇹","🇭🇺","🇮🇨","🇮🇩","🇮🇪","🇮🇱","🇮🇲","🇮🇳","🇮🇴","🇮🇶","🇮🇷","🇮🇸","🇮🇹","🇯🇪","🇯🇲","🇯🇴","🇯🇵","🇰🇪","🇰🇬","🇰🇭","🇰🇮","🇰🇲","🇰🇳","🇰🇵","🇰🇷","🇰🇼","🇰🇾","🇰🇿","🇱🇦","🇱🇧","🇱🇨","🇱🇮","🇱🇰","🇱🇷","🇱🇸","🇱🇹","🇱🇺","🇱🇻","🇱🇾","🇲🇦","🇲🇨","🇲🇩","🇲🇪","🇲🇫","🇲🇬","🇲🇭","🇲🇰","🇲🇱","🇲🇲","🇲🇳","🇲🇴","🇲🇵","🇲🇶","🇲🇷","🇲🇸","🇲🇹","🇲🇺","🇲🇻","🇲🇼","🇲🇽","🇲🇾","🇲🇿","🇳🇦","🇳🇨","🇳🇪","🇳🇫","🇳🇬","🇳🇮","🇳🇱","🇳🇴","🇳🇵","🇳🇷","🇳🇺","🇳🇿","🇴🇲","🇵🇦","🇵🇪","🇵🇫","🇵🇬","🇵🇭","🇵🇰","🇵🇱","🇵🇲","🇵🇳","🇵🇷","🇵🇸","🇵🇹","🇵🇼","🇵🇾","🇶🇦","🇷🇪","🇷🇴","🇷🇸","🇷🇺","🇷🇼","🇸🇦","🇸🇧","🇸🇨","🇸🇩","🇸🇪","🇸🇬","🇸🇭","🇸🇮","🇸🇯","🇸🇰","🇸🇱","🇸🇲","🇸🇳","🇸🇴","🇸🇷","🇸🇸","🇸🇹","🇸🇻","🇸🇽","🇸🇾","🇸🇿","🇹🇦","🇹🇨","🇹🇩","🇹🇫","🇹🇬","🇹🇭","🇹🇯","🇹🇰","🇹🇱","🇹🇲","🇹🇳","🇹🇴","🇹🇷","🇹🇹","🇹🇻","🇹🇼","🇹🇿","🇺🇦","🇺🇬","🇺🇲","🇺🇸","🇺🇾","🇺🇿","🇻🇦","🇻🇨","🇻🇪","🇻🇬","🇻🇮","🇻🇳","🇻🇺","🇼🇫","🇼🇸","🇽🇰","🇾🇪","🇾🇹","🇿🇦","🇿🇲","🇿🇼"]'); -pref('services.sync.prefs.sync.zen.workspaces.icons', true); -pref('services.sync.engine.workspaces', false); -pref('zen.essentials.enabled', true); -pref('zen.workspaces.container-specific-essentials-enabled', false); - -// Zen Watermark -pref('zen.watermark.enabled', true, sticky); - -// Smooth scrolling -pref('apz.overscroll.enabled', true); // not DEFAULT on Linux -pref('general.smoothScroll', true); // DEFAULT - -// Privacy -pref('dom.private-attribution.submission.enabled', false); -pref('dom.security.https_only_mode', true); - -pref('media.eme.enabled', true); - -// Enable importers for other browsers -pref('browser.migrate.vivaldi.enabled', true); -pref('browser.migrate.opera-gx.enabled', true); -pref('browser.migrate.opera.enabled', true); - -// DNS -// pref('network.trr.mode', 5); - -// security: They must enable this themselves, to avoid people downloading malware -//pref('xpinstall.signatures.required', false); - -// Experimental Zen Features -// Strategy to use for bytecode cache (Thanks https://github.com/gunir) -pref('dom.script_loader.bytecode_cache.strategy', 2); -pref("dom.text_fragments.enabled", true); - -// Enable private suggestions -pref('browser.search.suggest.enabled', true); -pref('browser.search.suggest.enabled.private', true); - -pref("extensions.enabledScopes", 5); // [HIDDEN PREF] - -// Enable JXL support -pref('image.jxl.enabled', true); - -#if defined(XP_WIN) - pref("dom.ipc.processPriorityManager.backgroundUsesEcoQoS", false); -#endif - -pref('browser.sessionstore.restore_pinned_tabs_on_demand', true); -pref('browser.newtabpage.activity-stream.system.showWeather', true); - -pref("browser.toolbars.bookmarks.visibility", "never"); - -// Enable experimental settings page (Usef for Zen Labs) -pref('browser.preferences.experimental', true); - -#include better-fox.js - -// Betterfox overrides (Stay below the include directive) - -// Jang's personal speedups (Thanks to Jang for these!) - -// Prefetching: -pref("network.dns.disablePrefetch", false); -pref("network.prefetch-next", true); -pref("network.predictor.enabled", true); -pref("network.dns.disablePrefetchFromHTTPS", false); -pref("network.predictor.enable-hover-on-ssl", true); -pref("network.http.speculative-parallel-limit", 10); -pref("network.http.rcwn.enabled", false); - -// Enable Browser Toolbox, Ctrl+Shift+Alt+I for debugging and modifying UI -pref("devtools.debugger.remote-enabled", false); -pref("devtools.chrome.enabled", true); - -// Disable firefox's revamp -pref("sidebar.revamp", false, locked); -pref("sidebar.verticalTabs", false, locked); - -// Better Windows theming -pref("widget.non-native-theme.scrollbar.style", 2); -pref("widget.non-native-theme.use-theme-accent", true); - -// Expose Letterboxing https://github.com/zen-browser/desktop/issues/475 -pref("privacy.resistFingerprinting.letterboxing", false); -pref("privacy.resistFingerprinting.letterboxing.dimensions", ""); - -// Remove Inspect Accessibity Properties menu -pref("devtools.accessibility.enabled", false); - -// Enable GPU by default -//pref('gfx.webrender.all', true); -pref("gfx.canvas.accelerated", true); -pref("media.hardware-video-decoding.enabled", true); -pref("layers.gpu-process.enabled", true); - -// VAAPI/FFMPEG is Linux only -#ifdef XP_UNIX -pref('media.ffmpeg.vaapi.enabled', true); -pref('media.ffmpeg.encoder.enabled', true); -#endif - -// Fix buffering issues: Youtube, Archive bugzilla.mozilla.org/show_bug.cgi?id=1854077 -pref("network.fetchpriority.enabled", true); - -// No Proxy should be default, Use system proxy allows antivirus, virus or system proxy to MITM or slowing down Zen -pref("network.proxy.type", 0); - -// for the new layout: -pref('browser.download.autohideButton', false); - -// Enable transparent background for macos -#ifdef XP_MACOSX -pref('widget.macos.titlebar-blend-mode.behind-window', true); -#endif +// 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/. + +#ifdef XP_UNIX + #ifndef XP_MACOSX + #define UNIX_BUT_NOT_MAC + #endif +#endif + +pref("browser.tabs.cardPreview.enabled", true); +pref("browser.tabs.hoverPreview.enabled", true); +pref("browser.tabs.cardPreview.delayMs", 100); + +#ifdef MOZ_UPDATE_CHANNEL +pref("devtools.debugger.prompt-connection", true); +#endif + +// Dont download the multilingual dictionary +pref("intl.multilingual.downloadEnabled", false); + +// Restore session on startup +pref("browser.startup.page", 3); + +// Theme +pref('toolkit.legacyUserProfileCustomizations.stylesheets', true); +pref('browser.compactmode.show', true); + +pref('browser.newtabpage.activity-stream.newtabWallpapers.enabled', true); +pref('browser.newtabpage.activity-stream.newtabWallpapers.v2.enabled', true); +pref('browser.translations.newSettingsUI.enable', true); + +pref('privacy.userContext.enabled', true); +pref('privacy.userContext.ui.enabled', true); + +pref("browser.urlbar.trimHttps", true); +pref("browser.urlbar.untrimOnUserInteraction.featureGate", true); + +// Url bar +pref('browser.urlbar.unitConversion.enabled', true); +pref('browser.urlbar.trending.featureGate', false); +pref('browser.urlbar.weather.featureGate', true); +pref('browser.urlbar.quickactions.enabled', true); +pref('browser.urlbar.clipboard.featureGate', true); + +// new tab page +pref('browser.newtabpage.activity-stream.feeds.topsites', false); +pref('browser.newtabpage.activity-stream.feeds.section.topstories', false); +pref("browser.topsites.contile.enabled", true); + +// Pdf +pref('browser.download.open_pdf_attachments_inline', true); +pref('pdfjs.enableHighlightEditor', true); +pref('pdfjs.enableHighlightFloatingButton', true); + +pref("alerts.showFavicons", true); + +pref("browser.tabs.loadBookmarksInTabs", false); +pref('browser.toolbars.bookmarks.visibility', 'never'); + +// Enable Do Not Track and GPC by default. +pref("privacy.donottrackheader.enabled", false); +pref("privacy.globalprivacycontrol.enabled", true); +// Disable more telemetry +pref("toolkit.telemetry.enabled", false); +pref("browser.ping-centre.telemetry", false); +pref("browser.attribution.enabled", false); +pref("toolkit.telemetry.pioneer-new-studies-available", false); + +pref("app.update.checkInstallTime.days", 6); + +// CUSTOM ZEN PREFS + +pref('zen.welcomeScreen.enabled', true); +pref('zen.welcomeScreen.seen', false); + +pref('zen.tabs.vertical', true); +pref('zen.tabs.vertical.right-side', false); +pref('zen.theme.accent-color', "#ffb787"); +pref('zen.theme.content-element-separation', 6); // In pixels +pref('zen.theme.pill-button', false); +pref('zen.theme.gradient', true); + +pref('zen.tabs.show-newtab-vertical', true); +pref('zen.view.show-newtab-button-border-top', true); +pref('zen.view.show-newtab-button-top', false); +pref("zen.tabs.openNewTabByDblclick", true); + +#ifdef XP_MACOSX +pref('zen.theme.border-radius', 10); // In pixels +#else +#ifdef XP_WIN +pref('zen.theme.border-radius', 6); // In pixels +#else +pref('zen.theme.border-radius', 8); // In pixels +#endif +#endif + +pref('zen.theme.color-prefs.use-workspace-colors', true); +pref('zen.theme.color-prefs.amoled', false); +pref('zen.theme.color-prefs.colorful', false); + +pref('zen.view.compact', false); +pref('zen.view.compact.hide-tabbar', true); +pref('zen.view.compact.hide-toolbar', false); +pref('zen.view.compact.toolbar-flash-popup', true); +pref('zen.view.compact.toolbar-flash-popup.duration', 800); +pref('zen.view.compact.toolbar-hide-after-hover.duration', 1000); +pref('zen.view.compact.color-toolbar', true); +pref('zen.view.compact.color-sidebar', true); + +pref('zen.glance.enabled', true); +pref('zen.glance.hold-duration', 300); // in ms + +pref('zen.glance.activation-method', 'alt'); // ctrl, alt, shift, none, hold + +pref('zen.view.sidebar-height-throttle', 200); // in ms +pref('zen.view.sidebar-expanded.max-width', 400); + +pref('zen.view.show-bottom-border', false); +pref('zen.view.use-single-toolbar', true); +pref('zen.view.sidebar-expanded', true); +pref('zen.view.sidebar-collapsed.hide-mute-button', true); + +#ifndef XP_MACOSX +pref('zen.view.hide-window-controls', true); +#endif + +pref('zen.tabs.dim-pending', true); +pref('zen.tabs.newtab-on-middle-click', true); + +pref('zen.keyboard.shortcuts.enabled', true); +pref('zen.keyboard.shortcuts.version', 0); // Empty string means default shortcuts +pref('zen.keyboard.shortcuts.disable-mainkeyset-clear', false); // for debugging + +pref('zen.themes.updated-value-observer', false); + +pref('zen.tab-unloader.enabled', true); +pref('zen.tab-unloader.timeout-minutes', 20); +pref('zen.tab-unloader.excluded-urls', "example.com,example.org"); + +pref('zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', false); +pref('zen.pinned-tab-manager.close-shortcut-behavior', 'switch'); + +// Pref to enable the new profiles (TODO: Check this out!) +//pref("browser.profiles.enabled", true); + +// Zen Sidebar +pref('zen.sidebar.data', "{\"data\":\n {\"p1\":{\n \"url\":\"https://www.wikipedia.org/\"\n },\n\"p2\":{\n \"url\":\"https://m.twitter.com/\",\n\"ua\": true\n },\n\"p3\": {\n \"url\": \"https://www.youtube.com/\",\n\"ua\": true\n},\n\"p4\": {\n \"url\": \"https://translate.google.com/\",\n\"ua\": true\n},\n\"p5\": {\n \"url\": \"https://todoist.com/\",\n\"ua\": true\n}},\n\"index\":[\"p1\",\"p2\",\"p3\",\"p4\",\"p5\"]}"); +pref('zen.sidebar.enabled', true); +pref('zen.sidebar.close-on-blur', true); +pref('zen.sidebar.max-webpanels', 8); + +// Zen Split View +pref('zen.splitView.working', false); +pref('zen.splitView.min-resize-width', 7); +pref('zen.splitView.change-on-hover', false); +pref('zen.splitView.rearrange-hover-size', 24); + +// Zen Workspaces +pref('zen.workspaces.enabled', true); +pref('zen.workspaces.hide-deactivated-workspaces', false); +pref('zen.workspaces.hide-default-container-indicator', true); +pref('zen.workspaces.individual-pinned-tabs', true); +pref('zen.workspaces.show-icon-strip', true); +pref('zen.workspaces.force-container-workspace', false); +pref('zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', true); +pref('zen.workspaces.show-workspace-indicator', true); +pref('zen.workspaces.swipe-actions', true); +pref('zen.workspaces.icons', '["⌚","⌛","⏪","⏫","⏬","⏰","⏳","⚽","⚾","⛄","⛅","⛎","⛔","⛪","⛲","⛳","⛵","⛺","⛽","✅","✊","✋","✨","❌","❎","❓","⭐","⭕","🀄","🃏","🆎","🆑","🆒","🆓","🆔","🆕","🆖","🆗","🆘","🆙","🆚","🈁","🈚","🈯","🈲","🈳","🈴","🈵","🈶","🈸","🈹","🈺","🉐","🉑","🌀","🌁","🌂","🌃","🌄","🌅","🌆","🌇","🌈","🌉","🌊","🌋","🌌","🌍","🌎","🌏","🌐","🌑","🌒","🌓","🌔","🌕","🌖","🌗","🌘","🌙","🌚","🌛","🌜","🌝","🌞","🌟","🌠","🌭","🌮","🌯","🌰","🌱","🌲","🌳","🌴","🌵","🌷","🌸","🌹","🌺","🌻","🌼","🌽","🌾","🌿","🍀","🍁","🍂","🍃","🍄","🍅","🍆","🍇","🍈","🍉","🍊","🍋","🍌","🍍","🍎","🍏","🍐","🍑","🍒","🍓","🍔","🍕","🍖","🍗","🍘","🍙","🍚","🍛","🍜","🍝","🍞","🍟","🍠","🍡","🍢","🍣","🍤","🍥","🍦","🍧","🍨","🍩","🍪","🍫","🍬","🍭","🍮","🍯","🍰","🍱","🍲","🍳","🍴","🍵","🍶","🍷","🍸","🍹","🍺","🍻","🍼","🍾","🍿","🎀","🎁","🎂","🎃","🎄","🎅","🎆","🎇","🎈","🎉","🎊","🎋","🎌","🎍","🎎","🎏","🎐","🎑","🎒","🎓","🎠","🎡","🎢","🎣","🎤","🎥","🎦","🎧","🎨","🎩","🎪","🎫","🎬","🎭","🎮","🎯","🎰","🎱","🎲","🎳","🎴","🎵","🎶","🎷","🎸","🎹","🎺","🎻","🎼","🎽","🎾","🎿","🏀","🏁","🏂","🏃","🏄","🏅","🏆","🏇","🏈","🏉","🏊","🏏","🏐","🏑","🏒","🏓","🏠","🏡","🏢","🏣","🏤","🏥","🏦","🏧","🏨","🏩","🏪","🏫","🏬","🏭","🏮","🏯","🏰","🏴","🏸","🏹","🏺","🏻","🏼","🏽","🏾","🏿","🐀","🐁","🐂","🐃","🐄","🐅","🐆","🐇","🐈","🐉","🐊","🐋","🐌","🐍","🐎","🐏","🐐","🐑","🐒","🐓","🐔","🐕","🐖","🐗","🐘","🐙","🐚","🐛","🐜","🐝","🐞","🐟","🐠","🐡","🐢","🐣","🐤","🐥","🐦","🐧","🐨","🐩","🐪","🐫","🐬","🐭","🐮","🐯","🐰","🐱","🐲","🐳","🐴","🐵","🐶","🐷","🐸","🐹","🐺","🐻","🐼","🐽","🐾","👀","👂","👃","👄","👅","👆","👇","👈","👉","👊","👋","👌","👍","👎","👏","👐","👑","👒","👓","👔","👕","👖","👗","👘","👙","👚","👛","👜","👝","👞","👟","👠","👡","👢","👣","👤","👥","👦","👧","👨","👩","👪","👫","👬","👭","👮","👯","👰","👱","👲","👳","👴","👵","👶","👷","👸","👹","👺","👻","👼","👽","👾","👿","💀","💁","💂","💃","💄","💅","💆","💇","💈","💉","💊","💋","💌","💍","💎","💏","💐","💑","💒","💓","💔","💕","💖","💗","💘","💙","💚","💛","💜","💝","💞","💟","💠","💡","💢","💣","💤","💥","💦","💧","💨","💩","💪","💫","💬","💭","💮","💯","💰","💱","💲","💳","💴","💵","💶","💷","💸","💹","💺","💻","💼","💽","💾","💿","📀","📁","📂","📃","📄","📅","📆","📇","📈","📉","📊","📋","📌","📍","📎","📏","📐","📑","📒","📓","📔","📕","📖","📗","📘","📙","📚","📛","📜","📝","📞","📟","📠","📡","📢","📣","📤","📥","📦","📧","📨","📩","📪","📫","📬","📭","📮","📯","📰","📱","📲","📳","📴","📵","📶","📷","📸","📹","📺","📻","📼","📿","🔀","🔁","🔂","🔃","🔄","🔅","🔆","🔇","🔈","🔉","🔊","🔋","🔌","🔍","🔎","🔏","🔐","🔑","🔒","🔓","🔔","🔕","🔖","🔗","🔘","🔙","🔚","🔛","🔜","🔝","🔞","🔟","🔠","🔡","🔢","🔣","🔤","🔥","🔦","🔧","🔨","🔩","🔪","🔫","🔬","🔭","🔮","🔯","🔰","🔱","🔲","🔳","🔴","🔵","🔶","🔷","🔸","🔹","🔺","🔻","🔼","🔽","🕋","🕌","🕍","🕎","🕐","🕑","🕒","🕓","🕔","🕕","🕖","🕗","🕘","🕙","🕚","🕛","🕜","🕝","🕞","🕟","🕠","🕡","🕢","🕣","🕤","🕥","🕦","🕧","🖕","🖖","🗻","🗼","🗽","🗾","🗿","😀","😁","😂","😃","😄","😅","😆","😇","😈","😉","😊","😋","😌","😍","😎","😏","😐","😑","😒","😓","😔","😕","😖","😗","😘","😙","😚","😛","😜","😝","😞","😟","😠","😡","😢","😣","😤","😥","😦","😧","😨","😩","😪","😫","😬","😭","😮","😯","😰","😱","😲","😳","😴","😵","😶","😷","😸","😹","😺","😻","😼","😽","😾","😿","🙀","🙁","🙂","🙃","🙄","🙅","🙆","🙇","🙈","🙉","🙊","🙋","🙌","🙍","🙎","🙏","🚀","🚁","🚂","🚃","🚄","🚅","🚆","🚇","🚈","🚉","🚊","🚋","🚌","🚍","🚎","🚏","🚐","🚑","🚒","🚓","🚔","🚕","🚖","🚗","🚘","🚙","🚚","🚛","🚜","🚝","🚞","🚟","🚠","🚡","🚢","🚣","🚤","🚥","🚦","🚧","🚨","🚩","🚪","🚫","🚬","🚭","🚮","🚯","🚰","🚱","🚲","🚳","🚴","🚵","🚶","🚷","🚸","🚹","🚺","🚻","🚼","🚽","🚾","🚿","🛀","🛁","🛂","🛃","🛄","🛅","🛌","🛐","🛫","🛬","🤐","🤑","🤒","🤓","🤔","🤕","🤖","🤗","🤘","🦀","🦁","🦂","🦃","🦄","🧀","🇦🇨","🇦🇩","🇦🇪","🇦🇫","🇦🇬","🇦🇮","🇦🇱","🇦🇲","🇦🇴","🇦🇶","🇦🇷","🇦🇸","🇦🇹","🇦🇺","🇦🇼","🇦🇽","🇦🇿","🇧🇦","🇧🇧","🇧🇩","🇧🇪","🇧🇫","🇧🇬","🇧🇭","🇧🇮","🇧🇯","🇧🇱","🇧🇲","🇧🇳","🇧🇴","🇧🇶","🇧🇷","🇧🇸","🇧🇹","🇧🇻","🇧🇼","🇧🇾","🇧🇿","🇨🇦","🇨🇨","🇨🇩","🇨🇫","🇨🇬","🇨🇭","🇨🇮","🇨🇰","🇨🇱","🇨🇲","🇨🇳","🇨🇴","🇨🇵","🇨🇷","🇨🇺","🇨🇻","🇨🇼","🇨🇽","🇨🇾","🇨🇿","🇩🇪","🇩🇬","🇩🇯","🇩🇰","🇩🇲","🇩🇴","🇩🇿","🇪🇦","🇪🇨","🇪🇪","🇪🇬","🇪🇭","🇪🇷","🇪🇸","🇪🇹","🇪🇺","🇫🇮","🇫🇯","🇫🇰","🇫🇲","🇫🇴","🇫🇷","🇬🇦","🇬🇧","🇬🇩","🇬🇪","🇬🇫","🇬🇬","🇬🇭","🇬🇮","🇬🇱","🇬🇲","🇬🇳","🇬🇵","🇬🇶","🇬🇷","🇬🇸","🇬🇹","🇬🇺","🇬🇼","🇬🇾","🇭🇰","🇭🇲","🇭🇳","🇭🇷","🇭🇹","🇭🇺","🇮🇨","🇮🇩","🇮🇪","🇮🇱","🇮🇲","🇮🇳","🇮🇴","🇮🇶","🇮🇷","🇮🇸","🇮🇹","🇯🇪","🇯🇲","🇯🇴","🇯🇵","🇰🇪","🇰🇬","🇰🇭","🇰🇮","🇰🇲","🇰🇳","🇰🇵","🇰🇷","🇰🇼","🇰🇾","🇰🇿","🇱🇦","🇱🇧","🇱🇨","🇱🇮","🇱🇰","🇱🇷","🇱🇸","🇱🇹","🇱🇺","🇱🇻","🇱🇾","🇲🇦","🇲🇨","🇲🇩","🇲🇪","🇲🇫","🇲🇬","🇲🇭","🇲🇰","🇲🇱","🇲🇲","🇲🇳","🇲🇴","🇲🇵","🇲🇶","🇲🇷","🇲🇸","🇲🇹","🇲🇺","🇲🇻","🇲🇼","🇲🇽","🇲🇾","🇲🇿","🇳🇦","🇳🇨","🇳🇪","🇳🇫","🇳🇬","🇳🇮","🇳🇱","🇳🇴","🇳🇵","🇳🇷","🇳🇺","🇳🇿","🇴🇲","🇵🇦","🇵🇪","🇵🇫","🇵🇬","🇵🇭","🇵🇰","🇵🇱","🇵🇲","🇵🇳","🇵🇷","🇵🇸","🇵🇹","🇵🇼","🇵🇾","🇶🇦","🇷🇪","🇷🇴","🇷🇸","🇷🇺","🇷🇼","🇸🇦","🇸🇧","🇸🇨","🇸🇩","🇸🇪","🇸🇬","🇸🇭","🇸🇮","🇸🇯","🇸🇰","🇸🇱","🇸🇲","🇸🇳","🇸🇴","🇸🇷","🇸🇸","🇸🇹","🇸🇻","🇸🇽","🇸🇾","🇸🇿","🇹🇦","🇹🇨","🇹🇩","🇹🇫","🇹🇬","🇹🇭","🇹🇯","🇹🇰","🇹🇱","🇹🇲","🇹🇳","🇹🇴","🇹🇷","🇹🇹","🇹🇻","🇹🇼","🇹🇿","🇺🇦","🇺🇬","🇺🇲","🇺🇸","🇺🇾","🇺🇿","🇻🇦","🇻🇨","🇻🇪","🇻🇬","🇻🇮","🇻🇳","🇻🇺","🇼🇫","🇼🇸","🇽🇰","🇾🇪","🇾🇹","🇿🇦","🇿🇲","🇿🇼"]'); +pref('services.sync.prefs.sync.zen.workspaces.icons', true); +pref('services.sync.engine.workspaces', false); +pref('zen.essentials.enabled', true); +pref('zen.workspaces.container-specific-essentials-enabled', false); + +// Zen Watermark +pref('zen.watermark.enabled', true, sticky); + +// Smooth scrolling +pref('apz.overscroll.enabled', true); // not DEFAULT on Linux +pref('general.smoothScroll', true); // DEFAULT + +// Privacy +pref('dom.private-attribution.submission.enabled', false); +pref('dom.security.https_only_mode', true); + +pref('media.eme.enabled', true); + +// Enable importers for other browsers +pref('browser.migrate.vivaldi.enabled', true); +pref('browser.migrate.opera-gx.enabled', true); +pref('browser.migrate.opera.enabled', true); + +// DNS +// pref('network.trr.mode', 5); + +// security: They must enable this themselves, to avoid people downloading malware +//pref('xpinstall.signatures.required', false); + +// Experimental Zen Features +// Strategy to use for bytecode cache (Thanks https://github.com/gunir) +pref('dom.script_loader.bytecode_cache.strategy', 2); +pref("dom.text_fragments.enabled", true); + +// Enable private suggestions +pref('browser.search.suggest.enabled', true); +pref('browser.search.suggest.enabled.private', true); + +pref("extensions.enabledScopes", 5); // [HIDDEN PREF] + +// Enable JXL support +pref('image.jxl.enabled', true); + +#if defined(XP_WIN) + pref("dom.ipc.processPriorityManager.backgroundUsesEcoQoS", false); +#endif + +pref('browser.sessionstore.restore_pinned_tabs_on_demand', true); +pref('browser.newtabpage.activity-stream.system.showWeather', true); + +pref("browser.toolbars.bookmarks.visibility", "never"); + +// Enable experimental settings page (Usef for Zen Labs) +pref('browser.preferences.experimental', true); + +#include better-fox.js + +// Betterfox overrides (Stay below the include directive) + +// Jang's personal speedups (Thanks to Jang for these!) + +// Prefetching: +pref("network.dns.disablePrefetch", false); +pref("network.prefetch-next", true); +pref("network.predictor.enabled", true); +pref("network.dns.disablePrefetchFromHTTPS", false); +pref("network.predictor.enable-hover-on-ssl", true); +pref("network.http.speculative-parallel-limit", 10); +pref("network.http.rcwn.enabled", false); + +// Enable Browser Toolbox, Ctrl+Shift+Alt+I for debugging and modifying UI +pref("devtools.debugger.remote-enabled", false); +pref("devtools.chrome.enabled", true); + +// Disable firefox's revamp +pref("sidebar.revamp", false, locked); +pref("sidebar.verticalTabs", false, locked); + +// Better Windows theming +pref("widget.non-native-theme.scrollbar.style", 2); +pref("widget.non-native-theme.use-theme-accent", true); + +// Expose Letterboxing https://github.com/zen-browser/desktop/issues/475 +pref("privacy.resistFingerprinting.letterboxing", false); +pref("privacy.resistFingerprinting.letterboxing.dimensions", ""); + +// Remove Inspect Accessibity Properties menu +pref("devtools.accessibility.enabled", false); + +// Enable GPU by default +//pref('gfx.webrender.all', true); +pref("gfx.canvas.accelerated", true); +pref("media.hardware-video-decoding.enabled", true); +pref("layers.gpu-process.enabled", true); + +// VAAPI/FFMPEG is Linux only +#ifdef XP_UNIX +pref('media.ffmpeg.vaapi.enabled', true); +pref('media.ffmpeg.encoder.enabled', true); +#endif + +// Fix buffering issues: Youtube, Archive bugzilla.mozilla.org/show_bug.cgi?id=1854077 +pref("network.fetchpriority.enabled", true); + +// No Proxy should be default, Use system proxy allows antivirus, virus or system proxy to MITM or slowing down Zen +pref("network.proxy.type", 0); + +// for the new layout: +pref('browser.download.autohideButton', false); + +// Enable transparent background for macos +#ifdef XP_MACOSX +pref('widget.macos.titlebar-blend-mode.behind-window', true); +#endif diff --git a/src/browser/components/preferences/zen-settings.js b/src/browser/components/preferences/zen-settings.js index e0961cc1c..ea51f3b4d 100644 --- a/src/browser/components/preferences/zen-settings.js +++ b/src/browser/components/preferences/zen-settings.js @@ -1,1074 +1,1079 @@ -// 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/. -var gZenMarketplaceManager = { - async init() { - const checkForUpdates = document.getElementById('zenThemeMarketplaceCheckForUpdates'); - const header = document.getElementById('zenMarketplaceHeader'); - - if (!checkForUpdates || !header) { - return; // We haven't entered the settings page yet. - } - - if (this.__hasInitializedEvents) { - return; - } - - header.appendChild(this._initDisableAll()); - - this.__hasInitializedEvents = true; - - await this._buildThemesList(); - - Services.prefs.addObserver(this.updatePref, this); - - const checkForUpdateClick = (event) => { - if (event.target === checkForUpdates) { - event.preventDefault(); - this._checkForThemeUpdates(event); - } - }; - - checkForUpdates.addEventListener('click', checkForUpdateClick); - - document.addEventListener('ZenThemeMarketplace:CheckForUpdatesFinished', (event) => { - checkForUpdates.disabled = false; - const updates = event.detail.updates; - const success = document.getElementById('zenThemeMarketplaceUpdatesSuccess'); - const error = document.getElementById('zenThemeMarketplaceUpdatesFailure'); - if (updates) { - success.hidden = false; - error.hidden = true; - } else { - success.hidden = true; - error.hidden = false; - } - }); - - window.addEventListener('unload', () => { - Services.prefs.removeObserver(this.updatePref, this); - this.__hasInitializedEvents = false; - document.removeEventListener('ZenThemeMarketplace:CheckForUpdatesFinished', this); - document.removeEventListener('ZenCheckForThemeUpdates', this); - checkForUpdates.removeEventListener('click', checkForUpdateClick); - this.themesList.innerHTML = ''; - this._doNotRebuildThemesList = false; - }); - }, - - _initDisableAll() { - const areThemesDisabled = Services.prefs.getBoolPref('zen.themes.disable-all', false); - const browser = ZenThemesCommon.currentBrowser; - const mozToggle = document.createElement('moz-toggle'); - - mozToggle.className = 'zenThemeMarketplaceItemPreferenceToggle zenThemeMarketplaceDisableAllToggle'; - mozToggle.pressed = !areThemesDisabled; - - browser.document.l10n.setAttributes(mozToggle, `zen-theme-disable-all-${!areThemesDisabled ? 'enabled' : 'disabled'}`); - - mozToggle.addEventListener('toggle', async (event) => { - const { pressed = false } = event.target || {}; - - this.themesList.style.display = pressed ? '' : 'none'; - Services.prefs.setBoolPref('zen.themes.disable-all', !pressed); - browser.document.l10n.setAttributes(mozToggle, `zen-theme-disable-all-${pressed ? 'enabled' : 'disabled'}`); - }); - - if (areThemesDisabled) { - this.themesList.style.display = 'none'; - } - - return mozToggle; - }, - - async observe() { - ZenThemesCommon.resetThemesCache(); - await this._buildThemesList(); - }, - - _checkForThemeUpdates(event) { - // Send a message to the child to check for theme updates. - event.target.disabled = true; - // send an event that will be listened by the child process. - document.dispatchEvent(new CustomEvent('ZenCheckForThemeUpdates')); - }, - - get updatePref() { - return 'zen.themes.updated-value-observer'; - }, - - triggerThemeUpdate() { - Services.prefs.setBoolPref(this.updatePref, !Services.prefs.getBoolPref(this.updatePref)); - }, - - get themesList() { - if (!this._themesList) { - this._themesList = document.getElementById('zenThemeMarketplaceList'); - } - return this._themesList; - }, - - async removeTheme(themeId) { - const themePath = ZenThemesCommon.getThemeFolder(themeId); - - console.info(`[ZenThemeMarketplaceParent:settings]: Removing theme ${themePath}`); - - await IOUtils.remove(themePath, { recursive: true, ignoreAbsent: true }); - - const themes = await ZenThemesCommon.getThemes(); - delete themes[themeId]; - await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); - - this.triggerThemeUpdate(); - }, - - async disableTheme(themeId) { - const themes = await ZenThemesCommon.getThemes(); - const theme = themes[themeId]; - - console.log(`[ZenThemeMarketplaceParent:settings]: Disabling theme ${theme.name}`); - - theme.enabled = false; - - await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); - this._doNotRebuildThemesList = true; - this.triggerThemeUpdate(); - }, - - async enableTheme(themeId) { - const themes = await ZenThemesCommon.getThemes(); - const theme = themes[themeId]; - - console.log(`[ZenThemeMarketplaceParent:settings]: Enabling theme ${theme.name}`); - - theme.enabled = true; - - await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); - this._doNotRebuildThemesList = true; - this.triggerThemeUpdate(); - }, - - _triggerBuildUpdateWithoutRebuild() { - this._doNotRebuildThemesList = true; - this.triggerThemeUpdate(); - }, - - async _buildThemesList() { - if (!this.themesList) { - return; - } - - if (this._doNotRebuildThemesList) { - this._doNotRebuildThemesList = false; - return; - } - - const themes = await ZenThemesCommon.getThemes(); - const browser = ZenMultiWindowFeature.currentBrowser; - const themeList = document.createElement('div'); - - for (const theme of Object.values(themes)) { - const sanitizedName = `theme-${theme.name?.replaceAll(/\s/g, '-')?.replaceAll(/[^A-z_-]+/g, '')}`; - const isThemeEnabled = theme.enabled === undefined || theme.enabled; - - const fragment = window.MozXULElement.parseXULToFragment(` - - - - - - - - - ${theme.preferences ? `` : ''} - - - - `); - - const themeName = `${theme.name} (v${theme.version || '1.0.0'})`; - - const base = fragment.querySelector('.zenThemeMarketplaceItem'); - const baseHeader = fragment.querySelector('#zenThemeMarketplaceItemContentHeader'); - - const dialog = document.createElement('dialog'); - const mainDialogDiv = document.createElement('div'); - const headerDiv = document.createElement('div'); - const headerTitle = document.createElement('h3'); - const closeButton = document.createElement('button'); - const contentDiv = document.createElement('div'); - const mozToggle = document.createElement('moz-toggle'); - - mainDialogDiv.className = 'zenThemeMarketplaceItemPreferenceDialog'; - headerDiv.className = 'zenThemeMarketplaceItemPreferenceDialogTopBar'; - headerTitle.textContent = themeName; - browser.document.l10n.setAttributes(headerTitle, 'zen-theme-marketplace-theme-header-title', { - name: sanitizedName, - }); - headerTitle.className = 'zenThemeMarketplaceItemTitle'; - closeButton.id = `${sanitizedName}-modal-close`; - browser.document.l10n.setAttributes(closeButton, 'zen-theme-marketplace-close-modal'); - contentDiv.id = `${sanitizedName}-preferences-content`; - contentDiv.className = 'zenThemeMarketplaceItemPreferenceDialogContent'; - mozToggle.className = 'zenThemeMarketplaceItemPreferenceToggle'; - - mozToggle.pressed = isThemeEnabled; - browser.document.l10n.setAttributes( - mozToggle, - `zen-theme-marketplace-toggle-${isThemeEnabled ? 'enabled' : 'disabled'}-button` - ); - - baseHeader.appendChild(mozToggle); - - headerDiv.appendChild(headerTitle); - headerDiv.appendChild(closeButton); - - mainDialogDiv.appendChild(headerDiv); - mainDialogDiv.appendChild(contentDiv); - dialog.appendChild(mainDialogDiv); - base.appendChild(dialog); - - closeButton.addEventListener('click', () => { - dialog.close(); - }); - - mozToggle.addEventListener('toggle', async (event) => { - const themeId = event.target - .closest('.zenThemeMarketplaceItem') - .querySelector('.zenThemeMarketplaceItemUninstallButton') - .getAttribute('zen-theme-id'); - event.target.setAttribute('disabled', true); - - if (!event.target.hasAttribute('pressed')) { - await this.disableTheme(themeId); - - browser.document.l10n.setAttributes(mozToggle, 'zen-theme-marketplace-toggle-disabled-button'); - - if (theme.preferences) { - document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).setAttribute('hidden', true); - } - } else { - await this.enableTheme(themeId); - - browser.document.l10n.setAttributes(mozToggle, 'zen-theme-marketplace-toggle-enabled-button'); - - if (theme.preferences) { - document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).removeAttribute('hidden'); - } - } - setTimeout(() => { - // We use a timeout to make sure the theme list has been updated before re-enabling the button. - event.target.removeAttribute('disabled'); - }, 400); - }); - - fragment.querySelector('.zenThemeMarketplaceItemTitle').textContent = themeName; - fragment.querySelector('.zenThemeMarketplaceItemDescription').textContent = theme.description; - fragment.querySelector('.zenThemeMarketplaceItemUninstallButton').addEventListener('click', async (event) => { - const [msg] = await document.l10n.formatValues([{ id: 'zen-theme-marketplace-remove-confirmation' }]); - - if (!confirm(msg)) { - return; - } - - await this.removeTheme(event.target.getAttribute('zen-theme-id')); - }); - - if (theme.preferences) { - fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').addEventListener('click', () => { - dialog.showModal(); - }); - - if (isThemeEnabled) { - fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').removeAttribute('hidden'); - } - } - - const preferences = await ZenThemesCommon.getThemePreferences(theme); - - if (preferences.length > 0) { - const preferencesWrapper = document.createXULElement('vbox'); - - preferencesWrapper.setAttribute('flex', '1'); - - for (const entry of preferences) { - const { property, label, type, placeholder } = entry; - - switch (type) { - case 'dropdown': { - const { options } = entry; - - const container = document.createXULElement('hbox'); - container.classList.add('zenThemeMarketplaceItemPreference'); - container.setAttribute('align', 'center'); - container.setAttribute('role', 'group'); - - const menulist = document.createXULElement('menulist'); - const menupopup = document.createXULElement('menupopup'); - - menulist.setAttribute('sizetopopup', 'none'); - menulist.setAttribute('id', property + '-popup-menulist'); - - const savedValue = Services.prefs.getStringPref(property, 'none'); - - menulist.setAttribute('value', savedValue); - menulist.setAttribute('tooltiptext', property); - - const defaultItem = document.createXULElement('menuitem'); - - defaultItem.setAttribute('value', 'none'); - - if (placeholder) { - defaultItem.setAttribute('label', placeholder || '-'); - } else { - browser.document.l10n.setAttributes(defaultItem, 'zen-theme-marketplace-dropdown-default-label'); - } - - menupopup.appendChild(defaultItem); - - for (const option of options) { - const { label, value } = option; - - const valueType = typeof value; - - if (!['string', 'number'].includes(valueType)) { - console.log( - `[ZenThemeMarketplaceParent:settings]: Warning, invalid data type received (${valueType}), skipping.` - ); - continue; - } - - const menuitem = document.createXULElement('menuitem'); - - menuitem.setAttribute('value', value.toString()); - menuitem.setAttribute('label', label); - - menupopup.appendChild(menuitem); - } - - menulist.appendChild(menupopup); - - menulist.addEventListener('command', () => { - const value = menulist.selectedItem.value; - - let element = browser.document.getElementById(sanitizedName); - - if (!element) { - element = browser.document.createElement('div'); - - element.style.display = 'none'; - element.setAttribute('id', sanitizedName); - - browser.document.body.appendChild(element); - } - - element.setAttribute(property?.replaceAll(/\./g, '-'), value); - - Services.prefs.setStringPref(property, value === 'none' ? '' : value); - this._triggerBuildUpdateWithoutRebuild(); - }); - - const nameLabel = document.createXULElement('label'); - nameLabel.setAttribute('flex', '1'); - nameLabel.setAttribute('class', 'zenThemeMarketplaceItemPreferenceLabel'); - nameLabel.setAttribute('value', label); - nameLabel.setAttribute('tooltiptext', property); - - container.appendChild(nameLabel); - container.appendChild(menulist); - container.setAttribute('aria-labelledby', label); - - preferencesWrapper.appendChild(container); - break; - } - - case 'checkbox': { - const checkbox = window.MozXULElement.parseXULToFragment(` - - - - `); - - const checkboxElement = checkbox.querySelector('.zenThemeMarketplaceItemPreferenceCheckbox'); - checkboxElement.setAttribute('label', label); - checkboxElement.setAttribute('tooltiptext', property); - checkboxElement.setAttribute('zen-pref', property); - - // Checkbox only works with "true" and "false" values, it's not like HTML checkboxes. - if (Services.prefs.getBoolPref(property, false)) { - checkboxElement.setAttribute('checked', 'true'); - } - - checkboxElement.addEventListener('click', (event) => { - const target = event.target.closest('.zenThemeMarketplaceItemPreferenceCheckbox'); - const key = target.getAttribute('zen-pref'); - const checked = target.hasAttribute('checked'); - - if (!checked) { - target.removeAttribute('checked'); - } else { - target.setAttribute('checked', 'true'); - } - - Services.prefs.setBoolPref(key, !checked); - }); - - preferencesWrapper.appendChild(checkbox); - break; - } - - case 'string': { - const container = document.createXULElement('hbox'); - container.classList.add('zenThemeMarketplaceItemPreference'); - container.setAttribute('align', 'center'); - container.setAttribute('role', 'group'); - - const savedValue = Services.prefs.getStringPref(property, ''); - const sanitizedProperty = property?.replaceAll(/\./g, '-'); - - const input = document.createElement('input'); - input.setAttribute('flex', '1'); - input.setAttribute('type', 'text'); - input.id = `${sanitizedProperty}-input`; - input.value = savedValue; - - if (placeholder) { - input.setAttribute('placeholder', placeholder || '-'); - } else { - browser.document.l10n.setAttributes(input, 'zen-theme-marketplace-input-default-placeholder'); - } - - input.addEventListener( - 'input', - ZenThemesCommon.throttle((event) => { - const value = event.target.value; - - Services.prefs.setStringPref(property, value); - this._triggerBuildUpdateWithoutRebuild(); - - if (value === '') { - browser.document.querySelector(':root').style.removeProperty(`--${sanitizedProperty}`); - } else { - browser.document.querySelector(':root').style.setProperty(`--${sanitizedProperty}`, value); - } - }, 500) - ); - - const nameLabel = document.createXULElement('label'); - nameLabel.setAttribute('flex', '1'); - nameLabel.setAttribute('class', 'zenThemeMarketplaceItemPreferenceLabel'); - nameLabel.setAttribute('value', label); - nameLabel.setAttribute('tooltiptext', property); - - container.appendChild(nameLabel); - container.appendChild(input); - container.setAttribute('aria-labelledby', label); - - preferencesWrapper.appendChild(container); - break; - } - - default: - console.log( - `[ZenThemeMarketplaceParent:settings]: Warning, unknown preference type received (${type}), skipping.` - ); - continue; - } - } - contentDiv.appendChild(preferencesWrapper); - } - themeList.appendChild(fragment); - } - - this.themesList.replaceChildren(...themeList.children); - themeList.remove(); - }, -}; - -var gZenLooksAndFeel = { - init() { - if (this.__hasInitialized) return; - this.__hasInitialized = true; - this._initializeColorPicker(this._getInitialAccentColor()); - window.zenPageAccentColorChanged = this._handleAccentColorChange.bind(this); - gZenThemeBuilder.init(); - gZenMarketplaceManager.init(); - var onPreferColorSchemeChange = this.onPreferColorSchemeChange.bind(this); - window.matchMedia('(prefers-color-scheme: dark)').addListener(onPreferColorSchemeChange); - this.onPreferColorSchemeChange(); - window.addEventListener('unload', () => { - window.matchMedia('(prefers-color-scheme: dark)').removeListener(onPreferColorSchemeChange); - }); - this.setDarkThemeListener(); - this.setCompactModeStyle(); - }, - - onPreferColorSchemeChange(event) { - const darkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches; - let elem = document.getElementById('ZenDarkThemeStyles'); - if (darkTheme) { - elem.removeAttribute('hidden'); - } else { - elem.setAttribute('hidden', 'true'); - } - }, - - setDarkThemeListener() { - const chooser = document.getElementById('zen-dark-theme-styles-form'); - const radios = [...chooser.querySelectorAll('input')]; - for (let radio of radios) { - if (radio.value === 'amoled' && Services.prefs.getBoolPref('zen.theme.color-prefs.amoled')) { - radio.checked = true; - } else if (radio.value === 'colorful' && Services.prefs.getBoolPref('zen.theme.color-prefs.colorful')) { - radio.checked = true; - } else if ( - radio.value === 'default' && - !Services.prefs.getBoolPref('zen.theme.color-prefs.amoled') && - !Services.prefs.getBoolPref('zen.theme.color-prefs.colorful') - ) { - radio.checked = true; - } - radio.addEventListener('change', (e) => { - let value = e.target.value; - switch (value) { - case 'amoled': - Services.prefs.setBoolPref('zen.theme.color-prefs.amoled', true); - Services.prefs.setBoolPref('zen.theme.color-prefs.colorful', false); - break; - case 'colorful': - Services.prefs.setBoolPref('zen.theme.color-prefs.amoled', false); - Services.prefs.setBoolPref('zen.theme.color-prefs.colorful', true); - break; - default: - Services.prefs.setBoolPref('zen.theme.color-prefs.amoled', false); - Services.prefs.setBoolPref('zen.theme.color-prefs.colorful', false); - break; - } - }); - } - }, - - setCompactModeStyle() { - const chooser = document.getElementById('zen-compact-mode-styles-form'); - const radios = [...chooser.querySelectorAll('input')]; - - let value = ''; - if ( - Services.prefs.getBoolPref('zen.view.compact.hide-tabbar') && - Services.prefs.getBoolPref('zen.view.compact.hide-toolbar') - ) { - value = 'both'; - } else { - value = Services.prefs.getBoolPref('zen.view.compact.hide-tabbar') ? 'left' : 'top'; - } - chooser.querySelector(`[value='${value}']`).checked = true; - for (let radio of radios) { - radio.addEventListener('change', (e) => { - let value = e.target.value; - switch (value) { - case 'left': - Services.prefs.setBoolPref('zen.view.compact.hide-tabbar', true); - Services.prefs.setBoolPref('zen.view.compact.hide-toolbar', false); - break; - case 'top': - Services.prefs.setBoolPref('zen.view.compact.hide-tabbar', false); - Services.prefs.setBoolPref('zen.view.compact.hide-toolbar', true); - break; - default: - Services.prefs.setBoolPref('zen.view.compact.hide-tabbar', true); - Services.prefs.setBoolPref('zen.view.compact.hide-toolbar', true); - break; - } - }); - } - }, - - _initializeColorPicker(accentColor) { - let elem = document.getElementById('zenLooksAndFeelColorOptions'); - elem.innerHTML = ''; - for (let color of ZenThemesCommon.kZenColors) { - let colorElemParen = document.createElement('div'); - let colorElem = document.createElement('div'); - colorElemParen.classList.add('zenLooksAndFeelColorOptionParen'); - colorElem.classList.add('zenLooksAndFeelColorOption'); - colorElem.style.setProperty('--zen-primary-color', color, 'important'); - if (accentColor === color) { - colorElemParen.setAttribute('selected', 'true'); - } - colorElemParen.addEventListener('click', () => { - Services.prefs.setBoolPref('zen.theme.color-prefs.use-workspace-colors', false); - Services.prefs.setStringPref('zen.theme.accent-color', color); - }); - colorElemParen.appendChild(colorElem); - elem.appendChild(colorElemParen); - } - // TODO: add custom color selection! - }, - - _handleAccentColorChange(accentColor) { - this._initializeColorPicker(accentColor); - }, - - _getInitialAccentColor() { - return Services.prefs.getStringPref('zen.theme.accent-color', ZenThemesCommon.kZenColors[0]); - }, -}; - -var gZenWorkspacesSettings = { - init() { - var tabsUnloaderPrefListener = { - async observe(subject, topic, data) { - let buttonIndex = await confirmRestartPrompt(true, 1, true, true); - if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { - Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); - } - }, - }; - Services.prefs.addObserver('zen.workspaces.enabled', this); - Services.prefs.addObserver('zen.tab-unloader.enabled', tabsUnloaderPrefListener); - Services.prefs.addObserver('zen.glance.enabled', tabsUnloaderPrefListener); // We can use the same listener for both prefs - Services.prefs.addObserver('zen.glance.activation-method', tabsUnloaderPrefListener); - window.addEventListener('unload', () => { - Services.prefs.removeObserver('zen.workspaces.enabled', this); - Services.prefs.removeObserver('zen.tab-unloader.enabled', tabsUnloaderPrefListener); - Services.prefs.removeObserver('zen.glance.enabled', tabsUnloaderPrefListener); - Services.prefs.removeObserver('zen.glance.activation-method', tabsUnloaderPrefListener); - }); - }, - - async observe(subject, topic, data) { - await this.onWorkspaceChange(Services.prefs.getBoolPref('zen.workspaces.enabled')); - }, - - async onWorkspaceChange(checked) { - if (checked) { - let buttonIndex = await confirmRestartPrompt(true, 1, true, false); - if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { - Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); - return; - } - } - }, -}; - -const ZEN_CKS_CLASS_BASE = 'zenCKSOption'; -const ZEN_CKS_INPUT_FIELD_CLASS = `${ZEN_CKS_CLASS_BASE}-input`; -const ZEN_CKS_LABEL_CLASS = `${ZEN_CKS_CLASS_BASE}-label`; -const ZEN_CKS_WRAPPER_ID = `${ZEN_CKS_CLASS_BASE}-wrapper`; -const ZEN_CKS_GROUP_PREFIX = `${ZEN_CKS_CLASS_BASE}-group`; -const KEYBIND_ATTRIBUTE_KEY = 'key'; - -var zenMissingKeyboardShortcutL10n = { - key_quickRestart: 'zen-key-quick-restart', - key_delete: 'zen-key-delete', - goBackKb: 'zen-key-go-back', - goForwardKb: 'zen-key-go-forward', - key_enterFullScreen: 'zen-key-enter-full-screen', - key_exitFullScreen: 'zen-key-exit-full-screen', - key_aboutProcesses: 'zen-key-about-processes', - key_stop: 'zen-key-stop', - key_sanitize: 'zen-key-sanitize', - key_wrCaptureCmd: 'zen-key-wr-capture-cmd', - key_wrToggleCaptureSequenceCmd: 'zen-key-wr-toggle-capture-sequence-cmd', - key_undoCloseWindow: 'zen-key-undo-close-window', - - key_selectTab1: 'zen-key-select-tab-1', - key_selectTab2: 'zen-key-select-tab-2', - key_selectTab3: 'zen-key-select-tab-3', - key_selectTab4: 'zen-key-select-tab-4', - key_selectTab5: 'zen-key-select-tab-5', - key_selectTab6: 'zen-key-select-tab-6', - key_selectTab7: 'zen-key-select-tab-7', - key_selectTab8: 'zen-key-select-tab-8', - key_selectLastTab: 'zen-key-select-tab-last', - - key_showAllTabs: 'zen-key-show-all-tabs', - key_gotoHistory: 'zen-key-goto-history', - - goHome: 'zen-key-go-home', - key_redo: 'zen-key-redo', -}; - -var gZenCKSSettings = { - async init() { - await this._initializeCKS(); - if (this.__hasInitialized) return; - this.__hasInitialized = true; - this._currentActionID = null; - this._initializeEvents(); - window.addEventListener('unload', () => { - this.__hasInitialized = false; - document.getElementById(ZEN_CKS_WRAPPER_ID).innerHTML = ''; - }); - }, - - _initializeEvents() { - const resetAllListener = this.resetAllShortcuts.bind(this); - const handleKeyDown = this._handleKeyDown.bind(this); - window.addEventListener('keydown', handleKeyDown); - const button = document.getElementById('zenCKSResetButton'); - button.addEventListener('click', resetAllListener); - window.addEventListener('unload', () => { - window.removeEventListener('keydown', handleKeyDown); - button.removeEventListener('click', resetAllListener); - }); - }, - - async resetAllShortcuts() { - let buttonIndex = await confirmRestartPrompt(true, 1, true, false); - if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { - await gZenKeyboardShortcutsManager.resetAllShortcuts(); - Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); - } - }, - - async _initializeCKS() { - let wrapper = document.getElementById(ZEN_CKS_WRAPPER_ID); - wrapper.innerHTML = ''; - - let shortcuts = await gZenKeyboardShortcutsManager.getModifiableShortcuts(); - - if (!shortcuts) { - throw Error('No shortcuts defined!'); - } - - // Generate section per each group - for (let group of VALID_SHORTCUT_GROUPS) { - let groupClass = `${ZEN_CKS_GROUP_PREFIX}-${group}`; - if (!wrapper.querySelector(`[data-group="${groupClass}"]`)) { - let groupElem = document.createElement('h2'); - groupElem.setAttribute('data-group', groupClass); - document.l10n.setAttributes(groupElem, groupClass); - wrapper.appendChild(groupElem); - } - } - - for (let shortcut of shortcuts) { - const keyID = shortcut.getID(); - const action = shortcut.getAction(); - const l10nID = shortcut.getL10NID(); - const group = shortcut.getGroup(); - const keyInString = shortcut.toUserString(); - - const labelValue = zenMissingKeyboardShortcutL10n[keyID] ?? l10nID; - - let fragment = window.MozXULElement.parseXULToFragment(` - - - - - - - `); - - const label = fragment.querySelector(`.${ZEN_CKS_LABEL_CLASS}`); - if (!labelValue) { - label.textContent = action; // Just in case - } else { - document.l10n.setAttributes(label, labelValue); - } - - let input = fragment.querySelector(`.${ZEN_CKS_INPUT_FIELD_CLASS}`); - if (keyInString && !shortcut.isEmpty()) { - input.value = keyInString; - } else { - this._resetShortcut(input); - } - - input.setAttribute(KEYBIND_ATTRIBUTE_KEY, keyID); - input.setAttribute('data-group', group); - input.setAttribute('data-id', keyID); - - input.addEventListener('focus', (event) => { - const value = event.target.getAttribute(KEYBIND_ATTRIBUTE_KEY); - this._currentActionID = event.target.getAttribute('data-id'); - event.target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - this._hasSafed = true; - }); - - input.addEventListener('editDone', (event) => { - const target = event.target; - target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - }); - - input.addEventListener('blur', (event) => { - const target = event.target; - target.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - if (!this._hasSafed) { - target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-unsafed`); - if (!target.nextElementSibling) { - target.after( - window.MozXULElement.parseXULToFragment(` - - `) - ); - target.value = 'Not set'; - } - } else { - target.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-unsafed`); - const sibling = target.nextElementSibling; - if (sibling && sibling.classList.contains(`${ZEN_CKS_CLASS_BASE}-unsafed`)) { - sibling.remove(); - } - } - }); - - const groupElem = wrapper.querySelector(`[data-group="${ZEN_CKS_GROUP_PREFIX}-${group}"]`); - groupElem.after(fragment); - } - }, - - async _resetShortcut(input) { - input.value = 'Not set'; - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-not-set`); - - if (this._currentActionID) { - this._editDone(); - await gZenKeyboardShortcutsManager.setShortcut(this._currentActionID, null, null); - } - }, - - _editDone(shortcut, modifiers) { - // Check if we have a valid key - if (!shortcut || !modifiers) { - return; - } - gZenKeyboardShortcutsManager.setShortcut(this._currentActionID, shortcut, modifiers); - this._currentActionID = null; - }, - - //TODO Check for duplicates - async _handleKeyDown(event) { - if (!this._currentActionID || document.hidden) { - return; - } - - event.preventDefault(); - - let input = document.querySelector(`.${ZEN_CKS_INPUT_FIELD_CLASS}[${KEYBIND_ATTRIBUTE_KEY}="${this._currentActionID}"]`); - const modifiers = new KeyShortcutModifiers(event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, false); - const modifiersActive = modifiers.areAnyActive(); - - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-not-set`); - - // This is because on some OSs (windows/macos mostly) the key is not the same as the keycode - // e.g. CTRL+ALT+3 may be displayed as the euro sign - let shortcut = event.key; - - shortcut = shortcut.replace(/Ctrl|Control|Shift|Alt|Option|Cmd|Meta/, ''); // Remove all modifiers - - if (shortcut == 'Tab' && !modifiersActive) { - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - this._latestValidKey = null; - return; - } else if (shortcut == 'Escape' && !modifiersActive) { - const hasConflicts = gZenKeyboardShortcutsManager.checkForConflicts( - this._latestValidKey ? this._latestValidKey : shortcut, - this._latestModifier ? this._latestModifier : modifiers, - this._currentActionID - ); - - if (!this._latestValidKey && !this._latestModifier) { - } else if (!this._latestValidKey || hasConflicts) { - if (!input.classList.contains(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`)) { - input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); - } - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-unsafed`); - if (hasConflicts && !input.nextElementSibling) { - input.after( - window.MozXULElement.parseXULToFragment(` - - `) - ); - } - } else { - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); - - this._editDone(this._latestValidKey, this._latestModifier); - this._latestValidKey = null; - this._latestModifier = null; - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); - input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-valid`); - setTimeout(() => { - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-valid`); - }, 1000); - const sibling = input.nextElementSibling; - if (sibling && sibling.classList.contains(`${ZEN_CKS_CLASS_BASE}-conflict`)) { - sibling.remove(); - } - } - this._hasSafed = true; - input.blur(); - this._currentActionID = null; - return; - } else if (shortcut == 'Backspace' && !modifiersActive) { - this._resetShortcut(input); - this._latestValidKey = null; - this._latestModifier = null; - this._hasSafed = true; - return; - } - - this._latestModifier = modifiers; - this._hasSafed = false; - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); - input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-not-set`); - input.value = modifiers.toUserString() + shortcut; - this._latestValidKey = shortcut; - }, -}; - -Preferences.addAll([ - { - id: 'zen.sidebar.enabled', - type: 'bool', - default: true, - }, - { - id: 'zen.sidebar.close-on-blur', - type: 'bool', - default: true, - }, - { - id: 'zen.view.compact', - type: 'bool', - default: false, - }, - { - id: 'zen.view.compact.hide-toolbar', - type: 'bool', - default: false, - }, - { - id: 'zen.view.compact.toolbar-flash-popup', - type: 'bool', - default: true, - }, - { - id: 'zen.workspaces.enabled', - type: 'bool', - default: true, - }, - { - id: 'zen.theme.pill-button', - type: 'bool', - default: true, - }, - { - id: 'zen.workspaces.hide-default-container-indicator', - type: 'bool', - default: true, - }, - { - id: 'zen.workspaces.individual-pinned-tabs', - type: 'bool', - default: true, - }, - { - id: 'zen.workspaces.show-icon-strip', - type: 'bool', - default: true, - }, - { - id: 'zen.tab-unloader.enabled', - type: 'bool', - default: true, - }, - { - id: 'zen.splitView.change-on-hover', - type: 'bool', - default: true, - }, - { - id: 'zen.tab-unloader.timeout-minutes', - type: 'int', - default: 10, - }, - { - id: 'zen.view.show-bottom-border', - type: 'bool', - default: false, - }, - { - id: 'zen.workspaces.hide-deactivated-workspaces', - type: 'bool', - default: true, - }, - { - id: 'zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', - type: 'bool', - default: true, - }, - { - id: 'zen.pinned-tab-manager.close-shortcut-behavior', - type: 'string', - default: 'switch', - }, - { - id: 'zen.workspaces.force-container-workspace', - type: 'bool', - default: true, - }, - { - id: 'zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', - type: 'bool', - default: true, - }, - { - id: 'zen.tabs.show-newtab-under', - type: 'bool', - default: false, - }, - { - id: "zen.glance.activation-method", - type: "string", - default: "ctrl", - }, - { - id: "zen.glance.enabled", - type: "bool", - default: true, - }, - { - id: "zen.theme.color-prefs.use-workspace-colors", - type: "bool", - default: false, - }, - { - id: "zen.view.compact.color-toolbar", - type: "bool", - default: true, - }, - { - id: "zen.view.compact.color-sidebar", - type: "bool", - default: true, - }, - { - id: "zen.essentials.enabled", - type: "bool", - default: true, - }, - { - id: 'zen.workspaces.container-specific-essentials-enabled', - type: 'bool', - default: false, - }, - { - id: "zen.tabs.show-newtab-vertical", - type: "bool", - default: true, - }, - { - id: "zen.view.show-newtab-button-border-top", - type: "bool", - default: false, - }, - { - id: "zen.view.show-newtab-button-top", - type: "bool", - default: true, - }, -]); +// 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/. +var gZenMarketplaceManager = { + async init() { + const checkForUpdates = document.getElementById('zenThemeMarketplaceCheckForUpdates'); + const header = document.getElementById('zenMarketplaceHeader'); + + if (!checkForUpdates || !header) { + return; // We haven't entered the settings page yet. + } + + if (this.__hasInitializedEvents) { + return; + } + + header.appendChild(this._initDisableAll()); + + this.__hasInitializedEvents = true; + + await this._buildThemesList(); + + Services.prefs.addObserver(this.updatePref, this); + + const checkForUpdateClick = (event) => { + if (event.target === checkForUpdates) { + event.preventDefault(); + this._checkForThemeUpdates(event); + } + }; + + checkForUpdates.addEventListener('click', checkForUpdateClick); + + document.addEventListener('ZenThemeMarketplace:CheckForUpdatesFinished', (event) => { + checkForUpdates.disabled = false; + const updates = event.detail.updates; + const success = document.getElementById('zenThemeMarketplaceUpdatesSuccess'); + const error = document.getElementById('zenThemeMarketplaceUpdatesFailure'); + if (updates) { + success.hidden = false; + error.hidden = true; + } else { + success.hidden = true; + error.hidden = false; + } + }); + + window.addEventListener('unload', () => { + Services.prefs.removeObserver(this.updatePref, this); + this.__hasInitializedEvents = false; + document.removeEventListener('ZenThemeMarketplace:CheckForUpdatesFinished', this); + document.removeEventListener('ZenCheckForThemeUpdates', this); + checkForUpdates.removeEventListener('click', checkForUpdateClick); + this.themesList.innerHTML = ''; + this._doNotRebuildThemesList = false; + }); + }, + + _initDisableAll() { + const areThemesDisabled = Services.prefs.getBoolPref('zen.themes.disable-all', false); + const browser = ZenThemesCommon.currentBrowser; + const mozToggle = document.createElement('moz-toggle'); + + mozToggle.className = 'zenThemeMarketplaceItemPreferenceToggle zenThemeMarketplaceDisableAllToggle'; + mozToggle.pressed = !areThemesDisabled; + + browser.document.l10n.setAttributes(mozToggle, `zen-theme-disable-all-${!areThemesDisabled ? 'enabled' : 'disabled'}`); + + mozToggle.addEventListener('toggle', async (event) => { + const { pressed = false } = event.target || {}; + + this.themesList.style.display = pressed ? '' : 'none'; + Services.prefs.setBoolPref('zen.themes.disable-all', !pressed); + browser.document.l10n.setAttributes(mozToggle, `zen-theme-disable-all-${pressed ? 'enabled' : 'disabled'}`); + }); + + if (areThemesDisabled) { + this.themesList.style.display = 'none'; + } + + return mozToggle; + }, + + async observe() { + ZenThemesCommon.resetThemesCache(); + await this._buildThemesList(); + }, + + _checkForThemeUpdates(event) { + // Send a message to the child to check for theme updates. + event.target.disabled = true; + // send an event that will be listened by the child process. + document.dispatchEvent(new CustomEvent('ZenCheckForThemeUpdates')); + }, + + get updatePref() { + return 'zen.themes.updated-value-observer'; + }, + + triggerThemeUpdate() { + Services.prefs.setBoolPref(this.updatePref, !Services.prefs.getBoolPref(this.updatePref)); + }, + + get themesList() { + if (!this._themesList) { + this._themesList = document.getElementById('zenThemeMarketplaceList'); + } + return this._themesList; + }, + + async removeTheme(themeId) { + const themePath = ZenThemesCommon.getThemeFolder(themeId); + + console.info(`[ZenThemeMarketplaceParent:settings]: Removing theme ${themePath}`); + + await IOUtils.remove(themePath, { recursive: true, ignoreAbsent: true }); + + const themes = await ZenThemesCommon.getThemes(); + delete themes[themeId]; + await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); + + this.triggerThemeUpdate(); + }, + + async disableTheme(themeId) { + const themes = await ZenThemesCommon.getThemes(); + const theme = themes[themeId]; + + console.log(`[ZenThemeMarketplaceParent:settings]: Disabling theme ${theme.name}`); + + theme.enabled = false; + + await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); + this._doNotRebuildThemesList = true; + this.triggerThemeUpdate(); + }, + + async enableTheme(themeId) { + const themes = await ZenThemesCommon.getThemes(); + const theme = themes[themeId]; + + console.log(`[ZenThemeMarketplaceParent:settings]: Enabling theme ${theme.name}`); + + theme.enabled = true; + + await IOUtils.writeJSON(ZenThemesCommon.themesDataFile, themes); + this._doNotRebuildThemesList = true; + this.triggerThemeUpdate(); + }, + + _triggerBuildUpdateWithoutRebuild() { + this._doNotRebuildThemesList = true; + this.triggerThemeUpdate(); + }, + + async _buildThemesList() { + if (!this.themesList) { + return; + } + + if (this._doNotRebuildThemesList) { + this._doNotRebuildThemesList = false; + return; + } + + const themes = await ZenThemesCommon.getThemes(); + const browser = ZenMultiWindowFeature.currentBrowser; + const themeList = document.createElement('div'); + + for (const theme of Object.values(themes)) { + const sanitizedName = `theme-${theme.name?.replaceAll(/\s/g, '-')?.replaceAll(/[^A-z_-]+/g, '')}`; + const isThemeEnabled = theme.enabled === undefined || theme.enabled; + + const fragment = window.MozXULElement.parseXULToFragment(` + + + + + + + + + ${theme.preferences ? `` : ''} + + + + `); + + const themeName = `${theme.name} (v${theme.version || '1.0.0'})`; + + const base = fragment.querySelector('.zenThemeMarketplaceItem'); + const baseHeader = fragment.querySelector('#zenThemeMarketplaceItemContentHeader'); + + const dialog = document.createElement('dialog'); + const mainDialogDiv = document.createElement('div'); + const headerDiv = document.createElement('div'); + const headerTitle = document.createElement('h3'); + const closeButton = document.createElement('button'); + const contentDiv = document.createElement('div'); + const mozToggle = document.createElement('moz-toggle'); + + mainDialogDiv.className = 'zenThemeMarketplaceItemPreferenceDialog'; + headerDiv.className = 'zenThemeMarketplaceItemPreferenceDialogTopBar'; + headerTitle.textContent = themeName; + browser.document.l10n.setAttributes(headerTitle, 'zen-theme-marketplace-theme-header-title', { + name: sanitizedName, + }); + headerTitle.className = 'zenThemeMarketplaceItemTitle'; + closeButton.id = `${sanitizedName}-modal-close`; + browser.document.l10n.setAttributes(closeButton, 'zen-theme-marketplace-close-modal'); + contentDiv.id = `${sanitizedName}-preferences-content`; + contentDiv.className = 'zenThemeMarketplaceItemPreferenceDialogContent'; + mozToggle.className = 'zenThemeMarketplaceItemPreferenceToggle'; + + mozToggle.pressed = isThemeEnabled; + browser.document.l10n.setAttributes( + mozToggle, + `zen-theme-marketplace-toggle-${isThemeEnabled ? 'enabled' : 'disabled'}-button` + ); + + baseHeader.appendChild(mozToggle); + + headerDiv.appendChild(headerTitle); + headerDiv.appendChild(closeButton); + + mainDialogDiv.appendChild(headerDiv); + mainDialogDiv.appendChild(contentDiv); + dialog.appendChild(mainDialogDiv); + base.appendChild(dialog); + + closeButton.addEventListener('click', () => { + dialog.close(); + }); + + mozToggle.addEventListener('toggle', async (event) => { + const themeId = event.target + .closest('.zenThemeMarketplaceItem') + .querySelector('.zenThemeMarketplaceItemUninstallButton') + .getAttribute('zen-theme-id'); + event.target.setAttribute('disabled', true); + + if (!event.target.hasAttribute('pressed')) { + await this.disableTheme(themeId); + + browser.document.l10n.setAttributes(mozToggle, 'zen-theme-marketplace-toggle-disabled-button'); + + if (theme.preferences) { + document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).setAttribute('hidden', true); + } + } else { + await this.enableTheme(themeId); + + browser.document.l10n.setAttributes(mozToggle, 'zen-theme-marketplace-toggle-enabled-button'); + + if (theme.preferences) { + document.getElementById(`zenThemeMarketplaceItemConfigureButton-${sanitizedName}`).removeAttribute('hidden'); + } + } + setTimeout(() => { + // We use a timeout to make sure the theme list has been updated before re-enabling the button. + event.target.removeAttribute('disabled'); + }, 400); + }); + + fragment.querySelector('.zenThemeMarketplaceItemTitle').textContent = themeName; + fragment.querySelector('.zenThemeMarketplaceItemDescription').textContent = theme.description; + fragment.querySelector('.zenThemeMarketplaceItemUninstallButton').addEventListener('click', async (event) => { + const [msg] = await document.l10n.formatValues([{ id: 'zen-theme-marketplace-remove-confirmation' }]); + + if (!confirm(msg)) { + return; + } + + await this.removeTheme(event.target.getAttribute('zen-theme-id')); + }); + + if (theme.preferences) { + fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').addEventListener('click', () => { + dialog.showModal(); + }); + + if (isThemeEnabled) { + fragment.querySelector('.zenThemeMarketplaceItemConfigureButton').removeAttribute('hidden'); + } + } + + const preferences = await ZenThemesCommon.getThemePreferences(theme); + + if (preferences.length > 0) { + const preferencesWrapper = document.createXULElement('vbox'); + + preferencesWrapper.setAttribute('flex', '1'); + + for (const entry of preferences) { + const { property, label, type, placeholder } = entry; + + switch (type) { + case 'dropdown': { + const { options } = entry; + + const container = document.createXULElement('hbox'); + container.classList.add('zenThemeMarketplaceItemPreference'); + container.setAttribute('align', 'center'); + container.setAttribute('role', 'group'); + + const menulist = document.createXULElement('menulist'); + const menupopup = document.createXULElement('menupopup'); + + menulist.setAttribute('sizetopopup', 'none'); + menulist.setAttribute('id', property + '-popup-menulist'); + + const savedValue = Services.prefs.getStringPref(property, 'none'); + + menulist.setAttribute('value', savedValue); + menulist.setAttribute('tooltiptext', property); + + const defaultItem = document.createXULElement('menuitem'); + + defaultItem.setAttribute('value', 'none'); + + if (placeholder) { + defaultItem.setAttribute('label', placeholder || '-'); + } else { + browser.document.l10n.setAttributes(defaultItem, 'zen-theme-marketplace-dropdown-default-label'); + } + + menupopup.appendChild(defaultItem); + + for (const option of options) { + const { label, value } = option; + + const valueType = typeof value; + + if (!['string', 'number'].includes(valueType)) { + console.log( + `[ZenThemeMarketplaceParent:settings]: Warning, invalid data type received (${valueType}), skipping.` + ); + continue; + } + + const menuitem = document.createXULElement('menuitem'); + + menuitem.setAttribute('value', value.toString()); + menuitem.setAttribute('label', label); + + menupopup.appendChild(menuitem); + } + + menulist.appendChild(menupopup); + + menulist.addEventListener('command', () => { + const value = menulist.selectedItem.value; + + let element = browser.document.getElementById(sanitizedName); + + if (!element) { + element = browser.document.createElement('div'); + + element.style.display = 'none'; + element.setAttribute('id', sanitizedName); + + browser.document.body.appendChild(element); + } + + element.setAttribute(property?.replaceAll(/\./g, '-'), value); + + Services.prefs.setStringPref(property, value === 'none' ? '' : value); + this._triggerBuildUpdateWithoutRebuild(); + }); + + const nameLabel = document.createXULElement('label'); + nameLabel.setAttribute('flex', '1'); + nameLabel.setAttribute('class', 'zenThemeMarketplaceItemPreferenceLabel'); + nameLabel.setAttribute('value', label); + nameLabel.setAttribute('tooltiptext', property); + + container.appendChild(nameLabel); + container.appendChild(menulist); + container.setAttribute('aria-labelledby', label); + + preferencesWrapper.appendChild(container); + break; + } + + case 'checkbox': { + const checkbox = window.MozXULElement.parseXULToFragment(` + + + + `); + + const checkboxElement = checkbox.querySelector('.zenThemeMarketplaceItemPreferenceCheckbox'); + checkboxElement.setAttribute('label', label); + checkboxElement.setAttribute('tooltiptext', property); + checkboxElement.setAttribute('zen-pref', property); + + // Checkbox only works with "true" and "false" values, it's not like HTML checkboxes. + if (Services.prefs.getBoolPref(property, false)) { + checkboxElement.setAttribute('checked', 'true'); + } + + checkboxElement.addEventListener('click', (event) => { + const target = event.target.closest('.zenThemeMarketplaceItemPreferenceCheckbox'); + const key = target.getAttribute('zen-pref'); + const checked = target.hasAttribute('checked'); + + if (!checked) { + target.removeAttribute('checked'); + } else { + target.setAttribute('checked', 'true'); + } + + Services.prefs.setBoolPref(key, !checked); + }); + + preferencesWrapper.appendChild(checkbox); + break; + } + + case 'string': { + const container = document.createXULElement('hbox'); + container.classList.add('zenThemeMarketplaceItemPreference'); + container.setAttribute('align', 'center'); + container.setAttribute('role', 'group'); + + const savedValue = Services.prefs.getStringPref(property, ''); + const sanitizedProperty = property?.replaceAll(/\./g, '-'); + + const input = document.createElement('input'); + input.setAttribute('flex', '1'); + input.setAttribute('type', 'text'); + input.id = `${sanitizedProperty}-input`; + input.value = savedValue; + + if (placeholder) { + input.setAttribute('placeholder', placeholder || '-'); + } else { + browser.document.l10n.setAttributes(input, 'zen-theme-marketplace-input-default-placeholder'); + } + + input.addEventListener( + 'input', + ZenThemesCommon.throttle((event) => { + const value = event.target.value; + + Services.prefs.setStringPref(property, value); + this._triggerBuildUpdateWithoutRebuild(); + + if (value === '') { + browser.document.querySelector(':root').style.removeProperty(`--${sanitizedProperty}`); + } else { + browser.document.querySelector(':root').style.setProperty(`--${sanitizedProperty}`, value); + } + }, 500) + ); + + const nameLabel = document.createXULElement('label'); + nameLabel.setAttribute('flex', '1'); + nameLabel.setAttribute('class', 'zenThemeMarketplaceItemPreferenceLabel'); + nameLabel.setAttribute('value', label); + nameLabel.setAttribute('tooltiptext', property); + + container.appendChild(nameLabel); + container.appendChild(input); + container.setAttribute('aria-labelledby', label); + + preferencesWrapper.appendChild(container); + break; + } + + default: + console.log( + `[ZenThemeMarketplaceParent:settings]: Warning, unknown preference type received (${type}), skipping.` + ); + continue; + } + } + contentDiv.appendChild(preferencesWrapper); + } + themeList.appendChild(fragment); + } + + this.themesList.replaceChildren(...themeList.children); + themeList.remove(); + }, +}; + +var gZenLooksAndFeel = { + init() { + if (this.__hasInitialized) return; + this.__hasInitialized = true; + this._initializeColorPicker(this._getInitialAccentColor()); + window.zenPageAccentColorChanged = this._handleAccentColorChange.bind(this); + gZenThemeBuilder.init(); + gZenMarketplaceManager.init(); + var onPreferColorSchemeChange = this.onPreferColorSchemeChange.bind(this); + window.matchMedia('(prefers-color-scheme: dark)').addListener(onPreferColorSchemeChange); + this.onPreferColorSchemeChange(); + window.addEventListener('unload', () => { + window.matchMedia('(prefers-color-scheme: dark)').removeListener(onPreferColorSchemeChange); + }); + this.setDarkThemeListener(); + this.setCompactModeStyle(); + }, + + onPreferColorSchemeChange(event) { + const darkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches; + let elem = document.getElementById('ZenDarkThemeStyles'); + if (darkTheme) { + elem.removeAttribute('hidden'); + } else { + elem.setAttribute('hidden', 'true'); + } + }, + + setDarkThemeListener() { + const chooser = document.getElementById('zen-dark-theme-styles-form'); + const radios = [...chooser.querySelectorAll('input')]; + for (let radio of radios) { + if (radio.value === 'amoled' && Services.prefs.getBoolPref('zen.theme.color-prefs.amoled')) { + radio.checked = true; + } else if (radio.value === 'colorful' && Services.prefs.getBoolPref('zen.theme.color-prefs.colorful')) { + radio.checked = true; + } else if ( + radio.value === 'default' && + !Services.prefs.getBoolPref('zen.theme.color-prefs.amoled') && + !Services.prefs.getBoolPref('zen.theme.color-prefs.colorful') + ) { + radio.checked = true; + } + radio.addEventListener('change', (e) => { + let value = e.target.value; + switch (value) { + case 'amoled': + Services.prefs.setBoolPref('zen.theme.color-prefs.amoled', true); + Services.prefs.setBoolPref('zen.theme.color-prefs.colorful', false); + break; + case 'colorful': + Services.prefs.setBoolPref('zen.theme.color-prefs.amoled', false); + Services.prefs.setBoolPref('zen.theme.color-prefs.colorful', true); + break; + default: + Services.prefs.setBoolPref('zen.theme.color-prefs.amoled', false); + Services.prefs.setBoolPref('zen.theme.color-prefs.colorful', false); + break; + } + }); + } + }, + + setCompactModeStyle() { + const chooser = document.getElementById('zen-compact-mode-styles-form'); + const radios = [...chooser.querySelectorAll('input')]; + + let value = ''; + if ( + Services.prefs.getBoolPref('zen.view.compact.hide-tabbar') && + Services.prefs.getBoolPref('zen.view.compact.hide-toolbar') + ) { + value = 'both'; + } else { + value = Services.prefs.getBoolPref('zen.view.compact.hide-tabbar') ? 'left' : 'top'; + } + chooser.querySelector(`[value='${value}']`).checked = true; + for (let radio of radios) { + radio.addEventListener('change', (e) => { + let value = e.target.value; + switch (value) { + case 'left': + Services.prefs.setBoolPref('zen.view.compact.hide-tabbar', true); + Services.prefs.setBoolPref('zen.view.compact.hide-toolbar', false); + break; + case 'top': + Services.prefs.setBoolPref('zen.view.compact.hide-tabbar', false); + Services.prefs.setBoolPref('zen.view.compact.hide-toolbar', true); + break; + default: + Services.prefs.setBoolPref('zen.view.compact.hide-tabbar', true); + Services.prefs.setBoolPref('zen.view.compact.hide-toolbar', true); + break; + } + }); + } + }, + + _initializeColorPicker(accentColor) { + let elem = document.getElementById('zenLooksAndFeelColorOptions'); + elem.innerHTML = ''; + for (let color of ZenThemesCommon.kZenColors) { + let colorElemParen = document.createElement('div'); + let colorElem = document.createElement('div'); + colorElemParen.classList.add('zenLooksAndFeelColorOptionParen'); + colorElem.classList.add('zenLooksAndFeelColorOption'); + colorElem.style.setProperty('--zen-primary-color', color, 'important'); + if (accentColor === color) { + colorElemParen.setAttribute('selected', 'true'); + } + colorElemParen.addEventListener('click', () => { + Services.prefs.setBoolPref('zen.theme.color-prefs.use-workspace-colors', false); + Services.prefs.setStringPref('zen.theme.accent-color', color); + }); + colorElemParen.appendChild(colorElem); + elem.appendChild(colorElemParen); + } + // TODO: add custom color selection! + }, + + _handleAccentColorChange(accentColor) { + this._initializeColorPicker(accentColor); + }, + + _getInitialAccentColor() { + return Services.prefs.getStringPref('zen.theme.accent-color', ZenThemesCommon.kZenColors[0]); + }, +}; + +var gZenWorkspacesSettings = { + init() { + var tabsUnloaderPrefListener = { + async observe(subject, topic, data) { + let buttonIndex = await confirmRestartPrompt(true, 1, true, true); + if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { + Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); + } + }, + }; + Services.prefs.addObserver('zen.workspaces.enabled', this); + Services.prefs.addObserver('zen.tab-unloader.enabled', tabsUnloaderPrefListener); + Services.prefs.addObserver('zen.glance.enabled', tabsUnloaderPrefListener); // We can use the same listener for both prefs + Services.prefs.addObserver('zen.glance.activation-method', tabsUnloaderPrefListener); + window.addEventListener('unload', () => { + Services.prefs.removeObserver('zen.workspaces.enabled', this); + Services.prefs.removeObserver('zen.tab-unloader.enabled', tabsUnloaderPrefListener); + Services.prefs.removeObserver('zen.glance.enabled', tabsUnloaderPrefListener); + Services.prefs.removeObserver('zen.glance.activation-method', tabsUnloaderPrefListener); + }); + }, + + async observe(subject, topic, data) { + await this.onWorkspaceChange(Services.prefs.getBoolPref('zen.workspaces.enabled')); + }, + + async onWorkspaceChange(checked) { + if (checked) { + let buttonIndex = await confirmRestartPrompt(true, 1, true, false); + if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { + Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); + return; + } + } + }, +}; + +const ZEN_CKS_CLASS_BASE = 'zenCKSOption'; +const ZEN_CKS_INPUT_FIELD_CLASS = `${ZEN_CKS_CLASS_BASE}-input`; +const ZEN_CKS_LABEL_CLASS = `${ZEN_CKS_CLASS_BASE}-label`; +const ZEN_CKS_WRAPPER_ID = `${ZEN_CKS_CLASS_BASE}-wrapper`; +const ZEN_CKS_GROUP_PREFIX = `${ZEN_CKS_CLASS_BASE}-group`; +const KEYBIND_ATTRIBUTE_KEY = 'key'; + +var zenMissingKeyboardShortcutL10n = { + key_quickRestart: 'zen-key-quick-restart', + key_delete: 'zen-key-delete', + goBackKb: 'zen-key-go-back', + goForwardKb: 'zen-key-go-forward', + key_enterFullScreen: 'zen-key-enter-full-screen', + key_exitFullScreen: 'zen-key-exit-full-screen', + key_aboutProcesses: 'zen-key-about-processes', + key_stop: 'zen-key-stop', + key_sanitize: 'zen-key-sanitize', + key_wrCaptureCmd: 'zen-key-wr-capture-cmd', + key_wrToggleCaptureSequenceCmd: 'zen-key-wr-toggle-capture-sequence-cmd', + key_undoCloseWindow: 'zen-key-undo-close-window', + + key_selectTab1: 'zen-key-select-tab-1', + key_selectTab2: 'zen-key-select-tab-2', + key_selectTab3: 'zen-key-select-tab-3', + key_selectTab4: 'zen-key-select-tab-4', + key_selectTab5: 'zen-key-select-tab-5', + key_selectTab6: 'zen-key-select-tab-6', + key_selectTab7: 'zen-key-select-tab-7', + key_selectTab8: 'zen-key-select-tab-8', + key_selectLastTab: 'zen-key-select-tab-last', + + key_showAllTabs: 'zen-key-show-all-tabs', + key_gotoHistory: 'zen-key-goto-history', + + goHome: 'zen-key-go-home', + key_redo: 'zen-key-redo', +}; + +var gZenCKSSettings = { + async init() { + await this._initializeCKS(); + if (this.__hasInitialized) return; + this.__hasInitialized = true; + this._currentActionID = null; + this._initializeEvents(); + window.addEventListener('unload', () => { + this.__hasInitialized = false; + document.getElementById(ZEN_CKS_WRAPPER_ID).innerHTML = ''; + }); + }, + + _initializeEvents() { + const resetAllListener = this.resetAllShortcuts.bind(this); + const handleKeyDown = this._handleKeyDown.bind(this); + window.addEventListener('keydown', handleKeyDown); + const button = document.getElementById('zenCKSResetButton'); + button.addEventListener('click', resetAllListener); + window.addEventListener('unload', () => { + window.removeEventListener('keydown', handleKeyDown); + button.removeEventListener('click', resetAllListener); + }); + }, + + async resetAllShortcuts() { + let buttonIndex = await confirmRestartPrompt(true, 1, true, false); + if (buttonIndex == CONFIRM_RESTART_PROMPT_RESTART_NOW) { + await gZenKeyboardShortcutsManager.resetAllShortcuts(); + Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart); + } + }, + + async _initializeCKS() { + let wrapper = document.getElementById(ZEN_CKS_WRAPPER_ID); + wrapper.innerHTML = ''; + + let shortcuts = await gZenKeyboardShortcutsManager.getModifiableShortcuts(); + + if (!shortcuts) { + throw Error('No shortcuts defined!'); + } + + // Generate section per each group + for (let group of VALID_SHORTCUT_GROUPS) { + let groupClass = `${ZEN_CKS_GROUP_PREFIX}-${group}`; + if (!wrapper.querySelector(`[data-group="${groupClass}"]`)) { + let groupElem = document.createElement('h2'); + groupElem.setAttribute('data-group', groupClass); + document.l10n.setAttributes(groupElem, groupClass); + wrapper.appendChild(groupElem); + } + } + + for (let shortcut of shortcuts) { + const keyID = shortcut.getID(); + const action = shortcut.getAction(); + const l10nID = shortcut.getL10NID(); + const group = shortcut.getGroup(); + const keyInString = shortcut.toUserString(); + + const labelValue = zenMissingKeyboardShortcutL10n[keyID] ?? l10nID; + + let fragment = window.MozXULElement.parseXULToFragment(` + + + + + + + `); + + const label = fragment.querySelector(`.${ZEN_CKS_LABEL_CLASS}`); + if (!labelValue) { + label.textContent = action; // Just in case + } else { + document.l10n.setAttributes(label, labelValue); + } + + let input = fragment.querySelector(`.${ZEN_CKS_INPUT_FIELD_CLASS}`); + if (keyInString && !shortcut.isEmpty()) { + input.value = keyInString; + } else { + this._resetShortcut(input); + } + + input.setAttribute(KEYBIND_ATTRIBUTE_KEY, keyID); + input.setAttribute('data-group', group); + input.setAttribute('data-id', keyID); + + input.addEventListener('focus', (event) => { + const value = event.target.getAttribute(KEYBIND_ATTRIBUTE_KEY); + this._currentActionID = event.target.getAttribute('data-id'); + event.target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); + this._hasSafed = true; + }); + + input.addEventListener('editDone', (event) => { + const target = event.target; + target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); + }); + + input.addEventListener('blur', (event) => { + const target = event.target; + target.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); + if (!this._hasSafed) { + target.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-unsafed`); + if (!target.nextElementSibling) { + target.after( + window.MozXULElement.parseXULToFragment(` + + `) + ); + target.value = 'Not set'; + } + } else { + target.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-unsafed`); + const sibling = target.nextElementSibling; + if (sibling && sibling.classList.contains(`${ZEN_CKS_CLASS_BASE}-unsafed`)) { + sibling.remove(); + } + } + }); + + const groupElem = wrapper.querySelector(`[data-group="${ZEN_CKS_GROUP_PREFIX}-${group}"]`); + groupElem.after(fragment); + } + }, + + async _resetShortcut(input) { + input.value = 'Not set'; + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); + input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-not-set`); + + if (this._currentActionID) { + this._editDone(); + await gZenKeyboardShortcutsManager.setShortcut(this._currentActionID, null, null); + } + }, + + _editDone(shortcut, modifiers) { + // Check if we have a valid key + if (!shortcut || !modifiers) { + return; + } + gZenKeyboardShortcutsManager.setShortcut(this._currentActionID, shortcut, modifiers); + this._currentActionID = null; + }, + + //TODO Check for duplicates + async _handleKeyDown(event) { + if (!this._currentActionID || document.hidden) { + return; + } + + event.preventDefault(); + + let input = document.querySelector(`.${ZEN_CKS_INPUT_FIELD_CLASS}[${KEYBIND_ATTRIBUTE_KEY}="${this._currentActionID}"]`); + const modifiers = new KeyShortcutModifiers(event.ctrlKey, event.altKey, event.shiftKey, event.metaKey, false); + const modifiersActive = modifiers.areAnyActive(); + + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-not-set`); + + // This is because on some OSs (windows/macos mostly) the key is not the same as the keycode + // e.g. CTRL+ALT+3 may be displayed as the euro sign + let shortcut = event.key; + + shortcut = shortcut.replace(/Ctrl|Control|Shift|Alt|Option|Cmd|Meta/, ''); // Remove all modifiers + + if (shortcut == 'Tab' && !modifiersActive) { + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); + this._latestValidKey = null; + return; + } else if (shortcut == 'Escape' && !modifiersActive) { + const hasConflicts = gZenKeyboardShortcutsManager.checkForConflicts( + this._latestValidKey ? this._latestValidKey : shortcut, + this._latestModifier ? this._latestModifier : modifiers, + this._currentActionID + ); + + if (!this._latestValidKey && !this._latestModifier) { + } else if (!this._latestValidKey || hasConflicts) { + if (!input.classList.contains(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`)) { + input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); + } + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-unsafed`); + if (hasConflicts && !input.nextElementSibling) { + input.after( + window.MozXULElement.parseXULToFragment(` + + `) + ); + } + } else { + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-editing`); + + this._editDone(this._latestValidKey, this._latestModifier); + this._latestValidKey = null; + this._latestModifier = null; + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); + input.classList.add(`${ZEN_CKS_INPUT_FIELD_CLASS}-valid`); + setTimeout(() => { + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-valid`); + }, 1000); + const sibling = input.nextElementSibling; + if (sibling && sibling.classList.contains(`${ZEN_CKS_CLASS_BASE}-conflict`)) { + sibling.remove(); + } + } + this._hasSafed = true; + input.blur(); + this._currentActionID = null; + return; + } else if (shortcut == 'Backspace' && !modifiersActive) { + this._resetShortcut(input); + this._latestValidKey = null; + this._latestModifier = null; + this._hasSafed = true; + return; + } + + this._latestModifier = modifiers; + this._hasSafed = false; + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-invalid`); + input.classList.remove(`${ZEN_CKS_INPUT_FIELD_CLASS}-not-set`); + input.value = modifiers.toUserString() + shortcut; + this._latestValidKey = shortcut; + }, +}; + +Preferences.addAll([ + { + id: 'zen.sidebar.enabled', + type: 'bool', + default: true, + }, + { + id: 'zen.sidebar.close-on-blur', + type: 'bool', + default: true, + }, + { + id: 'zen.view.compact', + type: 'bool', + default: false, + }, + { + id: 'zen.view.compact.hide-toolbar', + type: 'bool', + default: false, + }, + { + id: 'zen.view.compact.toolbar-flash-popup', + type: 'bool', + default: true, + }, + { + id: 'zen.workspaces.enabled', + type: 'bool', + default: true, + }, + { + id: 'zen.theme.pill-button', + type: 'bool', + default: true, + }, + { + id: 'zen.workspaces.hide-default-container-indicator', + type: 'bool', + default: true, + }, + { + id: 'zen.workspaces.individual-pinned-tabs', + type: 'bool', + default: true, + }, + { + id: 'zen.workspaces.show-icon-strip', + type: 'bool', + default: true, + }, + { + id: 'zen.tab-unloader.enabled', + type: 'bool', + default: true, + }, + { + id: 'zen.splitView.change-on-hover', + type: 'bool', + default: true, + }, + { + id: 'zen.tab-unloader.timeout-minutes', + type: 'int', + default: 10, + }, + { + id: 'zen.view.show-bottom-border', + type: 'bool', + default: false, + }, + { + id: 'zen.workspaces.hide-deactivated-workspaces', + type: 'bool', + default: true, + }, + { + id: 'zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', + type: 'bool', + default: true, + }, + { + id: 'zen.pinned-tab-manager.close-shortcut-behavior', + type: 'string', + default: 'switch', + }, + { + id: 'zen.workspaces.force-container-workspace', + type: 'bool', + default: true, + }, + { + id: 'zen.workspaces.open-new-tab-if-last-unpinned-tab-is-closed', + type: 'bool', + default: true, + }, + { + id: 'zen.tabs.show-newtab-under', + type: 'bool', + default: false, + }, + { + id: "zen.glance.activation-method", + type: "string", + default: "ctrl", + }, + { + id: "zen.glance.enabled", + type: "bool", + default: true, + }, + { + id: "zen.theme.color-prefs.use-workspace-colors", + type: "bool", + default: false, + }, + { + id: "zen.view.compact.color-toolbar", + type: "bool", + default: true, + }, + { + id: "zen.view.compact.color-sidebar", + type: "bool", + default: true, + }, + { + id: "zen.essentials.enabled", + type: "bool", + default: true, + }, + { + id: 'zen.workspaces.container-specific-essentials-enabled', + type: 'bool', + default: false, + }, + { + id: "zen.tabs.show-newtab-vertical", + type: "bool", + default: true, + }, + { + id: "zen.view.show-newtab-button-border-top", + type: "bool", + default: false, + }, + { + id: "zen.view.show-newtab-button-top", + type: "bool", + default: true, + }, + { + id: "zen.tabs.openNewTabByDblclick", + type: "bool", + default: true, + }, +]); diff --git a/src/browser/components/preferences/zenLooksAndFeel.inc.xhtml b/src/browser/components/preferences/zenLooksAndFeel.inc.xhtml index 2c92b5fd5..9fd0a788c 100644 --- a/src/browser/components/preferences/zenLooksAndFeel.inc.xhtml +++ b/src/browser/components/preferences/zenLooksAndFeel.inc.xhtml @@ -1,342 +1,345 @@ -