tor-browser

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

SearchShortcutsForm.jsx (5413B)


      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 file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
      6 import React from "react";
      7 import { TOP_SITES_SOURCE } from "./TopSitesConstants";
      8 
      9 export class SelectableSearchShortcut extends React.PureComponent {
     10  render() {
     11    const { shortcut, selected } = this.props;
     12    const imageStyle = { backgroundImage: `url("${shortcut.tippyTopIcon}")` };
     13    return (
     14      <div className="top-site-outer search-shortcut">
     15        <input
     16          type="checkbox"
     17          id={shortcut.keyword}
     18          name={shortcut.keyword}
     19          checked={selected}
     20          onChange={this.props.onChange}
     21        />
     22        <label htmlFor={shortcut.keyword}>
     23          <div className="top-site-inner">
     24            <span>
     25              <div className="tile">
     26                <div
     27                  className="top-site-icon rich-icon"
     28                  style={imageStyle}
     29                  data-fallback="@"
     30                />
     31                <div className="top-site-icon search-topsite" />
     32              </div>
     33              <div className="title">
     34                <span dir="auto">{shortcut.keyword}</span>
     35              </div>
     36            </span>
     37          </div>
     38        </label>
     39      </div>
     40    );
     41  }
     42 }
     43 
     44 export class SearchShortcutsForm extends React.PureComponent {
     45  constructor(props) {
     46    super(props);
     47    this.handleChange = this.handleChange.bind(this);
     48    this.onCancelButtonClick = this.onCancelButtonClick.bind(this);
     49    this.onSaveButtonClick = this.onSaveButtonClick.bind(this);
     50 
     51    // clone the shortcuts and add them to the state so we can add isSelected property
     52    const shortcuts = [];
     53    const { rows, searchShortcuts } = props.TopSites;
     54    searchShortcuts.forEach(shortcut => {
     55      shortcuts.push({
     56        ...shortcut,
     57        isSelected: !!rows.find(
     58          row =>
     59            row &&
     60            row.isPinned &&
     61            row.searchTopSite &&
     62            row.label === shortcut.keyword
     63        ),
     64      });
     65    });
     66    this.state = { shortcuts };
     67  }
     68 
     69  handleChange(event) {
     70    const { target } = event;
     71    const { name: targetName, checked } = target;
     72    this.setState(prevState => {
     73      const shortcuts = prevState.shortcuts.slice();
     74      let shortcut = shortcuts.find(({ keyword }) => keyword === targetName);
     75      shortcut.isSelected = checked;
     76      return { shortcuts };
     77    });
     78  }
     79 
     80  onCancelButtonClick(ev) {
     81    ev.preventDefault();
     82    this.props.onClose();
     83  }
     84 
     85  onSaveButtonClick(ev) {
     86    ev.preventDefault();
     87 
     88    // Check if there were any changes and act accordingly
     89    const { rows } = this.props.TopSites;
     90    const pinQueue = [];
     91    const unpinQueue = [];
     92    this.state.shortcuts.forEach(shortcut => {
     93      const alreadyPinned = rows.find(
     94        row =>
     95          row &&
     96          row.isPinned &&
     97          row.searchTopSite &&
     98          row.label === shortcut.keyword
     99      );
    100      if (shortcut.isSelected && !alreadyPinned) {
    101        pinQueue.push(this._searchTopSite(shortcut));
    102      } else if (!shortcut.isSelected && alreadyPinned) {
    103        unpinQueue.push({
    104          url: alreadyPinned.url,
    105          searchVendor: shortcut.shortURL,
    106        });
    107      }
    108    });
    109 
    110    // Tell the feed to do the work.
    111    this.props.dispatch(
    112      ac.OnlyToMain({
    113        type: at.UPDATE_PINNED_SEARCH_SHORTCUTS,
    114        data: {
    115          addedShortcuts: pinQueue,
    116          deletedShortcuts: unpinQueue,
    117        },
    118      })
    119    );
    120 
    121    // Send the Telemetry pings.
    122    pinQueue.forEach(shortcut => {
    123      this.props.dispatch(
    124        ac.UserEvent({
    125          source: TOP_SITES_SOURCE,
    126          event: "SEARCH_EDIT_ADD",
    127          value: { search_vendor: shortcut.searchVendor },
    128        })
    129      );
    130    });
    131    unpinQueue.forEach(shortcut => {
    132      this.props.dispatch(
    133        ac.UserEvent({
    134          source: TOP_SITES_SOURCE,
    135          event: "SEARCH_EDIT_DELETE",
    136          value: { search_vendor: shortcut.searchVendor },
    137        })
    138      );
    139    });
    140 
    141    this.props.onClose();
    142  }
    143 
    144  _searchTopSite(shortcut) {
    145    return {
    146      url: shortcut.url,
    147      searchTopSite: true,
    148      label: shortcut.keyword,
    149      searchVendor: shortcut.shortURL,
    150    };
    151  }
    152 
    153  render() {
    154    return (
    155      <form className="topsite-form">
    156        <div className="search-shortcuts-container">
    157          <h3
    158            className="section-title grey-title"
    159            data-l10n-id="newtab-topsites-add-search-engine-header"
    160          />
    161          <div>
    162            {this.state.shortcuts.map(shortcut => (
    163              <SelectableSearchShortcut
    164                key={shortcut.keyword}
    165                shortcut={shortcut}
    166                selected={shortcut.isSelected}
    167                onChange={this.handleChange}
    168              />
    169            ))}
    170          </div>
    171        </div>
    172        <section className="actions">
    173          <button
    174            className="cancel"
    175            type="button"
    176            onClick={this.onCancelButtonClick}
    177            data-l10n-id="newtab-topsites-cancel-button"
    178          />
    179          <button
    180            className="done"
    181            type="submit"
    182            onClick={this.onSaveButtonClick}
    183            data-l10n-id="newtab-topsites-save-button"
    184          />
    185        </section>
    186      </form>
    187    );
    188  }
    189 }