From 50ac86a8d530c8673e9ce5f3eeadbca437c40d98 Mon Sep 17 00:00:00 2001 From: Jason Crist Date: Thu, 11 Jan 2024 12:06:31 -0500 Subject: [PATCH] Download then upload font face assets when installing from a collection (#57694) * Download then upload font face assets when installing from a collection * Add error handling to font download-then-upload * Check for downloadFromUrl property before downloading to upload * Simplify downloadFontFaceAsset and move to utils. * Add error handling to downloadFontFaceAsset * Use Promise.all to handle multiple asynchronous font face downloads. > > Co-authored-by: Sarah Norris --------- Co-authored-by: Jeff Ong Co-authored-by: Sarah Norris --- .../font-library-modal/font-collection.js | 30 +++++++++++++++- .../font-library-modal/utils/index.js | 35 +++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js index fc39e2e0096531..f7f33032f1e3f5 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/font-collection.js @@ -31,6 +31,7 @@ import { toggleFont } from './utils/toggleFont'; import { getFontsOutline } from './utils/fonts-outline'; import GoogleFontsConfirmDialog from './google-fonts-confirm-dialog'; import { getNoticeFromInstallResponse } from './utils/get-notice-from-response'; +import { downloadFontFaceAsset } from './utils'; const DEFAULT_CATEGORY = { id: 'all', @@ -154,7 +155,34 @@ function FontCollection( { id } ) { }; const handleInstall = async () => { - const response = await installFont( fontsToInstall[ 0 ] ); + const fontFamily = fontsToInstall[ 0 ]; + + try { + if ( fontFamily?.fontFace ) { + await Promise.all( + fontFamily.fontFace.map( async ( fontFace ) => { + if ( fontFace.downloadFromUrl ) { + fontFace.file = await downloadFontFaceAsset( + fontFace.downloadFromUrl + ); + delete fontFace.downloadFromUrl; + } + } ) + ); + } + } catch ( error ) { + // If any of the fonts fail to download, + // show an error notice and stop the request from being sent. + setNotice( { + type: 'error', + message: __( + 'Error installing the fonts, could not be downloaded.' + ), + } ); + return; + } + + const response = await installFont( fontFamily ); const installNotice = getNoticeFromInstallResponse( response ); setNotice( installNotice ); resetFontsToInstall(); diff --git a/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js b/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js index 2874dd446efb45..0aa0f7edb4aec9 100644 --- a/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js +++ b/packages/edit-site/src/components/global-styles/font-library-modal/utils/index.js @@ -9,6 +9,11 @@ import { privateApis as componentsPrivateApis } from '@wordpress/components'; import { FONT_WEIGHTS, FONT_STYLES } from './constants'; import { unlock } from '../../../../lock-unlock'; +/** + * Browser dependencies + */ +const { File } = window; + export function setUIValuesNeeded( font, extraValues = {} ) { if ( ! font.name && ( font.fontFamily || font.slug ) ) { font.name = font.fontFamily || font.slug; @@ -164,3 +169,33 @@ export function makeFormDataFromFontFamily( fontFamily ) { formData.append( 'font_family_settings', JSON.stringify( newFontFamily ) ); return formData; } + +/* + * Downloads a font face asset from a URL to the client and returns a File object. + */ +export async function downloadFontFaceAsset( url ) { + return fetch( new Request( url ) ) + .then( ( response ) => { + if ( ! response.ok ) { + throw new Error( + `Error downloading font face asset from ${ url }. Server responded with status: ${ response.status }` + ); + } + return response.blob(); + } ) + .then( ( blob ) => { + const filename = url.split( '/' ).pop(); + const file = new File( [ blob ], filename, { + type: blob.type, + } ); + return file; + } ) + .catch( ( error ) => { + // eslint-disable-next-line no-console + console.error( + `Error downloading font face asset from ${ url }:`, + error + ); + throw error; + } ); +}