@automattic/jetpack-ai-client 0.16.4 → 0.18.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.
Files changed (43) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/build/components/ai-control/extension-ai-control.d.ts +2 -1
  3. package/build/components/ai-control/extension-ai-control.js +5 -2
  4. package/build/components/message/index.d.ts +6 -0
  5. package/build/components/message/index.js +13 -0
  6. package/build/jwt/index.js +1 -1
  7. package/build/logo-generator/components/fair-usage-notice.d.ts +11 -0
  8. package/build/logo-generator/components/fair-usage-notice.js +19 -0
  9. package/build/logo-generator/components/generator-modal.js +13 -6
  10. package/build/logo-generator/components/history-carousel.js +6 -5
  11. package/build/logo-generator/components/logo-presenter.js +8 -3
  12. package/build/logo-generator/components/prompt.js +5 -4
  13. package/build/logo-generator/hooks/use-checkout.js +3 -2
  14. package/build/logo-generator/hooks/use-fair-usage-notice-message.d.ts +3 -0
  15. package/build/logo-generator/hooks/use-fair-usage-notice-message.js +43 -0
  16. package/build/logo-generator/hooks/use-logo-generator.d.ts +3 -0
  17. package/build/logo-generator/hooks/use-logo-generator.js +7 -2
  18. package/build/logo-generator/store/actions.d.ts +4 -0
  19. package/build/logo-generator/store/actions.js +8 -1
  20. package/build/logo-generator/store/constants.d.ts +1 -0
  21. package/build/logo-generator/store/constants.js +1 -0
  22. package/build/logo-generator/store/reducer.d.ts +37 -0
  23. package/build/logo-generator/store/reducer.js +10 -1
  24. package/build/logo-generator/store/selectors.d.ts +14 -0
  25. package/build/logo-generator/store/selectors.js +21 -0
  26. package/build/logo-generator/store/types.d.ts +13 -0
  27. package/package.json +13 -13
  28. package/src/components/ai-control/extension-ai-control.tsx +10 -1
  29. package/src/components/message/index.tsx +20 -0
  30. package/src/jwt/index.ts +1 -2
  31. package/src/logo-generator/components/fair-usage-notice.tsx +38 -0
  32. package/src/logo-generator/components/generator-modal.tsx +24 -7
  33. package/src/logo-generator/components/history-carousel.tsx +8 -1
  34. package/src/logo-generator/components/logo-presenter.tsx +16 -5
  35. package/src/logo-generator/components/prompt.tsx +8 -4
  36. package/src/logo-generator/hooks/use-checkout.ts +7 -2
  37. package/src/logo-generator/hooks/use-fair-usage-notice-message.tsx +68 -0
  38. package/src/logo-generator/hooks/use-logo-generator.ts +8 -0
  39. package/src/logo-generator/store/actions.ts +9 -0
  40. package/src/logo-generator/store/constants.ts +1 -0
  41. package/src/logo-generator/store/reducer.ts +12 -0
  42. package/src/logo-generator/store/selectors.ts +24 -0
  43. package/src/logo-generator/store/types.ts +13 -0
@@ -20,10 +20,11 @@ import type { Selectors } from '../store/types.js';
20
20
  const debug = debugFactory( 'ai-client:logo-generator:use-checkout' );
21
21
 
22
22
  export const useCheckout = () => {
23
- const { nextTier } = useSelect( select => {
23
+ const { nextTier, tierPlansEnabled } = useSelect( select => {
24
24
  const selectors: Selectors = select( STORE_NAME );
25
25
  return {
26
26
  nextTier: selectors.getAiAssistantFeature().nextTier,
27
+ tierPlansEnabled: selectors.getAiAssistantFeature().tierPlansEnabled,
27
28
  };
28
29
  }, [] );
29
30
 
@@ -33,7 +34,11 @@ export const useCheckout = () => {
33
34
  const wpcomCheckoutUrl = new URL( `https://jetpack.com/redirect/` );
34
35
  wpcomCheckoutUrl.searchParams.set( 'source', 'jetpack-ai-yearly-tier-upgrade-nudge' );
35
36
  wpcomCheckoutUrl.searchParams.set( 'site', getSiteFragment() as string );
36
- wpcomCheckoutUrl.searchParams.set( 'path', `jetpack_ai_yearly:-q-${ nextTier?.limit }` );
37
+
38
+ wpcomCheckoutUrl.searchParams.set(
39
+ 'path',
40
+ tierPlansEnabled ? `jetpack_ai_yearly:-q-${ nextTier?.limit }` : 'jetpack_ai_yearly'
41
+ );
37
42
 
38
43
  /**
39
44
  * Open the product interstitial page
@@ -0,0 +1,68 @@
1
+ import { useSelect } from '@wordpress/data';
2
+ import { createInterpolateElement } from '@wordpress/element';
3
+ import { __, sprintf } from '@wordpress/i18n';
4
+ /**
5
+ * Internal dependencies
6
+ */
7
+ import { STORE_NAME } from '../store/index.js';
8
+ /**
9
+ * Types
10
+ */
11
+ import type { Selectors } from '../store/types.js';
12
+
13
+ const useFairUsageNoticeMessage = () => {
14
+ const { usagePeriod } = useSelect( select => {
15
+ const selectors: Selectors = select( STORE_NAME );
16
+ return {
17
+ usagePeriod: selectors.getAiAssistantFeature().nextTier,
18
+ };
19
+ }, [] );
20
+ const getFormattedUsagePeriodStartDate = planUsagePeriod => {
21
+ if ( ! planUsagePeriod?.nextStart ) {
22
+ return null;
23
+ }
24
+
25
+ const nextUsagePeriodStartDate = new Date( planUsagePeriod.nextStart );
26
+ return (
27
+ nextUsagePeriodStartDate.toLocaleString( 'default', { month: 'long' } ) +
28
+ ' ' +
29
+ nextUsagePeriodStartDate.getDate()
30
+ );
31
+ };
32
+
33
+ const getFairUsageNoticeMessage = resetDateString => {
34
+ const fairUsageMessage = __(
35
+ "You've reached this month's request limit, per our <link>fair usage policy</link>.",
36
+ 'jetpack-ai-client'
37
+ );
38
+
39
+ if ( ! resetDateString ) {
40
+ return fairUsageMessage;
41
+ }
42
+
43
+ // Translators: %s is the date when the requests will reset.
44
+ const dateMessage = __( 'Requests will reset on %s.', 'jetpack-ai-client' );
45
+ const formattedDateMessage = sprintf( dateMessage, resetDateString );
46
+
47
+ return `${ fairUsageMessage } ${ formattedDateMessage }`;
48
+ };
49
+
50
+ const nextUsagePeriodStartDateString = getFormattedUsagePeriodStartDate( usagePeriod );
51
+
52
+ // Get the proper template based on the presence of the next usage period start date.
53
+ const fairUsageNoticeMessage = getFairUsageNoticeMessage( nextUsagePeriodStartDateString );
54
+
55
+ const fairUsageNoticeMessageElement = createInterpolateElement( fairUsageNoticeMessage, {
56
+ link: (
57
+ <a
58
+ href="https://jetpack.com/redirect/?source=ai-logo-generator-fair-usage-policy"
59
+ target="_blank"
60
+ rel="noreferrer"
61
+ />
62
+ ),
63
+ } );
64
+
65
+ return fairUsageNoticeMessageElement;
66
+ };
67
+
68
+ export default useFairUsageNoticeMessage;
@@ -31,6 +31,7 @@ const useLogoGenerator = () => {
31
31
  increaseAiAssistantRequestsCount,
32
32
  addLogoToHistory,
33
33
  setContext,
34
+ setIsLoadingHistory,
34
35
  } = useDispatch( STORE_NAME );
35
36
 
36
37
  const {
@@ -46,6 +47,8 @@ const useLogoGenerator = () => {
46
47
  getAiAssistantFeature,
47
48
  requireUpgrade,
48
49
  context,
50
+ tierPlansEnabled,
51
+ isLoadingHistory,
49
52
  } = useSelect( select => {
50
53
  const selectors: Selectors = select( STORE_NAME );
51
54
 
@@ -62,6 +65,8 @@ const useLogoGenerator = () => {
62
65
  getAiAssistantFeature: selectors.getAiAssistantFeature,
63
66
  requireUpgrade: selectors.getRequireUpgrade(),
64
67
  context: selectors.getContext(),
68
+ tierPlansEnabled: selectors.getTierPlansEnabled(),
69
+ isLoadingHistory: selectors.getIsLoadingHistory(),
65
70
  };
66
71
  }, [] );
67
72
 
@@ -383,6 +388,9 @@ User request:${ prompt }`;
383
388
  getAiAssistantFeature,
384
389
  requireUpgrade,
385
390
  context,
391
+ tierPlansEnabled,
392
+ isLoadingHistory,
393
+ setIsLoadingHistory,
386
394
  };
387
395
  };
388
396
 
@@ -28,6 +28,7 @@ import {
28
28
  ACTION_SET_LOGO_UPDATE_ERROR,
29
29
  ACTION_SET_SAVE_TO_LIBRARY_ERROR,
30
30
  ACTION_SET_CONTEXT,
31
+ ACTION_SET_IS_LOADING_HISTORY,
31
32
  } from './constants.js';
32
33
  import type {
33
34
  AiFeatureProps,
@@ -64,6 +65,7 @@ export function mapAiFeatureResponseToAiFeatureProps(
64
65
  nextTier: response[ 'next-tier' ],
65
66
  tierPlansEnabled: !! response[ 'tier-plans-enabled' ],
66
67
  costs: response.costs,
68
+ featuresControl: response[ 'features-control' ],
67
69
  };
68
70
  }
69
71
 
@@ -246,6 +248,13 @@ const actions = {
246
248
  context,
247
249
  };
248
250
  },
251
+
252
+ setIsLoadingHistory( isLoadingHistory: boolean ) {
253
+ return {
254
+ type: ACTION_SET_IS_LOADING_HISTORY,
255
+ isLoadingHistory,
256
+ };
257
+ },
249
258
  };
250
259
 
251
260
  export default actions;
@@ -37,6 +37,7 @@ export const ACTION_SAVE_SELECTED_LOGO = 'SAVE_SELECTED_LOGO';
37
37
  export const ACTION_SET_IS_REQUESTING_IMAGE = 'SET_IS_REQUESTING_IMAGE';
38
38
  export const ACTION_SET_IS_ENHANCING_PROMPT = 'SET_IS_ENHANCING_PROMPT';
39
39
  export const ACTION_SET_SITE_HISTORY = 'SET_SITE_HISTORY';
40
+ export const ACTION_SET_IS_LOADING_HISTORY = 'SET_IS_LOADING_HISTORY';
40
41
 
41
42
  /**
42
43
  * Logo generator error actions
@@ -27,6 +27,7 @@ import {
27
27
  ACTION_SET_SAVE_TO_LIBRARY_ERROR,
28
28
  ACTION_SET_LOGO_UPDATE_ERROR,
29
29
  ACTION_SET_CONTEXT,
30
+ ACTION_SET_IS_LOADING_HISTORY,
30
31
  } from './constants.js';
31
32
  import INITIAL_STATE from './initial-state.js';
32
33
  import type {
@@ -61,6 +62,7 @@ import type { SiteDetails } from '../types.js';
61
62
  * @param {Array< { url: string; description: string; mediaId?: number } >} action.history - The logo history
62
63
  * @param {RequestError} action.error - The error to set
63
64
  * @param {string} action.context - The context where the tool is being used
65
+ * @param {boolean} action.isLoadingHistory - Whether the history is being loaded
64
66
  * @return {LogoGeneratorStateProp} The new state
65
67
  */
66
68
  export default function reducer(
@@ -83,6 +85,7 @@ export default function reducer(
83
85
  history?: Array< { url: string; description: string; mediaId?: number } >;
84
86
  error?: RequestError;
85
87
  context?: string;
88
+ isLoadingHistory?: boolean;
86
89
  }
87
90
  ) {
88
91
  switch ( action.type ) {
@@ -381,6 +384,15 @@ export default function reducer(
381
384
  context: action.context,
382
385
  },
383
386
  };
387
+
388
+ case ACTION_SET_IS_LOADING_HISTORY:
389
+ return {
390
+ ...state,
391
+ _meta: {
392
+ ...( state._meta ?? {} ),
393
+ isLoadingHistory: action.isLoadingHistory,
394
+ },
395
+ };
384
396
  }
385
397
 
386
398
  return state;
@@ -121,6 +121,10 @@ const selectors = {
121
121
  */
122
122
  getRequireUpgrade( state: LogoGeneratorStateProp ): boolean {
123
123
  const feature = state.features.aiAssistantFeature;
124
+
125
+ if ( ! feature?.tierPlansEnabled ) {
126
+ return feature?.requireUpgrade;
127
+ }
124
128
  const logoCost = feature?.costs?.[ 'jetpack-ai-logo-generator' ]?.logo ?? DEFAULT_LOGO_COST;
125
129
  const currentLimit = feature?.currentTier?.value || 0;
126
130
  const currentUsage = feature?.usagePeriod?.requestsCount || 0;
@@ -196,6 +200,26 @@ const selectors = {
196
200
  getContext( state: LogoGeneratorStateProp ): string {
197
201
  return state._meta?.context ?? '';
198
202
  },
203
+
204
+ /**
205
+ * Get tier plans enabled status.
206
+ *
207
+ * @param {LogoGeneratorStateProp} state - The app state tree.
208
+ * @return {boolean} The tier plans enabled status.
209
+ */
210
+ getTierPlansEnabled( state: LogoGeneratorStateProp ): boolean {
211
+ return state.features.aiAssistantFeature?.tierPlansEnabled ?? false;
212
+ },
213
+
214
+ /**
215
+ * Get tier plans enabled status.
216
+ *
217
+ * @param {LogoGeneratorStateProp} state - The app state tree.
218
+ * @return {boolean} The loading logo history status.
219
+ */
220
+ getIsLoadingHistory( state: LogoGeneratorStateProp ): boolean {
221
+ return state._meta?.isLoadingHistory ?? false;
222
+ },
199
223
  };
200
224
 
201
225
  export default selectors;
@@ -88,6 +88,14 @@ export type TierValueProp =
88
88
  | Tier750Props[ 'value' ]
89
89
  | Tier1000Props[ 'value' ];
90
90
 
91
+ export type FeatureControl = {
92
+ enabled: boolean;
93
+ 'min-jetpack-version': string;
94
+ [ key: string ]: FeatureControl | boolean | string;
95
+ };
96
+
97
+ export type FeaturesControl = { [ key: string ]: FeatureControl };
98
+
91
99
  export type AiFeatureProps = {
92
100
  hasFeature: boolean;
93
101
  isOverLimit: boolean;
@@ -110,6 +118,7 @@ export type AiFeatureProps = {
110
118
  logo: number;
111
119
  };
112
120
  };
121
+ featuresControl?: FeaturesControl;
113
122
  };
114
123
 
115
124
  // Type used in the `wordpress-com/plans` store.
@@ -143,6 +152,7 @@ export type LogoGeneratorStateProp = {
143
152
  saveToLibraryError?: RequestError;
144
153
  logoUpdateError?: RequestError;
145
154
  context: string;
155
+ isLoadingHistory: boolean;
146
156
  };
147
157
  siteDetails?: SiteDetails | Record< string, never >;
148
158
  features: {
@@ -172,6 +182,8 @@ export type Selectors = {
172
182
  getSaveToLibraryError(): RequestError;
173
183
  getLogoUpdateError(): RequestError;
174
184
  getContext(): string;
185
+ getTierPlansEnabled(): boolean;
186
+ getIsLoadingHistory(): boolean;
175
187
  };
176
188
 
177
189
  /*
@@ -202,6 +214,7 @@ export type AiAssistantFeatureEndpointResponseProps = {
202
214
  logo: number;
203
215
  };
204
216
  };
217
+ 'features-control'?: FeaturesControl;
205
218
  };
206
219
 
207
220
  export type SaveLogo = ( logo: Logo ) => Promise< { mediaId: number; mediaURL: string } >;