From 048b95a8df1ec99cfc24cabfe6e8422949dfac4b Mon Sep 17 00:00:00 2001 From: Hubert Boma Manilla Date: Wed, 29 Mar 2023 18:43:01 +0000 Subject: [PATCH] Bug 1811000 - [devtools] Move the project search to the side panel r=devtools-reviewers,nchevobbe,perftest-reviewers,sparky Differential Revision: https://phabricator.services.mozilla.com/D172985 --- .../debugger/src/actions/sources/select.js | 8 +- .../client/debugger/src/components/App.js | 33 +++++-- .../debugger/src/components/Editor/Tab.js | 6 +- .../{ => PrimaryPanes}/ProjectSearch.css | 1 - .../{ => PrimaryPanes}/ProjectSearch.js | 67 +++---------- .../src/components/PrimaryPanes/index.js | 64 +++++++------ .../src/components/PrimaryPanes/moz.build | 1 + .../PrimaryPanes/tests/PrimaryPanes.spec.js | 2 + .../tests}/ProjectSearch.spec.js | 6 +- .../__snapshots__/PrimaryPanes.spec.js.snap | 24 ++++- .../__snapshots__/ProjectSearch.spec.js.snap | 96 ++++++++++--------- .../debugger/src/components/WelcomeBox.js | 13 ++- .../client/debugger/src/components/moz.build | 1 - .../src/components/shared/SearchInput.js | 1 - .../src/components/test/WelcomeBox.spec.js | 1 + devtools/client/debugger/src/constants.js | 6 ++ devtools/client/debugger/src/debugger.css | 2 +- .../src/reducers/project-text-search.js | 7 +- .../mochitest/browser_dbg-project-search.js | 40 ++------ .../browser_dbg-sources-project-search.js | 8 +- .../debugger/test/mochitest/shared-head.js | 14 +-- devtools/client/jar.mn | 2 +- .../locales/en-US/components.properties | 16 ++-- .../client/locales/en-US/debugger.properties | 3 + .../shared/components/SearchModifiers.js | 10 +- .../addon/content/tests/debugger/custom.js | 1 + 26 files changed, 201 insertions(+), 232 deletions(-) rename devtools/client/debugger/src/components/{ => PrimaryPanes}/ProjectSearch.css (98%) rename devtools/client/debugger/src/components/{ => PrimaryPanes}/ProjectSearch.js (83%) rename devtools/client/debugger/src/components/{test => PrimaryPanes/tests}/ProjectSearch.spec.js (97%) rename devtools/client/debugger/src/components/{test => PrimaryPanes/tests}/__snapshots__/ProjectSearch.spec.js.snap (95%) diff --git a/devtools/client/debugger/src/actions/sources/select.js b/devtools/client/debugger/src/actions/sources/select.js index 863ac57f9f62..5fd094cc9025 100644 --- a/devtools/client/debugger/src/actions/sources/select.js +++ b/devtools/client/debugger/src/actions/sources/select.js @@ -11,7 +11,7 @@ import { isOriginalId } from "devtools/client/shared/source-map-loader/index"; import { setSymbols } from "./symbols"; import { setInScopeLines } from "../ast"; -import { closeActiveSearch, updateActiveFileSearch } from "../ui"; +import { updateActiveFileSearch } from "../ui"; import { togglePrettyPrint } from "./prettyPrint"; import { addTab, closeTab } from "../tabs"; import { loadSourceText } from "./loadSourceText"; @@ -28,7 +28,6 @@ import { getFirstSourceActorForGeneratedSource, getSourceByURL, getPrettySource, - getActiveSearch, getSelectedLocation, getSelectedSource, canPrettyPrintSource, @@ -138,11 +137,6 @@ export function selectLocation(cx, location, { keepContext = true } = {}) { return; } - const activeSearch = getActiveSearch(getState()); - if (activeSearch && activeSearch !== "file") { - dispatch(closeActiveSearch()); - } - // Preserve the current source map context (original / generated) // when navigating to a new location. // i.e. if keepContext isn't manually overriden to false, diff --git a/devtools/client/debugger/src/components/App.js b/devtools/client/debugger/src/components/App.js index b3e359f4b925..57b8ebe56ac9 100644 --- a/devtools/client/debugger/src/components/App.js +++ b/devtools/client/debugger/src/components/App.js @@ -8,6 +8,7 @@ import classnames from "classnames"; import { connect } from "../utils/connect"; import { prefs, features } from "../utils/prefs"; +import { primaryPaneTabs } from "../constants"; import actions from "../actions"; import A11yIntention from "./A11yIntention"; import { ShortcutsModal } from "./ShortcutsModal"; @@ -40,7 +41,6 @@ import "./App.css"; import "./shared/menu.css"; -import ProjectSearch from "./ProjectSearch"; import PrimaryPanes from "./PrimaryPanes"; import Editor from "./Editor"; import SecondaryPanes from "./SecondaryPanes"; @@ -63,7 +63,6 @@ class App extends Component { return { activeSearch: PropTypes.oneOf(["file", "project"]), closeActiveSearch: PropTypes.func.isRequired, - closeProjectSearch: PropTypes.func.isRequired, closeQuickOpen: PropTypes.func.isRequired, endPanelCollapsed: PropTypes.bool.isRequired, fluentBundles: PropTypes.array.isRequired, @@ -73,6 +72,7 @@ class App extends Component { selectedSource: PropTypes.object, setActiveSearch: PropTypes.func.isRequired, setOrientation: PropTypes.func.isRequired, + setPrimaryPaneTab: PropTypes.func.isRequired, startPanelCollapsed: PropTypes.bool.isRequired, toolboxDoc: PropTypes.object.isRequired, }; @@ -96,16 +96,20 @@ class App extends Component { this.toggleQuickOpenModal(e, "@") ); - const searchKeys = [ + [ L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key"), - ]; - searchKeys.forEach(key => shortcuts.on(key, this.toggleQuickOpenModal)); + ].forEach(key => shortcuts.on(key, this.toggleQuickOpenModal)); shortcuts.on(L10N.getStr("gotoLineModal.key3"), e => this.toggleQuickOpenModal(e, ":") ); + shortcuts.on( + L10N.getStr("projectTextSearch.key"), + this.jumpToProjectSearch + ); + shortcuts.on("Escape", this.onEscape); shortcuts.on("CmdOrCtrl+/", this.onCommandSlash); } @@ -118,18 +122,28 @@ class App extends Component { this.toggleQuickOpenModal ); - const searchKeys = [ + [ L10N.getStr("sources.search.key2"), L10N.getStr("sources.search.alt.key"), - ]; - searchKeys.forEach(key => shortcuts.off(key, this.toggleQuickOpenModal)); + ].forEach(key => shortcuts.off(key, this.toggleQuickOpenModal)); shortcuts.off(L10N.getStr("gotoLineModal.key3"), this.toggleQuickOpenModal); + shortcuts.off( + L10N.getStr("projectTextSearch.key"), + this.jumpToProjectSearch + ); + shortcuts.off("Escape", this.onEscape); shortcuts.off("CmdOrCtrl+/", this.onCommandSlash); } + jumpToProjectSearch = e => { + e.preventDefault(); + this.props.setPrimaryPaneTab(primaryPaneTabs.PROJECT_SEARCH); + this.props.setActiveSearch(primaryPaneTabs.PROJECT_SEARCH); + }; + onEscape = e => { const { activeSearch, @@ -217,7 +231,6 @@ class App extends Component { /> ) : null} - ); @@ -335,8 +348,8 @@ const mapStateToProps = state => ({ export default connect(mapStateToProps, { setActiveSearch: actions.setActiveSearch, closeActiveSearch: actions.closeActiveSearch, - closeProjectSearch: actions.closeProjectSearch, openQuickOpen: actions.openQuickOpen, closeQuickOpen: actions.closeQuickOpen, setOrientation: actions.setOrientation, + setPrimaryPaneTab: actions.setPrimaryPaneTab, })(App); diff --git a/devtools/client/debugger/src/components/Editor/Tab.js b/devtools/client/debugger/src/components/Editor/Tab.js index 506b34ecc741..d19ba2c318c0 100644 --- a/devtools/client/debugger/src/components/Editor/Tab.js +++ b/devtools/client/debugger/src/components/Editor/Tab.js @@ -54,6 +54,7 @@ class Tab extends PureComponent { tabSources: PropTypes.array.isRequired, toggleBlackBox: PropTypes.func.isRequired, togglePrettyPrint: PropTypes.func.isRequired, + isBlackBoxed: PropTypes.bool.isRequired, }; } @@ -167,10 +168,6 @@ class Tab extends PureComponent { showMenu(e, buildMenu(items)); } - isProjectSearchEnabled() { - return this.props.activeSearch === "project"; - } - isSourceSearchEnabled() { return this.props.activeSearch === "source"; } @@ -192,7 +189,6 @@ class Tab extends PureComponent { const active = selectedLocation && sourceId == selectedLocation.sourceId && - !this.isProjectSearchEnabled() && !this.isSourceSearchEnabled(); const isPrettyCode = isPretty(source); diff --git a/devtools/client/debugger/src/components/ProjectSearch.css b/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.css similarity index 98% rename from devtools/client/debugger/src/components/ProjectSearch.css rename to devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.css index 83725d1aee67..16f6f78511fb 100644 --- a/devtools/client/debugger/src/components/ProjectSearch.css +++ b/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.css @@ -11,7 +11,6 @@ display: flex; flex-direction: column; z-index: 20; - background-color: var(--theme-body-background); overflow-y: hidden; /* Using the same colors as the Netmonitor's --table-selection-background-hover */ diff --git a/devtools/client/debugger/src/components/ProjectSearch.js b/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.js similarity index 83% rename from devtools/client/debugger/src/components/ProjectSearch.js rename to devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.js index 9cb56e671e7f..bcdcb9079196 100644 --- a/devtools/client/debugger/src/components/ProjectSearch.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/ProjectSearch.js @@ -4,27 +4,26 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; -import { connect } from "../utils/connect"; +import { connect } from "../../utils/connect"; import classnames from "classnames"; -import actions from "../actions"; +import actions from "../../actions"; -import { getEditor } from "../utils/editor"; -import { searchKeys } from "../constants"; +import { getEditor } from "../../utils/editor"; +import { searchKeys } from "../../constants"; -import { statusType } from "../reducers/project-text-search"; -import { getRelativePath } from "../utils/sources-tree/utils"; -import { getFormattedSourceId } from "../utils/source"; +import { statusType } from "../../reducers/project-text-search"; +import { getRelativePath } from "../../utils/sources-tree/utils"; +import { getFormattedSourceId } from "../../utils/source"; import { - getActiveSearch, getProjectSearchResults, getProjectSearchStatus, getProjectSearchQuery, getContext, -} from "../selectors"; +} from "../../selectors"; -import ManagedTree from "./shared/ManagedTree"; -import SearchInput from "./shared/SearchInput"; -import AccessibleImage from "./shared/AccessibleImage"; +import ManagedTree from "../shared/ManagedTree"; +import SearchInput from "../shared/SearchInput"; +import AccessibleImage from "../shared/AccessibleImage"; const { PluralForm } = require("devtools/shared/plural-form"); @@ -50,9 +49,7 @@ export class ProjectSearch extends Component { static get propTypes() { return { - activeSearch: PropTypes.string, clearSearch: PropTypes.func.isRequired, - closeProjectSearch: PropTypes.func.isRequired, cx: PropTypes.object.isRequired, doSearchForHighlight: PropTypes.func.isRequired, query: PropTypes.string.isRequired, @@ -74,20 +71,11 @@ export class ProjectSearch extends Component { componentDidMount() { const { shortcuts } = this.context; - - shortcuts.on( - L10N.getStr("projectTextSearch.key"), - this.toggleProjectTextSearch - ); shortcuts.on("Enter", this.onEnterPress); } componentWillUnmount() { const { shortcuts } = this.context; - shortcuts.off( - L10N.getStr("projectTextSearch.key"), - this.toggleProjectTextSearch - ); shortcuts.off("Enter", this.onEnterPress); } @@ -104,21 +92,6 @@ export class ProjectSearch extends Component { } } - toggleProjectTextSearch = e => { - const { cx, closeProjectSearch, setActiveSearch } = this.props; - if (e) { - e.preventDefault(); - } - - if (this.isProjectSearchEnabled()) { - return closeProjectSearch(cx); - } - - return setActiveSearch("project"); - }; - - isProjectSearchEnabled = () => this.props.activeSearch === "project"; - selectMatchItem = matchItem => { this.props.selectSpecificLocation(this.props.cx, matchItem.location); this.props.doSearchForHighlight( @@ -167,11 +140,8 @@ export class ProjectSearch extends Component { }; onEnterPress = () => { - if ( - !this.isProjectSearchEnabled() || - !this.state.focusedItem || - this.state.inputFocused - ) { + // This is to select a match from the search result. + if (!this.state.focusedItem || this.state.inputFocused) { return; } if (this.state.focusedItem.type === "MATCH") { @@ -278,7 +248,7 @@ export class ProjectSearch extends Component { } renderInput() { - const { closeProjectSearch, status } = this.props; + const { status } = this.props; return ( this.setState({ inputFocused: false })} onKeyDown={this.onKeyDown} onHistoryScroll={this.onHistoryScroll} - showClose={true} + showClose={false} showExcludePatterns={true} excludePatternsLabel={L10N.getStr( "projectTextSearch.excludePatterns.label" @@ -302,7 +272,6 @@ export class ProjectSearch extends Component { excludePatternsPlaceholder={L10N.getStr( "projectTextSearch.excludePatterns.placeholder" )} - handleClose={closeProjectSearch} ref="searchInput" showSearchModifiers={true} searchKey={searchKeys.PROJECT_SEARCH} @@ -312,10 +281,6 @@ export class ProjectSearch extends Component { } render() { - if (!this.isProjectSearchEnabled()) { - return null; - } - return (
@@ -333,14 +298,12 @@ ProjectSearch.contextTypes = { const mapStateToProps = state => ({ cx: getContext(state), - activeSearch: getActiveSearch(state), results: getProjectSearchResults(state), query: getProjectSearchQuery(state), status: getProjectSearchStatus(state), }); export default connect(mapStateToProps, { - closeProjectSearch: actions.closeProjectSearch, searchSources: actions.searchSources, clearSearch: actions.clearSearch, selectSpecificLocation: actions.selectSpecificLocation, diff --git a/devtools/client/debugger/src/components/PrimaryPanes/index.js b/devtools/client/debugger/src/components/PrimaryPanes/index.js index 33fad62b58de..f1ce672bdec2 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/index.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/index.js @@ -15,14 +15,22 @@ import { } from "../../selectors"; import { prefs } from "../../utils/prefs"; import { connect } from "../../utils/connect"; +import { primaryPaneTabs } from "../../constants"; import { formatKeyShortcut } from "../../utils/text"; import Outline from "./Outline"; import SourcesTree from "./SourcesTree"; +import ProjectSearch from "./ProjectSearch"; import AccessibleImage from "../shared/AccessibleImage"; import "./Sources.css"; +const tabs = [ + primaryPaneTabs.SOURCES, + primaryPaneTabs.OUTLINE, + primaryPaneTabs.PROJECT_SEARCH, +]; + class PrimaryPanes extends Component { constructor(props) { super(props); @@ -37,15 +45,13 @@ class PrimaryPanes extends Component { clearProjectDirectoryRoot: PropTypes.func.isRequired, cx: PropTypes.object.isRequired, projectRootName: PropTypes.string.isRequired, - selectedTab: PropTypes.oneOf(["sources", "outline"]).isRequired, + selectedTab: PropTypes.oneOf(tabs).isRequired, setPrimaryPaneTab: PropTypes.func.isRequired, + setActiveSearch: PropTypes.func.isRequired, + closeActiveSearch: PropTypes.func.isRequired, }; } - showPane = selectedPane => { - this.props.setPrimaryPaneTab(selectedPane); - }; - onAlphabetizeClick = () => { const alphabetizeOutline = !prefs.alphabetizeOutline; prefs.alphabetizeOutline = alphabetizeOutline; @@ -53,31 +59,40 @@ class PrimaryPanes extends Component { }; onActivateTab = index => { - if (index === 0) { - this.showPane("sources"); + const tab = tabs.at(index); + this.props.setPrimaryPaneTab(tab); + if (tab == primaryPaneTabs.PROJECT_SEARCH) { + this.props.setActiveSearch(tab); } else { - this.showPane("outline"); + this.props.closeActiveSearch(); } }; - renderOutlineTabs() { - const sources = formatKeyShortcut(L10N.getStr("sources.header")); - const outline = formatKeyShortcut(L10N.getStr("outline.header")); - const isSources = this.props.selectedTab === "sources"; - const isOutline = this.props.selectedTab === "outline"; - + renderTabList() { return [ - {sources} + {formatKeyShortcut(L10N.getStr("sources.header"))} , - {outline} + {formatKeyShortcut(L10N.getStr("outline.header"))} + , + + {formatKeyShortcut(L10N.getStr("search.header"))} , ]; } @@ -104,22 +119,16 @@ class PrimaryPanes extends Component { ); } - renderThreadSources() { - return ; - } - render() { const { selectedTab, projectRootName } = this.props; - const activeIndex = selectedTab === "sources" ? 0 : 1; - return ( - {this.renderOutlineTabs()} + {this.renderTabList()}
{this.renderProjectRootHeader()} - {this.renderThreadSources()} +
+
); diff --git a/devtools/client/debugger/src/components/PrimaryPanes/moz.build b/devtools/client/debugger/src/components/PrimaryPanes/moz.build index e0886041964c..fc73b7bee79d 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/moz.build +++ b/devtools/client/debugger/src/components/PrimaryPanes/moz.build @@ -9,6 +9,7 @@ CompiledModules( "index.js", "Outline.js", "OutlineFilter.js", + "ProjectSearch.js", "SourcesTree.js", "SourcesTreeItem.js", ) diff --git a/devtools/client/debugger/src/components/PrimaryPanes/tests/PrimaryPanes.spec.js b/devtools/client/debugger/src/components/PrimaryPanes/tests/PrimaryPanes.spec.js index 52fcac877abd..888bd540529e 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/tests/PrimaryPanes.spec.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/tests/PrimaryPanes.spec.js @@ -38,6 +38,8 @@ function generateDefaults(overrides) { setActiveSearch: jest.fn(), closeActiveSearch: jest.fn(), clearProjectDirectoryRoot: jest.fn(), + selectedTab: "sources", + cx: {}, threads: [], ...overrides, }; diff --git a/devtools/client/debugger/src/components/test/ProjectSearch.spec.js b/devtools/client/debugger/src/components/PrimaryPanes/tests/ProjectSearch.spec.js similarity index 97% rename from devtools/client/debugger/src/components/test/ProjectSearch.spec.js rename to devtools/client/debugger/src/components/PrimaryPanes/tests/ProjectSearch.spec.js index c21a69f20ec8..10f9f197fe44 100644 --- a/devtools/client/debugger/src/components/test/ProjectSearch.spec.js +++ b/devtools/client/debugger/src/components/PrimaryPanes/tests/ProjectSearch.spec.js @@ -9,9 +9,9 @@ import PropTypes from "prop-types"; import { mount, shallow } from "enzyme"; import { ProjectSearch } from "../ProjectSearch"; -import { statusType } from "../../reducers/project-text-search"; -import { mockcx } from "../../utils/test-mockup"; -import { searchKeys } from "../../constants"; +import { statusType } from "../../../reducers/project-text-search"; +import { mockcx } from "../../../utils/test-mockup"; +import { searchKeys } from "../../../constants"; const hooks = { on: [], off: [] }; const shortcuts = { diff --git a/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap b/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap index 2153b01f1386..3c7833c451b7 100644 --- a/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap +++ b/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/PrimaryPanes.spec.js.snap @@ -2,7 +2,7 @@ exports[`PrimaryPanes should not render the directory root header if the directory root has not been set. 1`] = ` @@ -14,7 +14,7 @@ exports[`PrimaryPanes should not render the directory root header if the directo > Sources @@ -26,6 +26,13 @@ exports[`PrimaryPanes should not render the directory root header if the directo > Outline + + Search + + `; exports[`PrimaryPanes should render the directory root header if the directory root has been set. 1`] = ` @@ -59,7 +67,7 @@ exports[`PrimaryPanes should render the directory root header if the directory r > Sources @@ -71,6 +79,13 @@ exports[`PrimaryPanes should render the directory root header if the directory r > Outline + + Search + + `; diff --git a/devtools/client/debugger/src/components/test/__snapshots__/ProjectSearch.spec.js.snap b/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/ProjectSearch.spec.js.snap similarity index 95% rename from devtools/client/debugger/src/components/test/__snapshots__/ProjectSearch.spec.js.snap rename to devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/ProjectSearch.spec.js.snap index bf7f5a83ee9c..88e9a4b2bdd8 100644 --- a/devtools/client/debugger/src/components/test/__snapshots__/ProjectSearch.spec.js.snap +++ b/devtools/client/debugger/src/components/PrimaryPanes/tests/__snapshots__/ProjectSearch.spec.js.snap @@ -14,7 +14,6 @@ exports[`ProjectSearch found no search results 1`] = ` count={0} excludePatternsLabel="files to exclude" excludePatternsPlaceholder="e.g. **/node_modules/**,app.js" - handleClose={[MockFunction]} isLoading={false} onBlur={[Function]} onChange={[Function]} @@ -25,7 +24,7 @@ exports[`ProjectSearch found no search results 1`] = ` placeholder="Find in files…" query="foo" searchKey="project-search" - showClose={true} + showClose={false} showErrorEmoji={true} showExcludePatterns={true} showSearchModifiers={true} @@ -143,7 +142,6 @@ exports[`ProjectSearch found search results 1`] = ` count={5} excludePatternsLabel="files to exclude" excludePatternsPlaceholder="e.g. **/node_modules/**,app.js" - handleClose={[MockFunction]} isLoading={false} onBlur={[Function]} onChange={[Function]} @@ -154,7 +152,7 @@ exports[`ProjectSearch found search results 1`] = ` placeholder="Find in files…" query="match" searchKey="project-search" - showClose={true} + showClose={false} showErrorEmoji={false} showExcludePatterns={true} showSearchModifiers={true} @@ -166,7 +164,6 @@ exports[`ProjectSearch found search results 1`] = ` excludePatternsLabel="files to exclude" excludePatternsPlaceholder="e.g. **/node_modules/**,app.js" expanded={false} - handleClose={[MockFunction]} hasPrefix={false} isLoading={false} onBlur={[Function]} @@ -188,7 +185,7 @@ exports[`ProjectSearch found search results 1`] = ` } selectedItemId="" setSearchOptions={[Function]} - showClose={true} + showClose={false} showErrorEmoji={false} showExcludePatterns={true} showSearchModifiers={true} @@ -250,16 +247,11 @@ exports[`ProjectSearch found search results 1`] = ` - - Modifiers: -
- - - -
`; -exports[`ProjectSearch renders nothing when disabled 1`] = `""`; +exports[`ProjectSearch renders nothing when disabled 1`] = ` +
+
+
+ +
+
+ No results found +
+
+
+`; exports[`ProjectSearch should display loading message while search is in progress 1`] = `
has not been pressed 1`] = ` count={0} excludePatternsLabel="files to exclude" excludePatternsPlaceholder="e.g. **/node_modules/**,app.js" - handleClose={[MockFunction]} isLoading={false} onBlur={[Function]} onChange={[Function]} @@ -1106,7 +1112,7 @@ exports[`ProjectSearch where has not been pressed 1`] = ` placeholder="Find in files…" query="" searchKey="project-search" - showClose={true} + showClose={false} showErrorEmoji={true} showExcludePatterns={true} showSearchModifiers={true} diff --git a/devtools/client/debugger/src/components/WelcomeBox.js b/devtools/client/debugger/src/components/WelcomeBox.js index 8776ec98d21a..18567d31f744 100644 --- a/devtools/client/debugger/src/components/WelcomeBox.js +++ b/devtools/client/debugger/src/components/WelcomeBox.js @@ -6,6 +6,7 @@ import React, { Component } from "react"; import PropTypes from "prop-types"; import { connect } from "../utils/connect"; +import { primaryPaneTabs } from "../constants"; import actions from "../actions"; import { getPaneCollapse } from "../selectors"; @@ -19,6 +20,7 @@ export class WelcomeBox extends Component { openQuickOpen: PropTypes.func.isRequired, setActiveSearch: PropTypes.func.isRequired, toggleShortcutsModal: PropTypes.func.isRequired, + setPrimaryPaneTab: PropTypes.func.isRequired, }; } @@ -38,7 +40,6 @@ export class WelcomeBox extends Component { const allShortcutsLabel = L10N.getStr("welcome.allShortcuts"); const searchSourcesLabel = L10N.getStr("welcome.search2").substring(2); const searchProjectLabel = L10N.getStr("welcome.findInFiles2").substring(2); - const { setActiveSearch, openQuickOpen, toggleShortcutsModal } = this.props; return (
@@ -48,7 +49,7 @@ export class WelcomeBox extends Component { className="welcomebox__searchSources" role="button" tabIndex="0" - onClick={() => openQuickOpen()} + onClick={() => this.props.openQuickOpen()} > {searchSourcesShortcut} {searchSourcesLabel} @@ -57,7 +58,10 @@ export class WelcomeBox extends Component { className="welcomebox__searchProject" role="button" tabIndex="0" - onClick={setActiveSearch.bind(null, "project")} + onClick={() => { + this.props.setActiveSearch(primaryPaneTabs.PROJECT_SEARCH); + this.props.setPrimaryPaneTab(primaryPaneTabs.PROJECT_SEARCH); + }} > {searchProjectShortcut} {searchProjectLabel} @@ -66,7 +70,7 @@ export class WelcomeBox extends Component { className="welcomebox__allShortcuts" role="button" tabIndex="0" - onClick={() => toggleShortcutsModal()} + onClick={() => this.props.toggleShortcutsModal()} > {allShortcutsShortcut} {allShortcutsLabel} @@ -86,4 +90,5 @@ export default connect(mapStateToProps, { togglePaneCollapse: actions.togglePaneCollapse, setActiveSearch: actions.setActiveSearch, openQuickOpen: actions.openQuickOpen, + setPrimaryPaneTab: actions.setPrimaryPaneTab, })(WelcomeBox); diff --git a/devtools/client/debugger/src/components/moz.build b/devtools/client/debugger/src/components/moz.build index cf7841897315..41ced8d47418 100644 --- a/devtools/client/debugger/src/components/moz.build +++ b/devtools/client/debugger/src/components/moz.build @@ -13,7 +13,6 @@ DIRS += [ CompiledModules( "A11yIntention.js", "App.js", - "ProjectSearch.js", "QuickOpenModal.js", "ShortcutsModal.js", "WelcomeBox.js", diff --git a/devtools/client/debugger/src/components/shared/SearchInput.js b/devtools/client/debugger/src/components/shared/SearchInput.js index d86f69edb277..8ac7ed96bbe5 100644 --- a/devtools/client/debugger/src/components/shared/SearchInput.js +++ b/devtools/client/debugger/src/components/shared/SearchInput.js @@ -42,7 +42,6 @@ export class SearchInput extends Component { constructor(props) { super(props); - this.state = { history: [], excludePatterns: props.searchOptions.excludePatterns, diff --git a/devtools/client/debugger/src/components/test/WelcomeBox.spec.js b/devtools/client/debugger/src/components/test/WelcomeBox.spec.js index 7e07f36203e9..0a1dbc74596f 100644 --- a/devtools/client/debugger/src/components/test/WelcomeBox.spec.js +++ b/devtools/client/debugger/src/components/test/WelcomeBox.spec.js @@ -15,6 +15,7 @@ function render(overrides = {}) { setActiveSearch: jest.fn(), openQuickOpen: jest.fn(), toggleShortcutsModal: jest.fn(), + setPrimaryPaneTab: jest.fn(), ...overrides, }; const component = shallow(); diff --git a/devtools/client/debugger/src/constants.js b/devtools/client/debugger/src/constants.js index a6b9a105d1cf..67b6ca536224 100644 --- a/devtools/client/debugger/src/constants.js +++ b/devtools/client/debugger/src/constants.js @@ -7,3 +7,9 @@ export const searchKeys = { FILE_SEARCH: "file-search", QUICKOPEN_SEARCH: "quickopen-search", }; + +export const primaryPaneTabs = { + SOURCES: "sources", + OUTLINE: "outline", + PROJECT_SEARCH: "project", +}; diff --git a/devtools/client/debugger/src/debugger.css b/devtools/client/debugger/src/debugger.css index dc4e28e64303..6138b7f1de5b 100644 --- a/devtools/client/debugger/src/debugger.css +++ b/devtools/client/debugger/src/debugger.css @@ -38,8 +38,8 @@ @import url("chrome://devtools/content/debugger/src/components/Editor/Tabs.css"); @import url("chrome://devtools/content/debugger/src/components/PrimaryPanes/Outline.css"); @import url("chrome://devtools/content/debugger/src/components/PrimaryPanes/OutlineFilter.css"); +@import url("chrome://devtools/content/debugger/src/components/PrimaryPanes/ProjectSearch.css"); @import url("chrome://devtools/content/debugger/src/components/PrimaryPanes/Sources.css"); -@import url("chrome://devtools/content/debugger/src/components/ProjectSearch.css"); @import url("chrome://devtools/content/debugger/src/components/QuickOpenModal.css"); @import url("chrome://devtools/content/debugger/src/components/SecondaryPanes/Breakpoints/Breakpoints.css"); @import url("chrome://devtools/content/debugger/src/components/SecondaryPanes/CommandBar.css"); diff --git a/devtools/client/debugger/src/reducers/project-text-search.js b/devtools/client/debugger/src/reducers/project-text-search.js index 276e5034625e..e8037182408e 100644 --- a/devtools/client/debugger/src/reducers/project-text-search.js +++ b/devtools/client/debugger/src/reducers/project-text-search.js @@ -19,9 +19,9 @@ export const statusType = { error: "ERROR", }; -export function initialProjectTextSearchState() { +export function initialProjectTextSearchState(state) { return { - query: "", + query: state?.query || "", results: [], ongoingSearch: null, status: statusType.initial, @@ -72,8 +72,9 @@ function update(state = initialProjectTextSearchState(), action) { case "CLEAR_SEARCH": case "CLOSE_PROJECT_SEARCH": - case "NAVIGATE": return initialProjectTextSearchState(); + case "NAVIGATE": + return initialProjectTextSearchState(state); } return state; } diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-project-search.js b/devtools/client/debugger/test/mochitest/browser_dbg-project-search.js index 5be882f87e17..625f50e6e826 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-project-search.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-project-search.js @@ -8,15 +8,6 @@ requestLongerTimeout(3); -add_task(async function testOpeningAndClosingEmptyProjectSearch() { - const dbg = await initDebugger( - "doc-script-switching.html", - "script-switching-01.js" - ); - await openProjectSearch(dbg); - await closeProjectSearch(dbg); -}); - add_task(async function testProjectSearchCloseOnNavigation() { const dbg = await initDebugger( "doc-script-switching.html", @@ -42,8 +33,6 @@ add_task(async function testSimpleProjectSearch() { "script-switching-01.js" ); - await selectSource(dbg, "script-switching-01.js"); - await openProjectSearch(dbg); const searchTerm = "first"; await doProjectSearch(dbg, searchTerm); @@ -58,15 +47,8 @@ add_task(async function testSimpleProjectSearch() { ); info("Select a result match to open the location in the source"); - await selectResultMatch(dbg); - await waitForLoadedSource(dbg, "script-switching-01.js"); - - is(dbg.selectors.getActiveSearch(), null); - - ok( - dbg.selectors.getSelectedSource().url.includes("script-switching-01.js"), - "The correct source (script-switching-01.js) is selected" - ); + await clickElement(dbg, "fileMatch"); + await waitForSelectedSource(dbg, "script-switching-01.js"); }); add_task(async function testMatchesForRegexSearches() { @@ -90,7 +72,6 @@ add_task(async function testMatchesForRegexSearches() { // Turn off the regex modifier so does not break tests below await clickElement(dbg, "projectSearchModifiersRegexMatch"); - await closeProjectSearch(dbg); }); // Test expanding search results to reveal the search matches. @@ -113,6 +94,8 @@ add_task(async function testExpandSearchResultsToShowMatches() { add_task(async function testSearchModifiers() { const dbg = await initDebugger("doc-react.html", "App.js"); + await openProjectSearch(dbg); + await assertProjectSearchModifier( dbg, "projectSearchModifiersCaseSensitive", @@ -212,7 +195,8 @@ add_task(async function testSearchExcludePatterns() { "The exclude pattern for node modules is persisted accross reloads" ); - // Clear the exclude patterns field so that it does not impact on the subsequent tests + // Clear the fields so that it does not impact on the subsequent tests + await clearElement(dbg, "projectSearchSearchInput"); await clearElement(dbg, "excludePatternsInput"); pressKey(dbg, "Enter"); }); @@ -225,11 +209,10 @@ async function assertProjectSearchModifier( expected ) { info(`Assert ${title} search modifier`); - await openProjectSearch(dbg); + type(dbg, searchTerm); info(`Turn on the ${title} search modifier option`); await clickElement(dbg, searchModifierBtn); - let results = await waitForSearchResults(dbg, expected.resultWithModifierOn); is( results.length, @@ -246,12 +229,5 @@ async function assertProjectSearchModifier( expected.resultWithModifierOff, `${results.length} results where found` ); - - await closeProjectSearch(dbg); -} - -async function selectResultMatch(dbg) { - const select = waitForState(dbg, () => !dbg.selectors.getActiveSearch()); - await clickElement(dbg, "fileMatch"); - return select; + await clearElement(dbg, "projectSearchSearchInput"); } diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-sources-project-search.js b/devtools/client/debugger/test/mochitest/browser_dbg-sources-project-search.js index 8451deb10886..c74292b4b7fa 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-sources-project-search.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-sources-project-search.js @@ -6,6 +6,8 @@ "use strict"; +requestLongerTimeout(3); + // Tests for searching in dynamic (without urls) sources add_task(async function testSearchDynamicScripts() { const dbg = await initDebugger("doc-minified.html"); @@ -22,7 +24,6 @@ add_task(async function testSearchDynamicScripts() { "The search result was found in the eval script." ); - await closeProjectSearch(dbg); await resume(dbg); await executeComplete; }); @@ -41,15 +42,12 @@ add_task(async function testIgnoreMinifiedSourceForPrettySource() { "The search result was found in the minified (pretty.js) source" ); - await closeProjectSearch(dbg); - await selectSource(dbg, "pretty.js"); await waitForSelectedSource(dbg, "pretty.js"); info("Pretty print the source"); await prettyPrint(dbg); - await openProjectSearch(dbg); fileResults = await doProjectSearch(dbg, "stuff"); is( @@ -114,8 +112,6 @@ add_task(async function testBlackBoxedSources() { is(fileResults.length, 0, "No results were found as pretty.js is blackboxed"); - await closeProjectSearch(dbg); - info("Unblackbox pretty.js"); await toggleBlackbox(dbg); diff --git a/devtools/client/debugger/test/mochitest/shared-head.js b/devtools/client/debugger/test/mochitest/shared-head.js index e3b3519c7c40..825e602a7670 100644 --- a/devtools/client/debugger/test/mochitest/shared-head.js +++ b/devtools/client/debugger/test/mochitest/shared-head.js @@ -1667,6 +1667,7 @@ const selectors = { logPointInSecPane: ".breakpoint.is-log", searchField: ".search-field", blackbox: ".action.black-box", + projectSearchSearchInput: ".project-text-search .search-field input", projectSearchCollapsed: ".project-text-search .arrow:not(.expanded)", projectSearchExpandedResults: ".project-text-search .result", projectSearchFileResults: ".project-text-search .file-result", @@ -2486,6 +2487,7 @@ function openProjectSearch(dbg) { * @return {Array} List of search results element nodes */ async function doProjectSearch(dbg, searchTerm) { + await clearElement(dbg, "projectSearchSearchInput"); type(dbg, searchTerm); pressKey(dbg, "Enter"); return waitForSearchResults(dbg); @@ -2510,18 +2512,6 @@ async function waitForSearchResults(dbg, expectedResults) { return findAllElements(dbg, "projectSearchFileResults"); } -/** - * Closes the project search panel - * - * @param {Object} dbg - * @return {Boolean} When the panel closes - */ -function closeProjectSearch(dbg) { - info("Closing the project search panel"); - synthesizeKeyShortcut("CmdOrCtrl+Shift+F"); - return waitForState(dbg, state => !dbg.selectors.getActiveSearch()); -} - /** * Get the no of expanded search results * diff --git a/devtools/client/jar.mn b/devtools/client/jar.mn index 18c3c9a5d831..65d5bf595aca 100644 --- a/devtools/client/jar.mn +++ b/devtools/client/jar.mn @@ -287,7 +287,6 @@ devtools.jar: content/debugger/src/components/variables.css (debugger/src/components/variables.css) content/debugger/src/components/A11yIntention.css (debugger/src/components/A11yIntention.css) content/debugger/src/components/App.css (debugger/src/components/App.css) - content/debugger/src/components/ProjectSearch.css (debugger/src/components/ProjectSearch.css) content/debugger/src/components/QuickOpenModal.css (debugger/src/components/QuickOpenModal.css) content/debugger/src/components/ShortcutsModal.css (debugger/src/components/ShortcutsModal.css) content/debugger/src/components/WelcomeBox.css (debugger/src/components/WelcomeBox.css) @@ -319,6 +318,7 @@ devtools.jar: content/debugger/src/components/Editor/Tabs.css (debugger/src/components/Editor/Tabs.css) content/debugger/src/components/PrimaryPanes/Outline.css (debugger/src/components/PrimaryPanes/Outline.css) content/debugger/src/components/PrimaryPanes/OutlineFilter.css (debugger/src/components/PrimaryPanes/OutlineFilter.css) + content/debugger/src/components/PrimaryPanes/ProjectSearch.css (debugger/src/components/PrimaryPanes/ProjectSearch.css) content/debugger/src/components/PrimaryPanes/Sources.css (debugger/src/components/PrimaryPanes/Sources.css) content/debugger/src/components/SecondaryPanes/Breakpoints/Breakpoints.css (debugger/src/components/SecondaryPanes/Breakpoints/Breakpoints.css) content/debugger/src/components/SecondaryPanes/CommandBar.css (debugger/src/components/SecondaryPanes/CommandBar.css) diff --git a/devtools/client/locales/en-US/components.properties b/devtools/client/locales/en-US/components.properties index b1000c52b2dd..7849afba30d2 100644 --- a/devtools/client/locales/en-US/components.properties +++ b/devtools/client/locales/en-US/components.properties @@ -36,18 +36,14 @@ appErrorBoundary.fileBugButton=File Bug Report # after the panel errors to instruct the user to reload the panel. appErrorBoundary.reloadPanelInfo=Close and reopen the toolbox to clear this error. -# LOCALIZATION NOTE(searchModifier.modifiersLabel): A label -# preceding the group of modifiers -searchModifier.modifiersLabel=Modifiers: - -# LOCALIZATION NOTE(searchModifier.regex): A search option +# LOCALIZATION NOTE(searchModifier.regExpModifier): A search option # when searching text in a file -searchModifier.regex=Regex +searchModifier.regExpModifier=Use Regular Expression -# LOCALIZATION NOTE(searchModifier.caseSensitive): A search option +# LOCALIZATION NOTE(searchModifier.caseSensitiveModifier): A search option # when searching text in a file -searchModifier.caseSensitive=Case sensitive +searchModifier.caseSensitiveModifier=Match Case -# LOCALIZATION NOTE(searchModifier.wholeWord): A search option +# LOCALIZATION NOTE(searchModifier.wholeWordModifier): A search option # when searching text in a file -searchModifier.wholeWord=Whole word +searchModifier.wholeWordModifier=Match Whole Word diff --git a/devtools/client/locales/en-US/debugger.properties b/devtools/client/locales/en-US/debugger.properties index 83a1c11285f3..411b877d8d12 100644 --- a/devtools/client/locales/en-US/debugger.properties +++ b/devtools/client/locales/en-US/debugger.properties @@ -766,6 +766,9 @@ sources.header=Sources # LOCALIZATION NOTE (outline.header): Outline left sidebar header outline.header=Outline +# LOCALIZATION NOTE (search.header): Search left sidebar header +search.header=Search + # LOCALIZATION NOTE (outline.placeholder): Placeholder text for the filter input # element outline.placeholder=Filter functions diff --git a/devtools/client/shared/components/SearchModifiers.js b/devtools/client/shared/components/SearchModifiers.js index fbfb7c87c8e3..d221b9839bff 100644 --- a/devtools/client/shared/components/SearchModifiers.js +++ b/devtools/client/shared/components/SearchModifiers.js @@ -26,19 +26,19 @@ const modifierOptions = [ value: "regexMatch", className: "regex-match-btn", svgName: "regex-match", - tooltip: l10n.getStr("searchModifier.regex"), + tooltip: l10n.getStr("searchModifier.regExpModifier"), }, { value: "caseSensitive", className: "case-sensitive-btn", svgName: "case-match", - tooltip: l10n.getStr("searchModifier.caseSensitive"), + tooltip: l10n.getStr("searchModifier.caseSensitiveModifier"), }, { value: "wholeWord", className: "whole-word-btn", svgName: "whole-word-match", - tooltip: l10n.getStr("searchModifier.wholeWord"), + tooltip: l10n.getStr("searchModifier.wholeWordModifier"), }, ]; @@ -76,10 +76,6 @@ class SearchModifiers extends Component { return div( { className: "search-modifiers" }, span({ className: "pipe-divider" }), - span( - { className: "search-type-name" }, - l10n.getStr("searchModifier.modifiersLabel") - ), modifierOptions.map(options => this.#renderSearchModifier(options)) ); } diff --git a/testing/talos/talos/tests/devtools/addon/content/tests/debugger/custom.js b/testing/talos/talos/tests/devtools/addon/content/tests/debugger/custom.js index cb87294a0ebb..113efb26874f 100644 --- a/testing/talos/talos/tests/devtools/addon/content/tests/debugger/custom.js +++ b/testing/talos/talos/tests/devtools/addon/content/tests/debugger/custom.js @@ -133,6 +133,7 @@ async function testProjectSearch(tab, toolbox) { const firstSearchResultTest = runTest( `custom.jsdebugger.project-search.first-search-result.DAMP` ); + await dbg.actions.setPrimaryPaneTab("project"); await dbg.actions.setActiveSearch("project"); const complete = dbg.actions.searchSources(cx, "return"); // Wait till the first search result match is rendered