tor-browser

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

ConfirmDialog.js (5512B)


      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 "use strict";
      6 
      7 loader.lazyRequireGetter(
      8  this,
      9  "PropTypes",
     10  "resource://devtools/client/shared/vendor/react-prop-types.js"
     11 );
     12 loader.lazyRequireGetter(
     13  this,
     14  "HTMLTooltip",
     15  "resource://devtools/client/shared/widgets/tooltip/HTMLTooltip.js",
     16  true
     17 );
     18 
     19 // React & Redux
     20 const {
     21  Component,
     22 } = require("resource://devtools/client/shared/vendor/react.mjs");
     23 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     24 const {
     25  createPortal,
     26 } = require("resource://devtools/client/shared/vendor/react-dom.mjs");
     27 const {
     28  connect,
     29 } = require("resource://devtools/client/shared/vendor/react-redux.js");
     30 
     31 const {
     32  getAutocompleteState,
     33 } = require("resource://devtools/client/webconsole/selectors/autocomplete.js");
     34 const autocompleteActions = require("resource://devtools/client/webconsole/actions/autocomplete.js");
     35 const {
     36  l10n,
     37 } = require("resource://devtools/client/webconsole/utils/messages.js");
     38 
     39 const LEARN_MORE_URL = `https://firefox-source-docs.mozilla.org/devtools-user/web_console/invoke_getters_from_autocomplete/`;
     40 
     41 class ConfirmDialog extends Component {
     42  static get propTypes() {
     43    return {
     44      // Console object.
     45      webConsoleUI: PropTypes.object.isRequired,
     46      // Update autocomplete popup state.
     47      autocompleteUpdate: PropTypes.func.isRequired,
     48      autocompleteClear: PropTypes.func.isRequired,
     49      // Data to be displayed in the confirm dialog.
     50      getterPath: PropTypes.array,
     51      serviceContainer: PropTypes.object.isRequired,
     52    };
     53  }
     54 
     55  constructor(props) {
     56    super(props);
     57 
     58    const { webConsoleUI } = props;
     59    webConsoleUI.confirmDialog = this;
     60 
     61    this.cancel = this.cancel.bind(this);
     62    this.confirm = this.confirm.bind(this);
     63    this.onLearnMoreClick = this.onLearnMoreClick.bind(this);
     64  }
     65 
     66  componentDidMount() {
     67    const doc = this.props.webConsoleUI.document;
     68    const { toolbox } = this.props.webConsoleUI.wrapper;
     69    const tooltipDoc = toolbox ? toolbox.doc : doc;
     70    // The popup will be attached to the toolbox document or HUD document in the case
     71    // such as the browser console which doesn't have a toolbox.
     72    this.tooltip = new HTMLTooltip(tooltipDoc, {
     73      className: "invoke-confirm",
     74    });
     75  }
     76 
     77  componentDidUpdate() {
     78    const { getterPath, serviceContainer } = this.props;
     79 
     80    if (getterPath) {
     81      this.tooltip.show(serviceContainer.getJsTermTooltipAnchor(), { y: 5 });
     82    } else {
     83      this.tooltip.hide();
     84      this.props.webConsoleUI.jsterm.focus();
     85    }
     86  }
     87 
     88  componentDidThrow(e) {
     89    console.error("Error in ConfirmDialog", e);
     90    this.setState(state => ({ ...state, hasError: true }));
     91  }
     92 
     93  onLearnMoreClick(e) {
     94    this.props.serviceContainer.openLink(LEARN_MORE_URL, e);
     95  }
     96 
     97  cancel() {
     98    this.tooltip.hide();
     99    this.props.autocompleteClear();
    100  }
    101 
    102  confirm() {
    103    this.tooltip.hide();
    104    this.props.autocompleteUpdate(this.props.getterPath);
    105  }
    106 
    107  render() {
    108    if (
    109      (this.state && this.state.hasError) ||
    110      !this.props ||
    111      !this.props.getterPath
    112    ) {
    113      return null;
    114    }
    115 
    116    const { getterPath } = this.props;
    117    const getterName = getterPath.join(".");
    118 
    119    // We deliberately use getStr, and not getFormatStr, because we want getterName to
    120    // be wrapped in its own span.
    121    const description = l10n.getStr("webconsole.confirmDialog.getter.label");
    122    const [descriptionPrefix, descriptionSuffix] = description.split("%S");
    123 
    124    const closeButtonTooltip = l10n.getFormatStr(
    125      "webconsole.confirmDialog.getter.closeButton.tooltip",
    126      ["Esc"]
    127    );
    128    const invokeButtonLabel = l10n.getFormatStr(
    129      "webconsole.confirmDialog.getter.invokeButtonLabelWithShortcut",
    130      ["Tab"]
    131    );
    132 
    133    const learnMoreElement = dom.a(
    134      {
    135        className: "learn-more-link",
    136        key: "learn-more-link",
    137        title: LEARN_MORE_URL.split("?")[0],
    138        onClick: this.onLearnMoreClick,
    139      },
    140      l10n.getStr("webConsoleMoreInfoLabel")
    141    );
    142 
    143    return createPortal(
    144      [
    145        dom.div(
    146          {
    147            className: "confirm-label",
    148            key: "confirm-label",
    149          },
    150          dom.p(
    151            {},
    152            dom.span({}, descriptionPrefix),
    153            dom.span({ className: "emphasized" }, getterName),
    154            dom.span({}, descriptionSuffix)
    155          ),
    156          dom.button({
    157            className: "devtools-button close-confirm-dialog-button",
    158            key: "close-button",
    159            title: closeButtonTooltip,
    160            onClick: this.cancel,
    161          })
    162        ),
    163        dom.button(
    164          {
    165            className: "confirm-button",
    166            key: "confirm-button",
    167            onClick: this.confirm,
    168          },
    169          invokeButtonLabel
    170        ),
    171        learnMoreElement,
    172      ],
    173      this.tooltip.panel
    174    );
    175  }
    176 }
    177 
    178 // Redux connect
    179 function mapStateToProps(state) {
    180  const autocompleteData = getAutocompleteState(state);
    181  return {
    182    getterPath: autocompleteData.getterPath,
    183  };
    184 }
    185 
    186 function mapDispatchToProps(dispatch) {
    187  return {
    188    autocompleteUpdate: getterPath =>
    189      dispatch(autocompleteActions.autocompleteUpdate(true, getterPath)),
    190    autocompleteClear: () => dispatch(autocompleteActions.autocompleteClear()),
    191  };
    192 }
    193 
    194 module.exports = connect(mapStateToProps, mapDispatchToProps)(ConfirmDialog);