summaryrefslogtreecommitdiffstats
path: root/devtools/client/debugger/src/actions/project-text-search.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/debugger/src/actions/project-text-search.js')
-rw-r--r--devtools/client/debugger/src/actions/project-text-search.js136
1 files changed, 136 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/actions/project-text-search.js b/devtools/client/debugger/src/actions/project-text-search.js
new file mode 100644
index 0000000000..73f1c45e6a
--- /dev/null
+++ b/devtools/client/debugger/src/actions/project-text-search.js
@@ -0,0 +1,136 @@
+/* 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 <http://mozilla.org/MPL/2.0/>. */
+
+/**
+ * Redux actions for the search state
+ * @module actions/search
+ */
+
+import { isFulfilled } from "../utils/async-value";
+import {
+ getFirstSourceActorForGeneratedSource,
+ hasPrettySource,
+ getSourceList,
+ getSettledSourceTextContent,
+} from "../selectors";
+import { isThirdParty } from "../utils/source";
+import { createLocation } from "../utils/location";
+import { loadSourceText } from "./sources/loadSourceText";
+import {
+ getTextSearchOperation,
+ getTextSearchStatus,
+} from "../selectors/project-text-search";
+import { statusType } from "../reducers/project-text-search";
+
+export function addSearchQuery(cx, query) {
+ return { type: "ADD_QUERY", cx, query };
+}
+
+export function addOngoingSearch(cx, ongoingSearch) {
+ return { type: "ADD_ONGOING_SEARCH", cx, ongoingSearch };
+}
+
+export function addSearchResult(cx, sourceId, filepath, matches) {
+ return {
+ type: "ADD_SEARCH_RESULT",
+ cx,
+ result: { sourceId, filepath, matches },
+ };
+}
+
+export function clearSearchResults(cx) {
+ return { type: "CLEAR_SEARCH_RESULTS", cx };
+}
+
+export function clearSearch(cx) {
+ return { type: "CLEAR_SEARCH", cx };
+}
+
+export function updateSearchStatus(cx, status) {
+ return { type: "UPDATE_STATUS", cx, status };
+}
+
+export function closeProjectSearch(cx) {
+ return ({ dispatch, getState }) => {
+ dispatch(stopOngoingSearch(cx));
+ dispatch({ type: "CLOSE_PROJECT_SEARCH" });
+ };
+}
+
+export function stopOngoingSearch(cx) {
+ return ({ dispatch, getState }) => {
+ const state = getState();
+ const ongoingSearch = getTextSearchOperation(state);
+ const status = getTextSearchStatus(state);
+ if (ongoingSearch && status !== statusType.done) {
+ ongoingSearch.cancel();
+ dispatch(updateSearchStatus(cx, statusType.cancelled));
+ }
+ };
+}
+
+export function searchSources(cx, query) {
+ let cancelled = false;
+
+ const search = async ({ dispatch, getState }) => {
+ dispatch(stopOngoingSearch(cx));
+ await dispatch(addOngoingSearch(cx, search));
+ await dispatch(clearSearchResults(cx));
+ await dispatch(addSearchQuery(cx, query));
+ dispatch(updateSearchStatus(cx, statusType.fetching));
+ let validSources = getSourceList(getState()).filter(
+ source => !hasPrettySource(getState(), source.id) && !isThirdParty(source)
+ );
+ // Sort original entries first so that search results are more useful.
+ // See bug 1642778.
+ validSources = [
+ ...validSources.filter(x => x.isOriginal),
+ ...validSources.filter(x => !x.isOriginal),
+ ];
+ for (const source of validSources) {
+ if (cancelled) {
+ return;
+ }
+
+ const sourceActor = getFirstSourceActorForGeneratedSource(
+ getState(),
+ source.id
+ );
+ await dispatch(loadSourceText(cx, source, sourceActor));
+ await dispatch(searchSource(cx, source, sourceActor, query));
+ }
+ dispatch(updateSearchStatus(cx, statusType.done));
+ };
+
+ search.cancel = () => {
+ cancelled = true;
+ };
+
+ return search;
+}
+
+export function searchSource(cx, source, sourceActor, query) {
+ return async ({ dispatch, getState, searchWorker }) => {
+ if (!source) {
+ return;
+ }
+ const location = createLocation({
+ sourceId: source.id,
+ sourceActorId: sourceActor ? sourceActor.actor : null,
+ });
+ const content = getSettledSourceTextContent(getState(), location);
+ let matches = [];
+ if (content && isFulfilled(content) && content.value.type === "text") {
+ matches = await searchWorker.findSourceMatches(
+ source.id,
+ content.value,
+ query
+ );
+ }
+ if (!matches.length) {
+ return;
+ }
+ dispatch(addSearchResult(cx, source.id, source.url, matches));
+ };
+}