diff --git a/docs/reference-guides/data/data-core-edit-site.md b/docs/reference-guides/data/data-core-edit-site.md index 83e9b09dfd7d8..0cac2268b2ab2 100644 --- a/docs/reference-guides/data/data-core-edit-site.md +++ b/docs/reference-guides/data/data-core-edit-site.md @@ -408,6 +408,10 @@ _Returns_ Undocumented declaration. +### toggleDistractionFree + +Action that toggles Distraction free mode. Distraction free mode expects there are no sidebars, as due to the z-index values set, you can't close sidebars. + ### toggleFeature Dispatches an action that toggles a feature flag. diff --git a/packages/edit-site/src/components/keyboard-shortcuts/edit-mode.js b/packages/edit-site/src/components/keyboard-shortcuts/edit-mode.js index 49efa11368a7d..1346041b6a94c 100644 --- a/packages/edit-site/src/components/keyboard-shortcuts/edit-mode.js +++ b/packages/edit-site/src/components/keyboard-shortcuts/edit-mode.js @@ -1,15 +1,12 @@ /** * WordPress dependencies */ -import { __ } from '@wordpress/i18n'; import { useShortcut } from '@wordpress/keyboard-shortcuts'; import { useDispatch, useSelect } from '@wordpress/data'; import { store as coreStore } from '@wordpress/core-data'; import { store as blockEditorStore } from '@wordpress/block-editor'; import { store as interfaceStore } from '@wordpress/interface'; import { createBlock } from '@wordpress/blocks'; -import { store as preferencesStore } from '@wordpress/preferences'; -import { store as noticesStore } from '@wordpress/notices'; /** * Internal dependencies @@ -32,12 +29,8 @@ function KeyboardShortcutsEditMode() { [] ); const { redo, undo } = useDispatch( coreStore ); - const { - setIsListViewOpened, - switchEditorMode, - setIsInserterOpened, - closeGeneralSidebar, - } = useDispatch( editSiteStore ); + const { setIsListViewOpened, switchEditorMode, toggleDistractionFree } = + useDispatch( editSiteStore ); const { enableComplementaryArea, disableComplementaryArea } = useDispatch( interfaceStore ); @@ -45,17 +38,6 @@ function KeyboardShortcutsEditMode() { const { getBlockName, getSelectedBlockClientId, getBlockAttributes } = useSelect( blockEditorStore ); - const { get: getPreference } = useSelect( preferencesStore ); - const { set: setPreference, toggle } = useDispatch( preferencesStore ); - const { createInfoNotice } = useDispatch( noticesStore ); - - const toggleDistractionFree = () => { - setPreference( 'core/edit-site', 'fixedToolbar', false ); - setIsInserterOpened( false ); - setIsListViewOpened( false ); - closeGeneralSidebar(); - }; - const handleTextLevelShortcut = ( event, level ) => { event.preventDefault(); const destinationBlockName = @@ -134,16 +116,6 @@ function KeyboardShortcutsEditMode() { useShortcut( 'core/edit-site/toggle-distraction-free', () => { toggleDistractionFree(); - toggle( 'core/edit-site', 'distractionFree' ); - createInfoNotice( - getPreference( 'core/edit-site', 'distractionFree' ) - ? __( 'Distraction free mode turned on.' ) - : __( 'Distraction free mode turned off.' ), - { - id: 'core/edit-site/distraction-free-mode/notice', - type: 'snackbar', - } - ); } ); return null; diff --git a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js index a156bd40c2211..5ad7691c5e5a2 100644 --- a/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js +++ b/packages/edit-site/src/components/sidebar-navigation-screen-global-styles/index.js @@ -15,8 +15,6 @@ import { useViewportMatch } from '@wordpress/compose'; import { BlockEditorProvider } from '@wordpress/block-editor'; import { humanTimeDiff } from '@wordpress/date'; import { useCallback } from '@wordpress/element'; -import { store as noticesStore } from '@wordpress/notices'; -import { store as preferencesStore } from '@wordpress/preferences'; /** * Internal dependencies @@ -35,24 +33,7 @@ const noop = () => {}; export function SidebarNavigationItemGlobalStyles( props ) { const { openGeneralSidebar } = useDispatch( editSiteStore ); const { setCanvasMode } = unlock( useDispatch( editSiteStore ) ); - const { createNotice } = useDispatch( noticesStore ); - const { set: setPreference } = useDispatch( preferencesStore ); - const { get: getPreference } = useSelect( preferencesStore ); - const turnOffDistractionFreeMode = useCallback( () => { - const isDistractionFree = getPreference( - editSiteStore.name, - 'distractionFree' - ); - if ( ! isDistractionFree ) { - return; - } - setPreference( editSiteStore.name, 'distractionFree', false ); - createNotice( 'info', __( 'Distraction free mode turned off' ), { - isDismissible: true, - type: 'snackbar', - } ); - }, [ createNotice, setPreference, getPreference ] ); const hasGlobalStyleVariations = useSelect( ( select ) => !! select( @@ -73,7 +54,6 @@ export function SidebarNavigationItemGlobalStyles( props ) { { - turnOffDistractionFreeMode(); // Switch to edit mode. setCanvasMode( 'edit' ); // Open global styles sidebar. @@ -150,9 +130,6 @@ export default function SidebarNavigationScreenGlobalStyles() { const { setCanvasMode, setEditorCanvasContainerView } = unlock( useDispatch( editSiteStore ) ); - const { createNotice } = useDispatch( noticesStore ); - const { set: setPreference } = useDispatch( preferencesStore ); - const { get: getPreference } = useSelect( preferencesStore ); const { isViewMode, isStyleBookOpened, revisionsCount } = useSelect( ( select ) => { const { getCanvasMode, getEditorCanvasContainerView } = unlock( @@ -176,28 +153,12 @@ export default function SidebarNavigationScreenGlobalStyles() { [] ); - const turnOffDistractionFreeMode = useCallback( () => { - const isDistractionFree = getPreference( - editSiteStore.name, - 'distractionFree' - ); - if ( ! isDistractionFree ) { - return; - } - setPreference( editSiteStore.name, 'distractionFree', false ); - createNotice( 'info', __( 'Distraction free mode turned off' ), { - isDismissible: true, - type: 'snackbar', - } ); - }, [ createNotice, setPreference, getPreference ] ); - const openGlobalStyles = useCallback( async () => { - turnOffDistractionFreeMode(); return Promise.all( [ setCanvasMode( 'edit' ), openGeneralSidebar( 'edit-site/global-styles' ), ] ); - }, [ setCanvasMode, openGeneralSidebar, turnOffDistractionFreeMode ] ); + }, [ setCanvasMode, openGeneralSidebar ] ); const openStyleBook = useCallback( async () => { await openGlobalStyles(); diff --git a/packages/edit-site/src/hooks/commands/use-common-commands.js b/packages/edit-site/src/hooks/commands/use-common-commands.js index c1a023d0b1b20..16d07132ad7c7 100644 --- a/packages/edit-site/src/hooks/commands/use-common-commands.js +++ b/packages/edit-site/src/hooks/commands/use-common-commands.js @@ -10,7 +10,6 @@ import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { privateApis as routerPrivateApis } from '@wordpress/router'; import { store as preferencesStore } from '@wordpress/preferences'; import { store as coreStore } from '@wordpress/core-data'; -import { store as noticesStore } from '@wordpress/notices'; import { useViewportMatch } from '@wordpress/compose'; /** @@ -31,16 +30,7 @@ function useGlobalStylesOpenStylesCommands() { const isMobileViewport = useViewportMatch( 'medium', '<' ); const isEditorPage = ! getIsListPage( params, isMobileViewport ); const { getCanvasMode } = unlock( useSelect( editSiteStore ) ); - const { set } = useDispatch( preferencesStore ); - const { createInfoNotice } = useDispatch( noticesStore ); - const history = useHistory(); - const isDistractionFree = useSelect( ( select ) => { - return select( preferencesStore ).get( - editSiteStore.name, - 'distractionFree' - ); - }, [] ); const isBlockBasedTheme = useSelect( ( select ) => { return select( coreStore ).getCurrentTheme().is_block_theme; @@ -66,15 +56,6 @@ function useGlobalStylesOpenStylesCommands() { if ( isEditorPage && getCanvasMode() !== 'edit' ) { setCanvasMode( 'edit' ); } - if ( isDistractionFree ) { - set( editSiteStore.name, 'distractionFree', false ); - createInfoNotice( - __( 'Distraction free mode turned off.' ), - { - type: 'snackbar', - } - ); - } openGeneralSidebar( 'edit-site/global-styles' ); }, icon: styles, @@ -85,11 +66,8 @@ function useGlobalStylesOpenStylesCommands() { openGeneralSidebar, setCanvasMode, isEditorPage, - createInfoNotice, getCanvasMode, - isDistractionFree, isBlockBasedTheme, - set, ] ); return { diff --git a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js index 6079c01773be7..76c7eea513743 100644 --- a/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js +++ b/packages/edit-site/src/hooks/commands/use-edit-mode-commands.js @@ -195,7 +195,7 @@ function useEditUICommands() { const { openGeneralSidebar, closeGeneralSidebar, - setIsInserterOpened, + toggleDistractionFree, setIsListViewOpened, switchEditorMode, } = useDispatch( editSiteStore ); @@ -205,6 +205,7 @@ function useEditUICommands() { activeSidebar, showBlockBreadcrumbs, isListViewOpen, + isDistractionFree, } = useSelect( ( select ) => { const { isListViewOpened, getEditorMode } = select( editSiteStore ); return { @@ -218,11 +219,14 @@ function useEditUICommands() { 'showBlockBreadcrumbs' ), isListViewOpen: isListViewOpened(), + isDistractionFree: select( preferencesStore ).get( + editSiteStore.name, + 'distractionFree' + ), }; }, [] ); const { openModal } = useDispatch( interfaceStore ); - const { get: getPreference } = useSelect( preferencesStore ); - const { set: setPreference, toggle } = useDispatch( preferencesStore ); + const { toggle } = useDispatch( preferencesStore ); const { createInfoNotice } = useDispatch( noticesStore ); if ( canvasMode !== 'edit' ) { @@ -272,20 +276,7 @@ function useEditUICommands() { name: 'core/toggle-distraction-free', label: __( 'Toggle distraction free' ), callback: ( { close } ) => { - setPreference( 'core/edit-site', 'fixedToolbar', false ); - setIsInserterOpened( false ); - setIsListViewOpened( false ); - closeGeneralSidebar(); - toggle( 'core/edit-site', 'distractionFree' ); - createInfoNotice( - getPreference( 'core/edit-site', 'distractionFree' ) - ? __( 'Distraction free on.' ) - : __( 'Distraction free off.' ), - { - id: 'core/edit-site/distraction-free-mode/notice', - type: 'snackbar', - } - ); + toggleDistractionFree(); close(); }, } ); @@ -295,6 +286,9 @@ function useEditUICommands() { label: __( 'Toggle top toolbar' ), callback: ( { close } ) => { toggle( 'core/edit-site', 'fixedToolbar' ); + if ( isDistractionFree ) { + toggleDistractionFree(); + } close(); }, } ); diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index ac07ac5beaa2a..0ad521a9c9a54 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -373,12 +373,20 @@ export function updateSettings( settings ) { * @param {boolean} isOpen If true, opens the list view. If false, closes it. * It does not toggle the state, but sets it directly. */ -export function setIsListViewOpened( isOpen ) { - return { - type: 'SET_IS_LIST_VIEW_OPENED', - isOpen, +export const setIsListViewOpened = + ( isOpen ) => + ( { dispatch, registry } ) => { + const isDistractionFree = registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ); + if ( isDistractionFree && isOpen ) { + dispatch.toggleDistractionFree(); + } + dispatch( { + type: 'SET_IS_LIST_VIEW_OPENED', + isOpen, + } ); }; -} /** * Sets whether the save view panel should be open. @@ -533,7 +541,13 @@ export const revertTemplate = */ export const openGeneralSidebar = ( name ) => - ( { registry } ) => { + ( { dispatch, registry } ) => { + const isDistractionFree = registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ); + if ( isDistractionFree ) { + dispatch.toggleDistractionFree(); + } registry .dispatch( interfaceStore ) .enableComplementaryArea( editSiteStoreName, name ); @@ -552,7 +566,7 @@ export const closeGeneralSidebar = export const switchEditorMode = ( mode ) => - ( { registry } ) => { + ( { dispatch, registry } ) => { registry .dispatch( 'core/preferences' ) .set( 'core/edit-site', 'editorMode', mode ); @@ -565,6 +579,12 @@ export const switchEditorMode = if ( mode === 'visual' ) { speak( __( 'Visual editor selected' ), 'assertive' ); } else if ( mode === 'text' ) { + const isDistractionFree = registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ); + if ( isDistractionFree ) { + dispatch.toggleDistractionFree(); + } speak( __( 'Code editor selected' ), 'assertive' ); } }; @@ -587,3 +607,46 @@ export const setHasPageContentFocus = hasPageContentFocus, } ); }; + +/** + * Action that toggles Distraction free mode. + * Distraction free mode expects there are no sidebars, as due to the + * z-index values set, you can't close sidebars. + */ +export const toggleDistractionFree = + () => + ( { dispatch, registry } ) => { + const isDistractionFree = registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ); + if ( ! isDistractionFree ) { + registry.batch( () => { + registry + .dispatch( preferencesStore ) + .set( 'core/edit-site', 'fixedToolbar', false ); + dispatch.setIsInserterOpened( false ); + dispatch.setIsListViewOpened( false ); + dispatch.closeGeneralSidebar(); + } ); + } + registry.batch( () => { + registry + .dispatch( preferencesStore ) + .set( + 'core/edit-site', + 'distractionFree', + ! isDistractionFree + ); + registry + .dispatch( noticesStore ) + .createInfoNotice( + isDistractionFree + ? __( 'Distraction free off.' ) + : __( 'Distraction free on.' ), + { + id: 'core/edit-site/distraction-free-mode/notice', + type: 'snackbar', + } + ); + } ); + }; diff --git a/packages/edit-site/src/store/test/actions.js b/packages/edit-site/src/store/test/actions.js index 8ce914b00b208..345fcddbbba3b 100644 --- a/packages/edit-site/src/store/test/actions.js +++ b/packages/edit-site/src/store/test/actions.js @@ -215,6 +215,94 @@ describe( 'actions', () => { false ); } ); + it( 'should turn off distraction free mode when opening the list view', () => { + const registry = createRegistryWithStores(); + registry + .dispatch( preferencesStore ) + .set( 'core/edit-site', 'distractionFree', true ); + registry.dispatch( editSiteStore ).setIsListViewOpened( true ); + expect( + registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ) + ).toBe( false ); + } ); + } ); + + describe( 'openGeneralSidebar', () => { + it( 'should turn off distraction free mode when opening a general sidebar', () => { + const registry = createRegistryWithStores(); + registry + .dispatch( preferencesStore ) + .set( 'core/edit-site', 'distractionFree', true ); + + registry + .dispatch( editSiteStore ) + .openGeneralSidebar( 'edit-site/global-styles' ); + expect( + registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ) + ).toBe( false ); + } ); + } ); + + describe( 'switchEditorMode', () => { + it( 'should turn off distraction free mode when switching to code editor', () => { + const registry = createRegistryWithStores(); + registry + .dispatch( preferencesStore ) + .set( 'core/edit-site', 'distractionFree', true ); + registry.dispatch( editSiteStore ).switchEditorMode( 'visual' ); + expect( + registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ) + ).toBe( true ); + registry.dispatch( editSiteStore ).switchEditorMode( 'text' ); + expect( + registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ) + ).toBe( false ); + } ); + } ); + + describe( 'toggleDistractionFree', () => { + it( 'should properly update settings to prevent layout corruption when enabling distraction free mode', () => { + const registry = createRegistryWithStores(); + // Enable everything that shouldn't be enabled in distraction free mode. + registry + .dispatch( preferencesStore ) + .set( 'core/edit-site', 'fixedToolbar', true ); + registry.dispatch( editSiteStore ).setIsListViewOpened( true ); + registry + .dispatch( editSiteStore ) + .openGeneralSidebar( 'edit-site/global-styles' ); + // Initial state is falsy. + registry.dispatch( editSiteStore ).toggleDistractionFree(); + expect( + registry + .select( preferencesStore ) + .get( 'core/edit-site', 'fixedToolbar' ) + ).toBe( false ); + expect( registry.select( editSiteStore ).isListViewOpened() ).toBe( + false + ); + expect( registry.select( editSiteStore ).isInserterOpened() ).toBe( + false + ); + expect( + registry + .select( interfaceStore ) + .getActiveComplementaryArea( editSiteStore.name ) + ).toBeNull(); + expect( + registry + .select( preferencesStore ) + .get( 'core/edit-site', 'distractionFree' ) + ).toBe( true ); + } ); } ); describe( 'setHasPageContentFocus', () => { diff --git a/packages/edit-site/src/store/test/reducer.js b/packages/edit-site/src/store/test/reducer.js index 9ab7f8e3964f8..fc06faf925b38 100644 --- a/packages/edit-site/src/store/test/reducer.js +++ b/packages/edit-site/src/store/test/reducer.js @@ -14,7 +14,7 @@ import { hasPageContentFocus, } from '../reducer'; -import { setIsInserterOpened, setIsListViewOpened } from '../actions'; +import { setIsInserterOpened } from '../actions'; describe( 'state', () => { describe( 'settings()', () => { @@ -95,13 +95,19 @@ describe( 'state', () => { it( 'should close the inserter when opening the list view panel', () => { expect( - blockInserterPanel( true, setIsListViewOpened( true ) ) + blockInserterPanel( true, { + type: 'SET_IS_LIST_VIEW_OPENED', + isOpen: true, + } ) ).toBe( false ); } ); it( 'should not change the state when closing the list view panel', () => { expect( - blockInserterPanel( true, setIsListViewOpened( false ) ) + blockInserterPanel( true, { + type: 'SET_IS_LIST_VIEW_OPENED', + isOpen: false, + } ) ).toBe( true ); } ); } ); @@ -116,12 +122,19 @@ describe( 'state', () => { } ); it( 'should set the open state of the list view panel', () => { - expect( listViewPanel( false, setIsListViewOpened( true ) ) ).toBe( - true - ); - expect( listViewPanel( true, setIsListViewOpened( false ) ) ).toBe( - false - ); + // registry.dispatch( editSiteStore ).toggleFeature( 'name' ); + expect( + listViewPanel( false, { + type: 'SET_IS_LIST_VIEW_OPENED', + isOpen: true, + } ) + ).toBe( true ); + expect( + listViewPanel( true, { + type: 'SET_IS_LIST_VIEW_OPENED', + isOpen: false, + } ) + ).toBe( false ); } ); it( 'should close the list view when opening the inserter panel', () => {