tor-browser

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

LayoutApp.js (6831B)


      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 const {
      8  createFactory,
      9  createRef,
     10  PureComponent,
     11 } = require("resource://devtools/client/shared/vendor/react.mjs");
     12 const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js");
     13 const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.mjs");
     14 const {
     15  connect,
     16 } = require("resource://devtools/client/shared/vendor/react-redux.js");
     17 const {
     18  getSelectorFromGrip,
     19  translateNodeFrontToGrip,
     20 } = require("resource://devtools/client/inspector/shared/utils.js");
     21 const { LocalizationHelper } = require("resource://devtools/shared/l10n.js");
     22 
     23 const Accordion = createFactory(
     24  require("resource://devtools/client/shared/components/Accordion.js")
     25 );
     26 const BoxModel = createFactory(
     27  require("resource://devtools/client/inspector/boxmodel/components/BoxModel.js")
     28 );
     29 const Flexbox = createFactory(
     30  require("resource://devtools/client/inspector/flexbox/components/Flexbox.js")
     31 );
     32 const Grid = createFactory(
     33  require("resource://devtools/client/inspector/grids/components/Grid.js")
     34 );
     35 
     36 const BoxModelTypes = require("resource://devtools/client/inspector/boxmodel/types.js");
     37 const FlexboxTypes = require("resource://devtools/client/inspector/flexbox/types.js");
     38 const GridTypes = require("resource://devtools/client/inspector/grids/types.js");
     39 
     40 const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
     41 const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
     42 
     43 const LAYOUT_STRINGS_URI = "devtools/client/locales/layout.properties";
     44 const LAYOUT_L10N = new LocalizationHelper(LAYOUT_STRINGS_URI);
     45 
     46 const FLEXBOX_OPENED_PREF = "devtools.layout.flexbox.opened";
     47 const FLEX_CONTAINER_OPENED_PREF = "devtools.layout.flex-container.opened";
     48 const FLEX_ITEM_OPENED_PREF = "devtools.layout.flex-item.opened";
     49 const GRID_OPENED_PREF = "devtools.layout.grid.opened";
     50 const BOXMODEL_OPENED_PREF = "devtools.layout.boxmodel.opened";
     51 
     52 class LayoutApp extends PureComponent {
     53  static get propTypes() {
     54    return {
     55      boxModel: PropTypes.shape(BoxModelTypes.boxModel).isRequired,
     56      dispatch: PropTypes.func.isRequired,
     57      flexbox: PropTypes.shape(FlexboxTypes.flexbox).isRequired,
     58      getSwatchColorPickerTooltip: PropTypes.func.isRequired,
     59      grids: PropTypes.arrayOf(PropTypes.shape(GridTypes.grid)).isRequired,
     60      highlighterSettings: PropTypes.shape(GridTypes.highlighterSettings)
     61        .isRequired,
     62      onSetFlexboxOverlayColor: PropTypes.func.isRequired,
     63      onSetGridOverlayColor: PropTypes.func.isRequired,
     64      onShowBoxModelEditor: PropTypes.func.isRequired,
     65      onShowGridOutlineHighlight: PropTypes.func,
     66      onToggleGeometryEditor: PropTypes.func.isRequired,
     67      onToggleGridHighlighter: PropTypes.func.isRequired,
     68      onToggleShowGridAreas: PropTypes.func.isRequired,
     69      onToggleShowGridLineNumbers: PropTypes.func.isRequired,
     70      onToggleShowInfiniteLines: PropTypes.func.isRequired,
     71      setSelectedNode: PropTypes.func.isRequired,
     72      showBoxModelProperties: PropTypes.bool.isRequired,
     73    };
     74  }
     75 
     76  constructor(props) {
     77    super(props);
     78    this.containerRef = createRef();
     79 
     80    this.scrollToTop = this.scrollToTop.bind(this);
     81  }
     82 
     83  getBoxModelSection() {
     84    return {
     85      component: BoxModel,
     86      componentProps: this.props,
     87      contentClassName: "layout-content",
     88      header: BOXMODEL_L10N.getStr("boxmodel.title"),
     89      id: "layout-section-boxmodel",
     90      opened: Services.prefs.getBoolPref(BOXMODEL_OPENED_PREF),
     91      onToggle: opened => {
     92        Services.prefs.setBoolPref(BOXMODEL_OPENED_PREF, opened);
     93      },
     94    };
     95  }
     96 
     97  getFlexAccordionData(flexContainer) {
     98    if (!flexContainer.actorID) {
     99      // No flex container or flex item selected.
    100      return {
    101        pref: FLEXBOX_OPENED_PREF,
    102        id: "layout-section-flex",
    103        header: LAYOUT_L10N.getStr("flexbox.header"),
    104      };
    105    } else if (!flexContainer.flexItemShown) {
    106      // No flex item selected.
    107      return {
    108        pref: FLEX_CONTAINER_OPENED_PREF,
    109        id: "layout-section-flex-container",
    110        header: LAYOUT_L10N.getStr("flexbox.flexContainer"),
    111      };
    112    }
    113 
    114    return {
    115      pref: FLEX_ITEM_OPENED_PREF,
    116      id: "layout-section-flex-item",
    117      header: LAYOUT_L10N.getFormatStr(
    118        "flexbox.flexItemOf",
    119        getSelectorFromGrip(translateNodeFrontToGrip(flexContainer.nodeFront))
    120      ),
    121    };
    122  }
    123 
    124  getFlexSection(flexContainer) {
    125    const { pref, id, header } = this.getFlexAccordionData(flexContainer);
    126 
    127    return {
    128      className: "flex-accordion",
    129      component: Flexbox,
    130      componentProps: {
    131        ...this.props,
    132        flexContainer,
    133        scrollToTop: this.scrollToTop,
    134      },
    135      contentClassName: "layout-content",
    136      header,
    137      id,
    138      opened: Services.prefs.getBoolPref(pref),
    139      onToggle: opened => {
    140        Services.prefs.setBoolPref(pref, opened);
    141      },
    142    };
    143  }
    144 
    145  getGridSection() {
    146    return {
    147      component: Grid,
    148      componentProps: this.props,
    149      contentClassName: "layout-content",
    150      header: LAYOUT_L10N.getStr("layout.header"),
    151      id: "layout-grid-section",
    152      opened: Services.prefs.getBoolPref(GRID_OPENED_PREF),
    153      onToggle: opened => {
    154        Services.prefs.setBoolPref(GRID_OPENED_PREF, opened);
    155      },
    156    };
    157  }
    158 
    159  /**
    160   * Scrolls to the top of the layout container.
    161   */
    162  scrollToTop() {
    163    this.containerRef.current.scrollTop = 0;
    164  }
    165 
    166  render() {
    167    const { flexContainer, flexItemContainer } = this.props.flexbox;
    168 
    169    const items = [
    170      this.getFlexSection(flexContainer),
    171      this.getGridSection(),
    172      this.getBoxModelSection(),
    173    ];
    174 
    175    // If the current selected node is both a flex container and flex item. Render
    176    // an extra accordion with another Flexbox component where the node is shown as an
    177    // item of its parent flex container.
    178    // If the node was selected from the markup-view, then show this accordion after the
    179    // container accordion. Otherwise show it first.
    180    // The reason is that if the user selects an item-container in the markup view, it
    181    // is assumed that they want to primarily see that element as a container, so the
    182    // container info should be at the top.
    183    if (flexItemContainer?.actorID) {
    184      items.splice(
    185        this.props.flexbox.initiatedByMarkupViewSelection ? 1 : 0,
    186        0,
    187        this.getFlexSection(flexItemContainer)
    188      );
    189    }
    190 
    191    return dom.div(
    192      {
    193        className: "layout-container",
    194        ref: this.containerRef,
    195        role: "document",
    196      },
    197      Accordion({ items })
    198    );
    199  }
    200 }
    201 
    202 module.exports = connect(state => state)(LayoutApp);