| @@ -2,9 +2,16 @@ | ||
| 2 | 2 | import { useEditorReady } from '@shared/hooks/gutenberg'; |
| 3 | 3 | import { store as blockEditorStore } from '@wordpress/block-editor'; |
| 4 | 4 | import { createBlock } from '@wordpress/blocks'; |
| 5 | 5 | import { Flex, FlexBlock } from '@wordpress/components'; |
| 6 | -import { useDispatch, useSelect } from '@wordpress/data'; | |
| 6 | +import { | |
| 7 | + dispatch, | |
| 8 | + resolveSelect, | |
| 9 | + select, | |
| 10 | + subscribe, | |
| 11 | + useDispatch, | |
| 12 | + useSelect, | |
| 13 | +} from '@wordpress/data'; | |
| 7 | 14 | import { store as editPostStore } from '@wordpress/edit-post'; |
| 8 | 15 | import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/editor'; |
| 9 | 16 | import { useEffect, useRef } from '@wordpress/element'; |
| 10 | 17 | import { addFilter } from '@wordpress/hooks'; |
| @@ -37,10 +44,51 @@ | ||
| 37 | 44 | </ExtendifyDraft> |
| 38 | 45 | ), |
| 39 | 46 | }); |
| 40 | 47 | |
| 48 | +const untilRenderingMode = (mode) => | |
| 49 | + new Promise((resolve) => { | |
| 50 | + const isMode = () => select('core/editor').getRenderingMode() === mode; | |
| 51 | + if (isMode()) return resolve(); | |
| 52 | + const unsubscribe = subscribe(() => { | |
| 53 | + if (!isMode()) return; | |
| 54 | + unsubscribe(); | |
| 55 | + resolve(); | |
| 56 | + }, 'core/editor'); | |
| 57 | + }); | |
| 58 | + | |
| 59 | +const nextFrame = () => | |
| 60 | + new Promise((resolve) => requestAnimationFrame(resolve)); | |
| 61 | + | |
| 62 | +// Template-locked drops root inserts, and every mode switch clears the selection. | |
| 63 | +const addImageBlock = async () => { | |
| 64 | + const theme = (await resolveSelect('core').getCurrentTheme())?.stylesheet; | |
| 65 | + const isTemplateShown = | |
| 66 | + select('core/preferences').get('core', 'renderingModes')?.[theme]?.page === | |
| 67 | + 'template-locked'; | |
| 68 | + const { setRenderingMode } = dispatch('core/editor'); | |
| 69 | + | |
| 70 | + if (isTemplateShown) { | |
| 71 | + // The editor applies the saved mode after mount, undoing any earlier switch. | |
| 72 | + await untilRenderingMode('template-locked'); | |
| 73 | + setRenderingMode('post-only'); | |
| 74 | + await nextFrame(); | |
| 75 | + } | |
| 76 | + const { getBlocks } = select(blockEditorStore); | |
| 77 | + const { insertBlocks, selectBlock } = dispatch(blockEditorStore); | |
| 78 | + let imageBlock = getBlocks().find((block) => block.name === 'core/image'); | |
| 79 | + if (!imageBlock) { | |
| 80 | + imageBlock = createBlock('core/image'); | |
| 81 | + insertBlocks([imageBlock]); | |
| 82 | + } | |
| 83 | + if (isTemplateShown) { | |
| 84 | + setRenderingMode('template-locked'); | |
| 85 | + await nextFrame(); | |
| 86 | + } | |
| 87 | + selectBlock(imageBlock.clientId); | |
| 88 | +}; | |
| 89 | + | |
| 41 | 90 | const ExtendifyDraft = ({ children }) => { |
| 42 | - const { insertBlocks, selectBlock } = useDispatch(blockEditorStore); | |
| 43 | 91 | const { navigateTo } = useRouter(); |
| 44 | 92 | const { openGeneralSidebar } = useDispatch(editPostStore); |
| 45 | 93 | const sidebarName = useSelect((select) => |
| 46 | 94 | select(editPostStore).getActiveGeneralSidebarName(), |
| @@ -47,10 +95,8 @@ | ||
| 47 | 95 | ); |
| 48 | 96 | const ready = useEditorReady(); |
| 49 | 97 | const once = useRef(false); |
| 50 | 98 | |
| 51 | - const { getBlocks } = useSelect((select) => select(blockEditorStore), []); | |
| 52 | - | |
| 53 | 99 | useEffect(() => { |
| 54 | 100 | const search = new URLSearchParams(window.location.search); |
| 55 | 101 | // Lets Assist add an image block to highlight the feature |
| 56 | 102 | if (!search.has('ext-add-image-block')) return; |
| @@ -61,22 +107,15 @@ | ||
| 61 | 107 | `${window.location.pathname}?${search.toString()}`, |
| 62 | 108 | ); |
| 63 | 109 | |
| 64 | 110 | navigateTo('ai-image'); |
| 65 | - | |
| 66 | - const imageBlock = getBlocks()?.find( | |
| 67 | - (block) => block.name === 'core/image', | |
| 111 | + addImageBlock().then(() => | |
| 112 | + setTimeout(() => { | |
| 113 | + // Focus the textarea but give time for wp to finish it's autofocus | |
| 114 | + document.getElementById('draft-ai-image-textarea')?.focus(); | |
| 115 | + }, 300), | |
| 68 | 116 | ); |
| 69 | - requestAnimationFrame(() => | |
| 70 | - imageBlock | |
| 71 | - ? selectBlock(imageBlock.clientId) | |
| 72 | - : insertBlocks([createBlock('core/image')]), | |
| 73 | - ); | |
| 74 | - setTimeout(() => { | |
| 75 | - // Focus the textarea but give time for wp to finish it's autofocus | |
| 76 | - document.getElementById('draft-ai-image-textarea')?.focus(); | |
| 77 | - }, 300); | |
| 78 | - }, [selectBlock, insertBlocks, navigateTo, getBlocks]); | |
| 117 | + }, [navigateTo]); | |
| 79 | 118 | |
| 80 | 119 | useEffect(() => { |
| 81 | 120 | if (!ready || once.current) return; |
| 82 | 121 | |