tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

sidebar-customize.mjs (12017B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import {
      6  html,
      7  when,
      8  ifDefined,
      9 } from "chrome://global/content/vendor/lit.all.mjs";
     10 
     11 import { SidebarPage } from "./sidebar-page.mjs";
     12 
     13 const { XPCOMUtils } = ChromeUtils.importESModule(
     14  "resource://gre/modules/XPCOMUtils.sys.mjs"
     15 );
     16 
     17 const l10nMap = new Map([
     18  ["viewGenaiChatSidebar", "sidebar-menu-genai-chat-label"],
     19  ["viewGenaiPageAssistSidebar", "sidebar-menu-genai-page-assist-label"],
     20  ["viewGenaiSmartAssistSidebar", "sidebar-menu-genai-smart-assist-label"],
     21  ["viewHistorySidebar", "sidebar-menu-history-label"],
     22  ["viewTabsSidebar", "sidebar-menu-synced-tabs-label"],
     23  ["viewBookmarksSidebar", "sidebar-menu-bookmarks-label"],
     24  ["viewCPMSidebar", "sidebar-menu-contextual-password-manager-label"],
     25 ]);
     26 const VISIBILITY_SETTING_PREF = "sidebar.visibility";
     27 const EXPAND_ON_HOVER_PREF = "sidebar.expandOnHover";
     28 const POSITION_SETTING_PREF = "sidebar.position_start";
     29 const TAB_DIRECTION_SETTING_PREF = "sidebar.verticalTabs";
     30 
     31 export class SidebarCustomize extends SidebarPage {
     32  constructor() {
     33    super();
     34    XPCOMUtils.defineLazyPreferenceGetter(
     35      this.#prefValues,
     36      "visibility",
     37      VISIBILITY_SETTING_PREF,
     38      "always-show",
     39      (_aPreference, _previousValue, newValue) => {
     40        this.visibility = newValue;
     41      }
     42    );
     43    XPCOMUtils.defineLazyPreferenceGetter(
     44      this.#prefValues,
     45      "isPositionStart",
     46      POSITION_SETTING_PREF,
     47      true,
     48      (_aPreference, _previousValue, newValue) => {
     49        this.isPositionStart = newValue;
     50      }
     51    );
     52    XPCOMUtils.defineLazyPreferenceGetter(
     53      this.#prefValues,
     54      "verticalTabsEnabled",
     55      TAB_DIRECTION_SETTING_PREF,
     56      false,
     57      (_aPreference, _previousValue, newValue) => {
     58        this.verticalTabsEnabled = newValue;
     59      }
     60    );
     61    XPCOMUtils.defineLazyPreferenceGetter(
     62      this.#prefValues,
     63      "expandOnHoverEnabled",
     64      EXPAND_ON_HOVER_PREF,
     65      false,
     66      (_aPreference, _previousValue, newValue) => {
     67        this.expandOnHoverEnabled = newValue;
     68      }
     69    );
     70    this.visibility = this.#prefValues.visibility;
     71    this.isPositionStart = this.#prefValues.isPositionStart;
     72    this.verticalTabsEnabled = this.#prefValues.verticalTabsEnabled;
     73    this.expandOnHoverEnabled = this.#prefValues.expandOnHoverEnabled;
     74    this.boundObserve = (...args) => this.observe(...args);
     75  }
     76 
     77  #prefValues = {};
     78 
     79  static properties = {
     80    visibility: { type: String },
     81    isPositionStart: { type: Boolean },
     82    verticalTabsEnabled: { type: Boolean },
     83    expandOnHoverEnabled: { type: Boolean },
     84  };
     85 
     86  static queries = {
     87    toolInputs: { all: ".tools > .tool" },
     88    extensionInputs: { all: ".extensions > .tool" },
     89    extensionLink: ".extension-item a",
     90    positionInput: "#position",
     91    visibilityInput: "#hide-sidebar",
     92    verticalTabsInput: "#vertical-tabs",
     93    expandOnHoverInput: "#expand-on-hover",
     94  };
     95 
     96  connectedCallback() {
     97    super.connectedCallback();
     98    this.getWindow().addEventListener("SidebarItemAdded", this);
     99    this.getWindow().addEventListener("SidebarItemChanged", this);
    100    this.getWindow().addEventListener("SidebarItemRemoved", this);
    101  }
    102 
    103  disconnectedCallback() {
    104    super.disconnectedCallback();
    105    this.getWindow().removeEventListener("SidebarItemAdded", this);
    106    this.getWindow().removeEventListener("SidebarItemChanged", this);
    107    this.getWindow().removeEventListener("SidebarItemRemoved", this);
    108  }
    109 
    110  get fluentStrings() {
    111    if (!this._fluentStrings) {
    112      this._fluentStrings = new Localization(["browser/sidebar.ftl"], true);
    113    }
    114    return this._fluentStrings;
    115  }
    116 
    117  getWindow() {
    118    return window.browsingContext.embedderWindowGlobal.browsingContext.window;
    119  }
    120 
    121  handleEvent(e) {
    122    switch (e.type) {
    123      case "SidebarItemAdded":
    124      case "SidebarItemChanged":
    125      case "SidebarItemRemoved":
    126        this.requestUpdate();
    127        break;
    128    }
    129  }
    130 
    131  async onToggleToolInput(e, commandID) {
    132    e.preventDefault();
    133    this.getWindow().SidebarController.toggleTool(commandID);
    134    switch (commandID) {
    135      case "viewGenaiChatSidebar":
    136        Glean.sidebarCustomize.chatbotEnabled.record({
    137          checked: e.target.checked,
    138        });
    139        break;
    140      case "viewTabsSidebar":
    141        Glean.sidebarCustomize.syncedTabsEnabled.record({
    142          checked: e.target.checked,
    143        });
    144        break;
    145      case "viewHistorySidebar":
    146        Glean.sidebarCustomize.historyEnabled.record({
    147          checked: e.target.checked,
    148        });
    149        break;
    150      case "viewBookmarksSidebar":
    151        Glean.sidebarCustomize.bookmarksEnabled.record({
    152          checked: e.target.checked,
    153        });
    154        break;
    155      case "viewCPMSidebar":
    156        Glean.contextualManager.passwordsEnabled.record({
    157          checked: e.target.checked,
    158        });
    159        break;
    160    }
    161  }
    162 
    163  getInputL10nId(view) {
    164    return l10nMap.get(view);
    165  }
    166 
    167  openFirefoxSettings(e) {
    168    if (e.type == "click" || (e.type == "keydown" && e.code == "Enter")) {
    169      e.preventDefault();
    170      this.getWindow().openPreferences();
    171      Glean.sidebarCustomize.firefoxSettingsClicked.record();
    172    }
    173  }
    174 
    175  toolInputTemplate(tool) {
    176    if (tool.hidden) {
    177      return null;
    178    }
    179 
    180    return html`
    181      <moz-checkbox
    182        class="tool"
    183        type="checkbox"
    184        id=${tool.view}
    185        name=${tool.name}
    186        iconsrc=${tool.iconUrl}
    187        data-l10n-id=${ifDefined(this.getInputL10nId(tool.view))}
    188        label=${ifDefined(tool.tooltiptext)}
    189        @change=${e => this.onToggleToolInput(e, tool.commandID)}
    190        ?checked=${!tool.disabled}
    191      ></moz-checkbox>
    192    `;
    193  }
    194 
    195  manageAddons(e) {
    196    if (e.type == "click" || (e.type == "keydown" && e.code == "Enter")) {
    197      e.preventDefault();
    198      this.getWindow().BrowserAddonUI.openAddonsMgr("addons://list/extension");
    199      Glean.sidebarCustomize.extensionsClicked.record();
    200    }
    201  }
    202 
    203  reversePosition() {
    204    const { SidebarController } = this.getWindow();
    205    SidebarController.reversePosition();
    206    Glean.sidebarCustomize.sidebarPosition.record({
    207      position:
    208        this.isPositionStart !== this.getWindow().RTL_UI ? "left" : "right",
    209    });
    210  }
    211 
    212  render() {
    213    let extensions = this.getWindow().SidebarController.getExtensions();
    214    return html`
    215      ${this.stylesheet()}
    216      <link rel="stylesheet" href="chrome://browser/content/sidebar/sidebar-customize.css"></link>
    217      <div class="sidebar-panel">
    218        <sidebar-panel-header data-l10n-id="sidebar-menu-customize-header" data-l10n-attrs="heading" view="viewCustomizeSidebar">
    219        </sidebar-panel-header>
    220        <div class="sidebar-panel-scrollable-content">
    221          <moz-fieldset class="customize-group no-end-margin" data-l10n-id="sidebar-settings">
    222            <moz-checkbox
    223              type="checkbox"
    224              id="vertical-tabs"
    225              name="verticalTabs"
    226              iconsrc="chrome://browser/skin/sidebar-collapsed.svg"
    227              data-l10n-id="sidebar-vertical-tabs"
    228              @change=${this.#handleTabDirectionChange}
    229              ?checked=${this.verticalTabsEnabled}
    230            >
    231            ${when(
    232              this.verticalTabsEnabled,
    233              () => html`
    234                ${when(
    235                  this.expandOnHoverEnabled,
    236                  () => html`
    237                    <moz-checkbox
    238                      slot="nested"
    239                      type="checkbox"
    240                      id="expand-on-hover"
    241                      name="expand-on-hover"
    242                      data-l10n-id="expand-sidebar-on-hover"
    243                      @change=${this.#toggleExpandOnHover}
    244                      ?checked=${this.getWindow().SidebarController._state
    245                        .revampVisibility === "expand-on-hover"}
    246                      ?disabled=${this.visibility == "hide-sidebar"}
    247                    ></moz-checkbox>
    248                  `
    249                )}
    250                <moz-checkbox
    251                  slot="nested"
    252                  type="checkbox"
    253                  id="hide-sidebar"
    254                  name="hideSidebar"
    255                  data-l10n-id="sidebar-hide-tabs-and-sidebar"
    256                  @change=${this.#handleVisibilityChange}
    257                  ?checked=${this.visibility == "hide-sidebar"}
    258                  ?disabled=${this.getWindow().SidebarController._state
    259                    .revampVisibility === "expand-on-hover"}
    260                ></moz-checkbox>
    261              `
    262            )}
    263            </moz-checkbox>
    264          </moz-fieldset>
    265          <moz-fieldset class="customize-group medium-top-margin no-label">
    266            <moz-checkbox
    267              type="checkbox"
    268              id="position"
    269              name="position"
    270              data-l10n-id=${document.dir == "rtl" ? "sidebar-show-on-the-left" : "sidebar-show-on-the-right"}
    271              @change=${this.reversePosition}
    272              ?checked=${!this.isPositionStart}
    273          ></moz-checkbox>
    274          </moz-fieldset>
    275          <moz-fieldset class="customize-group tools" data-l10n-id="sidebar-customize-firefox-tools-header">
    276            ${this.getWindow()
    277              .SidebarController.getTools()
    278              .map(tool => this.toolInputTemplate(tool))}
    279          </moz-fieldset>
    280          ${when(
    281            extensions.length,
    282            () =>
    283              html`<div class="customize-group">
    284                <h4
    285                  class="customize-extensions-heading"
    286                  data-l10n-id="sidebar-customize-extensions-header"
    287                ></h4>
    288                <div role="list" class="extensions">
    289                  ${extensions.map(extension =>
    290                    this.toolInputTemplate(extension)
    291                  )}
    292                  <div class="extension-item">
    293                    <img
    294                      src="chrome://mozapps/skin/extensions/category-extensions.svg"
    295                      class="icon"
    296                      role="presentation"
    297                    />
    298                    <a
    299                      href="about:addons"
    300                      @click=${this.manageAddons}
    301                      @keydown=${this.manageAddons}
    302                      data-l10n-id="sidebar-manage-extensions"
    303                    >
    304                    </a>
    305                  </div>
    306                </div>
    307              </div>`
    308          )}
    309          <div id="manage-settings">
    310            <img src="chrome://browser/skin/preferences/category-general.svg" class="icon" role="presentation" />
    311            <a
    312              href="about:preferences"
    313              @click=${this.openFirefoxSettings}
    314              @keydown=${this.openFirefoxSettings}
    315              data-l10n-id="sidebar-customize-firefox-settings"
    316            >
    317            </a>
    318          </div>
    319        </div>
    320      </div>
    321    `;
    322  }
    323 
    324  #handleVisibilityChange(e) {
    325    e.stopPropagation();
    326    this.visibility = e.target.checked ? "hide-sidebar" : "always-show";
    327    Services.prefs.setStringPref(
    328      VISIBILITY_SETTING_PREF,
    329      e.target.checked ? "hide-sidebar" : "always-show"
    330    );
    331    Glean.sidebarCustomize.sidebarDisplay.record({
    332      preference: e.target.checked ? "hide" : "always",
    333    });
    334  }
    335 
    336  #toggleExpandOnHover(e) {
    337    e.stopPropagation();
    338    if (e.target.checked) {
    339      Services.prefs.setStringPref("sidebar.visibility", "expand-on-hover");
    340      Glean.sidebarCustomize.expandOnHoverEnabled.record({
    341        checked: true,
    342      });
    343    } else {
    344      Services.prefs.setStringPref("sidebar.visibility", "always-show");
    345    }
    346  }
    347 
    348  #handleTabDirectionChange({ target: { checked } }) {
    349    const verticalTabsEnabled = checked;
    350    Services.prefs.setBoolPref(TAB_DIRECTION_SETTING_PREF, verticalTabsEnabled);
    351    Glean.sidebarCustomize.tabsLayout.record({
    352      orientation: verticalTabsEnabled ? "vertical" : "horizontal",
    353    });
    354  }
    355 }
    356 
    357 customElements.define("sidebar-customize", SidebarCustomize);