Remove search params from /grid

This commit is contained in:
Sam Becker 2024-01-18 14:50:59 -06:00
parent 927b80ab8a
commit 19965a1aea
7 changed files with 121 additions and 77 deletions

View File

@ -1,26 +1,24 @@
import { getPhotosCached } from '@/cache';
import SiteGrid from '@/components/SiteGrid';
import { generateOgImageMetaForPhotos } from '@/photo';
import {
PHOTO_LOAD_MULTIPLE_GRID,
generateOgImageMetaForPhotos,
} from '@/photo';
import PhotoGrid from '@/photo/PhotoGrid';
import PhotosEmptyState from '@/photo/PhotosEmptyState';
import { MAX_PHOTOS_TO_SHOW_OG } from '@/photo/image-response';
import { pathForGrid } from '@/site/paths';
import { Metadata } from 'next/types';
import {
PaginationParams,
getPaginationForSearchParams,
} from '@/site/pagination';
import PhotoGridSidebar from '@/photo/PhotoGridSidebar';
import { getPhotoSidebarDataCached } from '@/photo/data';
import { MorePhotosGrid } from '@/photo/MorePhotosGrid';
import { Suspense } from 'react';
export async function generateMetadata(): Promise<Metadata> {
const photos = await getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_OG });
return generateOgImageMetaForPhotos(photos);
}
export default async function GridPage({ searchParams }: PaginationParams) {
const { offset, limit } = getPaginationForSearchParams(searchParams);
export default async function GridPage() {
const [
photos,
photosCount,
@ -28,18 +26,23 @@ export default async function GridPage({ searchParams }: PaginationParams) {
cameras,
simulations,
] = await Promise.all([
getPhotosCached({ limit }),
getPhotosCached({ limit: PHOTO_LOAD_MULTIPLE_GRID }),
...getPhotoSidebarDataCached(),
]);
const showMorePath = photosCount > photos.length
? pathForGrid(offset + 1)
: undefined;
return (
photos.length > 0
? <SiteGrid
contentMain={<PhotoGrid {...{ photos, showMorePath }} />}
contentMain={<div className="space-y-0.5 sm:space-y-1">
<PhotoGrid {...{ photos }} />
<Suspense>
<MorePhotosGrid
initialOffset={PHOTO_LOAD_MULTIPLE_GRID}
itemsPerRequest={PHOTO_LOAD_MULTIPLE_GRID}
totalPhotosCount={photosCount}
/>
</Suspense>
</div>}
contentSide={<div className="sticky top-4 space-y-4">
<PhotoGridSidebar {...{
tags,

View File

@ -1,11 +1,14 @@
import { getPhotosCached, getPhotosCountCached } from '@/cache';
import { LARGE_PHOTOS_TO_SHOW, generateOgImageMetaForPhotos } from '@/photo';
import {
PHOTO_LOAD_MULTIPLE_ROOT,
generateOgImageMetaForPhotos,
} from '@/photo';
import PhotosEmptyState from '@/photo/PhotosEmptyState';
import { Metadata } from 'next/types';
import { MAX_PHOTOS_TO_SHOW_OG } from '@/photo/image-response';
import PhotosLarge from '@/photo/PhotosLarge';
import { Suspense } from 'react';
import { MorePhotosLarge } from '@/photo/MorePhotosLarge';
import { MorePhotosRoot } from '@/photo/MorePhotosRoot';
export const revalidate = 3600;
@ -22,7 +25,7 @@ export default async function HomePage() {
count,
] = await Promise.all([
// Make homepage queries resilient to error on first time setup
getPhotosCached({ limit: LARGE_PHOTOS_TO_SHOW }).catch(() => []),
getPhotosCached({ limit: PHOTO_LOAD_MULTIPLE_ROOT }).catch(() => []),
getPhotosCountCached().catch(() => 0),
]);
@ -31,9 +34,9 @@ export default async function HomePage() {
? <div className="space-y-1">
<PhotosLarge photos={photos} />
<Suspense>
<MorePhotosLarge
initialOffset={LARGE_PHOTOS_TO_SHOW}
itemsPerRequest={LARGE_PHOTOS_TO_SHOW}
<MorePhotosRoot
initialOffset={PHOTO_LOAD_MULTIPLE_ROOT}
itemsPerRequest={PHOTO_LOAD_MULTIPLE_ROOT}
totalPhotosCount={count}
/>
</Suspense>

View File

@ -0,0 +1,42 @@
import MoreComponents from '@/components/MoreComponents';
import { getPhotosCached } from '@/cache';
import PhotoGrid from './PhotoGrid';
export function MorePhotosGrid({
initialOffset,
itemsPerRequest,
totalPhotosCount,
}: {
initialOffset: number
itemsPerRequest: number
totalPhotosCount: number
}) {
return (
<MoreComponents
stateKey="PhotosGrid"
label="More photos"
initialOffset={initialOffset}
itemsPerRequest={itemsPerRequest}
getNextComponent={async (offset, limit) => {
'use server';
if (
process.env.NODE_ENV === 'development' &&
Math.random() < 0.95
) {
return { didFail: true };
}
const photos = await getPhotosCached({ limit: offset + limit })
.catch(() => undefined);
if (!photos) {
return { didFail: true };
} else {
const nextPhotos = photos.slice(offset);
return {
nextComponent: <PhotoGrid photos={nextPhotos} />,
isFinished: offset + limit >= totalPhotosCount,
};
}
}}
/>
);
}

View File

@ -2,7 +2,7 @@ import MoreComponents from '@/components/MoreComponents';
import PhotosLarge from './PhotosLarge';
import { getPhotosCached } from '@/cache';
export function MorePhotosLarge({
export function MorePhotosRoot({
initialOffset,
itemsPerRequest,
totalPhotosCount,
@ -13,7 +13,7 @@ export function MorePhotosLarge({
}) {
return (
<MoreComponents
stateKey="PhotosLarge"
stateKey="PhotosRoot"
label="More photos"
initialOffset={initialOffset}
itemsPerRequest={itemsPerRequest}

View File

@ -3,7 +3,6 @@ import PhotoSmall from './PhotoSmall';
import { clsx } from 'clsx/lite';
import AnimateItems from '@/components/AnimateItems';
import { Camera } from '@/camera';
import MoreComponentsClient from '@/components/MoreComponentsClient';
import { FilmSimulation } from '@/simulation';
import { GRID_ASPECT_RATIO, HIGH_DENSITY_GRID } from '@/site/config';
@ -17,7 +16,6 @@ export default function PhotoGrid({
animate = true,
animateOnFirstLoadOnly,
staggerOnFirstLoadOnly = true,
showMorePath,
additionalTile,
small,
}: {
@ -35,54 +33,47 @@ export default function PhotoGrid({
small?: boolean
}) {
return (
<div className="space-y-4">
<AnimateItems
className={clsx(
'grid gap-0.5 sm:gap-1',
small
? 'grid-cols-3 xs:grid-cols-6'
: HIGH_DENSITY_GRID
? 'grid-cols-2 xs:grid-cols-4 lg:grid-cols-5'
: 'grid-cols-2 sm:grid-cols-4 md:grid-cols-3 lg:grid-cols-4',
'items-center',
)}
type={animate === false ? 'none' : undefined}
duration={fast ? 0.3 : undefined}
staggerDelay={0.075}
distanceOffset={40}
animateOnFirstLoadOnly={animateOnFirstLoadOnly}
staggerOnFirstLoadOnly={staggerOnFirstLoadOnly}
items={photos.map(photo =>
<div
key={photo.id}
className={GRID_ASPECT_RATIO !== 0
? clsx(
'aspect-square',
'overflow-hidden',
'[&>*]:flex [&>*]:w-full [&>*]:h-full',
'[&>*>*]:object-cover [&>*>*]:min-h-full',
)
: undefined}
style={{
...GRID_ASPECT_RATIO !== 0 && {
aspectRatio: GRID_ASPECT_RATIO,
},
}}
>
<PhotoSmall {...{
photo,
tag,
camera,
simulation,
selected: photo.id === selectedPhoto?.id,
}} />
</div>).concat(additionalTile ?? [])}
/>
{showMorePath &&
<MoreComponentsClient
label="More photos"
path={showMorePath}
/>}
</div>
<AnimateItems
className={clsx(
'grid gap-0.5 sm:gap-1',
small
? 'grid-cols-3 xs:grid-cols-6'
: HIGH_DENSITY_GRID
? 'grid-cols-2 xs:grid-cols-4 lg:grid-cols-5'
: 'grid-cols-2 sm:grid-cols-4 md:grid-cols-3 lg:grid-cols-4',
'items-center',
)}
type={animate === false ? 'none' : undefined}
duration={fast ? 0.3 : undefined}
staggerDelay={0.075}
distanceOffset={40}
animateOnFirstLoadOnly={animateOnFirstLoadOnly}
staggerOnFirstLoadOnly={staggerOnFirstLoadOnly}
items={photos.map(photo =>
<div
key={photo.id}
className={GRID_ASPECT_RATIO !== 0
? clsx(
'aspect-square',
'overflow-hidden',
'[&>*]:flex [&>*]:w-full [&>*]:h-full',
'[&>*>*]:object-cover [&>*>*]:min-h-full',
)
: undefined}
style={{
...GRID_ASPECT_RATIO !== 0 && {
aspectRatio: GRID_ASPECT_RATIO,
},
}}
>
<PhotoSmall {...{
photo,
tag,
camera,
simulation,
selected: photo.id === selectedPhoto?.id,
}} />
</div>).concat(additionalTile ?? [])}
/>
);
};

View File

@ -11,8 +11,11 @@ import {
import camelcaseKeys from 'camelcase-keys';
import type { Metadata } from 'next';
export const LARGE_PHOTOS_TO_SHOW =
export const PHOTO_LOAD_MULTIPLE_ROOT =
process.env.NODE_ENV === 'development' ? 2 : 12;
export const PHOTO_LOAD_MULTIPLE_GRID =
process.env.NODE_ENV === 'development' ? 4 : 24;
export const GRID_THUMBNAILS_TO_SHOW_MAX = 12;
export const ACCEPTED_PHOTO_FILE_TYPES = [

View File

@ -1,7 +1,8 @@
import { createContext, useContext } from 'react';
export type MoreComponentsKey =
'PhotosLarge';
'PhotosRoot' |
'PhotosGrid';
export interface MoreComponentsStateForKey {
indexToView: number
@ -39,7 +40,8 @@ export interface MoreComponentsContext {
}
export const MORE_COMPONENTS_INITIAL_STATE: MoreComponentsState = {
PhotosLarge: createInitialStateForKey(),
PhotosRoot: createInitialStateForKey(),
PhotosGrid: createInitialStateForKey(),
};
export const MoreComponentsContext =