tor-browser

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

syncedtabs-tab-list.mjs (5940B)


      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  ifDefined,
      8  when,
      9 } from "chrome://global/content/vendor/lit.all.mjs";
     10 import {
     11  FxviewTabListBase,
     12  FxviewTabRowBase,
     13 } from "chrome://browser/content/firefoxview/fxview-tab-list.mjs";
     14 // eslint-disable-next-line import/no-unassigned-import
     15 import "chrome://global/content/elements/moz-button.mjs";
     16 
     17 const lazy = {};
     18 let XPCOMUtils;
     19 
     20 XPCOMUtils = ChromeUtils.importESModule(
     21  "resource://gre/modules/XPCOMUtils.sys.mjs"
     22 ).XPCOMUtils;
     23 XPCOMUtils.defineLazyPreferenceGetter(
     24  lazy,
     25  "virtualListEnabledPref",
     26  "browser.firefox-view.virtual-list.enabled"
     27 );
     28 
     29 /**
     30 * A list of synced tabs that are clickable and able to be remotely closed
     31 */
     32 
     33 export class SyncedTabsTabList extends FxviewTabListBase {
     34  constructor() {
     35    super();
     36  }
     37 
     38  static queries = {
     39    ...FxviewTabListBase.queries,
     40    rowEls: {
     41      all: "syncedtabs-tab-row",
     42    },
     43  };
     44 
     45  itemTemplate = (tabItem, i) => {
     46    return html`
     47      <syncedtabs-tab-row
     48        ?active=${i == this.activeIndex}
     49        .canClose=${ifDefined(tabItem.canClose)}
     50        .closeRequested=${ifDefined(tabItem.closeRequested)}
     51        ?compact=${this.compactRows}
     52        .currentActiveElementId=${this.currentActiveElementId}
     53        .favicon=${tabItem.icon}
     54        .fxaDeviceId=${tabItem.fxaDeviceId}
     55        .primaryL10nId=${tabItem.primaryL10nId}
     56        .primaryL10nArgs=${ifDefined(tabItem.primaryL10nArgs)}
     57        .secondaryL10nId=${tabItem.secondaryL10nId}
     58        .secondaryL10nArgs=${ifDefined(tabItem.secondaryL10nArgs)}
     59        .tertiaryL10nId=${ifDefined(tabItem.tertiaryL10nId)}
     60        .tertiaryL10nArgs=${ifDefined(tabItem.tertiaryL10nArgs)}
     61        .secondaryActionClass=${this.secondaryActionClass}
     62        .tertiaryActionClass=${ifDefined(tabItem.tertiaryActionClass)}
     63        .sourceClosedId=${ifDefined(tabItem.sourceClosedId)}
     64        .sourceWindowId=${ifDefined(tabItem.sourceWindowId)}
     65        .closedId=${ifDefined(tabItem.closedId || tabItem.closedId)}
     66        role="listitem"
     67        .tabElement=${ifDefined(tabItem.tabElement)}
     68        .title=${tabItem.title}
     69        .url=${tabItem.url}
     70        .searchQuery=${ifDefined(this.searchQuery)}
     71        .hasPopup=${this.hasPopup}
     72      ></fxview-tab-row>
     73    `;
     74  };
     75 
     76  stylesheets() {
     77    return [
     78      super.stylesheets(),
     79      html`<link
     80        rel="stylesheet"
     81        href="chrome://browser/content/firefoxview/syncedtabs-tab-list.css"
     82      />`,
     83    ];
     84  }
     85 
     86  render() {
     87    if (this.searchQuery && !this.tabItems.length) {
     88      return this.emptySearchResultsTemplate();
     89    }
     90    return html`
     91      ${this.stylesheets()}
     92      <div
     93        id="fxview-tab-list"
     94        class="fxview-tab-list"
     95        data-l10n-id="firefoxview-tabs"
     96        role="list"
     97        @keydown=${this.handleFocusElementInRow}
     98      >
     99        ${when(
    100          lazy.virtualListEnabledPref,
    101          () => html`
    102            <virtual-list
    103              .activeIndex=${this.activeIndex}
    104              .items=${this.tabItems}
    105              .template=${this.itemTemplate}
    106            ></virtual-list>
    107          `,
    108          () =>
    109            html`${this.tabItems.map((tabItem, i) =>
    110              this.itemTemplate(tabItem, i)
    111            )}`
    112        )}
    113      </div>
    114      <slot name="menu"></slot>
    115    `;
    116  }
    117 }
    118 
    119 customElements.define("syncedtabs-tab-list", SyncedTabsTabList);
    120 
    121 /**
    122 * A tab item that displays favicon, title, url, and time of last access
    123 *
    124 * @property {boolean} canClose - Whether the tab item has the ability to be closed remotely
    125 * @property {boolean} closeRequested - Whether the tab has been requested closed but not removed from the list
    126 * @property {string} fxaDeviceId - The device Id the tab item belongs to, for closing tabs remotely
    127 */
    128 
    129 export class SyncedTabsTabRow extends FxviewTabRowBase {
    130  constructor() {
    131    super();
    132  }
    133 
    134  static properties = {
    135    ...FxviewTabRowBase.properties,
    136    canClose: { type: Boolean },
    137    closeRequested: { type: Boolean },
    138    fxaDeviceId: { type: String },
    139  };
    140 
    141  secondaryButtonTemplate() {
    142    return html`${when(
    143      this.secondaryL10nId && this.secondaryActionHandler,
    144      () =>
    145        html`<moz-button
    146          type="icon ghost"
    147          class="fxview-tab-row-button"
    148          iconSrc=${this.getIconSrc(this.secondaryActionClass)}
    149          ?disabled=${this.closeRequested}
    150          id="fxview-tab-row-secondary-button"
    151          data-l10n-id=${this.secondaryL10nId}
    152          data-l10n-args=${ifDefined(this.secondaryL10nArgs)}
    153          aria-haspopup=${ifDefined(this.hasPopup)}
    154          @click=${this.secondaryActionHandler}
    155          tabindex=${this.active &&
    156          this.currentActiveElementId === "fxview-tab-row-secondary-button"
    157            ? "0"
    158            : "-1"}
    159        ></moz-button>`
    160    )}`;
    161  }
    162 
    163  render() {
    164    return html`
    165      ${this.stylesheets()}
    166      <a
    167        href=${ifDefined(this.url)}
    168        class="fxview-tab-row-main"
    169        id="fxview-tab-row-main"
    170        ?disabled=${this.closeRequested}
    171        tabindex=${this.active &&
    172        this.currentActiveElementId === "fxview-tab-row-main"
    173          ? "0"
    174          : "-1"}
    175        data-l10n-id=${ifDefined(this.primaryL10nId)}
    176        data-l10n-args=${ifDefined(this.primaryL10nArgs)}
    177        @click=${this.primaryActionHandler}
    178        @keydown=${this.primaryActionHandler}
    179        title=${!this.primaryL10nId ? this.url : null}
    180      >
    181        ${this.faviconTemplate()} ${this.titleTemplate()}
    182        ${when(
    183          !this.compact,
    184          () =>
    185            html`${this.urlTemplate()} ${this.dateTemplate()}
    186            ${this.timeTemplate()}`
    187        )}
    188      </a>
    189      ${this.secondaryButtonTemplate()} ${this.tertiaryButtonTemplate()}
    190    `;
    191  }
    192 }
    193 
    194 customElements.define("syncedtabs-tab-row", SyncedTabsTabRow);