/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at . */ // @flow import PropTypes from "prop-types"; import React, { Component } from "react"; import { connect } from "react-redux"; import { bindActionCreators } from "redux"; import { features } from "../utils/prefs"; import actions from "../actions"; import { ShortcutsModal } from "./ShortcutsModal"; import VisibilityHandler from "./shared/VisibilityHandler"; import { getSelectedSource, getPaneCollapse, getActiveSearch, getQuickOpenEnabled, getOrientation } from "../selectors"; import type { OrientationType } from "../reducers/types"; import type { SourceRecord } from "../types"; import { KeyShortcuts, Services } from "devtools-modules"; const shortcuts = new KeyShortcuts({ window }); const { appinfo } = Services; const isMacOS = appinfo.OS === "Darwin"; const horizontalLayoutBreakpoint = window.matchMedia("(min-width: 800px)"); const verticalLayoutBreakpoint = window.matchMedia( "(min-width: 10px) and (max-width: 800px)" ); import "./variables.css"; import "./App.css"; import "devtools-launchpad/src/components/Root.css"; import "./shared/menu.css"; import "./shared/reps.css"; import SplitBox from "devtools-splitter"; import ProjectSearch from "./ProjectSearch"; import PrimaryPanes from "./PrimaryPanes"; import Editor from "./Editor"; import SecondaryPanes from "./SecondaryPanes"; import WelcomeBox from "./WelcomeBox"; import EditorTabs from "./Editor/Tabs"; import QuickOpenModal from "./QuickOpenModal"; type Props = { selectedSource: SourceRecord, orientation: OrientationType, startPanelCollapsed: boolean, endPanelCollapsed: boolean, activeSearch: string, quickOpenEnabled: boolean, setActiveSearch: string => void, closeActiveSearch: () => void, closeProjectSearch: () => void, openQuickOpen: (query?: string) => void, closeQuickOpen: () => void, setOrientation: OrientationType => void }; type State = { shortcutsModalEnabled: boolean, startPanelSize: number, endPanelSize: number }; class App extends Component { onLayoutChange: Function; getChildContext: Function; renderEditorPane: Function; renderLayout: Function; toggleQuickOpenModal: Function; onEscape: Function; onCommandSlash: Function; constructor(props) { super(props); this.state = { shortcutsModalEnabled: false, startPanelSize: 0, endPanelSize: 0 }; } getChildContext = () => { return { shortcuts }; }; componentDidMount() { horizontalLayoutBreakpoint.addListener(this.onLayoutChange); verticalLayoutBreakpoint.addListener(this.onLayoutChange); this.setOrientation(); shortcuts.on(L10N.getStr("symbolSearch.search.key2"), (_, e) => this.toggleQuickOpenModal(_, e, "@") ); const searchKeys = [ L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key") ]; searchKeys.forEach(key => shortcuts.on(key, this.toggleQuickOpenModal)); shortcuts.on(L10N.getStr("gotoLineModal.key2"), (_, e) => this.toggleQuickOpenModal(_, e, ":") ); shortcuts.on("Escape", this.onEscape); shortcuts.on("Cmd+/", this.onCommandSlash); } componentWillUnmount() { horizontalLayoutBreakpoint.removeListener(this.onLayoutChange); verticalLayoutBreakpoint.removeListener(this.onLayoutChange); shortcuts.off( L10N.getStr("symbolSearch.search.key2"), this.toggleQuickOpenModal ); const searchKeys = [ L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key") ]; searchKeys.forEach(key => shortcuts.off(key, this.toggleQuickOpenModal)); shortcuts.off(L10N.getStr("gotoLineModal.key2"), this.toggleQuickOpenModal); shortcuts.off("Escape", this.onEscape); } onEscape = (_, e) => { const { activeSearch, quickOpenEnabled, closeActiveSearch, closeQuickOpen } = this.props; if (activeSearch) { e.preventDefault(); closeActiveSearch(); } if (quickOpenEnabled === true) { closeQuickOpen(); } }; onCommandSlash = () => { this.toggleShortcutsModal(); }; isHorizontal() { return this.props.orientation === "horizontal"; } toggleQuickOpenModal = ( _, e: SyntheticEvent, query?: string ) => { const { quickOpenEnabled, openQuickOpen, closeQuickOpen } = this.props; e.preventDefault(); e.stopPropagation(); if (quickOpenEnabled === true) { closeQuickOpen(); return; } if (query != null) { openQuickOpen(query); return; } openQuickOpen(); return; }; onLayoutChange = () => { this.setOrientation(); }; setOrientation() { // If the orientation does not match (if it is not visible) it will // not setOrientation, or if it is the same as before, calling // setOrientation will not cause a rerender. if (horizontalLayoutBreakpoint.matches) { this.props.setOrientation("horizontal"); } else if (verticalLayoutBreakpoint.matches) { this.props.setOrientation("vertical"); } } renderEditorPane = () => { const { startPanelCollapsed, endPanelCollapsed } = this.props; const { endPanelSize, startPanelSize } = this.state; const horizontal = this.isHorizontal(); return (
{!this.props.selectedSource ? ( ) : null}
); }; toggleShortcutsModal() { this.setState(prevState => ({ shortcutsModalEnabled: !prevState.shortcutsModalEnabled })); } renderLayout = () => { const { startPanelCollapsed, endPanelCollapsed } = this.props; const horizontal = this.isHorizontal(); const maxSize = horizontal ? "70%" : "95%"; const primaryInitialSize = horizontal ? "250px" : "150px"; return ( } endPanel={this.renderEditorPane()} /> } endPanelControl={true} endPanel={ this.toggleShortcutsModal()} /> } endPanelCollapsed={endPanelCollapsed} /> ); }; renderShortcutsModal() { const additionalClass = isMacOS ? "mac" : ""; if (!features.shortcuts) { return; } return ( this.toggleShortcutsModal()} /> ); } render() { const { quickOpenEnabled } = this.props; return (
{this.renderLayout()} {quickOpenEnabled === true && ( this.toggleShortcutsModal()} /> )} {this.renderShortcutsModal()}
); } } App.childContextTypes = { shortcuts: PropTypes.object }; function mapStateToProps(state) { return { selectedSource: getSelectedSource(state), startPanelCollapsed: getPaneCollapse(state, "start"), endPanelCollapsed: getPaneCollapse(state, "end"), activeSearch: getActiveSearch(state), quickOpenEnabled: getQuickOpenEnabled(state), orientation: getOrientation(state) }; } export default connect(mapStateToProps, dispatch => bindActionCreators(actions, dispatch) )(App);