* Add 'select all photos' to app state * Create general purpose bulk photo action * Fix infinite scroll pagination, temporarily hide "select all" * Refine batch edit behavior * Add admin endpoints to check storage * Add missing storage count * Refine missing file presentation * Finalize storage status page * Store image-dependent photo fields when reuploading * Move storage checks behind flag
204 lines
5.2 KiB
TypeScript
204 lines
5.2 KiB
TypeScript
import AnimateItems from '@/components/AnimateItems';
|
|
import { Photo, PhotoDateRangePostgres } from '.';
|
|
import { PhotoSetCategory } from '../category';
|
|
import PhotoLarge from './PhotoLarge';
|
|
import AppGrid from '@/components/AppGrid';
|
|
import PhotoGrid from './PhotoGrid';
|
|
import TagHeader from '@/tag/TagHeader';
|
|
import CameraHeader from '@/camera/CameraHeader';
|
|
import FilmHeader from '@/film/FilmHeader';
|
|
import { TAG_PRIVATE } from '@/tag';
|
|
import PrivateHeader from '@/tag/PrivateHeader';
|
|
import FocalLengthHeader from '@/focal/FocalLengthHeader';
|
|
import PhotoHeader from './PhotoHeader';
|
|
import RecipeHeader from '@/recipe/RecipeHeader';
|
|
import { ReactNode } from 'react';
|
|
import LensHeader from '@/lens/LensHeader';
|
|
import {
|
|
ADMIN_STORAGE_DEBUG_ENABLED,
|
|
AI_CONTENT_GENERATION_ENABLED,
|
|
} from '@/app/config';
|
|
import YearHeader from '@/year/YearHeader';
|
|
import RecentsHeader from '@/recents/RecentsHeader';
|
|
import AlbumHeader from '@/album/AlbumHeader';
|
|
|
|
export default function PhotoDetailPage({
|
|
photo,
|
|
photos,
|
|
photosGrid,
|
|
recent,
|
|
year,
|
|
camera,
|
|
lens,
|
|
album,
|
|
tag,
|
|
film,
|
|
recipe,
|
|
focal,
|
|
indexNumber,
|
|
count,
|
|
dateRange,
|
|
shouldShare,
|
|
includeFavoriteInAdminMenu,
|
|
}: {
|
|
photo: Photo
|
|
photos: Photo[]
|
|
photosGrid?: Photo[]
|
|
indexNumber?: number
|
|
count?: number
|
|
dateRange?: PhotoDateRangePostgres
|
|
shouldShare?: boolean
|
|
includeFavoriteInAdminMenu?: boolean
|
|
} & PhotoSetCategory) {
|
|
let customHeader: ReactNode | undefined;
|
|
|
|
if (year) {
|
|
customHeader = <YearHeader
|
|
year={year}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
} else if (recent) {
|
|
customHeader = <RecentsHeader
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
} else if (camera) {
|
|
customHeader = <CameraHeader
|
|
camera={camera}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
} else if (lens) {
|
|
customHeader = <LensHeader
|
|
lens={lens}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
} else if (album) {
|
|
customHeader = <AlbumHeader
|
|
album={album}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
} else if (tag) {
|
|
customHeader = tag === TAG_PRIVATE
|
|
? <PrivateHeader
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count ?? 0}
|
|
/>
|
|
: <TagHeader
|
|
key={tag}
|
|
tag={tag}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
} else if (film) {
|
|
customHeader = <FilmHeader
|
|
film={film}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
} else if (recipe) {
|
|
customHeader = <RecipeHeader
|
|
recipe={recipe}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
/>;
|
|
} else if (focal) {
|
|
customHeader = <FocalLengthHeader
|
|
focal={focal}
|
|
photos={photos}
|
|
selectedPhoto={photo}
|
|
indexNumber={indexNumber}
|
|
count={count}
|
|
dateRange={dateRange}
|
|
/>;
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<AppGrid
|
|
className="mt-1.5 mb-6"
|
|
contentMain={customHeader ?? <PhotoHeader
|
|
selectedPhoto={photo}
|
|
photos={photos}
|
|
recipe={recipe}
|
|
hasAiTextGeneration={AI_CONTENT_GENERATION_ENABLED}
|
|
/>}
|
|
/>
|
|
<AnimateItems
|
|
className="md:mb-8"
|
|
animateFromAppState
|
|
items={[
|
|
<PhotoLarge
|
|
key={photo.id}
|
|
photo={photo}
|
|
album={album}
|
|
primaryTag={tag}
|
|
priority
|
|
prefetchRelatedLinks
|
|
recent={recent}
|
|
year={year}
|
|
showTitle={Boolean(customHeader)}
|
|
showTitleAsH1
|
|
showCamera={!camera}
|
|
showLens={!lens}
|
|
showFilm={!film}
|
|
showRecipe={!recipe}
|
|
shouldShare={shouldShare}
|
|
shouldShareRecents={recent !== undefined}
|
|
shouldShareYear={year !== undefined}
|
|
shouldShareCamera={camera !== undefined}
|
|
shouldShareLens={lens !== undefined}
|
|
shouldShareAlbum={album !== undefined}
|
|
shouldShareTag={tag !== undefined}
|
|
shouldShareFilm={film !== undefined}
|
|
shouldShareRecipe={recipe !== undefined}
|
|
shouldShareFocalLength={focal !== undefined}
|
|
includeFavoriteInAdminMenu={includeFavoriteInAdminMenu}
|
|
showAdminKeyCommands
|
|
showStorageCheck={ADMIN_STORAGE_DEBUG_ENABLED}
|
|
/>,
|
|
]}
|
|
/>
|
|
<AppGrid
|
|
contentMain={<PhotoGrid
|
|
photos={photosGrid ?? photos}
|
|
tag={tag}
|
|
camera={camera}
|
|
film={film}
|
|
focal={focal}
|
|
year={year}
|
|
animateOnFirstLoadOnly
|
|
/>}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|