diff --git a/packages/edit-site/src/components/block-editor/index.js b/packages/edit-site/src/components/block-editor/index.js index 4f4dd2011302f7..fcd28948ccbb3f 100644 --- a/packages/edit-site/src/components/block-editor/index.js +++ b/packages/edit-site/src/components/block-editor/index.js @@ -16,21 +16,14 @@ import { ReusableBlocksMenuItems } from '@wordpress/reusable-blocks'; import TemplatePartConverter from '../template-part-converter'; import { SidebarInspectorFill } from '../sidebar-edit-mode'; import { store as editSiteStore } from '../../store'; -import { unlock } from '../../lock-unlock'; -import { DisableNonPageContentBlocks } from '../page-content-focus'; import SiteEditorCanvas from './site-editor-canvas'; import getBlockEditorProvider from './get-block-editor-provider'; export default function BlockEditor() { - const { entityType, hasPageContentFocus } = useSelect( ( select ) => { - const { getEditedPostType, hasPageContentFocus: _hasPageContentFocus } = - unlock( select( editSiteStore ) ); - - return { - entityType: getEditedPostType(), - hasPageContentFocus: _hasPageContentFocus(), - }; - }, [] ); + const entityType = useSelect( + ( select ) => select( editSiteStore ).getEditedPostType(), + [] + ); // Choose the provider based on the entity type currently // being edited. @@ -38,7 +31,6 @@ export default function BlockEditor() { return ( - { hasPageContentFocus && } diff --git a/packages/edit-site/src/components/block-editor/site-editor-canvas.js b/packages/edit-site/src/components/block-editor/site-editor-canvas.js index 29e980d1134340..ecd6a73f92c353 100644 --- a/packages/edit-site/src/components/block-editor/site-editor-canvas.js +++ b/packages/edit-site/src/components/block-editor/site-editor-canvas.js @@ -27,11 +27,11 @@ import BackButton from './back-button'; import ResizableEditor from './resizable-editor'; import EditorCanvas from './editor-canvas'; import EditorCanvasContainer from '../editor-canvas-container'; -import { usePageContentFocusNotifications } from '../page-content-focus'; import useSiteEditorSettings from './use-site-editor-settings'; import { store as editSiteStore } from '../../store'; import { FOCUSABLE_ENTITIES } from './constants'; import { unlock } from '../../lock-unlock'; +import PageContentFocusManager from '../page-content-focus-manager'; const LAYOUT = { type: 'default', @@ -82,7 +82,6 @@ export default function SiteEditorCanvas() { contentRef, useClipboardHandler(), useTypingObserver(), - usePageContentFocusNotifications(), ] ); const isTemplateTypeNavigation = templateType === 'wp_navigation'; @@ -98,55 +97,59 @@ export default function SiteEditorCanvas() { : undefined; return ( - - { ( [ editorCanvasView ] ) => - editorCanvasView ? ( -
- { editorCanvasView } -
- ) : ( - { - // Clear selected block when clicking on the gray background. - if ( event.target === event.currentTarget ) { - clearSelectedBlock(); - } - } } - > - - - + + { ( [ editorCanvasView ] ) => + editorCanvasView ? ( +
+ { editorCanvasView } +
+ ) : ( + { + // Clear selected block when clicking on the gray background. + if ( event.target === event.currentTarget ) { + clearSelectedBlock(); + } + } } > - + + - { resizeObserver } - - -
-
- ) - } -
+ + { resizeObserver } + + + + + ) + } + + + ); } diff --git a/packages/edit-site/src/components/page-content-focus-manager/back-to-page-notification.js b/packages/edit-site/src/components/page-content-focus-manager/back-to-page-notification.js new file mode 100644 index 00000000000000..171d4b6a5f7579 --- /dev/null +++ b/packages/edit-site/src/components/page-content-focus-manager/back-to-page-notification.js @@ -0,0 +1,65 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useEffect, useRef } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../store'; + +/** + * Component that displays a 'You are editing a template' notification when the + * user switches from focusing on editing page content to editing a template. + */ +export default function BackToPageNotification() { + useBackToPageNotification(); + return null; +} + +/** + * Hook that displays a 'You are editing a template' notification when the user + * switches from focusing on editing page content to editing a template. + */ +export function useBackToPageNotification() { + const hasPageContentFocus = useSelect( + ( select ) => select( editSiteStore ).hasPageContentFocus(), + [] + ); + + const alreadySeen = useRef( false ); + const prevHasPageContentFocus = useRef( false ); + + const { createInfoNotice } = useDispatch( noticesStore ); + const { setHasPageContentFocus } = useDispatch( editSiteStore ); + + useEffect( () => { + if ( + ! alreadySeen.current && + prevHasPageContentFocus.current && + ! hasPageContentFocus + ) { + createInfoNotice( __( 'You are editing a template.' ), { + isDismissible: true, + type: 'snackbar', + actions: [ + { + label: __( 'Back to page' ), + onClick: () => setHasPageContentFocus( true ), + }, + ], + } ); + alreadySeen.current = true; + } + prevHasPageContentFocus.current = hasPageContentFocus; + }, [ + alreadySeen, + prevHasPageContentFocus, + hasPageContentFocus, + createInfoNotice, + setHasPageContentFocus, + ] ); +} diff --git a/packages/edit-site/src/components/page-content-focus/constants.js b/packages/edit-site/src/components/page-content-focus-manager/constants.js similarity index 100% rename from packages/edit-site/src/components/page-content-focus/constants.js rename to packages/edit-site/src/components/page-content-focus-manager/constants.js diff --git a/packages/edit-site/src/components/page-content-focus/disable-non-page-content-blocks.js b/packages/edit-site/src/components/page-content-focus-manager/disable-non-page-content-blocks.js similarity index 96% rename from packages/edit-site/src/components/page-content-focus/disable-non-page-content-blocks.js rename to packages/edit-site/src/components/page-content-focus-manager/disable-non-page-content-blocks.js index 9bd86fb1b4e246..33ea486863d203 100644 --- a/packages/edit-site/src/components/page-content-focus/disable-non-page-content-blocks.js +++ b/packages/edit-site/src/components/page-content-focus-manager/disable-non-page-content-blocks.js @@ -18,7 +18,7 @@ const { useBlockEditingMode } = unlock( blockEditorPrivateApis ); * Component that when rendered, makes it so that the site editor allows only * page content to be edited. */ -export function DisableNonPageContentBlocks() { +export default function DisableNonPageContentBlocks() { useDisableNonPageContentBlocks(); } diff --git a/packages/edit-site/src/components/page-content-focus-manager/edit-template-notification.js b/packages/edit-site/src/components/page-content-focus-manager/edit-template-notification.js new file mode 100644 index 00000000000000..3518bc8c3c51dc --- /dev/null +++ b/packages/edit-site/src/components/page-content-focus-manager/edit-template-notification.js @@ -0,0 +1,108 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useEffect, useState, useRef } from '@wordpress/element'; +import { store as noticesStore } from '@wordpress/notices'; +import { __ } from '@wordpress/i18n'; +import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../store'; + +/** + * Component that: + * + * - Displays a 'Edit your template to edit this block' notification when the + * user is focusing on editing page content and clicks on a disabled template + * block. + * - Displays a 'Edit your template to edit this block' dialog when the user + * is focusing on editing page conetnt and double clicks on a disabled + * template block. + * + * @param {Object} props + * @param {import('react').RefObject} props.contentRef Ref to the block + * editor iframe canvas. + */ +export default function EditTemplateNotification( { contentRef } ) { + const hasPageContentFocus = useSelect( + ( select ) => select( editSiteStore ).hasPageContentFocus(), + [] + ); + const { getNotices } = useSelect( noticesStore ); + + const { createInfoNotice, removeNotice } = useDispatch( noticesStore ); + const { setHasPageContentFocus } = useDispatch( editSiteStore ); + + const [ isDialogOpen, setIsDialogOpen ] = useState( false ); + + const lastNoticeId = useRef( 0 ); + + useEffect( () => { + const handleClick = async ( event ) => { + if ( ! hasPageContentFocus ) { + return; + } + if ( ! event.target.classList.contains( 'is-root-container' ) ) { + return; + } + const isNoticeAlreadyShowing = getNotices().some( + ( notice ) => notice.id === lastNoticeId.current + ); + if ( isNoticeAlreadyShowing ) { + return; + } + const { notice } = await createInfoNotice( + __( 'Edit your template to edit this block.' ), + { + isDismissible: true, + type: 'snackbar', + actions: [ + { + label: __( 'Edit template' ), + onClick: () => setHasPageContentFocus( false ), + }, + ], + } + ); + lastNoticeId.current = notice.id; + }; + + const handleDblClick = ( event ) => { + if ( ! hasPageContentFocus ) { + return; + } + if ( ! event.target.classList.contains( 'is-root-container' ) ) { + return; + } + if ( lastNoticeId.current ) { + removeNotice( lastNoticeId.current ); + } + setIsDialogOpen( true ); + }; + + const canvas = contentRef.current; + canvas?.addEventListener( 'click', handleClick ); + canvas?.addEventListener( 'dblclick', handleDblClick ); + return () => { + canvas?.removeEventListener( 'click', handleClick ); + canvas?.removeEventListener( 'dblclick', handleDblClick ); + }; + }, [ lastNoticeId, hasPageContentFocus, contentRef.current ] ); + + return ( + { + setIsDialogOpen( false ); + setHasPageContentFocus( false ); + } } + onCancel={ () => setIsDialogOpen( false ) } + > + { __( 'Edit your template to edit this block.' ) } + + ); +} diff --git a/packages/edit-site/src/components/page-content-focus-manager/index.js b/packages/edit-site/src/components/page-content-focus-manager/index.js new file mode 100644 index 00000000000000..935ba1c96248cf --- /dev/null +++ b/packages/edit-site/src/components/page-content-focus-manager/index.js @@ -0,0 +1,26 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as editSiteStore } from '../../store'; +import DisableNonPageContentBlocks from './disable-non-page-content-blocks'; +import EditTemplateNotification from './edit-template-notification'; +import BackToPageNotification from './back-to-page-notification'; + +export default function PageContentFocusManager( { contentRef } ) { + const hasPageContentFocus = useSelect( + ( select ) => select( editSiteStore ).hasPageContentFocus(), + [] + ); + return ( + <> + { hasPageContentFocus && } + + + + ); +} diff --git a/packages/edit-site/src/components/page-content-focus/index.js b/packages/edit-site/src/components/page-content-focus/index.js deleted file mode 100644 index 81160f4a861f93..00000000000000 --- a/packages/edit-site/src/components/page-content-focus/index.js +++ /dev/null @@ -1,2 +0,0 @@ -export * from './disable-non-page-content-blocks'; -export { usePageContentFocusNotifications } from './use-page-content-focus-notifications'; diff --git a/packages/edit-site/src/components/page-content-focus/use-page-content-focus-notifications.js b/packages/edit-site/src/components/page-content-focus/use-page-content-focus-notifications.js deleted file mode 100644 index a1ebc729294d53..00000000000000 --- a/packages/edit-site/src/components/page-content-focus/use-page-content-focus-notifications.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect, useRef } from '@wordpress/element'; -import { store as noticesStore } from '@wordpress/notices'; -import { __ } from '@wordpress/i18n'; -import { useRefEffect } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import { store as editSiteStore } from '../../store'; - -/** - * Hook that displays notifications that guide the user towards using the - * content vs. template editing modes. - * - * @return {import('react').RefObject} Ref which should be passed - * (using useMergeRefs()) to - * the editor iframe canvas. - */ -export function usePageContentFocusNotifications() { - const ref = useEditTemplateNotification(); - useBackToPageNotification(); - return ref; -} - -/** - * Hook that displays a 'Edit your template to edit this block' notification - * when the user is focusing on editing page content and clicks on a disabled - * template block. - * - * @return {import('react').RefObject} Ref which should be passed - * (using useMergeRefs()) to - * the editor iframe canvas. - */ -function useEditTemplateNotification() { - const hasPageContentFocus = useSelect( - ( select ) => select( editSiteStore ).hasPageContentFocus(), - [] - ); - - const alreadySeen = useRef( false ); - - const { createInfoNotice } = useDispatch( noticesStore ); - const { setHasPageContentFocus } = useDispatch( editSiteStore ); - - return useRefEffect( - ( node ) => { - const handleClick = ( event ) => { - if ( - ! alreadySeen.current && - hasPageContentFocus && - event.target.classList.contains( 'is-root-container' ) - ) { - createInfoNotice( - __( 'Edit your template to edit this block' ), - { - isDismissible: true, - type: 'snackbar', - actions: [ - { - label: __( 'Edit template' ), - onClick: () => - setHasPageContentFocus( false ), - }, - ], - } - ); - alreadySeen.current = true; - } - }; - node.addEventListener( 'click', handleClick ); - return () => node.removeEventListener( 'click', handleClick ); - }, - [ - hasPageContentFocus, - alreadySeen, - createInfoNotice, - setHasPageContentFocus, - ] - ); -} - -/** - * Hook that displays a 'You are editing a template' notification when the user - * switches from focusing on editing page content to editing a template. - */ -function useBackToPageNotification() { - const hasPageContentFocus = useSelect( - ( select ) => select( editSiteStore ).hasPageContentFocus(), - [] - ); - - const alreadySeen = useRef( false ); - const prevHasPageContentFocus = useRef( false ); - - const { createInfoNotice } = useDispatch( noticesStore ); - const { setHasPageContentFocus } = useDispatch( editSiteStore ); - - useEffect( () => { - if ( - ! alreadySeen.current && - prevHasPageContentFocus.current && - ! hasPageContentFocus - ) { - createInfoNotice( __( 'You are editing a template' ), { - isDismissible: true, - type: 'snackbar', - actions: [ - { - label: __( 'Back to page' ), - onClick: () => setHasPageContentFocus( true ), - }, - ], - } ); - alreadySeen.current = true; - } - prevHasPageContentFocus.current = hasPageContentFocus; - }, [ - alreadySeen, - prevHasPageContentFocus, - hasPageContentFocus, - createInfoNotice, - setHasPageContentFocus, - ] ); -} diff --git a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js index 301f898d794a4b..d6e7dd23a709fa 100644 --- a/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js +++ b/packages/edit-site/src/components/sidebar-edit-mode/page-panels/page-content.js @@ -10,7 +10,7 @@ import { /** * Internal dependencies */ -import { PAGE_CONTENT_BLOCK_TYPES } from '../../page-content-focus/constants'; +import { PAGE_CONTENT_BLOCK_TYPES } from '../../page-content-focus-manager/constants'; import { unlock } from '../../../lock-unlock'; const { BlockQuickNavigation } = unlock( blockEditorPrivateApis );