@automattic/jetpack-ai-client 0.25.6 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/build/components/ai-icon/index.d.ts +10 -0
- package/build/components/ai-icon/index.js +16 -0
- package/build/components/ai-image/components/ai-image-modal.d.ts +57 -0
- package/build/components/ai-image/components/ai-image-modal.js +92 -0
- package/build/components/ai-image/components/carrousel.d.ts +28 -0
- package/build/components/ai-image/components/carrousel.js +69 -0
- package/build/components/ai-image/components/usage-counter.d.ts +16 -0
- package/build/components/ai-image/components/usage-counter.js +29 -0
- package/build/components/ai-image/featured-image.d.ts +17 -0
- package/build/components/ai-image/featured-image.js +278 -0
- package/build/components/ai-image/general-purpose-image.d.ts +23 -0
- package/build/components/ai-image/general-purpose-image.js +184 -0
- package/build/components/ai-image/hooks/use-ai-image.d.ts +48 -0
- package/build/components/ai-image/hooks/use-ai-image.js +219 -0
- package/build/components/ai-image/hooks/use-site-type.d.ts +6 -0
- package/build/components/ai-image/hooks/use-site-type.js +23 -0
- package/build/components/ai-image/index.d.ts +4 -0
- package/build/components/ai-image/index.js +4 -0
- package/build/components/ai-image/types.d.ts +16 -0
- package/build/components/ai-image/types.js +6 -0
- package/build/{ai-client/src/components → components}/index.d.ts +4 -0
- package/build/{ai-client/src/components → components}/index.js +4 -0
- package/build/components/modal/index.d.ts +18 -0
- package/build/components/modal/index.js +23 -0
- package/build/components/quota-exceeded-message/index.d.ts +13 -0
- package/build/components/quota-exceeded-message/index.js +152 -0
- package/build/components/quota-exceeded-message/light-nudge.d.ts +11 -0
- package/build/components/quota-exceeded-message/light-nudge.js +8 -0
- package/build/{ai-client/src/constants.d.ts → constants.d.ts} +3 -0
- package/build/{ai-client/src/constants.js → constants.js} +4 -0
- package/build/hooks/use-ai-checkout/index.d.ts +13 -0
- package/build/hooks/use-ai-checkout/index.js +41 -0
- package/build/hooks/use-ai-feature/index.d.ts +33 -0
- package/build/hooks/use-ai-feature/index.js +37 -0
- package/build/hooks/use-post-content.d.ts +5 -0
- package/build/hooks/use-post-content.js +20 -0
- package/build/hooks/use-save-to-media-library.d.ts +12 -0
- package/build/hooks/use-save-to-media-library.js +74 -0
- package/build/{ai-client/src/index.d.ts → index.d.ts} +3 -0
- package/build/{ai-client/src/index.js → index.js} +3 -0
- package/build/{ai-client/src/logo-generator → logo-generator}/components/upgrade-screen.js +1 -1
- package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-fair-usage-notice-message.js +1 -1
- package/package.json +20 -14
- package/src/components/ai-icon/index.tsx +39 -0
- package/src/components/ai-image/components/ai-image-modal.scss +88 -0
- package/src/components/ai-image/components/ai-image-modal.tsx +240 -0
- package/src/components/ai-image/components/carrousel.scss +163 -0
- package/src/components/ai-image/components/carrousel.tsx +217 -0
- package/src/components/ai-image/components/usage-counter.scss +19 -0
- package/src/components/ai-image/components/usage-counter.tsx +54 -0
- package/src/components/ai-image/featured-image.tsx +439 -0
- package/src/components/ai-image/general-purpose-image.tsx +303 -0
- package/src/components/ai-image/hooks/use-ai-image.ts +339 -0
- package/src/components/ai-image/hooks/use-site-type.ts +26 -0
- package/src/components/ai-image/index.ts +10 -0
- package/src/components/ai-image/style.scss +95 -0
- package/src/components/ai-image/types.ts +19 -0
- package/src/components/index.ts +12 -0
- package/src/components/modal/index.tsx +70 -0
- package/src/components/modal/style.scss +45 -0
- package/src/components/quota-exceeded-message/index.tsx +319 -0
- package/src/components/quota-exceeded-message/light-nudge.tsx +38 -0
- package/src/components/quota-exceeded-message/style.scss +35 -0
- package/src/constants.ts +5 -0
- package/src/hooks/use-ai-checkout/index.ts +65 -0
- package/src/hooks/use-ai-feature/Readme.md +20 -0
- package/src/hooks/use-ai-feature/index.ts +62 -0
- package/src/hooks/use-post-content.ts +27 -0
- package/src/hooks/use-save-to-media-library.ts +100 -0
- package/src/index.ts +3 -0
- package/src/logo-generator/components/upgrade-screen.tsx +1 -1
- package/src/logo-generator/hooks/use-fair-usage-notice-message.tsx +1 -1
- package/build/components/tools/jp-redirect/index.d.ts +0 -20
- package/build/components/tools/jp-redirect/index.js +0 -50
- package/build/components/tools/jp-redirect/types.d.ts +0 -39
- package/build/components/tools/jp-redirect/types.js +0 -1
- /package/build/{ai-client/src/api-fetch → api-fetch}/index.d.ts +0 -0
- /package/build/{ai-client/src/api-fetch → api-fetch}/index.js +0 -0
- /package/build/{ai-client/src/ask-question → ask-question}/index.d.ts +0 -0
- /package/build/{ai-client/src/ask-question → ask-question}/index.js +0 -0
- /package/build/{ai-client/src/ask-question → ask-question}/sync.d.ts +0 -0
- /package/build/{ai-client/src/ask-question → ask-question}/sync.js +0 -0
- /package/build/{ai-client/src/audio-transcription → audio-transcription}/index.d.ts +0 -0
- /package/build/{ai-client/src/audio-transcription → audio-transcription}/index.js +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/ai-control.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/ai-control.js +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/block-ai-control.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/block-ai-control.js +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/extension-ai-control.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/extension-ai-control.js +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/index.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/ai-control/index.js +0 -0
- /package/build/{ai-client/src/components → components}/ai-feedback/index.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/ai-feedback/index.js +0 -0
- /package/build/{ai-client/src/components → components}/ai-modal-footer/index.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/ai-modal-footer/index.js +0 -0
- /package/build/{ai-client/src/components → components}/ai-status-indicator/index.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/ai-status-indicator/index.js +0 -0
- /package/build/{ai-client/src/components → components}/audio-duration-display/index.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/audio-duration-display/index.js +0 -0
- /package/build/{ai-client/src/components → components}/audio-duration-display/lib/media.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/audio-duration-display/lib/media.js +0 -0
- /package/build/{ai-client/src/components → components}/message/index.d.ts +0 -0
- /package/build/{ai-client/src/components → components}/message/index.js +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/context.d.ts +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/context.js +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/index.d.ts +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/index.js +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/use-ai-context.d.ts +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/use-ai-context.js +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/with-ai-assistant-data.d.ts +0 -0
- /package/build/{ai-client/src/data-flow → data-flow}/with-ai-assistant-data.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-ai-suggestions/index.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-ai-suggestions/index.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-audio-transcription/index.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-audio-transcription/index.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-audio-validation/index.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-audio-validation/index.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-image-generator/constants.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-image-generator/constants.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-image-generator/index.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-image-generator/index.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-media-recording/index.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-media-recording/index.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-save-to-media-library/index.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-save-to-media-library/index.js +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-transcription-post-processing/index.d.ts +0 -0
- /package/build/{ai-client/src/hooks → hooks}/use-transcription-post-processing/index.js +0 -0
- /package/build/{ai-client/src/icons → icons}/ai-assistant.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/ai-assistant.js +0 -0
- /package/build/{ai-client/src/icons → icons}/error-exclamation.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/error-exclamation.js +0 -0
- /package/build/{ai-client/src/icons → icons}/index.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/index.js +0 -0
- /package/build/{ai-client/src/icons → icons}/mic.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/mic.js +0 -0
- /package/build/{ai-client/src/icons → icons}/origami-plane.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/origami-plane.js +0 -0
- /package/build/{ai-client/src/icons → icons}/player-pause.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/player-pause.js +0 -0
- /package/build/{ai-client/src/icons → icons}/player-play.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/player-play.js +0 -0
- /package/build/{ai-client/src/icons → icons}/player-stop.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/player-stop.js +0 -0
- /package/build/{ai-client/src/icons → icons}/speak-tone.d.ts +0 -0
- /package/build/{ai-client/src/icons → icons}/speak-tone.js +0 -0
- /package/build/{ai-client/src/jwt → jwt}/index.d.ts +0 -0
- /package/build/{ai-client/src/jwt → jwt}/index.js +0 -0
- /package/build/{ai-client/src/libs → libs}/index.d.ts +0 -0
- /package/build/{ai-client/src/libs → libs}/index.js +0 -0
- /package/build/{ai-client/src/libs → libs}/map-action-to-human-text.d.ts +0 -0
- /package/build/{ai-client/src/libs → libs}/map-action-to-human-text.js +0 -0
- /package/build/{ai-client/src/libs → libs}/markdown/html-to-markdown.d.ts +0 -0
- /package/build/{ai-client/src/libs → libs}/markdown/html-to-markdown.js +0 -0
- /package/build/{ai-client/src/libs → libs}/markdown/index.d.ts +0 -0
- /package/build/{ai-client/src/libs → libs}/markdown/index.js +0 -0
- /package/build/{ai-client/src/libs → libs}/markdown/markdown-to-html.d.ts +0 -0
- /package/build/{ai-client/src/libs → libs}/markdown/markdown-to-html.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/ai.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/ai.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/check.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/check.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/logo.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/logo.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/media.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/assets/icons/media.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/fair-usage-notice.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/fair-usage-notice.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/feature-fetch-failure-screen.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/feature-fetch-failure-screen.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/first-load-screen.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/first-load-screen.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/generator-modal.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/generator-modal.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/history-carousel.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/history-carousel.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/image-loader.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/image-loader.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/logo-presenter.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/logo-presenter.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/prompt.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/prompt.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/upgrade-nudge.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/upgrade-nudge.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/upgrade-screen.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/visit-site-banner.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/components/visit-site-banner.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/constants.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/constants.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-checkout.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-checkout.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-fair-usage-notice-message.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-logo-generator.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-logo-generator.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-request-errors.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/hooks/use-request-errors.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/index.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/index.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/logo-storage.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/logo-storage.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/media-exists.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/media-exists.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/set-site-logo.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/set-site-logo.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/wpcom-limited-request.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/lib/wpcom-limited-request.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/actions.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/actions.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/constants.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/constants.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/index.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/index.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/initial-state.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/initial-state.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/reducer.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/reducer.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/selectors.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/selectors.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/types.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/store/types.js +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/types.d.ts +0 -0
- /package/build/{ai-client/src/logo-generator → logo-generator}/types.js +0 -0
- /package/build/{ai-client/src/suggestions-event-source → suggestions-event-source}/index.d.ts +0 -0
- /package/build/{ai-client/src/suggestions-event-source → suggestions-event-source}/index.js +0 -0
- /package/build/{ai-client/src/types.d.ts → types.d.ts} +0 -0
- /package/build/{ai-client/src/types.js → types.js} +0 -0
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
useAnalytics,
|
|
6
|
+
PLAN_TYPE_UNLIMITED,
|
|
7
|
+
usePlanType,
|
|
8
|
+
} from '@automattic/jetpack-shared-extension-utils';
|
|
9
|
+
import { Button } from '@wordpress/components';
|
|
10
|
+
import { useCallback, useState } from '@wordpress/element';
|
|
11
|
+
import { __, sprintf } from '@wordpress/i18n';
|
|
12
|
+
import debugFactory from 'debug';
|
|
13
|
+
/**
|
|
14
|
+
* Internal dependencies
|
|
15
|
+
*/
|
|
16
|
+
import './style.scss';
|
|
17
|
+
import useAiFeature from '../../hooks/use-ai-feature/index.js';
|
|
18
|
+
import usePostContent from '../../hooks/use-post-content.js';
|
|
19
|
+
import useSaveToMediaLibrary from '../../hooks/use-save-to-media-library.js';
|
|
20
|
+
import AiImageModal from './components/ai-image-modal.js';
|
|
21
|
+
import useAiImage from './hooks/use-ai-image.js';
|
|
22
|
+
import useSiteType from './hooks/use-site-type.js';
|
|
23
|
+
import {
|
|
24
|
+
IMAGE_GENERATION_MODEL_STABLE_DIFFUSION,
|
|
25
|
+
IMAGE_GENERATION_MODEL_DALL_E_3,
|
|
26
|
+
GENERAL_IMAGE_FEATURE_NAME,
|
|
27
|
+
} from './types.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The type for the callback function that is called when the user selects an image.
|
|
31
|
+
*/
|
|
32
|
+
type SetImageCallbackProps = {
|
|
33
|
+
id: number;
|
|
34
|
+
url: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type GeneralPurposeImageProps = {
|
|
38
|
+
placement: string;
|
|
39
|
+
onClose?: () => void;
|
|
40
|
+
onSetImage?: ( image: SetImageCallbackProps ) => void;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const debug = debugFactory( 'jetpack-ai:general-purpose-image' );
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* GeneralPurposeImage component
|
|
47
|
+
* @param {GeneralPurposeImageProps} props - The component properties.
|
|
48
|
+
* @return {React.ReactElement} - rendered component.
|
|
49
|
+
*/
|
|
50
|
+
export default function GeneralPurposeImage( {
|
|
51
|
+
placement,
|
|
52
|
+
onClose = () => {},
|
|
53
|
+
onSetImage = () => {},
|
|
54
|
+
}: GeneralPurposeImageProps ) {
|
|
55
|
+
const [ isFeaturedImageModalVisible, setIsFeaturedImageModalVisible ] = useState( true );
|
|
56
|
+
const siteType = useSiteType();
|
|
57
|
+
const postContent = usePostContent();
|
|
58
|
+
const { saveToMediaLibrary } = useSaveToMediaLibrary();
|
|
59
|
+
const { tracks } = useAnalytics();
|
|
60
|
+
const { recordEvent } = tracks;
|
|
61
|
+
const [ prompt, setPrompt ] = useState( '' );
|
|
62
|
+
|
|
63
|
+
// Get feature data
|
|
64
|
+
const { requireUpgrade, requestsCount, requestsLimit, currentTier, costs } = useAiFeature();
|
|
65
|
+
const planType = usePlanType( currentTier );
|
|
66
|
+
const generalImageCost = costs?.[ GENERAL_IMAGE_FEATURE_NAME ]?.activeModel ?? 10;
|
|
67
|
+
const generalImageActiveModel =
|
|
68
|
+
generalImageCost === costs?.[ GENERAL_IMAGE_FEATURE_NAME ]?.stableDiffusion
|
|
69
|
+
? IMAGE_GENERATION_MODEL_STABLE_DIFFUSION
|
|
70
|
+
: IMAGE_GENERATION_MODEL_DALL_E_3;
|
|
71
|
+
const isUnlimited = planType === PLAN_TYPE_UNLIMITED;
|
|
72
|
+
const requestsBalance = requestsLimit - requestsCount;
|
|
73
|
+
const notEnoughRequests = requestsBalance < generalImageCost;
|
|
74
|
+
|
|
75
|
+
const {
|
|
76
|
+
current,
|
|
77
|
+
setCurrent,
|
|
78
|
+
processImageGeneration,
|
|
79
|
+
handlePreviousImage,
|
|
80
|
+
handleNextImage,
|
|
81
|
+
currentImage,
|
|
82
|
+
currentPointer,
|
|
83
|
+
images,
|
|
84
|
+
pointer,
|
|
85
|
+
imageStyles,
|
|
86
|
+
guessStyle,
|
|
87
|
+
} = useAiImage( {
|
|
88
|
+
cost: generalImageCost,
|
|
89
|
+
autoStart: false,
|
|
90
|
+
type: 'general-image-generation',
|
|
91
|
+
feature: GENERAL_IMAGE_FEATURE_NAME,
|
|
92
|
+
} );
|
|
93
|
+
|
|
94
|
+
const hasPrompt = prompt.length >= 3;
|
|
95
|
+
const disableInput = notEnoughRequests || currentPointer?.generating || requireUpgrade;
|
|
96
|
+
const disableAction = disableInput || ! hasPrompt;
|
|
97
|
+
|
|
98
|
+
const handleModalClose = useCallback( () => {
|
|
99
|
+
setIsFeaturedImageModalVisible( false );
|
|
100
|
+
onClose?.();
|
|
101
|
+
}, [ onClose ] );
|
|
102
|
+
|
|
103
|
+
const handleGenerate = useCallback(
|
|
104
|
+
async ( { userPrompt, style }: { userPrompt?: string; style?: string } ) => {
|
|
105
|
+
debug( 'handleGenerate', userPrompt, style );
|
|
106
|
+
|
|
107
|
+
// track the generate image event
|
|
108
|
+
recordEvent( 'jetpack_ai_general_image_generation_generate_image', {
|
|
109
|
+
placement,
|
|
110
|
+
model: generalImageActiveModel,
|
|
111
|
+
site_type: siteType,
|
|
112
|
+
style,
|
|
113
|
+
} );
|
|
114
|
+
processImageGeneration( { userPrompt, postContent, notEnoughRequests, style } ).catch(
|
|
115
|
+
error => {
|
|
116
|
+
recordEvent( 'jetpack_ai_general_image_generation_error', {
|
|
117
|
+
placement,
|
|
118
|
+
error: error?.message,
|
|
119
|
+
model: generalImageActiveModel,
|
|
120
|
+
site_type: siteType,
|
|
121
|
+
style,
|
|
122
|
+
} );
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
},
|
|
126
|
+
[
|
|
127
|
+
recordEvent,
|
|
128
|
+
placement,
|
|
129
|
+
generalImageActiveModel,
|
|
130
|
+
siteType,
|
|
131
|
+
processImageGeneration,
|
|
132
|
+
postContent,
|
|
133
|
+
notEnoughRequests,
|
|
134
|
+
]
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const handleRegenerate = useCallback(
|
|
138
|
+
( { userPrompt, style }: { userPrompt?: string; style?: string } ) => {
|
|
139
|
+
debug( 'handleRegenerate', userPrompt );
|
|
140
|
+
// track the regenerate image event
|
|
141
|
+
recordEvent( 'jetpack_ai_general_image_generation_generate_another_image', {
|
|
142
|
+
placement,
|
|
143
|
+
model: generalImageActiveModel,
|
|
144
|
+
site_type: siteType,
|
|
145
|
+
style,
|
|
146
|
+
} );
|
|
147
|
+
|
|
148
|
+
setCurrent( crrt => crrt + 1 );
|
|
149
|
+
processImageGeneration( { userPrompt, postContent, notEnoughRequests, style } ).catch(
|
|
150
|
+
error => {
|
|
151
|
+
recordEvent( 'jetpack_ai_general_image_generation_error', {
|
|
152
|
+
placement,
|
|
153
|
+
error: error?.message,
|
|
154
|
+
model: generalImageActiveModel,
|
|
155
|
+
site_type: siteType,
|
|
156
|
+
} );
|
|
157
|
+
}
|
|
158
|
+
);
|
|
159
|
+
},
|
|
160
|
+
[
|
|
161
|
+
recordEvent,
|
|
162
|
+
placement,
|
|
163
|
+
generalImageActiveModel,
|
|
164
|
+
siteType,
|
|
165
|
+
processImageGeneration,
|
|
166
|
+
postContent,
|
|
167
|
+
notEnoughRequests,
|
|
168
|
+
setCurrent,
|
|
169
|
+
]
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
const handleTryAgain = useCallback(
|
|
173
|
+
( { userPrompt, style }: { userPrompt?: string; style?: string } ) => {
|
|
174
|
+
debug( 'handleTryAgain', userPrompt );
|
|
175
|
+
// track the try again event
|
|
176
|
+
recordEvent( 'jetpack_ai_general_image_generation_try_again', {
|
|
177
|
+
placement,
|
|
178
|
+
model: generalImageActiveModel,
|
|
179
|
+
site_type: siteType,
|
|
180
|
+
style,
|
|
181
|
+
} );
|
|
182
|
+
|
|
183
|
+
processImageGeneration( { userPrompt, postContent, notEnoughRequests, style } ).catch(
|
|
184
|
+
error => {
|
|
185
|
+
recordEvent( 'jetpack_ai_general_image_generation_error', {
|
|
186
|
+
placement,
|
|
187
|
+
error: error?.message,
|
|
188
|
+
model: generalImageActiveModel,
|
|
189
|
+
site_type: siteType,
|
|
190
|
+
} );
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
},
|
|
194
|
+
[
|
|
195
|
+
recordEvent,
|
|
196
|
+
placement,
|
|
197
|
+
generalImageActiveModel,
|
|
198
|
+
siteType,
|
|
199
|
+
processImageGeneration,
|
|
200
|
+
postContent,
|
|
201
|
+
notEnoughRequests,
|
|
202
|
+
]
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const handleAccept = useCallback( () => {
|
|
206
|
+
// track the accept/use image event
|
|
207
|
+
recordEvent( 'jetpack_ai_general_image_generation_use_image', {
|
|
208
|
+
placement,
|
|
209
|
+
model: generalImageActiveModel,
|
|
210
|
+
site_type: siteType,
|
|
211
|
+
} );
|
|
212
|
+
|
|
213
|
+
const setImage = image => {
|
|
214
|
+
onSetImage?.( { id: image.id, url: image.url } );
|
|
215
|
+
handleModalClose();
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// If the image is already in the media library, use it directly, if it failed for some reason
|
|
219
|
+
// save it to the media library and then use it.
|
|
220
|
+
if ( currentImage?.libraryId ) {
|
|
221
|
+
setImage( {
|
|
222
|
+
id: currentImage?.libraryId,
|
|
223
|
+
url: currentImage?.libraryUrl,
|
|
224
|
+
} );
|
|
225
|
+
} else {
|
|
226
|
+
saveToMediaLibrary( currentImage?.image ).then( image => {
|
|
227
|
+
setImage( image );
|
|
228
|
+
} );
|
|
229
|
+
}
|
|
230
|
+
}, [
|
|
231
|
+
recordEvent,
|
|
232
|
+
placement,
|
|
233
|
+
generalImageActiveModel,
|
|
234
|
+
siteType,
|
|
235
|
+
currentImage?.libraryId,
|
|
236
|
+
currentImage?.libraryUrl,
|
|
237
|
+
currentImage?.image,
|
|
238
|
+
onSetImage,
|
|
239
|
+
handleModalClose,
|
|
240
|
+
saveToMediaLibrary,
|
|
241
|
+
] );
|
|
242
|
+
|
|
243
|
+
const generateAgainText = __( 'Generate another image', 'jetpack-ai-client' );
|
|
244
|
+
const generateText = __( 'Generate', 'jetpack-ai-client' );
|
|
245
|
+
|
|
246
|
+
const upgradeDescription = notEnoughRequests
|
|
247
|
+
? sprintf(
|
|
248
|
+
// Translators: %d is the cost of generating a featured image.
|
|
249
|
+
__(
|
|
250
|
+
"Image generation costs %d requests per image. You don't have enough requests to generate another image.",
|
|
251
|
+
'jetpack-ai-client'
|
|
252
|
+
),
|
|
253
|
+
generalImageCost
|
|
254
|
+
)
|
|
255
|
+
: null;
|
|
256
|
+
|
|
257
|
+
const acceptButton = (
|
|
258
|
+
<Button
|
|
259
|
+
onClick={ handleAccept }
|
|
260
|
+
variant="primary"
|
|
261
|
+
disabled={ ! currentImage?.image || currentImage?.generating }
|
|
262
|
+
>
|
|
263
|
+
{ __( 'Insert image', 'jetpack-ai-client' ) }
|
|
264
|
+
</Button>
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
return (
|
|
268
|
+
<AiImageModal
|
|
269
|
+
postContent={ true }
|
|
270
|
+
images={ images }
|
|
271
|
+
currentIndex={ current }
|
|
272
|
+
title={ __( 'Generate an image with AI', 'jetpack-ai-client' ) }
|
|
273
|
+
cost={ generalImageCost }
|
|
274
|
+
open={ isFeaturedImageModalVisible }
|
|
275
|
+
placement={ placement }
|
|
276
|
+
onClose={ handleModalClose }
|
|
277
|
+
onTryAgain={ handleTryAgain }
|
|
278
|
+
onGenerate={ pointer?.current > 0 ? handleRegenerate : handleGenerate }
|
|
279
|
+
generating={ currentPointer?.generating }
|
|
280
|
+
notEnoughRequests={ notEnoughRequests }
|
|
281
|
+
requireUpgrade={ requireUpgrade }
|
|
282
|
+
upgradeDescription={ upgradeDescription }
|
|
283
|
+
currentLimit={ requestsLimit }
|
|
284
|
+
currentUsage={ requestsCount }
|
|
285
|
+
isUnlimited={ isUnlimited }
|
|
286
|
+
hasError={ Boolean( currentPointer?.error ) }
|
|
287
|
+
handlePreviousImage={ handlePreviousImage }
|
|
288
|
+
handleNextImage={ handleNextImage }
|
|
289
|
+
acceptButton={ acceptButton }
|
|
290
|
+
generateButtonLabel={ pointer?.current > 0 ? generateAgainText : generateText }
|
|
291
|
+
instructionsPlaceholder={ __(
|
|
292
|
+
"Describe the image you'd like to create and select a style.",
|
|
293
|
+
'jetpack-ai-client'
|
|
294
|
+
) }
|
|
295
|
+
imageStyles={ imageStyles }
|
|
296
|
+
onGuessStyle={ guessStyle }
|
|
297
|
+
prompt={ prompt }
|
|
298
|
+
setPrompt={ setPrompt }
|
|
299
|
+
inputDisabled={ disableInput }
|
|
300
|
+
actionDisabled={ disableAction }
|
|
301
|
+
/>
|
|
302
|
+
);
|
|
303
|
+
}
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { useDispatch, useSelect } from '@wordpress/data';
|
|
5
|
+
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
|
|
6
|
+
import { __ } from '@wordpress/i18n';
|
|
7
|
+
import { cleanForSlug } from '@wordpress/url';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
/**
|
|
10
|
+
* Internal dependencies
|
|
11
|
+
*/
|
|
12
|
+
import askQuestionSync from '../../../ask-question/sync.js';
|
|
13
|
+
import useAiFeature from '../../../hooks/use-ai-feature/index.js';
|
|
14
|
+
import { ImageStyleObject, ImageStyle } from '../../../hooks/use-image-generator/constants.js';
|
|
15
|
+
import useImageGenerator from '../../../hooks/use-image-generator/index.js';
|
|
16
|
+
import useSaveToMediaLibrary from '../../../hooks/use-save-to-media-library.js';
|
|
17
|
+
/**
|
|
18
|
+
* Types
|
|
19
|
+
*/
|
|
20
|
+
import {
|
|
21
|
+
CoreSelectors,
|
|
22
|
+
FEATURED_IMAGE_FEATURE_NAME,
|
|
23
|
+
GENERAL_IMAGE_FEATURE_NAME,
|
|
24
|
+
} from '../types.js';
|
|
25
|
+
import type { RoleType } from '../../../types.js';
|
|
26
|
+
import type { CarrouselImageData, CarrouselImages } from '../components/carrousel.js';
|
|
27
|
+
import type { FeatureControl } from '@automattic/jetpack-shared-extension-utils/store/wordpress-com/types';
|
|
28
|
+
|
|
29
|
+
type ImageFeatureControl = FeatureControl & {
|
|
30
|
+
styles: Array< ImageStyleObject > | [];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type AiImageType = 'featured-image-generation' | 'general-image-generation';
|
|
34
|
+
type AiImageFeature = typeof FEATURED_IMAGE_FEATURE_NAME | typeof GENERAL_IMAGE_FEATURE_NAME;
|
|
35
|
+
export type ImageResponse = {
|
|
36
|
+
image?: string;
|
|
37
|
+
libraryId?: string;
|
|
38
|
+
libraryUrl?: string;
|
|
39
|
+
revisedPrompt?: string;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type ProcessImageGenerationProps = {
|
|
43
|
+
userPrompt?: string | null;
|
|
44
|
+
postContent?: string | null;
|
|
45
|
+
notEnoughRequests: boolean;
|
|
46
|
+
style?: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type GuessStyleFunction = (
|
|
50
|
+
prompt: string,
|
|
51
|
+
requestType: string,
|
|
52
|
+
content: string
|
|
53
|
+
) => Promise< ImageStyle | null >;
|
|
54
|
+
|
|
55
|
+
type UseAiImageProps = {
|
|
56
|
+
feature: AiImageFeature;
|
|
57
|
+
type: AiImageType;
|
|
58
|
+
cost: number;
|
|
59
|
+
autoStart?: boolean;
|
|
60
|
+
previousMediaId?: number;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
type UseAiImageReturn = {
|
|
64
|
+
current: number;
|
|
65
|
+
setCurrent: ( value: number ) => void;
|
|
66
|
+
processImageGeneration: ( props: ProcessImageGenerationProps ) => Promise< ImageResponse >;
|
|
67
|
+
handlePreviousImage: () => void;
|
|
68
|
+
handleNextImage: () => void;
|
|
69
|
+
currentImage: CarrouselImageData;
|
|
70
|
+
currentPointer: CarrouselImageData;
|
|
71
|
+
images: CarrouselImages;
|
|
72
|
+
pointer: React.RefObject< number >;
|
|
73
|
+
imageStyles: Array< ImageStyleObject >;
|
|
74
|
+
guessStyle: GuessStyleFunction;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Hook to get properties for AiImage
|
|
79
|
+
*
|
|
80
|
+
* @param {UseAiImageProps} props - The component properties.
|
|
81
|
+
* @return {UseAiImageReturn} - Object containing properties for AiImage.
|
|
82
|
+
*/
|
|
83
|
+
export default function useAiImage( {
|
|
84
|
+
feature,
|
|
85
|
+
type,
|
|
86
|
+
cost,
|
|
87
|
+
autoStart = true,
|
|
88
|
+
previousMediaId,
|
|
89
|
+
}: UseAiImageProps ) {
|
|
90
|
+
const { generateImageWithParameters } = useImageGenerator();
|
|
91
|
+
const { increaseRequestsCount, featuresControl } = useAiFeature();
|
|
92
|
+
const { saveToMediaLibrary } = useSaveToMediaLibrary();
|
|
93
|
+
const { createNotice } = useDispatch( 'core/notices' );
|
|
94
|
+
|
|
95
|
+
/* Images Control */
|
|
96
|
+
// pointer keeps track of request/generation iteration
|
|
97
|
+
const pointer = useRef( 0 );
|
|
98
|
+
// and current keeps track of what is the image exposed at the moment
|
|
99
|
+
// TODO: should current be any relevant here? It's just modal/carrousel logic after all
|
|
100
|
+
const [ current, setCurrent ] = useState( 0 );
|
|
101
|
+
const [ images, setImages ] = useState< CarrouselImages >( [ { generating: autoStart } ] );
|
|
102
|
+
|
|
103
|
+
// map feature-to-control prop, if this goes over 2 options, make a hook for it
|
|
104
|
+
const featureControl = feature === FEATURED_IMAGE_FEATURE_NAME ? 'featured-image' : 'image';
|
|
105
|
+
const imageFeatureControl = featuresControl?.[ featureControl ] as ImageFeatureControl;
|
|
106
|
+
const imageStyles: Array< ImageStyleObject > = imageFeatureControl?.styles;
|
|
107
|
+
|
|
108
|
+
/* Merge the image data with the new data. */
|
|
109
|
+
const updateImages = useCallback( ( data: CarrouselImageData, index ) => {
|
|
110
|
+
setImages( currentImages => {
|
|
111
|
+
const newImages = [ ...currentImages ];
|
|
112
|
+
newImages[ index ] = {
|
|
113
|
+
...newImages[ index ],
|
|
114
|
+
...data,
|
|
115
|
+
};
|
|
116
|
+
return newImages;
|
|
117
|
+
} );
|
|
118
|
+
}, [] );
|
|
119
|
+
|
|
120
|
+
// the selec/useEffect combo...
|
|
121
|
+
const loadedMedia = useSelect(
|
|
122
|
+
( select: ( store ) => CoreSelectors ) => select( 'core' )?.getMedia?.( previousMediaId ),
|
|
123
|
+
[ previousMediaId ]
|
|
124
|
+
);
|
|
125
|
+
useEffect( () => {
|
|
126
|
+
if ( loadedMedia ) {
|
|
127
|
+
updateImages(
|
|
128
|
+
{
|
|
129
|
+
image: loadedMedia.source_url,
|
|
130
|
+
libraryId: loadedMedia.id,
|
|
131
|
+
libraryUrl: loadedMedia.source_url,
|
|
132
|
+
generating: false,
|
|
133
|
+
},
|
|
134
|
+
pointer.current
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}, [ loadedMedia, updateImages ] );
|
|
138
|
+
|
|
139
|
+
/*
|
|
140
|
+
* Function to show a snackbar notice on the editor.
|
|
141
|
+
*/
|
|
142
|
+
const showSnackbarNotice = useCallback(
|
|
143
|
+
( message: string ) => {
|
|
144
|
+
createNotice( 'success', message, {
|
|
145
|
+
type: 'snackbar',
|
|
146
|
+
isDismissible: true,
|
|
147
|
+
} );
|
|
148
|
+
},
|
|
149
|
+
[ createNotice ]
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
/*
|
|
153
|
+
* Function to update the requests count after a featured image generation.
|
|
154
|
+
*/
|
|
155
|
+
const updateRequestsCount = useCallback( () => {
|
|
156
|
+
increaseRequestsCount( cost );
|
|
157
|
+
}, [ increaseRequestsCount, cost ] );
|
|
158
|
+
|
|
159
|
+
/*
|
|
160
|
+
* Function to suggest a name for the image based on the user prompt.
|
|
161
|
+
*/
|
|
162
|
+
const getImageNameSuggestion = useCallback( ( userPrompt: string ) => {
|
|
163
|
+
if ( ! userPrompt ) {
|
|
164
|
+
return 'image.png';
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const truncatedPrompt = userPrompt.split( ' ' ).slice( 0, 10 ).join( ' ' );
|
|
168
|
+
return cleanForSlug( truncatedPrompt ) + '.png';
|
|
169
|
+
}, [] );
|
|
170
|
+
|
|
171
|
+
/*
|
|
172
|
+
* Function to generate a new image with the current value of the post content.
|
|
173
|
+
*/
|
|
174
|
+
const processImageGeneration = useCallback(
|
|
175
|
+
( {
|
|
176
|
+
userPrompt,
|
|
177
|
+
postContent,
|
|
178
|
+
notEnoughRequests,
|
|
179
|
+
style = null,
|
|
180
|
+
}: ProcessImageGenerationProps ) => {
|
|
181
|
+
return new Promise< ImageResponse >( ( resolve, reject ) => {
|
|
182
|
+
if ( previousMediaId && pointer.current === 0 ) {
|
|
183
|
+
pointer.current++;
|
|
184
|
+
}
|
|
185
|
+
updateImages( { generating: true, error: null }, pointer.current );
|
|
186
|
+
|
|
187
|
+
// Ensure the site has enough requests to generate the image.
|
|
188
|
+
if ( notEnoughRequests ) {
|
|
189
|
+
updateImages(
|
|
190
|
+
{
|
|
191
|
+
generating: false,
|
|
192
|
+
error: new Error(
|
|
193
|
+
__(
|
|
194
|
+
"You don't have enough requests to generate another image.",
|
|
195
|
+
'jetpack-ai-client'
|
|
196
|
+
)
|
|
197
|
+
),
|
|
198
|
+
},
|
|
199
|
+
pointer.current
|
|
200
|
+
);
|
|
201
|
+
resolve( {} );
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Make a generic call to backend and let it decide the model.
|
|
207
|
+
*/
|
|
208
|
+
const generateImagePromise = generateImageWithParameters( {
|
|
209
|
+
feature,
|
|
210
|
+
size: '1792x1024', // the size, when the generation happens with DALL-E-3
|
|
211
|
+
responseFormat: 'b64_json', // the response format, when the generation happens with DALL-E-3
|
|
212
|
+
messages: [
|
|
213
|
+
{
|
|
214
|
+
role: 'jetpack-ai',
|
|
215
|
+
context: {
|
|
216
|
+
type,
|
|
217
|
+
request: userPrompt ? userPrompt : null,
|
|
218
|
+
content: postContent,
|
|
219
|
+
style,
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
style: style || '',
|
|
224
|
+
} );
|
|
225
|
+
|
|
226
|
+
const name = getImageNameSuggestion( userPrompt );
|
|
227
|
+
|
|
228
|
+
generateImagePromise
|
|
229
|
+
.then( result => {
|
|
230
|
+
if ( result.data.length > 0 ) {
|
|
231
|
+
const image = 'data:image/png;base64,' + result.data[ 0 ].b64_json;
|
|
232
|
+
const prompt = userPrompt || null;
|
|
233
|
+
const revisedPrompt = result.data[ 0 ].revised_prompt || null;
|
|
234
|
+
updateImages( { image, prompt, revisedPrompt }, pointer.current );
|
|
235
|
+
updateRequestsCount();
|
|
236
|
+
saveToMediaLibrary( image, name )
|
|
237
|
+
.then( savedImage => {
|
|
238
|
+
showSnackbarNotice( __( 'Image saved to media library.', 'jetpack-ai-client' ) );
|
|
239
|
+
updateImages(
|
|
240
|
+
{ libraryId: savedImage?.id, libraryUrl: savedImage?.url, generating: false },
|
|
241
|
+
pointer.current
|
|
242
|
+
);
|
|
243
|
+
pointer.current += 1;
|
|
244
|
+
resolve( {
|
|
245
|
+
image,
|
|
246
|
+
libraryId: savedImage?.id,
|
|
247
|
+
libraryUrl: savedImage?.url,
|
|
248
|
+
revisedPrompt,
|
|
249
|
+
} );
|
|
250
|
+
} )
|
|
251
|
+
.catch( () => {
|
|
252
|
+
updateImages( { generating: false }, pointer.current );
|
|
253
|
+
pointer.current += 1;
|
|
254
|
+
resolve( { image } );
|
|
255
|
+
} );
|
|
256
|
+
}
|
|
257
|
+
} )
|
|
258
|
+
.catch( e => {
|
|
259
|
+
updateImages( { generating: false, error: e }, pointer.current );
|
|
260
|
+
reject( e );
|
|
261
|
+
} );
|
|
262
|
+
} );
|
|
263
|
+
},
|
|
264
|
+
[
|
|
265
|
+
updateImages,
|
|
266
|
+
generateImageWithParameters,
|
|
267
|
+
feature,
|
|
268
|
+
type,
|
|
269
|
+
updateRequestsCount,
|
|
270
|
+
saveToMediaLibrary,
|
|
271
|
+
showSnackbarNotice,
|
|
272
|
+
getImageNameSuggestion,
|
|
273
|
+
previousMediaId,
|
|
274
|
+
]
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const handlePreviousImage = useCallback( () => {
|
|
278
|
+
setCurrent( Math.max( current - 1, 0 ) );
|
|
279
|
+
}, [ current ] );
|
|
280
|
+
|
|
281
|
+
const handleNextImage = useCallback( () => {
|
|
282
|
+
setCurrent( Math.min( current + 1, images.length - 1 ) );
|
|
283
|
+
}, [ current, images.length ] );
|
|
284
|
+
|
|
285
|
+
const guessStyle = useCallback(
|
|
286
|
+
async function (
|
|
287
|
+
prompt: string,
|
|
288
|
+
requestType: string = '',
|
|
289
|
+
content: string = ''
|
|
290
|
+
): Promise< ImageStyle | null > {
|
|
291
|
+
if ( ! imageStyles || ! imageStyles.length ) {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const messages = [
|
|
296
|
+
{
|
|
297
|
+
role: 'jetpack-ai' as RoleType,
|
|
298
|
+
context: {
|
|
299
|
+
type: requestType || 'general-image-guess-style',
|
|
300
|
+
request: prompt,
|
|
301
|
+
content,
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
];
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
const style = await askQuestionSync( messages, { feature: 'jetpack-ai-image-generator' } );
|
|
308
|
+
|
|
309
|
+
if ( ! style ) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
const styleObject = imageStyles.find( ( { value } ) => value === style );
|
|
313
|
+
|
|
314
|
+
if ( ! styleObject ) {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return styleObject.value;
|
|
319
|
+
} catch ( error ) {
|
|
320
|
+
Promise.reject( error );
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
[ imageStyles ]
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
return {
|
|
327
|
+
current,
|
|
328
|
+
setCurrent,
|
|
329
|
+
processImageGeneration,
|
|
330
|
+
handlePreviousImage,
|
|
331
|
+
handleNextImage,
|
|
332
|
+
currentImage: images[ current ],
|
|
333
|
+
currentPointer: images[ pointer.current ],
|
|
334
|
+
images,
|
|
335
|
+
pointer,
|
|
336
|
+
imageStyles,
|
|
337
|
+
guessStyle,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { isAtomicSite, isSimpleSite } from '@automattic/jetpack-shared-extension-utils';
|
|
5
|
+
import { useState } from '@wordpress/element';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Hook to get the type of site.
|
|
9
|
+
*
|
|
10
|
+
* @return {string} - The type of site.
|
|
11
|
+
*/
|
|
12
|
+
export default function useSiteType() {
|
|
13
|
+
const getSiteType = () => {
|
|
14
|
+
if ( isAtomicSite() ) {
|
|
15
|
+
return 'atomic';
|
|
16
|
+
}
|
|
17
|
+
if ( isSimpleSite() ) {
|
|
18
|
+
return 'simple';
|
|
19
|
+
}
|
|
20
|
+
return 'jetpack';
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const [ siteType ] = useState( getSiteType() );
|
|
24
|
+
|
|
25
|
+
return siteType;
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import FeaturedImage from './featured-image.js';
|
|
2
|
+
import GeneralPurposeImage from './general-purpose-image.js';
|
|
3
|
+
import { PLACEMENT_MEDIA_SOURCE_DROPDOWN, PLACEMENT_BLOCK_PLACEHOLDER_BUTTON } from './types.js';
|
|
4
|
+
|
|
5
|
+
export {
|
|
6
|
+
FeaturedImage,
|
|
7
|
+
PLACEMENT_MEDIA_SOURCE_DROPDOWN,
|
|
8
|
+
PLACEMENT_BLOCK_PLACEHOLDER_BUTTON,
|
|
9
|
+
GeneralPurposeImage,
|
|
10
|
+
};
|