diff --git a/mailpoet/assets/js/src/email-editor/engine/components/keybord-shortcuts/index.tsx b/mailpoet/assets/js/src/email-editor/engine/components/keybord-shortcuts/index.tsx new file mode 100644 index 0000000000..9a41c63e58 --- /dev/null +++ b/mailpoet/assets/js/src/email-editor/engine/components/keybord-shortcuts/index.tsx @@ -0,0 +1,81 @@ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; +import { + useShortcut, + store as keyboardShortcutsStore, +} from '@wordpress/keyboard-shortcuts'; +import { __ } from '@wordpress/i18n'; +import { storeName } from '../../store'; + +// See: +// https://github.com/WordPress/gutenberg/blob/9601a33e30ba41bac98579c8d822af63dd961488/packages/edit-post/src/components/keyboard-shortcuts/index.js +// https://github.com/WordPress/gutenberg/blob/0ee78b1bbe9c6f3e6df99f3b967132fa12bef77d/packages/edit-site/src/components/keyboard-shortcuts/index.js + +export function KeyboardShortcuts(): null { + const { isSidebarOpened, hasEdits, isSaving } = useSelect((select) => ({ + isSidebarOpened: select(storeName).isSidebarOpened(), + isSaving: select(storeName).isSaving(), + hasEdits: select(storeName).hasEdits(), + })); + + const { openSidebar, closeSidebar, saveEditedEmail, toggleFeature } = + useDispatch(storeName); + + const { registerShortcut } = useDispatch(keyboardShortcutsStore); + + useEffect(() => { + void registerShortcut({ + name: 'mailpoet/email-editor/toggle-fullscreen', + category: 'global', + description: __('Toggle fullscreen mode.', 'mailpoet'), + keyCombination: { + modifier: 'secondary', + character: 'f', + }, + }); + + void registerShortcut({ + name: 'mailpoet/email-editor/toggle-sidebar', + category: 'global', + description: __('Show or hide the settings sidebar.', 'mailpoet'), + keyCombination: { + modifier: 'primaryShift', + character: ',', + }, + }); + + void registerShortcut({ + name: 'mailpoet/email-editor/save', + category: 'global', + description: __('Save your changes.', 'mailpoet'), + keyCombination: { + modifier: 'primary', + character: 's', + }, + }); + }, [registerShortcut]); + + useShortcut('mailpoet/email-editor/toggle-fullscreen', () => { + toggleFeature('fullscreenMode'); + }); + + useShortcut('mailpoet/email-editor/toggle-sidebar', (event) => { + event.preventDefault(); + + if (isSidebarOpened) { + closeSidebar(); + } else { + openSidebar(); + } + }); + + useShortcut('mailpoet/email-editor/save', (event) => { + event.preventDefault(); + if (!hasEdits || isSaving) { + return; + } + saveEditedEmail(); + }); + + return null; +} diff --git a/mailpoet/assets/js/src/email-editor/engine/editor.tsx b/mailpoet/assets/js/src/email-editor/engine/editor.tsx index 9971a4b5a8..6f02948c1d 100644 --- a/mailpoet/assets/js/src/email-editor/engine/editor.tsx +++ b/mailpoet/assets/js/src/email-editor/engine/editor.tsx @@ -7,6 +7,7 @@ import { ShortcutProvider } from '@wordpress/keyboard-shortcuts'; import { EntityProvider } from '@wordpress/core-data'; import { BlockEditor } from './components/block-editor'; import { createStore, storeName } from './store'; +import { KeyboardShortcuts } from './components/keybord-shortcuts'; function Editor() { const { postId } = useSelect( @@ -20,6 +21,7 @@ function Editor() { + diff --git a/mailpoet/assets/js/src/email-editor/engine/store/actions.ts b/mailpoet/assets/js/src/email-editor/engine/store/actions.ts index d35f30af7e..308ff936ab 100644 --- a/mailpoet/assets/js/src/email-editor/engine/store/actions.ts +++ b/mailpoet/assets/js/src/email-editor/engine/store/actions.ts @@ -1,9 +1,15 @@ import { dispatch, select } from '@wordpress/data'; import { store as interfaceStore } from '@wordpress/interface'; import { store as coreDataStore } from '@wordpress/core-data'; +import { store as preferencesStore } from '@wordpress/preferences'; import { apiFetch } from '@wordpress/data-controls'; import { storeName, mainSidebarEmailKey } from './constants'; -import { SendingPreviewStatus, State } from './types'; +import { SendingPreviewStatus, State, Feature } from './types'; + +export const toggleFeature = + (feature: Feature) => + ({ registry }): unknown => + registry.dispatch(preferencesStore).toggle(storeName, feature); export function toggleInserterSidebar() { return { @@ -38,13 +44,15 @@ export function updateSendPreviewEmail(toEmail: string) { } as const; } -export function* openSidebar(key = mainSidebarEmailKey) { - yield dispatch(interfaceStore).enableComplementaryArea(storeName, key); -} +export const openSidebar = + (key = mainSidebarEmailKey) => + ({ registry }): unknown => + registry.dispatch(interfaceStore).enableComplementaryArea(storeName, key); -export const closeSidebar = () => { - dispatch(interfaceStore).disableComplementaryArea(storeName); -}; +export const closeSidebar = + () => + ({ registry }): unknown => + registry.dispatch(interfaceStore).disableComplementaryArea(storeName); export function* saveEditedEmail() { const postId = select(storeName).getEmailPostId();