PluginProbe
Extendify / 3.1.0
Extendify v3.1.0
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 0.6.0 All 127 releases
extendify / src / Draft / pages / GenerateImage.jsx

GenerateImage.jsx in Extendify 3.1.0, at src/Draft/pages/GenerateImage.jsx

129 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { GenerateForm } from '@draft/components/image-generation/GenerateForm';
2 import { ImagePreview } from '@draft/components/image-generation/ImagePreview';
3 import { useRouter } from '@draft/hooks/useRouter';
4 import { pageState } from '@draft/state/factory';
5 import { backArrow } from '@draft/svg/BackArrow';
6 import { generateImage } from '@shared/api/DataApi';
7 import { useImageGenerationStore } from '@shared/state/generate-images';
8 import {
9 BaseControl,
10 __experimentalHeading as Heading,
11 Panel,
12 PanelBody,
13 } from '@wordpress/components';
14 import { useEffect, useRef, useState } from '@wordpress/element';
15 import { __ } from '@wordpress/i18n';
16
17 const usePageState = pageState('AI Image', (set) => ({
18 imageDetails: { src: '', id: undefined },
19 setImageDetails: (newState) => {
20 set((state) => ({ ...state, imageDetails: newState }));
21 },
22 }));
23
24 export const GenerateImage = () => {
25 const {
26 imageCredits: curCredits,
27 updateImageCredits,
28 subtractOneCredit,
29 aiImageOptions,
30 } = useImageGenerationStore();
31 const [isGenerating, setIsGenerating] = useState(false);
32 const [errorMessage, setErrorMessage] = useState('');
33 const abortController = useRef(null);
34 const noCredits = curCredits.remaining === 0;
35 const { imageDetails, setImageDetails } = usePageState();
36 const { goBack } = useRouter();
37
38 const clearImageResponse = () => setImageDetails({ src: '', id: undefined });
39 const handleSubmit = async (event) => {
40 event.preventDefault();
41 setErrorMessage('');
42 if (noCredits) {
43 abortController.current?.abort();
44 return;
45 }
46
47 try {
48 setIsGenerating(true);
49 subtractOneCredit();
50 abortController.current = new AbortController();
51 const { imageCredits, images, id } = await generateImage(
52 { ...aiImageOptions, source: 'draft' },
53 abortController.current.signal,
54 );
55 updateImageCredits(imageCredits);
56 setImageDetails({ src: images[0].url, id });
57 } catch (error) {
58 // If the request was aborted (canceled), don't show an error
59 if (error?.code === 20) return;
60 // If we didn't get back any credit info, it was a server error
61 if (!error?.imageCredits) {
62 // Pause to prevent flickering
63 await new Promise((resolve) => setTimeout(resolve, 1000));
64 setErrorMessage(error.message);
65 // Add back the credit we subtracted
66 updateImageCredits({ remaining: curCredits.remaining });
67 return;
68 }
69 // Probably out of credits here
70 updateImageCredits(error.imageCredits);
71 setErrorMessage(error.message);
72 } finally {
73 setIsGenerating(false);
74 }
75 };
76
77 useEffect(() => {
78 if (imageDetails.src || isGenerating) return;
79 // refocus when image is removed
80 document.getElementById('draft-ai-image-textarea')?.focus();
81 }, [imageDetails.src, isGenerating]);
82
83 return (
84 <Panel>
85 <div className="flex h-12 items-center gap-1 pl-1">
86 <button
87 className="h-9 w-9 border-0 bg-transparent"
88 onClick={goBack}
89 type="button"
90 aria-label={__('Go Back', 'extendify-local')}
91 >
92 {backArrow}
93 </button>
94 <Heading className="mb-0">
95 {__('AI Image Generator', 'extendify-local')}
96 </Heading>
97 </div>
98 <PanelBody className="-mt-4 border-t-0">
99 <BaseControl label={__('Image Description', 'extendify-local')}>
100 <ImagePreview
101 prompt={aiImageOptions.prompt}
102 size={aiImageOptions.size}
103 isGenerating={isGenerating}
104 id={imageDetails?.id}
105 src={imageDetails?.src}
106 clearImageResponse={clearImageResponse}
107 />
108 {imageDetails.src ? null : (
109 <form onSubmit={handleSubmit} className="flex flex-col gap-5">
110 <GenerateForm
111 isGenerating={isGenerating}
112 errorMessage={errorMessage}
113 />
114 </form>
115 )}
116 </BaseControl>
117 </PanelBody>
118 </Panel>
119 );
120 };
121
122 export const routes = [
123 {
124 slug: 'ai-image',
125 title: __('AI Image', 'extendify-local'),
126 component: GenerateImage,
127 },
128 ];
129