import React from "react"; import { connect } from "react-redux"; import { AppState } from "reducers"; import { Hotkey, Hotkeys } from "@blueprintjs/core"; import { HotkeysTarget } from "@blueprintjs/core/lib/esnext/components/hotkeys/hotkeysTarget.js"; import { closePropertyPane, closeTableFilterPane, copyWidget, cutWidget, deleteSelectedWidget, groupWidgets, pasteWidget, } from "actions/widgetActions"; import { deselectAllInitAction, selectAllWidgetsInCanvasInitAction, } from "actions/widgetSelectionActions"; import { toggleShowGlobalSearchModal } from "actions/globalSearchActions"; import { isMac } from "utils/helpers"; import { getSelectedWidget, getSelectedWidgets } from "selectors/ui"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import { getSelectedText } from "utils/helpers"; import AnalyticsUtil from "utils/AnalyticsUtil"; import { WIDGETS_SEARCH_ID } from "constants/Explorer"; import { resetSnipingMode as resetSnipingModeAction } from "actions/propertyPaneActions"; import { showDebugger } from "actions/debuggerActions"; import { setCommentModeInUrl } from "pages/Editor/ToggleModeButton"; import { runActionViaShortcut } from "actions/pluginActionActions"; import { filterCategories, SearchCategory, SEARCH_CATEGORY_ID, } from "components/editorComponents/GlobalSearch/utils"; import { redoAction, undoAction } from "actions/pageActions"; import { Toaster } from "components/ads/Toast"; import { Variant } from "components/ads/common"; import { getAppMode } from "selectors/applicationSelectors"; import { APP_MODE } from "entities/App"; import { commentModeSelector } from "selectors/commentsSelectors"; import { createMessage, SAVE_HOTKEY_TOASTER_MESSAGE } from "constants/messages"; type Props = { copySelectedWidget: () => void; pasteCopiedWidget: () => void; deleteSelectedWidget: () => void; cutSelectedWidget: () => void; groupSelectedWidget: () => void; toggleShowGlobalSearchModal: (category: SearchCategory) => void; resetSnipingMode: () => void; openDebugger: () => void; closeProppane: () => void; closeTableFilterProppane: () => void; executeAction: () => void; selectAllWidgetsInit: () => void; deselectAllWidgets: () => void; selectedWidget?: string; selectedWidgets: string[]; isDebuggerOpen: boolean; children: React.ReactNode; undo: () => void; redo: () => void; appMode?: APP_MODE; isCommentMode: boolean; }; @HotkeysTarget class GlobalHotKeys extends React.Component { public stopPropagationIfWidgetSelected(e: KeyboardEvent): boolean { const multipleWidgetsSelected = this.props.selectedWidgets && this.props.selectedWidgets.length; const singleWidgetSelected = this.props.selectedWidget && this.props.selectedWidget != MAIN_CONTAINER_WIDGET_ID; if ( (singleWidgetSelected || multipleWidgetsSelected) && !getSelectedText() ) { e.preventDefault(); e.stopPropagation(); return true; } return false; } public onOnmnibarHotKeyDown( e: KeyboardEvent, categoryId: SEARCH_CATEGORY_ID = SEARCH_CATEGORY_ID.NAVIGATION, ) { e.preventDefault(); const category = filterCategories[categoryId]; this.props.toggleShowGlobalSearchModal(category); AnalyticsUtil.logEvent("OPEN_OMNIBAR", { source: "HOTKEY_COMBO", category: category.title, }); } public renderHotkeys() { return ( { const widgetSearchInput = document.getElementById( WIDGETS_SEARCH_ID, ); if (widgetSearchInput) { widgetSearchInput.focus(); e.preventDefault(); e.stopPropagation(); } }} /> this.onOnmnibarHotKeyDown(e)} /> this.onOnmnibarHotKeyDown(e, SEARCH_CATEGORY_ID.SNIPPETS) } /> this.onOnmnibarHotKeyDown(e, SEARCH_CATEGORY_ID.DOCUMENTATION) } /> this.onOnmnibarHotKeyDown(e, SEARCH_CATEGORY_ID.INIT) } /> { this.props.openDebugger(); if (this.props.isDebuggerOpen) { AnalyticsUtil.logEvent("OPEN_DEBUGGER", { source: "CANVAS", }); } }} preventDefault /> { if (this.stopPropagationIfWidgetSelected(e)) { this.props.copySelectedWidget(); } }} /> { this.props.pasteCopiedWidget(); }} /> { if (this.stopPropagationIfWidgetSelected(e) && isMac()) { this.props.deleteSelectedWidget(); } }} /> { if (this.stopPropagationIfWidgetSelected(e)) { this.props.deleteSelectedWidget(); } }} /> { if (this.stopPropagationIfWidgetSelected(e)) { this.props.cutSelectedWidget(); } }} /> { this.props.selectAllWidgetsInit(); e.preventDefault(); }} /> { if (this.props.isCommentMode) { AnalyticsUtil.logEvent("COMMENTS_TOGGLE_MODE", { mode: this.props.appMode, source: "HOTKEY", combo: "esc", }); } setCommentModeInUrl(false); this.props.resetSnipingMode(); this.props.deselectAllWidgets(); this.props.closeProppane(); this.props.closeTableFilterProppane(); e.preventDefault(); }} /> { if (this.props.isCommentMode) AnalyticsUtil.logEvent("COMMENTS_TOGGLE_MODE", { mode: this.props.appMode, source: "HOTKEY", combo: "v", }); setCommentModeInUrl(false); this.props.resetSnipingMode(); e.preventDefault(); }} /> { if (!this.props.isCommentMode) AnalyticsUtil.logEvent("COMMENTS_TOGGLE_MODE", { mode: "COMMENT", source: "HOTKEY", combo: "c", }); setCommentModeInUrl(true); }} /> { if (this.stopPropagationIfWidgetSelected(e)) { this.props.groupSelectedWidget(); } }} /> { Toaster.show({ text: createMessage(SAVE_HOTKEY_TOASTER_MESSAGE), variant: Variant.info, }); }} preventDefault stopPropagation /> ); } render() { return
{this.props.children}
; } } const mapStateToProps = (state: AppState) => ({ selectedWidget: getSelectedWidget(state), selectedWidgets: getSelectedWidgets(state), isDebuggerOpen: state.ui.debugger.isOpen, appMode: getAppMode(state), isCommentMode: commentModeSelector(state), }); const mapDispatchToProps = (dispatch: any) => { return { copySelectedWidget: () => dispatch(copyWidget(true)), pasteCopiedWidget: () => dispatch(pasteWidget()), deleteSelectedWidget: () => dispatch(deleteSelectedWidget(true)), cutSelectedWidget: () => dispatch(cutWidget()), groupSelectedWidget: () => dispatch(groupWidgets()), toggleShowGlobalSearchModal: (category: SearchCategory) => dispatch(toggleShowGlobalSearchModal(category)), resetSnipingMode: () => dispatch(resetSnipingModeAction()), openDebugger: () => dispatch(showDebugger()), closeProppane: () => dispatch(closePropertyPane()), closeTableFilterProppane: () => dispatch(closeTableFilterPane()), selectAllWidgetsInit: () => dispatch(selectAllWidgetsInCanvasInitAction()), deselectAllWidgets: () => dispatch(deselectAllInitAction()), executeAction: () => dispatch(runActionViaShortcut()), undo: () => dispatch(undoAction()), redo: () => dispatch(redoAction()), }; }; export default connect(mapStateToProps, mapDispatchToProps)(GlobalHotKeys);