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
← All changes | src/QuickEdit/components/modals/AiImagePickerModal.jsx +34 -17 3.1.3 → 3.2.2 View file →
@@ -1,10 +1,13 @@
1 1 import { generateImage } from '@shared/api/DataApi';
2 -import { importImage, importImageServer } from '@shared/api/wp';
2 +import { downloadImage } from '@shared/api/wp';
3 +import { useImageCreditsSync } from '@shared/hooks/useImageCreditsSync';
4 +import { useStampedPreview } from '@shared/hooks/useStampedPreview';
3 5 import { track } from '@shared/lib/track';
4 6 import { useImageGenerationStore } from '@shared/state/generate-images';
5 7 import {
6 8 Button,
9 + CheckboxControl,
7 10 Modal,
8 11 Notice,
9 12 Spinner,
10 13 TextareaControl,
@@ -47,14 +50,18 @@
47 50 subtractOneCredit,
48 51 aiImageOptions,
49 52 setAiImageOption,
50 53 } = useImageGenerationStore();
54 + const [disclose, setDisclose] = useState(false);
51 55 const [generating, setGenerating] = useState(false);
52 56 const [applying, setApplying] = useState(false);
53 57 const [error, setError] = useState('');
54 58 const [preview, setPreview] = useState(null); // { src, id }
55 59 const abortRef = useRef(null);
60 + const previewSrc = useStampedPreview(preview?.src, disclose);
56 61
62 + useImageCreditsSync();
63 +
57 64 const noCredits = imageCredits.remaining === 0;
58 65 const usedCredits = imageCredits.total - imageCredits.remaining;
59 66
60 67 const onGenerate = async (e) => {
@@ -70,9 +77,13 @@
70 77 images,
71 78 id: gid,
72 79 } = await generateImage(aiImageOptions, abortRef.current.signal);
73 80 updateImageCredits(newCredits);
74 - setPreview({ src: images[0].url, id: gid });
81 + setPreview({
82 + src: images[0].url,
83 + id: gid,
84 + alt: images[0].alt ?? aiImageOptions.prompt,
85 + });
75 86 track('ai_image_generated', { size: aiImageOptions.size });
76 87 } catch (err) {
77 88 if (err?.code === 20) return; // aborted
78 89 if (!err?.imageCredits) {
@@ -95,21 +106,19 @@
95 106 if (!preview?.src || applying) return;
96 107 setError('');
97 108 setApplying(true);
98 109 try {
99 - let attachment;
100 - try {
101 - attachment = await importImage(preview.src, {
102 - alt: aiImageOptions.prompt,
103 - filename: 'ai-image.jpg',
110 + const attachment = await downloadImage(
111 + preview.id,
112 + preview.src,
113 + 'ai-generated',
114 + null,
115 + {
116 + alt: preview.alt,
104 117 caption: '',
105 - });
106 - } catch (_e) {
107 - attachment = await importImageServer(preview.src, {
108 - alt: aiImageOptions.prompt,
109 - caption: '',
110 - });
111 - }
118 + disclose,
119 + },
120 + );
112 121 const mediaId = attachment?.id;
113 122 if (!mediaId) throw new Error('No media id returned');
114 123
115 124 // Product image: write the featured image via WC's save
@@ -152,9 +161,9 @@
152 161 fieldKey: field,
153 162 value: {
154 163 url: attachment.url || attachment.source_url,
155 164 id: mediaId,
156 - alt: aiImageOptions.prompt || '',
165 + alt: attachment.alt_text ?? '',
157 166 },
158 167 },
159 168 ],
160 169 });
@@ -212,15 +221,15 @@
212 221 </Notice>
213 222 ) : null}
214 223 {preview?.src ? (
215 224 <div className="extendify-quick-edit-ai-preview">
216 - <img src={preview.src} alt={aiImageOptions.prompt} />
225 + <img src={previewSrc} alt={preview.alt} />
217 226 </div>
218 227 ) : (
219 228 <form onSubmit={onGenerate} className="extendify-quick-edit-ai-form">
220 229 <TextareaControl
221 230 autoFocus
222 - label={__('Image prompt', 'extendify-local')}
231 + label={__('Image description', 'extendify-local')}
223 232 placeholder={__(
224 233 'Describe the image you want to create',
225 234 'extendify-local',
226 235 )}
@@ -258,8 +267,16 @@
258 267 __('Portrait', 'extendify-local')
259 268 }
260 269 />
261 270 </ToggleGroupControl>
271 + <CheckboxControl
272 + __nextHasNoMarginBottom
273 + // translators: Checkbox that adds a visible "AI Generated" mark onto the image.
274 + label={__('Label image as AI-generated', 'extendify-local')}
275 + checked={disclose}
276 + onChange={setDisclose}
277 + disabled={generating}
278 + />
262 279 {generating ? (
263 280 // biome-ignore lint/a11y/useSemanticElements: deliberate live region; <output> changes display + semantics
264 281 <div className="extendify-quick-edit-ai-generating" role="status">
265 282 <Spinner />