/* 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 . */ import React, { PureComponent } from "react"; import PropTypes from "prop-types"; import { connect } from "../../utils/connect"; import { createLocation } from "../../utils/location"; import actions from "../../actions"; import { getSelectedSource, getSelectedLocation, getSelectedSourceTextContent, getPrettySource, getPaneCollapse, getContext, getGeneratedSource, isSourceBlackBoxed, canPrettyPrintSource, getPrettyPrintMessage, isSourceOnSourceMapIgnoreList, isSourceMapIgnoreListEnabled, } from "../../selectors"; import { isPretty, getFilename, shouldBlackbox } from "../../utils/source"; import { PaneToggleButton } from "../shared/Button"; import AccessibleImage from "../shared/AccessibleImage"; const classnames = require("devtools/client/shared/classnames.js"); import "./Footer.css"; class SourceFooter extends PureComponent { constructor() { super(); this.state = { cursorPosition: { line: 0, column: 0 } }; } static get propTypes() { return { canPrettyPrint: PropTypes.bool.isRequired, prettyPrintMessage: PropTypes.string.isRequired, cx: PropTypes.object.isRequired, endPanelCollapsed: PropTypes.bool.isRequired, horizontal: PropTypes.bool.isRequired, jumpToMappedLocation: PropTypes.func.isRequired, mappedSource: PropTypes.object, selectedSource: PropTypes.object, isSelectedSourceBlackBoxed: PropTypes.bool.isRequired, sourceLoaded: PropTypes.bool.isRequired, toggleBlackBox: PropTypes.func.isRequired, togglePaneCollapse: PropTypes.func.isRequired, togglePrettyPrint: PropTypes.func.isRequired, isSourceOnIgnoreList: PropTypes.bool.isRequired, }; } componentDidUpdate() { const eventDoc = document.querySelector(".editor-mount .CodeMirror"); // querySelector can return null if (eventDoc) { this.toggleCodeMirror(eventDoc, true); } } componentWillUnmount() { const eventDoc = document.querySelector(".editor-mount .CodeMirror"); if (eventDoc) { this.toggleCodeMirror(eventDoc, false); } } toggleCodeMirror(eventDoc, toggle) { if (toggle === true) { eventDoc.CodeMirror.on("cursorActivity", this.onCursorChange); } else { eventDoc.CodeMirror.off("cursorActivity", this.onCursorChange); } } prettyPrintButton() { const { cx, selectedSource, canPrettyPrint, prettyPrintMessage, togglePrettyPrint, sourceLoaded, } = this.props; if (!selectedSource) { return null; } if (!sourceLoaded && selectedSource.isPrettyPrinted) { return (
); } const type = "prettyPrint"; return ( ); } blackBoxButton() { const { cx, selectedSource, isSelectedSourceBlackBoxed, toggleBlackBox, sourceLoaded, isSourceOnIgnoreList, } = this.props; if (!selectedSource || !shouldBlackbox(selectedSource)) { return null; } let tooltip = isSelectedSourceBlackBoxed ? L10N.getStr("sourceFooter.unignore") : L10N.getStr("sourceFooter.ignore"); if (isSourceOnIgnoreList) { tooltip = L10N.getStr("sourceFooter.ignoreList"); } const type = "black-box"; return ( ); } renderToggleButton() { if (this.props.horizontal) { return null; } return ( ); } renderCommands() { const commands = [this.blackBoxButton(), this.prettyPrintButton()].filter( Boolean ); return commands.length ?
{commands}
: null; } renderSourceSummary() { const { cx, mappedSource, jumpToMappedLocation, selectedSource } = this.props; if (!mappedSource || !selectedSource || !selectedSource.isOriginal) { return null; } const filename = getFilename(mappedSource); const tooltip = L10N.getFormatStr( "sourceFooter.mappedSourceTooltip", filename ); const title = L10N.getFormatStr("sourceFooter.mappedSource", filename); const mappedSourceLocation = createLocation({ source: selectedSource, line: 1, column: 1, }); return ( ); } onCursorChange = event => { const { line, ch } = event.doc.getCursor(); this.setState({ cursorPosition: { line, column: ch } }); }; renderCursorPosition() { if (!this.props.selectedSource) { return null; } const { line, column } = this.state.cursorPosition; const text = L10N.getFormatStr( "sourceFooter.currentCursorPosition", line + 1, column + 1 ); const title = L10N.getFormatStr( "sourceFooter.currentCursorPosition.tooltip", line + 1, column + 1 ); return (
{text}
); } render() { return (
{this.renderCommands()}
{this.renderSourceSummary()} {this.renderCursorPosition()} {this.renderToggleButton()}
); } } const mapStateToProps = state => { const selectedSource = getSelectedSource(state); const selectedLocation = getSelectedLocation(state); const sourceTextContent = getSelectedSourceTextContent(state); return { cx: getContext(state), selectedSource, isSelectedSourceBlackBoxed: selectedSource ? isSourceBlackBoxed(state, selectedSource) : null, isSourceOnIgnoreList: isSourceMapIgnoreListEnabled(state) && isSourceOnSourceMapIgnoreList(state, selectedSource), sourceLoaded: !!sourceTextContent, mappedSource: getGeneratedSource(state, selectedSource), prettySource: getPrettySource( state, selectedSource ? selectedSource.id : null ), endPanelCollapsed: getPaneCollapse(state, "end"), canPrettyPrint: selectedLocation ? canPrettyPrintSource(state, selectedLocation) : false, prettyPrintMessage: selectedLocation ? getPrettyPrintMessage(state, selectedLocation) : null, }; }; export default connect(mapStateToProps, { togglePrettyPrint: actions.togglePrettyPrint, toggleBlackBox: actions.toggleBlackBox, jumpToMappedLocation: actions.jumpToMappedLocation, togglePaneCollapse: actions.togglePaneCollapse, })(SourceFooter);