tor-browser

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

sidebar-pins-promo.mjs (5470B)


      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 https://mozilla.org/MPL/2.0/. */
      4 
      5 import {
      6  classMap,
      7  html,
      8  map,
      9  nothing,
     10 } from "chrome://global/content/vendor/lit.all.mjs";
     11 import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
     12 
     13 const { XPCOMUtils } = ChromeUtils.importESModule(
     14  "resource://gre/modules/XPCOMUtils.sys.mjs"
     15 );
     16 
     17 let lazy = {};
     18 ChromeUtils.defineESModuleGetters(lazy, {
     19  SidebarManager:
     20    "moz-src:///browser/components/sidebar/SidebarManager.sys.mjs",
     21 });
     22 const TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
     23 
     24 /**
     25 * A promotional card for drag-to-pin tabs.
     26 *
     27 * It is only displayed in the expanded sidebar state to vertical tab users who
     28 * do not have any pinned tabs.
     29 *
     30 * The card can be dismissed manually by clicking the X button. It is
     31 * automatically dismissed by adding a pin via a context menu or by dragging
     32 * the tab over the card and pinning.
     33 */
     34 export default class SidebarPinsPromo extends MozLitElement {
     35  static queries = {
     36    card: ".promo-card",
     37    closeButton: ".close-button",
     38  };
     39 
     40  constructor() {
     41    super();
     42    XPCOMUtils.defineLazyPreferenceGetter(
     43      this,
     44      "verticalTabsEnabled",
     45      "sidebar.verticalTabs",
     46      false,
     47      () => this.requestUpdate()
     48    );
     49    XPCOMUtils.defineLazyPreferenceGetter(
     50      this,
     51      "dragToPinPromoDismissed",
     52      "sidebar.verticalTabs.dragToPinPromo.dismissed",
     53      false,
     54      () => this.requestUpdate()
     55    );
     56    this.launcherObserver = new MutationObserver(() => this.requestUpdate());
     57  }
     58  #icons = [
     59    { name: "firefox", src: "chrome://browser/skin/sidebar/firefox.svg" },
     60    { name: "slack", src: "chrome://browser/skin/sidebar/slack.svg" },
     61    { name: "foxy", src: "chrome://browser/skin/sidebar/foxy.svg" },
     62    { name: "gmail", src: "chrome://browser/skin/sidebar/gmail.svg" },
     63  ];
     64 
     65  connectedCallback() {
     66    super.connectedCallback();
     67    window.addEventListener("TabPinned", this);
     68    this.addEventListener("dragover", this);
     69    this.addEventListener("drop", this);
     70    this.addEventListener("dragleave", this);
     71    lazy.SidebarManager.addEventListener("checkForPinnedTabsComplete", this);
     72    lazy.SidebarManager.checkForPinnedTabs();
     73    this.launcherObserver.observe(window.SidebarController.sidebarMain, {
     74      attributeFilter: ["expanded"],
     75    });
     76 
     77    XPCOMUtils.defineLazyPreferenceGetter(
     78      this,
     79      "verticalTabsEnabled",
     80      "sidebar.verticalTabs",
     81      false,
     82      () => this.requestUpdate()
     83    );
     84    XPCOMUtils.defineLazyPreferenceGetter(
     85      this,
     86      "dragToPinPromoDismissed",
     87      "sidebar.verticalTabs.dragToPinPromo.dismissed",
     88      false,
     89      () => this.requestUpdate()
     90    );
     91  }
     92 
     93  disconnectedCallback() {
     94    super.disconnectedCallback();
     95    window.removeEventListener("TabPinned", this);
     96    this.removeEventListener("dragover", this);
     97    this.removeEventListener("drop", this);
     98    this.removeEventListener("dragleave", this);
     99    lazy.SidebarManager.removeEventListener("checkForPinnedTabsComplete", this);
    100    this.launcherObserver.disconnect();
    101  }
    102 
    103  /**
    104   * Handle drag-and-drop events from MozTabbrowserTab elements.
    105   *
    106   * @param {DragEvent} event
    107   */
    108  handleEvent(event) {
    109    switch (event.type) {
    110      case "dragover":
    111        if (event.dataTransfer.types.includes(TAB_DROP_TYPE)) {
    112          event.preventDefault();
    113          this.card.toggleAttribute("dragactive", true);
    114        }
    115        break;
    116      case "drop":
    117      case "dragleave":
    118        this.card.toggleAttribute("dragactive", false);
    119        break;
    120      case "TabPinned":
    121        this.dismissDragToPinPromo();
    122        break;
    123      case "checkForPinnedTabsComplete":
    124        this.requestUpdate();
    125        break;
    126    }
    127  }
    128 
    129  dismissDragToPinPromo() {
    130    Services.prefs.setBoolPref(
    131      "sidebar.verticalTabs.dragToPinPromo.dismissed",
    132      true
    133    );
    134  }
    135 
    136  /**
    137   * Wrap one of the icons to be shown in a dotted border box.
    138   *
    139   * @param {object} icon
    140   * @returns {HTMLDivElement}
    141   */
    142  #iconCellTemplate(icon) {
    143    return html`<div
    144      class=${classMap({
    145        "icon-cell": true,
    146        [`icon-${icon.name}`]: true,
    147      })}
    148    >
    149      <img src=${icon.src} role="presentation" />
    150    </div>`;
    151  }
    152 
    153  get shouldRender() {
    154    return (
    155      this.verticalTabsEnabled &&
    156      lazy.SidebarManager.checkForPinnedTabsComplete &&
    157      !this.dragToPinPromoDismissed &&
    158      window.SidebarController.sidebarMain.hasAttribute("expanded")
    159    );
    160  }
    161 
    162  willUpdate() {
    163    this.toggleAttribute("hidden", !this.shouldRender);
    164  }
    165 
    166  render() {
    167    if (!this.shouldRender) {
    168      return nothing;
    169    }
    170    return html` <link
    171        rel="stylesheet"
    172        href="chrome://browser/content/sidebar/sidebar-pins-promo.css"
    173      />
    174      <moz-card class="promo-card">
    175        <div class="promo-text" data-l10n-id="sidebar-pins-promo-text"></div>
    176        <div class="icon-row">
    177          ${map(this.#icons, icon => this.#iconCellTemplate(icon))}
    178        </div>
    179      </moz-card>
    180      <moz-button
    181        class="close-button"
    182        iconsrc="resource://content-accessible/close-12.svg"
    183        data-l10n-id="sidebar-panel-header-close-button"
    184        @click=${this.dismissDragToPinPromo}
    185        size="small"
    186        type="icon ghost"
    187      >
    188      </moz-button>`;
    189  }
    190 }
    191 
    192 customElements.define("sidebar-pins-promo", SidebarPinsPromo);