tor-browser

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

CollapsibleSection.jsx (5158B)


      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 { ErrorBoundary } from "content-src/components/ErrorBoundary/ErrorBoundary";
      6 import { FluentOrText } from "content-src/components/FluentOrText/FluentOrText";
      7 import React from "react";
      8 import { connect } from "react-redux";
      9 import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
     10 
     11 /**
     12 * A section that can collapse. As of bug 1710937, it can no longer collapse.
     13 * See bug 1727365 for follow-up work to simplify this component.
     14 */
     15 export class _CollapsibleSection extends React.PureComponent {
     16  constructor(props) {
     17    super(props);
     18    this.onBodyMount = this.onBodyMount.bind(this);
     19    this.onMenuButtonMouseEnter = this.onMenuButtonMouseEnter.bind(this);
     20    this.onMenuButtonMouseLeave = this.onMenuButtonMouseLeave.bind(this);
     21    this.onMenuUpdate = this.onMenuUpdate.bind(this);
     22    this.setContextMenuButtonRef = this.setContextMenuButtonRef.bind(this);
     23    this.handleTopicSelectionButtonClick =
     24      this.handleTopicSelectionButtonClick.bind(this);
     25    this.state = {
     26      menuButtonHover: false,
     27      showContextMenu: false,
     28    };
     29  }
     30 
     31  setContextMenuButtonRef(element) {
     32    this.contextMenuButtonRef = element;
     33  }
     34 
     35  onBodyMount(node) {
     36    this.sectionBody = node;
     37  }
     38 
     39  onMenuButtonMouseEnter() {
     40    this.setState({ menuButtonHover: true });
     41  }
     42 
     43  onMenuButtonMouseLeave() {
     44    this.setState({ menuButtonHover: false });
     45  }
     46 
     47  onMenuUpdate(showContextMenu) {
     48    this.setState({ showContextMenu });
     49  }
     50 
     51  handleTopicSelectionButtonClick() {
     52    const maybeDisplay =
     53      this.props.Prefs.values[
     54        "discoverystream.topicSelection.onboarding.maybeDisplay"
     55      ];
     56 
     57    this.props.dispatch(ac.OnlyToMain({ type: at.TOPIC_SELECTION_USER_OPEN }));
     58 
     59    if (maybeDisplay) {
     60      // if still part of onboarding, remove user from onboarding flow
     61      this.props.dispatch(
     62        ac.SetPref(
     63          "discoverystream.topicSelection.onboarding.maybeDisplay",
     64          false
     65        )
     66      );
     67    }
     68    this.props.dispatch(
     69      ac.BroadcastToContent({ type: at.TOPIC_SELECTION_SPOTLIGHT_OPEN })
     70    );
     71  }
     72 
     73  render() {
     74    const { isAnimating, maxHeight, menuButtonHover, showContextMenu } =
     75      this.state;
     76    const {
     77      id,
     78      collapsed,
     79      title,
     80      subTitle,
     81      mayHaveTopicsSelection,
     82      sectionsEnabled,
     83    } = this.props;
     84    const active = menuButtonHover || showContextMenu;
     85    let bodyStyle;
     86    if (isAnimating && !collapsed) {
     87      bodyStyle = { maxHeight };
     88    } else if (!isAnimating && collapsed) {
     89      bodyStyle = { display: "none" };
     90    }
     91    let titleStyle;
     92    if (this.props.hideTitle) {
     93      titleStyle = { visibility: "hidden" };
     94    }
     95    const hasSubtitleClassName = subTitle ? `has-subtitle` : ``;
     96    const hasBeenUpdatedPreviously =
     97      this.props.Prefs.values[
     98        "discoverystream.topicSelection.hasBeenUpdatedPreviously"
     99      ];
    100    const selectedTopics =
    101      this.props.Prefs.values["discoverystream.topicSelection.selectedTopics"];
    102    const topicsHaveBeenPreviouslySet =
    103      hasBeenUpdatedPreviously || selectedTopics;
    104    return (
    105      <section
    106        className={`collapsible-section ${this.props.className}${
    107          active ? " active" : ""
    108        }`}
    109        // Note: data-section-id is used for web extension api tests in mozilla central
    110        data-section-id={id}
    111      >
    112        {!sectionsEnabled && (
    113          <div className="section-top-bar">
    114            <h2
    115              className={`section-title-container ${hasSubtitleClassName}`}
    116              style={titleStyle}
    117            >
    118              <span className="section-title">
    119                <FluentOrText message={title} />
    120              </span>
    121              {subTitle && (
    122                <span className="section-sub-title">
    123                  <FluentOrText message={subTitle} />
    124                </span>
    125              )}
    126            </h2>
    127            {mayHaveTopicsSelection && (
    128              <div className="button-topic-selection">
    129                <moz-button
    130                  data-l10n-id={
    131                    topicsHaveBeenPreviouslySet
    132                      ? "newtab-topic-selection-button-update-interests"
    133                      : "newtab-topic-selection-button-pick-interests"
    134                  }
    135                  type={topicsHaveBeenPreviouslySet ? "default" : "primary"}
    136                  onClick={this.handleTopicSelectionButtonClick}
    137                />
    138              </div>
    139            )}
    140          </div>
    141        )}
    142        <ErrorBoundary className="section-body-fallback">
    143          <div ref={this.onBodyMount} style={bodyStyle}>
    144            {this.props.children}
    145          </div>
    146        </ErrorBoundary>
    147      </section>
    148    );
    149  }
    150 }
    151 
    152 _CollapsibleSection.defaultProps = {
    153  document: globalThis.document || {
    154    addEventListener: () => {},
    155    removeEventListener: () => {},
    156    visibilityState: "hidden",
    157  },
    158 };
    159 
    160 export const CollapsibleSection = connect(state => ({
    161  Prefs: state.Prefs,
    162 }))(_CollapsibleSection);