/* 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 "devtools/client/shared/vendor/react"; import { div, span } from "devtools/client/shared/vendor/react-dom-factories"; import PropTypes from "devtools/client/shared/vendor/react-prop-types"; import { connect } from "devtools/client/shared/vendor/react-redux"; import SourceIcon from "../shared/SourceIcon"; import { CloseButton } from "../shared/Button/index"; import actions from "../../actions/index"; import { getDisplayPath, getFileURL, getTruncatedFileName, isPretty, } from "../../utils/source"; import { createLocation } from "../../utils/location"; import { getSelectedLocation, getSourcesForTabs, isSourceBlackBoxed, } from "../../selectors/index"; const classnames = require("resource://devtools/client/shared/classnames.js"); class Tab extends PureComponent { static get propTypes() { return { closeTab: PropTypes.func.isRequired, onDragEnd: PropTypes.func.isRequired, onDragOver: PropTypes.func.isRequired, onDragStart: PropTypes.func.isRequired, selectSource: PropTypes.func.isRequired, source: PropTypes.object.isRequired, sourceActor: PropTypes.object.isRequired, tabSources: PropTypes.array.isRequired, isBlackBoxed: PropTypes.bool.isRequired, }; } onContextMenu = event => { event.preventDefault(); this.props.showTabContextMenu(event, this.props.source); }; isSourceSearchEnabled() { return this.props.activeSearch === "source"; } render() { const { selectSource, closeTab, source, sourceActor, tabSources, onDragOver, onDragStart, onDragEnd, index, isActive, } = this.props; const sourceId = source.id; const isPrettyCode = isPretty(source); function onClickClose(e) { e.stopPropagation(); closeTab(source); } function handleTabClick(e) { e.preventDefault(); e.stopPropagation(); return selectSource(source, sourceActor); } const className = classnames("source-tab", { active: isActive, pretty: isPrettyCode, blackboxed: this.props.isBlackBoxed, }); const path = getDisplayPath(source, tabSources); return div( { draggable: true, onDragOver, onDragStart, onDragEnd, className, "data-index": index, "data-source-id": sourceId, onClick: handleTabClick, // Accommodate middle click to close tab onMouseUp: e => e.button === 1 && closeTab(source), onContextMenu: this.onContextMenu, title: getFileURL(source, false), }, React.createElement(SourceIcon, { location: createLocation({ source, sourceActor, }), forTab: true, modifier: icon => (["file", "javascript"].includes(icon) ? null : icon), }), div( { className: "filename", }, getTruncatedFileName(source), path && span(null, `../${path}/..`) ), React.createElement(CloseButton, { handleClick: onClickClose, tooltip: L10N.getStr("sourceTabs.closeTabButtonTooltip"), }) ); } } const mapStateToProps = (state, { source }) => { return { tabSources: getSourcesForTabs(state), isBlackBoxed: isSourceBlackBoxed(state, source), isActive: source.id === getSelectedLocation(state)?.source.id, }; }; export default connect( mapStateToProps, { selectSource: actions.selectSource, closeTab: actions.closeTab, showTabContextMenu: actions.showTabContextMenu, }, null, { withRef: true, } )(Tab);