CYS: Improve opt in flow (#50529)
* CYS: Improve opt in flow * Add changefile(s) from automation for the following project(s): woocommerce * fix import * fix imports and remove not used functions --------- Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
parent
1160414b14
commit
1fbfa83fb4
|
@ -45,12 +45,12 @@ import { addFilter } from '@wordpress/hooks';
|
|||
import { CustomizeStoreComponent } from '../types';
|
||||
import { Layout } from './layout';
|
||||
import './style.scss';
|
||||
import { PreloadFonts } from './preload-fonts';
|
||||
import { GoBackWarningModal } from './go-back-warning-modal';
|
||||
import { onBackButtonClicked } from '../utils';
|
||||
import { getNewPath } from '@woocommerce/navigation';
|
||||
import useBodyClass from '../hooks/use-body-class';
|
||||
|
||||
import { OptInSubscribe } from './opt-in/opt-in';
|
||||
import { OptInContextProvider } from './opt-in/context';
|
||||
import './tracking';
|
||||
|
||||
const { RouterProvider } = unlock( routerPrivateApis );
|
||||
|
@ -181,12 +181,14 @@ export const AssemblerHub: CustomizeStoreComponent = ( props ) => {
|
|||
) }
|
||||
<CustomizeStoreContext.Provider value={ props }>
|
||||
<ShortcutProvider style={ { height: '100%' } }>
|
||||
<GlobalStylesProvider>
|
||||
<RouterProvider>
|
||||
<Layout />
|
||||
</RouterProvider>
|
||||
<PreloadFonts />
|
||||
</GlobalStylesProvider>
|
||||
<OptInContextProvider>
|
||||
<GlobalStylesProvider>
|
||||
<RouterProvider>
|
||||
<Layout />
|
||||
</RouterProvider>
|
||||
<OptInSubscribe />
|
||||
</GlobalStylesProvider>
|
||||
</OptInContextProvider>
|
||||
</ShortcutProvider>
|
||||
</CustomizeStoreContext.Provider>
|
||||
</>
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import React, { createContext, useState } from '@wordpress/element';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export const enum OPTIN_FLOW_STATUS {
|
||||
'IDLE' = 'IDLE',
|
||||
'LOADING' = 'LOADING',
|
||||
'DONE' = 'DONE',
|
||||
}
|
||||
|
||||
export const OptInContext = createContext< {
|
||||
optInFlowStatus: OPTIN_FLOW_STATUS;
|
||||
setOptInFlowStatus: ( status: OPTIN_FLOW_STATUS ) => void;
|
||||
} >( {
|
||||
optInFlowStatus: OPTIN_FLOW_STATUS.IDLE,
|
||||
setOptInFlowStatus: () => {},
|
||||
} );
|
||||
|
||||
export const OptInContextProvider = ( {
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
} ) => {
|
||||
const isAllowTrackingEnabled = useSelect(
|
||||
( select ) =>
|
||||
select( OPTIONS_STORE_NAME ).getOption(
|
||||
'woocommerce_allow_tracking'
|
||||
) === 'yes',
|
||||
[]
|
||||
);
|
||||
|
||||
const [ optInFlowStatus, setOptInFlowStatus ] =
|
||||
useState< OPTIN_FLOW_STATUS >(
|
||||
isAllowTrackingEnabled
|
||||
? OPTIN_FLOW_STATUS.DONE
|
||||
: OPTIN_FLOW_STATUS.IDLE
|
||||
);
|
||||
|
||||
return (
|
||||
<OptInContext.Provider
|
||||
value={ {
|
||||
optInFlowStatus,
|
||||
setOptInFlowStatus,
|
||||
} }
|
||||
>
|
||||
{ children }
|
||||
</OptInContext.Provider>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { resolveSelect, select, subscribe, useDispatch } from '@wordpress/data';
|
||||
import { useContext, useEffect } from '@wordpress/element';
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
// eslint-disable-next-line @woocommerce/dependency-group
|
||||
import { store as coreStore } from '@wordpress/core-data';
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
// eslint-disable-next-line @woocommerce/dependency-group
|
||||
import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
// eslint-disable-next-line @woocommerce/dependency-group
|
||||
import { unlock } from '@wordpress/edit-site/build-module/lock-unlock';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { FontFamily, FontFace } from '../../types/font';
|
||||
import { usePatterns } from '../hooks/use-patterns';
|
||||
import { installFontFamilies } from '../utils/fonts';
|
||||
import { FONT_FAMILIES_TO_INSTALL } from '../sidebar/global-styles/font-pairing-variations/constants';
|
||||
import { OptInContext, OPTIN_FLOW_STATUS } from './context';
|
||||
|
||||
const { useGlobalSetting } = unlock( blockEditorPrivateApis );
|
||||
|
||||
export const OptInSubscribe = () => {
|
||||
const { setOptInFlowStatus } = useContext( OptInContext );
|
||||
|
||||
const [ enabledFontFamilies, setFontFamilies ]: [
|
||||
{
|
||||
custom: Array< FontFamily >;
|
||||
theme: Array< FontFamily >;
|
||||
},
|
||||
( font: {
|
||||
custom: Array< FontFamily >;
|
||||
theme: Array< FontFamily >;
|
||||
} ) => void
|
||||
] = useGlobalSetting( 'typography.fontFamilies' );
|
||||
|
||||
const {
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
__experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits,
|
||||
} = useDispatch( coreStore );
|
||||
|
||||
const installPatterns = async () => {
|
||||
await apiFetch< {
|
||||
success: boolean;
|
||||
} >( {
|
||||
path: `/wc/private/patterns`,
|
||||
method: 'POST',
|
||||
} );
|
||||
};
|
||||
|
||||
const installFonts = async () => {
|
||||
await installFontFamilies();
|
||||
|
||||
const globalStylesId =
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
select( coreStore ).__experimentalGetCurrentGlobalStylesId();
|
||||
|
||||
const installedFontFamilies = ( await resolveSelect(
|
||||
coreStore
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
).getEntityRecords( 'postType', 'wp_font_family', {
|
||||
_embed: true,
|
||||
per_page: -1,
|
||||
} ) ) as Array< {
|
||||
id: number;
|
||||
font_family_settings: FontFamily;
|
||||
_embedded: {
|
||||
font_faces: Array< {
|
||||
font_face_settings: FontFace;
|
||||
} >;
|
||||
};
|
||||
} >;
|
||||
|
||||
const parsedInstalledFontFamilies = ( installedFontFamilies || [] ).map(
|
||||
( fontFamilyPost ) => {
|
||||
return {
|
||||
id: fontFamilyPost.id,
|
||||
...fontFamilyPost.font_family_settings,
|
||||
fontFace:
|
||||
fontFamilyPost?._embedded?.font_faces.map(
|
||||
( face ) => face.font_face_settings
|
||||
) || [],
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const { custom } = enabledFontFamilies;
|
||||
|
||||
const enabledFontSlugs = [
|
||||
...( custom ? custom.map( ( font ) => font.slug ) : [] ),
|
||||
];
|
||||
|
||||
const fontFamiliesToEnable = parsedInstalledFontFamilies.reduce(
|
||||
( acc, font ) => {
|
||||
if (
|
||||
enabledFontSlugs.includes( font.slug ) ||
|
||||
FONT_FAMILIES_TO_INSTALL[ font.slug ] === undefined
|
||||
) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
...font,
|
||||
},
|
||||
];
|
||||
},
|
||||
[] as Array< FontFamily >
|
||||
);
|
||||
|
||||
setFontFamilies( {
|
||||
...enabledFontFamilies,
|
||||
custom: [
|
||||
...( enabledFontFamilies.custom ?? [] ),
|
||||
...( fontFamiliesToEnable ?? [] ),
|
||||
],
|
||||
} );
|
||||
|
||||
saveSpecifiedEntityEdits( 'root', 'globalStyles', globalStylesId, [
|
||||
'settings.typography.fontFamilies',
|
||||
] );
|
||||
};
|
||||
|
||||
const { invalidateCache } = usePatterns();
|
||||
|
||||
useEffect( () => {
|
||||
const unsubscribe = subscribe( async () => {
|
||||
const isOptedIn =
|
||||
select( OPTIONS_STORE_NAME ).getOption(
|
||||
'woocommerce_allow_tracking'
|
||||
) === 'yes';
|
||||
|
||||
if ( isOptedIn ) {
|
||||
setOptInFlowStatus( OPTIN_FLOW_STATUS.LOADING );
|
||||
await installPatterns();
|
||||
invalidateCache();
|
||||
await installFonts();
|
||||
|
||||
setOptInFlowStatus( OPTIN_FLOW_STATUS.DONE );
|
||||
|
||||
unsubscribe();
|
||||
}
|
||||
// @ts-expect-error The type is not updated.
|
||||
}, OPTIONS_STORE_NAME );
|
||||
|
||||
return () => {
|
||||
unsubscribe();
|
||||
};
|
||||
// We don't want to run this effect on every render, only once because it is a subscription.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [] );
|
||||
|
||||
return null;
|
||||
};
|
|
@ -2,9 +2,6 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
import { store as coreStore } from '@wordpress/core-data';
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
import {
|
||||
privateApis as blockEditorPrivateApis,
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
@ -16,26 +13,18 @@ import { unlock } from '@wordpress/edit-site/build-module/lock-unlock';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
FONT_PAIRINGS,
|
||||
FONT_FAMILIES_TO_INSTALL,
|
||||
} from './sidebar/global-styles/font-pairing-variations/constants';
|
||||
import { FONT_PAIRINGS } from './sidebar/global-styles/font-pairing-variations/constants';
|
||||
import { FontFamiliesLoader } from './sidebar/global-styles/font-pairing-variations/font-families-loader';
|
||||
import { useContext, useEffect, useMemo } from '@wordpress/element';
|
||||
import { FontFace, FontFamily } from '../types/font';
|
||||
import { useContext, useMemo } from '@wordpress/element';
|
||||
import { FontFamily } from '../types/font';
|
||||
import { FontFamiliesLoaderDotCom } from './sidebar/global-styles/font-pairing-variations/font-families-loader-dot-com';
|
||||
import { CustomizeStoreContext } from '.';
|
||||
import { isAIFlow, isNoAIFlow } from '../guards';
|
||||
|
||||
const { useGlobalSetting } = unlock( blockEditorPrivateApis );
|
||||
|
||||
let areFontsPreloaded = false;
|
||||
|
||||
export const PreloadFonts = () => {
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
const { __experimentalSaveSpecifiedEntityEdits: saveSpecifiedEntityEdits } =
|
||||
useDispatch( coreStore );
|
||||
const [ enabledFontFamilies, setFontFamilies ]: [
|
||||
const [ enabledFontFamilies ]: [
|
||||
{
|
||||
custom: Array< FontFamily >;
|
||||
theme: Array< FontFamily >;
|
||||
|
@ -55,99 +44,6 @@ export const PreloadFonts = () => {
|
|||
|
||||
const { context } = useContext( CustomizeStoreContext );
|
||||
|
||||
const { globalStylesId, installedFontFamilies } = useSelect( ( select ) => {
|
||||
// @ts-expect-error No types for this exist yet.
|
||||
const { __experimentalGetCurrentGlobalStylesId, getEntityRecords } =
|
||||
select( coreStore );
|
||||
return {
|
||||
globalStylesId: __experimentalGetCurrentGlobalStylesId(),
|
||||
installedFontFamilies: getEntityRecords(
|
||||
'postType',
|
||||
'wp_font_family',
|
||||
{ _embed: true, per_page: -1 }
|
||||
) as Array< {
|
||||
id: number;
|
||||
font_family_settings: FontFamily;
|
||||
_embedded: {
|
||||
font_faces: Array< {
|
||||
font_face_settings: FontFace;
|
||||
} >;
|
||||
};
|
||||
} >,
|
||||
};
|
||||
} );
|
||||
|
||||
const parsedInstalledFontFamilies = useMemo( () => {
|
||||
return (
|
||||
( installedFontFamilies || [] ).map( ( fontFamilyPost ) => {
|
||||
return {
|
||||
id: fontFamilyPost.id,
|
||||
...fontFamilyPost.font_family_settings,
|
||||
fontFace:
|
||||
fontFamilyPost?._embedded?.font_faces.map(
|
||||
( face ) => face.font_face_settings
|
||||
) || [],
|
||||
};
|
||||
} ) || []
|
||||
);
|
||||
}, [ installedFontFamilies ] );
|
||||
|
||||
useEffect( () => {
|
||||
if (
|
||||
areFontsPreloaded ||
|
||||
installedFontFamilies === null ||
|
||||
enabledFontFamilies === null
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { custom } = enabledFontFamilies;
|
||||
|
||||
const enabledFontSlugs = [
|
||||
...( custom ? custom.map( ( font ) => font.slug ) : [] ),
|
||||
];
|
||||
|
||||
const fontFamiliesToEnable = parsedInstalledFontFamilies.reduce(
|
||||
( acc, font ) => {
|
||||
if (
|
||||
enabledFontSlugs.includes( font.slug ) ||
|
||||
FONT_FAMILIES_TO_INSTALL[ font.slug ] === undefined
|
||||
) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
return [
|
||||
...acc,
|
||||
{
|
||||
...font,
|
||||
},
|
||||
];
|
||||
},
|
||||
[] as Array< FontFamily >
|
||||
);
|
||||
|
||||
setFontFamilies( {
|
||||
...enabledFontFamilies,
|
||||
custom: [
|
||||
...( enabledFontFamilies.custom ?? [] ),
|
||||
...( fontFamiliesToEnable ?? [] ),
|
||||
],
|
||||
} );
|
||||
|
||||
saveSpecifiedEntityEdits( 'root', 'globalStyles', globalStylesId, [
|
||||
'settings.typography.fontFamilies',
|
||||
] );
|
||||
|
||||
areFontsPreloaded = true;
|
||||
}, [
|
||||
enabledFontFamilies,
|
||||
globalStylesId,
|
||||
installedFontFamilies,
|
||||
parsedInstalledFontFamilies,
|
||||
saveSpecifiedEntityEdits,
|
||||
setFontFamilies,
|
||||
] );
|
||||
|
||||
const allFontChoices = FONT_PAIRINGS.map(
|
||||
( fontPair ) => fontPair?.settings?.typography?.fontFamilies?.theme
|
||||
);
|
||||
|
|
|
@ -30,6 +30,10 @@ import { CustomizeStoreContext } from '~/customize-store/assembler-hub';
|
|||
import { FlowType } from '~/customize-store/types';
|
||||
import { FontFamily } from './font-families-loader-dot-com';
|
||||
import { isAIFlow } from '~/customize-store/guards';
|
||||
import {
|
||||
OptInContext,
|
||||
OPTIN_FLOW_STATUS,
|
||||
} from '~/customize-store/assembler-hub/opt-in/context';
|
||||
|
||||
export const FontPairing = () => {
|
||||
const { aiSuggestions, isLoading } = useSelect( ( select ) => {
|
||||
|
@ -72,6 +76,8 @@ export const FontPairing = () => {
|
|||
) === 'yes'
|
||||
);
|
||||
|
||||
const { optInFlowStatus } = useContext( OptInContext );
|
||||
|
||||
const fontPairings = useMemo( () => {
|
||||
if ( isAIFlow( context.flowType ) ) {
|
||||
return aiOnline && aiSuggestions?.lookAndFeel
|
||||
|
@ -106,7 +112,15 @@ export const FontPairing = () => {
|
|||
}
|
||||
);
|
||||
|
||||
if ( ! trackingAllowed || ! isFontLibraryAvailable ) {
|
||||
// We only show the default fonts when:
|
||||
// - user did not allow tracking
|
||||
// - site doesn't have the Font Library available
|
||||
// - opt-in flow is still processing
|
||||
if (
|
||||
! trackingAllowed ||
|
||||
! isFontLibraryAvailable ||
|
||||
optInFlowStatus !== OPTIN_FLOW_STATUS.DONE
|
||||
) {
|
||||
return defaultFonts;
|
||||
}
|
||||
|
||||
|
@ -134,14 +148,15 @@ export const FontPairing = () => {
|
|||
}, [
|
||||
aiOnline,
|
||||
aiSuggestions?.lookAndFeel,
|
||||
baseFontFamilies,
|
||||
baseFontFamilies.theme,
|
||||
context.flowType,
|
||||
custom,
|
||||
isFontLibraryAvailable,
|
||||
optInFlowStatus,
|
||||
trackingAllowed,
|
||||
] );
|
||||
|
||||
if ( isLoading ) {
|
||||
if ( isLoading || optInFlowStatus === OPTIN_FLOW_STATUS.LOADING ) {
|
||||
return (
|
||||
<div className="woocommerce-customize-store_font-pairing-spinner-container">
|
||||
<Spinner />
|
||||
|
|
|
@ -163,7 +163,7 @@ export const SidebarNavigationScreenHomepagePTK = ( {
|
|||
const [ optInDataSharing, setIsOptInDataSharing ] =
|
||||
useState< boolean >( true );
|
||||
|
||||
const [ isFetchingPatterns, setIsFetchingPatterns ] = useState( false );
|
||||
const [ isSettingTracking, setIsSettingTracking ] = useState( false );
|
||||
|
||||
const optIn = () => {
|
||||
trackEvent(
|
||||
|
@ -324,25 +324,18 @@ export const SidebarNavigationScreenHomepagePTK = ( {
|
|||
onClick={ async () => {
|
||||
optIn();
|
||||
await enableTracking();
|
||||
setIsFetchingPatterns(
|
||||
setIsSettingTracking(
|
||||
true
|
||||
);
|
||||
await apiFetch< {
|
||||
success: boolean;
|
||||
} >( {
|
||||
path: `/wc/private/patterns`,
|
||||
method: 'POST',
|
||||
} );
|
||||
invalidateCache();
|
||||
closeModal();
|
||||
setIsFetchingPatterns(
|
||||
setIsSettingTracking(
|
||||
false
|
||||
);
|
||||
} }
|
||||
variant="primary"
|
||||
disabled={ ! optInDataSharing }
|
||||
>
|
||||
{ isFetchingPatterns ? (
|
||||
{ isSettingTracking ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
__(
|
||||
|
|
|
@ -24,7 +24,6 @@ import { FontPairing } from '../global-styles';
|
|||
import { CustomizeStoreContext } from '../..';
|
||||
import { FlowType } from '~/customize-store/types';
|
||||
import { trackEvent } from '~/customize-store/tracking';
|
||||
import { installFontFamilies } from '../../utils/fonts';
|
||||
import { enableTracking } from '~/customize-store/design-without-ai/services';
|
||||
|
||||
export const SidebarNavigationScreenTypography = ( {
|
||||
|
@ -91,7 +90,7 @@ export const SidebarNavigationScreenTypography = ( {
|
|||
const openModal = () => setIsModalOpen( true );
|
||||
const closeModal = () => setIsModalOpen( false );
|
||||
|
||||
const [ isFetchingFonts, setIsFetchingFonts ] = useState( false );
|
||||
const [ isSettingTracking, setIsSettingTracking ] = useState( false );
|
||||
|
||||
const [ OptInDataSharing, setIsOptInDataSharing ] =
|
||||
useState< boolean >( true );
|
||||
|
@ -175,17 +174,15 @@ export const SidebarNavigationScreenTypography = ( {
|
|||
<Button
|
||||
onClick={ async () => {
|
||||
optIn();
|
||||
setIsFetchingFonts( true );
|
||||
await enableTracking();
|
||||
await installFontFamilies();
|
||||
|
||||
closeModal();
|
||||
setIsFetchingFonts( false );
|
||||
setIsSettingTracking( false );
|
||||
} }
|
||||
variant="primary"
|
||||
disabled={ ! OptInDataSharing }
|
||||
>
|
||||
{ isFetchingFonts ? (
|
||||
{ isSettingTracking ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
__( 'Opt in', 'woocommerce' )
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: fix
|
||||
|
||||
CYS: Improve opt in flow
|
Loading…
Reference in New Issue