diff --git a/src/app/grid/page.tsx b/src/app/grid/page.tsx index 8a1ffb51..a9db1275 100644 --- a/src/app/grid/page.tsx +++ b/src/app/grid/page.tsx @@ -10,9 +10,9 @@ import { MAX_PHOTOS_TO_SHOW_OG } from '@/image-response'; import { Metadata } from 'next/types'; import PhotoGridSidebar from '@/photo/PhotoGridSidebar'; import { getPhotoSidebarData } from '@/photo/data'; -import InfinitePhotoScroll from '@/photo/InfinitePhotoScroll'; import { getPhotos } from '@/services/vercel-postgres'; import { cache } from 'react'; +import InfinitePhotoScrollGrid from '@/photo/InfinitePhotoScrollGrid'; export const dynamic = 'force-static'; @@ -41,8 +41,7 @@ export default async function GridPage() { contentMain={
{photosCount > photos.length && - } diff --git a/src/app/page.tsx b/src/app/page.tsx index 59ea960c..a4bfc36b 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,10 +6,11 @@ import { import PhotosEmptyState from '@/photo/PhotosEmptyState'; import { Metadata } from 'next/types'; import { MAX_PHOTOS_TO_SHOW_OG } from '@/image-response'; -import InfinitePhotoScroll from '../photo/InfinitePhotoScroll'; import PhotosLarge from '@/photo/PhotosLarge'; import { cache } from 'react'; import { getPhotos, getPhotosCount } from '@/services/vercel-postgres'; +import InfinitePhotoScrollPhotosLarge from + '@/photo/InfinitePhotoScrollPhotosLarge'; export const dynamic = 'force-static'; @@ -43,8 +44,7 @@ export default async function HomePage() { ?
{photosCount > photos.length && - } diff --git a/src/photo/InfinitePhotoScroll.tsx b/src/photo/InfinitePhotoScroll.tsx index 36db260e..a1c728ea 100644 --- a/src/photo/InfinitePhotoScroll.tsx +++ b/src/photo/InfinitePhotoScroll.tsx @@ -1,17 +1,16 @@ 'use client'; import useSwrInfinite from 'swr/infinite'; -import PhotosLarge from '@/photo/PhotosLarge'; import { + ReactNode, useCallback, useMemo, useRef, } from 'react'; import SiteGrid from '@/components/SiteGrid'; import Spinner from '@/components/Spinner'; -import { getPhotosAction } from '@/photo/actions'; +import { getPhotosCachedAction, getPhotosAction } from '@/photo/actions'; import { Photo } from '.'; -import PhotoGrid from './PhotoGrid'; import { clsx } from 'clsx/lite'; import { useAppState } from '@/state/AppState'; @@ -20,19 +19,31 @@ export type RevalidatePhoto = ( revalidateRemainingPhotos?: boolean, ) => Promise; -export default function InfinitePhotoScroll({ - type = 'full-frame', - initialOffset, - itemsPerPage, -}: { - type: 'full-frame' | 'grid' +export type InfinitePhotoScrollExternalProps = { initialOffset: number itemsPerPage: number - debug?: boolean +} + +export default function InfinitePhotoScroll({ + cacheKey, + initialOffset, + itemsPerPage, + wrapMoreButtonInGrid, + useCachedPhotos = true, + children, +}: InfinitePhotoScrollExternalProps & { + cacheKey: string + wrapMoreButtonInGrid: boolean + useCachedPhotos?: boolean + children: (props: { + photos: Photo[] + onLastPhotoVisible: () => void + revalidatePhoto?: RevalidatePhoto + }) => ReactNode }) { const { swrTimestamp, isUserSignedIn } = useAppState(); - const key = `${swrTimestamp}-${type}`; + const key = `${swrTimestamp}-${cacheKey}`; const keyGenerator = useCallback( (size: number, prev: Photo[]) => prev && prev.length === 0 @@ -40,12 +51,17 @@ export default function InfinitePhotoScroll({ : [key, size] , [key]); - const fetcher = useCallback(([_key, size]: [string, number]) => { - return getPhotosAction( - initialOffset + size * itemsPerPage, - itemsPerPage, - ); - }, [initialOffset, itemsPerPage]); + const fetcher = useCallback(([_key, size]: [string, number]) => + useCachedPhotos + ? getPhotosCachedAction( + initialOffset + size * itemsPerPage, + itemsPerPage, + ) + : getPhotosAction( + initialOffset + size * itemsPerPage, + itemsPerPage, + ) + , [useCachedPhotos, initialOffset, itemsPerPage]); const { data, isLoading, isValidating, error, mutate, setSize } = useSwrInfinite( @@ -106,17 +122,12 @@ export default function InfinitePhotoScroll({ return (
- {type === 'full-frame' - ? - : } - {!isFinished && (type === 'full-frame' + {children({ + photos, + onLastPhotoVisible: advance, + revalidatePhoto, + })} + {!isFinished && (wrapMoreButtonInGrid ? : renderMoreButton())}
diff --git a/src/photo/InfinitePhotoScrollGrid.tsx b/src/photo/InfinitePhotoScrollGrid.tsx new file mode 100644 index 00000000..d3ec43dd --- /dev/null +++ b/src/photo/InfinitePhotoScrollGrid.tsx @@ -0,0 +1,26 @@ +'use client'; + +import InfinitePhotoScroll, { + InfinitePhotoScrollExternalProps, +} from './InfinitePhotoScroll'; +import PhotoGrid from './PhotoGrid'; + +export default function InfinitePhotoScrollGrid({ + initialOffset, + itemsPerPage, +}: InfinitePhotoScrollExternalProps) { + return ( + + {({ photos, onLastPhotoVisible }) => + } + + ); +} diff --git a/src/photo/InfinitePhotoScrollPhotosLarge.tsx b/src/photo/InfinitePhotoScrollPhotosLarge.tsx new file mode 100644 index 00000000..cef46974 --- /dev/null +++ b/src/photo/InfinitePhotoScrollPhotosLarge.tsx @@ -0,0 +1,27 @@ +'use client'; + +import InfinitePhotoScroll, { + InfinitePhotoScrollExternalProps, +} from './InfinitePhotoScroll'; +import PhotosLarge from './PhotosLarge'; + +export default function InfinitePhotoScrollPhotosLarge({ + initialOffset, + itemsPerPage, +}: InfinitePhotoScrollExternalProps) { + return ( + + {({ photos, onLastPhotoVisible, revalidatePhoto }) => + } + + ); +} diff --git a/src/photo/actions.ts b/src/photo/actions.ts index b0c68911..fac16382 100644 --- a/src/photo/actions.ts +++ b/src/photo/actions.ts @@ -195,9 +195,12 @@ export async function streamAiImageQueryAction( streamOpenAiImageQuery(imageBase64, AI_IMAGE_QUERIES[query])); } -export const getPhotosAction = async (offset: number, limit: number) => +export const getPhotosCachedAction = async (offset: number, limit: number) => getPhotosCachedCached({ offset, limit }); +export const getPhotosAction = async (offset: number, limit: number) => + getPhotos({ offset, limit }); + export const queryPhotosByTitleAction = async (query: string) => (await getPhotos({ query, limit: 10 })) .filter(({ title }) => Boolean(title));