PluginProbe
Extendify / 3.2.2
Extendify v3.2.2
3.2.2 3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 All 128 releases
extendify / src / Draft / app.js

app.js in Extendify 3.2.2, at src/Draft/app.js

151 lines 4.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { Draft } from '@draft/Draft';
2 import { useEditorReady } from '@shared/hooks/gutenberg';
3 import { store as blockEditorStore } from '@wordpress/block-editor';
4 import { createBlock } from '@wordpress/blocks';
5 import { Flex, FlexBlock } from '@wordpress/components';
6 import {
7 dispatch,
8 resolveSelect,
9 select,
10 subscribe,
11 useDispatch,
12 useSelect,
13 } from '@wordpress/data';
14 import { store as editPostStore } from '@wordpress/edit-post';
15 import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/editor';
16 import { useEffect, useRef } from '@wordpress/element';
17 import { addFilter } from '@wordpress/hooks';
18 import { __ } from '@wordpress/i18n';
19 import { registerPlugin } from '@wordpress/plugins';
20 import '@draft/draft.css';
21 import { GenerateImageButtons } from '@draft/components/GenerateImageButtons';
22 import { ToolbarMenu } from '@draft/components/ToolbarMenu';
23 import { useRouter } from '@draft/hooks/useRouter';
24 import { magic } from '@draft/svg';
25
26 registerPlugin('extendify-draft', {
27 render: () => (
28 <ExtendifyDraft>
29 <PluginSidebarMoreMenuItem target="draft">
30 {__('AI Tools', 'extendify-local')}
31 </PluginSidebarMoreMenuItem>
32 <PluginSidebar
33 name="draft"
34 icon={magic}
35 title={__('AI Tools', 'extendify-local')}
36 className="extendify-draft h-full"
37 >
38 <Flex direction="column" expanded justify="space-between">
39 <FlexBlock>
40 <Draft />
41 </FlexBlock>
42 </Flex>
43 </PluginSidebar>
44 </ExtendifyDraft>
45 ),
46 });
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
90 const ExtendifyDraft = ({ children }) => {
91 const { navigateTo } = useRouter();
92 const { openGeneralSidebar } = useDispatch(editPostStore);
93 const sidebarName = useSelect((select) =>
94 select(editPostStore).getActiveGeneralSidebarName(),
95 );
96 const ready = useEditorReady();
97 const once = useRef(false);
98
99 useEffect(() => {
100 const search = new URLSearchParams(window.location.search);
101 // Lets Assist add an image block to highlight the feature
102 if (!search.has('ext-add-image-block')) return;
103 search.delete('ext-add-image-block');
104 window.history.replaceState(
105 {},
106 '',
107 `${window.location.pathname}?${search.toString()}`,
108 );
109
110 navigateTo('ai-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),
116 );
117 }, [navigateTo]);
118
119 useEffect(() => {
120 if (!ready || once.current) return;
121
122 const id = requestAnimationFrame(() => {
123 if (sidebarName === 'extendify-draft/draft') {
124 once.current = true;
125 return;
126 }
127
128 openGeneralSidebar('extendify-draft/draft');
129 });
130
131 return () => cancelAnimationFrame(id);
132 }, [openGeneralSidebar, sidebarName, ready]);
133
134 return children;
135 };
136
137 // Add the toolbar
138 addFilter(
139 'editor.BlockEdit',
140 'extendify-draft/draft-toolbar',
141 (CurrentMenuItems) => (props) => ToolbarMenu(CurrentMenuItems, props),
142 );
143
144 // Add the Generate with AI button
145 addFilter(
146 'editor.BlockEdit',
147 'extendify-draft/draft-image',
148 (CurrentComponents) => (props) =>
149 GenerateImageButtons(CurrentComponents, props),
150 );
151