diff --git a/src/image-response/components/ImagePhotoGrid.tsx b/src/image-response/components/ImagePhotoGrid.tsx index 5ba0717c..3a282e04 100644 --- a/src/image-response/components/ImagePhotoGrid.tsx +++ b/src/image-response/components/ImagePhotoGrid.tsx @@ -3,8 +3,11 @@ import { Photo } from '@/photo'; import { NextImageSize } from '@/platforms/next-image'; import { IS_PREVIEW } from '@/app/config'; -import { getOptimizedPhotoUrl } from '@/photo/storage'; -import { fetchBase64ImageFromUrl } from '@/utility/image'; +import { + getOptimizedPhotoUrl, + getOptimizedPhotoUrlForSuffix, +} from '@/photo/storage'; +// import { fetchBase64ImageFromUrl } from '@/utility/image'; import { getSignedUrlForUrl } from '@/platforms/storage'; export default async function ImagePhotoGrid({ @@ -36,6 +39,10 @@ export default async function ImagePhotoGrid({ ? width ?? 1080 : 640; + const optimizedSuffix = count <= 2 + ? 'lg' + : 'md'; + let rows = 1; if (count > 12) { rows = 4; } else if (count > 6) { rows = 3; } @@ -51,14 +58,26 @@ export default async function ImagePhotoGrid({ (rows - 1) * gap / rows; const photoDataUrls = await Promise.all(photos.map(async({ id, url }) => { - const optimizedUrl = getOptimizedPhotoUrl({ - imageUrl: url, - size: nextImageWidth, - addBypassSecret: IS_PREVIEW, - }); - const presignedUrl = await getSignedUrlForUrl(optimizedUrl, 'GET'); - const data = await fetchBase64ImageFromUrl(presignedUrl); - return { id, data }; + // Check for optimized image first + let optimizedUrl = getOptimizedPhotoUrlForSuffix(url, optimizedSuffix); + // Get presigned URL in case it's required + optimizedUrl = await getSignedUrlForUrl(optimizedUrl, 'GET'); + const optimizedUrlExists = await fetch(optimizedUrl) + .then(res => res.ok) + .catch(() => false); + + // Fall back on `next/image` if optimized image is not available + if (!optimizedUrlExists) { + optimizedUrl = getOptimizedPhotoUrl({ + imageUrl: url, + size: nextImageWidth, + addBypassSecret: IS_PREVIEW, + }); + } + + // const data = await fetchBase64ImageFromUrl(optimizedUrl, 'image/jpeg'); + + return { id, data: optimizedUrl }; })); const renderPhoto = ( diff --git a/src/photo/storage/index.ts b/src/photo/storage/index.ts index aa45c48d..1ecbe47a 100644 --- a/src/photo/storage/index.ts +++ b/src/photo/storage/index.ts @@ -5,7 +5,6 @@ import { import { generateFileNameWithId, getFileNamePartsFromStorageUrl, - getSignedUrlForUrl, getStorageUrlsForPrefix, uploadFileFromClient, } from '@/platforms/storage'; @@ -127,25 +126,20 @@ export const getOptimizedPhotoUrlForManipulation = ( compatibilityMode, }); -const getTestOptimizedPhotoUrl = (url: string) => { +export const getOptimizedPhotoUrlForSuffix = ( + url: string, + suffix: OptimizedSuffix, +) => { const { urlBase, fileNameBase } = getFileNamePartsFromStorageUrl(url); - return getOptimizedUrl({ - urlBase, - fileNameBase, - suffix: 'sm', - }); + return getOptimizedUrl({ urlBase, fileNameBase, suffix }); }; +const getTestOptimizedPhotoUrl = (url: string) => + getOptimizedPhotoUrlForSuffix(url, 'sm'); + export const doesPhotoUrlHaveOptimizedFiles = async (url: string) => fetch(getTestOptimizedPhotoUrl(url)).then(res => res.ok); -export const doAllPhotosHaveOptimizedFiles = async (photos: Photo[]) => - Promise.all(photos.map(async ({ url }) => fetch( - await getSignedUrlForUrl(getTestOptimizedPhotoUrl(url), 'GET'), - ))) - .then(urls => urls.every(url => url.ok)) - .catch(() => false); - export const getStorageUrlsForPhoto = async ({ url }: Photo) => { const getSortScoreForUrl = (url: string) => { const { fileNameBase } = getFileNamePartsFromStorageUrl(url); diff --git a/src/platforms/safe-photo-image-response.ts b/src/platforms/safe-photo-image-response.ts index 3fd7901f..e4d075fc 100644 --- a/src/platforms/safe-photo-image-response.ts +++ b/src/platforms/safe-photo-image-response.ts @@ -20,10 +20,14 @@ export const safePhotoImageResponse = async ( photos: Photo[], jsx: (isNextImageReady: boolean) => JSX.Element, options: ConstructorParameters[1], + disableCheck = true, ) => { // Make sure next/image can be reached from absolute urls, // which may not exist on first pre-render - const isNextImageReady = await isNextImageReadyBasedOnPhotos(photos); + const isNextImageReady = ( + disableCheck || + await isNextImageReadyBasedOnPhotos(photos) + ); return new ImageResponse( jsx(isNextImageReady), diff --git a/src/utility/image.ts b/src/utility/image.ts index 840fcf6c..56715297 100644 --- a/src/utility/image.ts +++ b/src/utility/image.ts @@ -4,11 +4,12 @@ export const removeBase64Prefix = (base64: string) => { export const fetchBase64ImageFromUrl = ( url: string, + contentType?: string, fetchOptions?: RequestInit, ) => fetch(url, fetchOptions) .then(async response => { const blob = await response.arrayBuffer(); // eslint-disable-next-line max-len - return `data:${response.headers.get('content-type')};base64,${Buffer.from(blob).toString('base64')}`; + return `data:${contentType ?? response.headers.get('content-type')};base64,${Buffer.from(blob).toString('base64')}`; });