diff options
Diffstat (limited to '')
-rw-r--r-- | devtools/client/debugger/src/actions/ui.js | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/devtools/client/debugger/src/actions/ui.js b/devtools/client/debugger/src/actions/ui.js new file mode 100644 index 0000000000..67b2629135 --- /dev/null +++ b/devtools/client/debugger/src/actions/ui.js @@ -0,0 +1,290 @@ +/* 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/>. */ + +import { + getActiveSearch, + getPaneCollapse, + getQuickOpenEnabled, + getSource, + getSourceContent, + getMainThread, + getIgnoreListSourceUrls, + getSourceByURL, + getBreakpointsForSource, +} from "../selectors"; +import { selectSource } from "../actions/sources/select"; +import { + getEditor, + getLocationsInViewport, + updateDocuments, +} from "../utils/editor"; +import { blackboxSourceActorsForSource } from "./sources/blackbox"; +import { toggleBreakpoints } from "./breakpoints"; +import { copyToTheClipboard } from "../utils/clipboard"; +import { isFulfilled } from "../utils/async-value"; +import { primaryPaneTabs } from "../constants"; + +export function setPrimaryPaneTab(tabName) { + return { type: "SET_PRIMARY_PANE_TAB", tabName }; +} + +export function closeActiveSearch() { + return { + type: "TOGGLE_ACTIVE_SEARCH", + value: null, + }; +} + +export function setActiveSearch(activeSearch) { + return ({ dispatch, getState }) => { + const activeSearchState = getActiveSearch(getState()); + if (activeSearchState === activeSearch) { + return; + } + + if (getQuickOpenEnabled(getState())) { + dispatch({ type: "CLOSE_QUICK_OPEN" }); + } + + // Open start panel if it was collapsed so the project search UI is visible + if ( + activeSearch === primaryPaneTabs.PROJECT_SEARCH && + getPaneCollapse(getState(), "start") + ) { + dispatch({ + type: "TOGGLE_PANE", + position: "start", + paneCollapsed: false, + }); + } + + dispatch({ + type: "TOGGLE_ACTIVE_SEARCH", + value: activeSearch, + }); + }; +} + +export function toggleFrameworkGrouping(toggleValue) { + return ({ dispatch, getState }) => { + dispatch({ + type: "TOGGLE_FRAMEWORK_GROUPING", + value: toggleValue, + }); + }; +} + +export function toggleInlinePreview(toggleValue) { + return ({ dispatch, getState }) => { + dispatch({ + type: "TOGGLE_INLINE_PREVIEW", + value: toggleValue, + }); + }; +} + +export function toggleEditorWrapping(toggleValue) { + return ({ dispatch, getState }) => { + updateDocuments(doc => doc.cm.setOption("lineWrapping", toggleValue)); + + dispatch({ + type: "TOGGLE_EDITOR_WRAPPING", + value: toggleValue, + }); + }; +} + +export function toggleSourceMapsEnabled(toggleValue) { + return ({ dispatch, getState }) => { + dispatch({ + type: "TOGGLE_SOURCE_MAPS_ENABLED", + value: toggleValue, + }); + }; +} + +export function showSource(cx, sourceId) { + return ({ dispatch, getState }) => { + const source = getSource(getState(), sourceId); + if (!source) { + return; + } + + if (getPaneCollapse(getState(), "start")) { + dispatch({ + type: "TOGGLE_PANE", + position: "start", + paneCollapsed: false, + }); + } + + dispatch(setPrimaryPaneTab("sources")); + + dispatch(selectSource(cx, source)); + }; +} + +export function togglePaneCollapse(position, paneCollapsed) { + return ({ dispatch, getState }) => { + const prevPaneCollapse = getPaneCollapse(getState(), position); + if (prevPaneCollapse === paneCollapsed) { + return; + } + + // Set active search to null when closing start panel if project search was active + if ( + position === "start" && + paneCollapsed && + getActiveSearch(getState()) === primaryPaneTabs.PROJECT_SEARCH + ) { + dispatch(closeActiveSearch()); + } + + dispatch({ + type: "TOGGLE_PANE", + position, + paneCollapsed, + }); + }; +} + +/** + * Highlight one or many lines in CodeMirror for a given source. + * + * @param {Object} location + * @param {String} location.sourceId + * The precise source to highlight. + * @param {Number} location.start + * The 1-based index of first line to highlight. + * @param {Number} location.end + * The 1-based index of last line to highlight. + */ +export function highlightLineRange(location) { + return { + type: "HIGHLIGHT_LINES", + location, + }; +} + +export function flashLineRange(location) { + return ({ dispatch }) => { + dispatch(highlightLineRange(location)); + setTimeout(() => dispatch(clearHighlightLineRange()), 200); + }; +} + +export function clearHighlightLineRange() { + return { + type: "CLEAR_HIGHLIGHT_LINES", + }; +} + +export function openConditionalPanel(location, log = false) { + if (!location) { + return null; + } + + return { + type: "OPEN_CONDITIONAL_PANEL", + location, + log, + }; +} + +export function closeConditionalPanel() { + return { + type: "CLOSE_CONDITIONAL_PANEL", + }; +} + +export function clearProjectDirectoryRoot(cx) { + return { + type: "SET_PROJECT_DIRECTORY_ROOT", + cx, + url: "", + name: "", + }; +} + +export function setProjectDirectoryRoot(cx, newRoot, newName) { + return ({ dispatch, getState }) => { + // If the new project root is against the top level thread, + // replace its thread ID with "top-level", so that later, + // getDirectoryForUniquePath could match the project root, + // even after a page reload where the new top level thread actor ID + // will be different. + const mainThread = getMainThread(getState()); + if (mainThread && newRoot.startsWith(mainThread.actor)) { + newRoot = newRoot.replace(mainThread.actor, "top-level"); + } + dispatch({ + type: "SET_PROJECT_DIRECTORY_ROOT", + cx, + url: newRoot, + name: newName, + }); + }; +} + +export function updateViewport() { + return { + type: "SET_VIEWPORT", + viewport: getLocationsInViewport(getEditor()), + }; +} + +export function updateCursorPosition(cursorPosition) { + return { type: "SET_CURSOR_POSITION", cursorPosition }; +} + +export function setOrientation(orientation) { + return { type: "SET_ORIENTATION", orientation }; +} + +export function setSearchOptions(searchKey, searchOptions) { + return { type: "SET_SEARCH_OPTIONS", searchKey, searchOptions }; +} + +export function copyToClipboard(location) { + return ({ dispatch, getState }) => { + const content = getSourceContent(getState(), location); + if (content && isFulfilled(content) && content.value.type === "text") { + copyToTheClipboard(content.value.value); + } + }; +} + +export function setJavascriptTracingLogMethod(value) { + return ({ dispatch, getState }) => { + dispatch({ + type: "SET_JAVASCRIPT_TRACING_LOG_METHOD", + value, + }); + }; +} + +export function setHideOrShowIgnoredSources(shouldHide) { + return ({ dispatch, getState }) => { + dispatch({ type: "HIDE_IGNORED_SOURCES", shouldHide }); + }; +} + +export function toggleSourceMapIgnoreList(cx, shouldEnable) { + return async thunkArgs => { + const { dispatch, getState } = thunkArgs; + const ignoreListSourceUrls = getIgnoreListSourceUrls(getState()); + // Blackbox the source actors on the server + for (const url of ignoreListSourceUrls) { + const source = getSourceByURL(getState(), url); + await blackboxSourceActorsForSource(thunkArgs, source, shouldEnable); + // Disable breakpoints in sources on the ignore list + const breakpoints = getBreakpointsForSource(getState(), source.id); + await dispatch(toggleBreakpoints(cx, shouldEnable, breakpoints)); + } + await dispatch({ + type: "ENABLE_SOURCEMAP_IGNORELIST", + shouldEnable, + }); + }; +} |