diff --git a/__tests__/path.test.ts b/__tests__/path.test.ts index 356e478e..9c8f8c56 100644 --- a/__tests__/path.test.ts +++ b/__tests__/path.test.ts @@ -1,11 +1,10 @@ -/* eslint-disable max-len */ import { getEscapePath, getPathComponents, isPathCamera, isPathCameraPhoto, - isPathFilmSimulation, - isPathFilmSimulationPhoto, + isPathFilm, + isPathFilmPhoto, isPathFocalLength, isPathFocalLengthPhoto, isPathPhoto, @@ -20,34 +19,34 @@ const TAG = 'tag-name'; const CAMERA_MAKE = 'fujifilm'; const CAMERA_MODEL = 'x-t1'; const CAMERA_OBJECT = { make: CAMERA_MAKE, model: CAMERA_MODEL }; -const FILM_SIMULATION = 'acros'; +const FILM = 'acros'; const FOCAL_LENGTH = 90; const FOCAL_LENGTH_STRING = `${FOCAL_LENGTH}mm`; -const PATH_ROOT = '/'; -const PATH_GRID = '/grid'; -const PATH_FEED = '/feed'; -const PATH_ADMIN = '/admin/photos'; -const PATH_OG = '/og'; -const PATH_OG_ALL = `${PATH_OG}/all`; -const PATH_OG_SAMPLE = `${PATH_OG}/sample`; +const PATH_ROOT = '/'; +const PATH_GRID = '/grid'; +const PATH_FEED = '/feed'; +const PATH_ADMIN = '/admin/photos'; +const PATH_OG = '/og'; +const PATH_OG_ALL = `${PATH_OG}/all`; +const PATH_OG_SAMPLE = `${PATH_OG}/sample`; -const PATH_PHOTO = `/p/${PHOTO_ID}`; +const PATH_PHOTO = `/p/${PHOTO_ID}`; -const PATH_TAG = `/tag/${TAG}`; -const PATH_TAG_PHOTO = `${PATH_TAG}/${PHOTO_ID}`; +const PATH_TAG = `/tag/${TAG}`; +const PATH_TAG_PHOTO = `${PATH_TAG}/${PHOTO_ID}`; -const PATH_TAG_HIDDEN = `/tag/${TAG_HIDDEN}`; -const PATH_TAG_HIDDEN_PHOTO = `${PATH_TAG_HIDDEN}/${PHOTO_ID}`; +const PATH_TAG_HIDDEN = `/tag/${TAG_HIDDEN}`; +const PATH_TAG_HIDDEN_PHOTO = `${PATH_TAG_HIDDEN}/${PHOTO_ID}`; -const PATH_CAMERA = `/shot-on/${CAMERA_MAKE}/${CAMERA_MODEL}`; -const PATH_CAMERA_PHOTO = `${PATH_CAMERA}/${PHOTO_ID}`; +const PATH_CAMERA = `/shot-on/${CAMERA_MAKE}/${CAMERA_MODEL}`; +const PATH_CAMERA_PHOTO = `${PATH_CAMERA}/${PHOTO_ID}`; -const PATH_FILM_SIMULATION = `/film/${FILM_SIMULATION}`; -const PATH_FILM_SIMULATION_PHOTO = `${PATH_FILM_SIMULATION}/${PHOTO_ID}`; +const PATH_FILM = `/film/${FILM}`; +const PATH_FILM_PHOTO = `${PATH_FILM}/${PHOTO_ID}`; -const PATH_FOCAL_LENGTH = `/focal/${FOCAL_LENGTH_STRING}`; -const PATH_FOCAL_LENGTH_PHOTO = `${PATH_FOCAL_LENGTH}/${PHOTO_ID}`; +const PATH_FOCAL_LENGTH = `/focal/${FOCAL_LENGTH_STRING}`; +const PATH_FOCAL_LENGTH_PHOTO = `${PATH_FOCAL_LENGTH}/${PHOTO_ID}`; describe('Paths', () => { it('can be protected', () => { @@ -57,7 +56,7 @@ describe('Paths', () => { expect(isPathProtected(PATH_TAG)).toBe(false); expect(isPathProtected(PATH_TAG_PHOTO)).toBe(false); expect(isPathProtected(PATH_CAMERA)).toBe(false); - expect(isPathProtected(PATH_FILM_SIMULATION)).toBe(false); + expect(isPathProtected(PATH_FILM)).toBe(false); // Private expect(isPathProtected(PATH_ADMIN)).toBe(true); expect(isPathProtected(PATH_OG)).toBe(true); @@ -73,13 +72,13 @@ describe('Paths', () => { expect(isPathTagPhoto(PATH_TAG_PHOTO)).toBe(true); expect(isPathCamera(PATH_CAMERA)).toBe(true); expect(isPathCameraPhoto(PATH_CAMERA_PHOTO)).toBe(true); - expect(isPathFilmSimulation(PATH_FILM_SIMULATION)).toBe(true); - expect(isPathFilmSimulationPhoto(PATH_FILM_SIMULATION_PHOTO)).toBe(true); + expect(isPathFilm(PATH_FILM)).toBe(true); + expect(isPathFilmPhoto(PATH_FILM_PHOTO)).toBe(true); expect(isPathFocalLength(PATH_FOCAL_LENGTH)).toBe(true); expect(isPathFocalLengthPhoto(PATH_FOCAL_LENGTH_PHOTO)).toBe(true); // Negative - expect(isPathFocalLength(PATH_FILM_SIMULATION)).toBe(false); - expect(isPathFocalLengthPhoto(PATH_FILM_SIMULATION_PHOTO)).toBe(false); + expect(isPathFocalLength(PATH_FILM)).toBe(false); + expect(isPathFocalLengthPhoto(PATH_FILM_PHOTO)).toBe(false); }); it('can be parsed', () => { // Core @@ -103,13 +102,13 @@ describe('Paths', () => { photoId: PHOTO_ID, camera: CAMERA_OBJECT, }); - // Film Simulation - expect(getPathComponents(PATH_FILM_SIMULATION)).toEqual({ - simulation: FILM_SIMULATION, + // Film + expect(getPathComponents(PATH_FILM)).toEqual({ + film: FILM, }); - expect(getPathComponents(PATH_FILM_SIMULATION_PHOTO)).toEqual({ + expect(getPathComponents(PATH_FILM_PHOTO)).toEqual({ photoId: PHOTO_ID, - simulation: FILM_SIMULATION, + film: FILM, }); // Focal Length expect(getPathComponents(PATH_FOCAL_LENGTH)).toEqual({ @@ -134,9 +133,9 @@ describe('Paths', () => { // Camera expect(getEscapePath(PATH_CAMERA)).toEqual(PATH_ROOT); expect(getEscapePath(PATH_CAMERA_PHOTO)).toEqual(PATH_CAMERA); - // Film Simulation - expect(getEscapePath(PATH_FILM_SIMULATION)).toEqual(PATH_ROOT); - expect(getEscapePath(PATH_FILM_SIMULATION_PHOTO)).toEqual(PATH_FILM_SIMULATION); + // Film + expect(getEscapePath(PATH_FILM)).toEqual(PATH_ROOT); + expect(getEscapePath(PATH_FILM_PHOTO)).toEqual(PATH_FILM); // Focal Length expect(getEscapePath(PATH_FOCAL_LENGTH)).toEqual(PATH_ROOT); expect(getEscapePath(PATH_FOCAL_LENGTH_PHOTO)).toEqual(PATH_FOCAL_LENGTH); diff --git a/app/admin/baseline/page.tsx b/app/admin/baseline/page.tsx index aa3b5706..099c4dd6 100644 --- a/app/admin/baseline/page.tsx +++ b/app/admin/baseline/page.tsx @@ -129,7 +129,7 @@ export default function ComponentsPage() {
} + icon={} label="Astia/Soft" type="icon-last" iconWide @@ -149,7 +149,7 @@ export default function ComponentsPage() {
} + icon={} label="Astia/Soft" type="icon-last" iconWide @@ -184,7 +184,7 @@ export default function ComponentsPage() {
} + icon={} label="Astia/Soft" type="icon-last" iconWide diff --git a/app/admin/recipes/[recipe]/edit/page.tsx b/app/admin/recipes/[recipe]/edit/page.tsx index 4c85519a..c9db0fbd 100644 --- a/app/admin/recipes/[recipe]/edit/page.tsx +++ b/app/admin/recipes/[recipe]/edit/page.tsx @@ -32,7 +32,7 @@ export default async function RecipePageEdit({ const { recipeData, - filmSimulation, + film, } = getPhotoWithRecipeFromPhotos(photos) ?? {}; if (count === 0) { redirect(PATH_ADMIN); } @@ -42,11 +42,11 @@ export default async function RecipePageEdit({ backPath={PATH_ADMIN_RECIPES} backLabel="Recipes" breadcrumb={} - accessory={recipeData && filmSimulation && + accessory={recipeData && film && } > diff --git a/app/admin/uploads/[uploadPath]/page.tsx b/app/admin/uploads/[uploadPath]/page.tsx index c31de425..d55b9912 100644 --- a/app/admin/uploads/[uploadPath]/page.tsx +++ b/app/admin/uploads/[uploadPath]/page.tsx @@ -49,10 +49,10 @@ export default async function UploadPage({ params }: Params) { ] = await Promise.all([ getUniqueTagsCached(), getUniqueRecipesCached(), - formDataFromExif?.recipeData && formDataFromExif.filmSimulation + formDataFromExif?.recipeData && formDataFromExif.film ? getRecipeTitleForData( formDataFromExif.recipeData, - formDataFromExif.filmSimulation as FilmSimulation, + formDataFromExif.film as FilmSimulation, ) : undefined, ]); diff --git a/app/film-demo/animate/page.tsx b/app/film-demo/animate/page.tsx index b7ad466c..0542cda2 100644 --- a/app/film-demo/animate/page.tsx +++ b/app/film-demo/animate/page.tsx @@ -28,7 +28,7 @@ export default function FilmPage() { Film Simulation:
diff --git a/app/film-demo/page.tsx b/app/film-demo/page.tsx index c1e5b94c..972e4143 100644 --- a/app/film-demo/page.tsx +++ b/app/film-demo/page.tsx @@ -9,7 +9,7 @@ export default function FilmPage() { {FILM_SIMULATION_FORM_INPUT_OPTIONS.map(({ value }) =>
)} diff --git a/app/film/[film]/[photoId]/page.tsx b/app/film/[film]/[photoId]/page.tsx index 610e077e..f20b5942 100644 --- a/app/film/[film]/[photoId]/page.tsx +++ b/app/film/[film]/[photoId]/page.tsx @@ -20,20 +20,20 @@ import { cache } from 'react'; const getPhotosNearIdCachedCached = cache(( photoId: string, - simulation: FilmSimulation, + film: FilmSimulation, ) => getPhotosNearIdCached( photoId, - { film: simulation, limit: RELATED_GRID_PHOTOS_TO_SHOW + 2 }, + { film, limit: RELATED_GRID_PHOTOS_TO_SHOW + 2 }, )); -interface PhotoFilmSimulationProps { +interface PhotoFilmProps { params: Promise<{ photoId: string, film: FilmSimulation }> } export async function generateMetadata({ params, -}: PhotoFilmSimulationProps): Promise { +}: PhotoFilmProps): Promise { const { photoId, film } = await params; const { photo } = await getPhotosNearIdCachedCached(photoId, film); @@ -65,7 +65,7 @@ export async function generateMetadata({ export default async function PhotoFilmPage({ params, -}: PhotoFilmSimulationProps) { +}: PhotoFilmProps) { const { photoId, film } = await params; const { photo, photos, photosGrid, indexNumber } = diff --git a/app/film/[film]/image/route.tsx b/app/film/[film]/image/route.tsx index 2fbe4010..83a77b22 100644 --- a/app/film/[film]/image/route.tsx +++ b/app/film/[film]/image/route.tsx @@ -9,14 +9,14 @@ import { FilmSimulation } from '@/film'; import { getIBMPlexMono } from '@/app/font'; import { ImageResponse } from 'next/og'; import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; -import { getUniqueFilmSimulations } from '@/photo/db/query'; +import { getUniqueFilms } from '@/photo/db/query'; import { staticallyGenerateCategoryIfConfigured } from '@/app/static'; export const generateStaticParams = staticallyGenerateCategoryIfConfigured( 'films', 'image', - getUniqueFilmSimulations, - simulations => simulations.map(({ film: simulation }) => ({ simulation })), + getUniqueFilms, + films => films.map(({ film }) => ({ film })), ); export async function GET( @@ -42,7 +42,7 @@ export async function GET( return new ImageResponse( films.map(({ film }) => ({ film })), ); -interface FilmSimulationProps { +interface FilmProps { params: Promise<{ film: FilmSimulation }> } export async function generateMetadata({ params, -}: FilmSimulationProps): Promise { +}: FilmProps): Promise { const { film } = await params; const [ photos, { count, dateRange }, - ] = await getPhotosFilmSimulationDataCachedCached({ - simulation: film, + ] = await getPhotosFilmDataCachedCached({ + film, limit: INFINITE_SCROLL_GRID_INITIAL, }); @@ -43,7 +43,7 @@ export async function generateMetadata({ title, description, images, - } = generateMetaForFilmSimulation(film, photos, count, dateRange); + } = generateMetaForFilm(film, photos, count, dateRange); return { title, @@ -64,14 +64,14 @@ export async function generateMetadata({ export default async function FilmPage({ params, -}: FilmSimulationProps) { +}: FilmProps) { const { film } = await params; const [ photos, { count, dateRange }, - ] = await getPhotosFilmSimulationDataCachedCached({ - simulation: film, + ] = await getPhotosFilmDataCachedCached({ + film, limit: INFINITE_SCROLL_GRID_INITIAL, }); @@ -79,7 +79,7 @@ export default async function FilmPage({ return ( photos[0]) @@ -32,7 +32,7 @@ export default async function OGOverviewPage() { .catch(() => []), getPhotosCached({ limit: 1, camera }) .catch(() => []), - getPhotosCached({ limit: 1, film: simulation }) + getPhotosCached({ limit: 1, film }) .catch(() => []), getPhotosCached({ limit: 1, focal }) .catch(() => []), @@ -45,7 +45,7 @@ export default async function OGOverviewPage() { - +
); diff --git a/app/page.tsx b/app/page.tsx index 4a952ca4..f738529f 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -35,7 +35,7 @@ export default async function HomePage() { lenses, tags, recipes, - simulations, + films, focalLengths, ] = await Promise.all([ getPhotosCached() @@ -59,7 +59,7 @@ export default async function HomePage() { lenses, tags, recipes, - films: simulations, + films, focalLengths, }} /> diff --git a/src/admin/AdminShowRecipeButton.tsx b/src/admin/AdminShowRecipeButton.tsx index 52c9f66d..bfe97689 100644 --- a/src/admin/AdminShowRecipeButton.tsx +++ b/src/admin/AdminShowRecipeButton.tsx @@ -9,11 +9,11 @@ import { TbChecklist } from 'react-icons/tb'; export default function AdminShowRecipeButton({ title, recipe, - simulation, + film, }: { title: string recipe: FujifilmRecipe - simulation: FujifilmSimulation + film: FujifilmSimulation }) { const { setRecipeModalProps } = useAppState(); @@ -26,7 +26,7 @@ export default function AdminShowRecipeButton({ onClick={() => setRecipeModalProps?.({ title, recipe, - simulation, + film, })} > Preview diff --git a/src/admin/insights/AdminAppInsights.tsx b/src/admin/insights/AdminAppInsights.tsx index ac11d13c..8595a9d0 100644 --- a/src/admin/insights/AdminAppInsights.tsx +++ b/src/admin/insights/AdminAppInsights.tsx @@ -1,7 +1,7 @@ import { getPhotosMeta, getUniqueCameras, - getUniqueFilmSimulations, + getUniqueFilms, getUniqueFocalLengths, getUniqueLenses, getUniqueRecipes, @@ -34,7 +34,7 @@ export default async function AdminAppInsights() { lenses, tags, recipes, - filmSimulations, + films, focalLengths, ] = await Promise.all([ getPhotosMeta({ hidden: 'include' }), @@ -46,7 +46,7 @@ export default async function AdminAppInsights() { getUniqueLenses(), getUniqueTags(), getUniqueRecipes(), - getUniqueFilmSimulations(), + getUniqueFilms(), getUniqueFocalLengths(), ]); @@ -94,7 +94,7 @@ export default async function AdminAppInsights() { lensesCount: lenses.length, tagsCount: tags.length, recipesCount: recipes.length, - filmSimulationsCount: filmSimulations.length, + filmsCount: films.length, focalLengthsCount: focalLengths.length, dateRange, }} diff --git a/src/admin/insights/AdminAppInsightsClient.tsx b/src/admin/insights/AdminAppInsightsClient.tsx index 15853981..da633400 100644 --- a/src/admin/insights/AdminAppInsightsClient.tsx +++ b/src/admin/insights/AdminAppInsightsClient.tsx @@ -96,7 +96,7 @@ export default function AdminAppInsightsClient({ lensesCount, tagsCount, recipesCount, - filmSimulationsCount, + filmsCount, focalLengthsCount, dateRange, }, @@ -487,11 +487,11 @@ export default function AdminAppInsightsClient({ /> : null; case 'films': - return filmSimulationsCount > 0 + return filmsCount > 0 ? } - content={pluralize(filmSimulationsCount, 'film simulation')} + content={pluralize(filmsCount, 'film')} /> : null; case 'focal-lengths': diff --git a/src/admin/insights/index.ts b/src/admin/insights/index.ts index 1a3edc9f..e6716a10 100644 --- a/src/admin/insights/index.ts +++ b/src/admin/insights/index.ts @@ -53,7 +53,7 @@ export interface PhotoStats { lensesCount: number tagsCount: number recipesCount: number - filmSimulationsCount: number + filmsCount: number focalLengthsCount: number dateRange?: PhotoDateRange } diff --git a/src/app/config.ts b/src/app/config.ts index e899ec7e..8ba47615 100644 --- a/src/app/config.ts +++ b/src/app/config.ts @@ -249,7 +249,7 @@ export const SHOW_TAGS = CATEGORY_VISIBILITY.includes('tags'); export const SHOW_RECIPES = CATEGORY_VISIBILITY.includes('recipes'); -export const SHOW_FILM_SIMULATIONS = +export const SHOW_FILMS = CATEGORY_VISIBILITY.includes('films'); export const SHOW_FOCAL_LENGTHS = CATEGORY_VISIBILITY.includes('focal-lengths'); diff --git a/src/app/paths.ts b/src/app/paths.ts index 1e93f3be..311f1da8 100644 --- a/src/app/paths.ts +++ b/src/app/paths.ts @@ -26,7 +26,7 @@ export const PREFIX_CAMERA = '/shot-on'; export const PREFIX_LENS = '/lens'; export const PREFIX_TAG = '/tag'; export const PREFIX_RECIPE = '/recipe'; -export const PREFIX_FILM_SIMULATION = '/film'; +export const PREFIX_FILM = '/film'; export const PREFIX_FOCAL_LENGTH = '/focal'; // Dynamic paths @@ -34,8 +34,7 @@ const PATH_PHOTO_DYNAMIC = `${PREFIX_PHOTO}/[photoId]`; const PATH_CAMERA_DYNAMIC = `${PREFIX_CAMERA}/[make]/[model]`; const PATH_LENS_DYNAMIC = `${PREFIX_LENS}/[make]/[model]`; const PATH_TAG_DYNAMIC = `${PREFIX_TAG}/[tag]`; -// eslint-disable-next-line max-len -const PATH_FILM_SIMULATION_DYNAMIC = `${PREFIX_FILM_SIMULATION}/[simulation]`; +const PATH_FILM_DYNAMIC = `${PREFIX_FILM}/[film]`; const PATH_FOCAL_LENGTH_DYNAMIC = `${PREFIX_FOCAL_LENGTH}/[focal]`; const PATH_RECIPE_DYNAMIC = `${PREFIX_RECIPE}/[recipe]`; @@ -86,7 +85,7 @@ export const PATHS_TO_CACHE = [ PATH_CAMERA_DYNAMIC, PATH_LENS_DYNAMIC, PATH_TAG_DYNAMIC, - PATH_FILM_SIMULATION_DYNAMIC, + PATH_FILM_DYNAMIC, PATH_FOCAL_LENGTH_DYNAMIC, PATH_RECIPE_DYNAMIC, ...PATHS_ADMIN, @@ -121,7 +120,7 @@ export const pathForPhoto = ({ camera, lens, tag, - film: simulation, + film, focal, recipe, }: PhotoPathParams) => { @@ -135,8 +134,8 @@ export const pathForPhoto = ({ prefix = pathForLens(lens); } else if (tag) { prefix = pathForTag(tag); - } else if (simulation) { - prefix = pathForFilmSimulation(simulation); + } else if (film) { + prefix = pathForFilm(film); } else if (recipe) { prefix = pathForRecipe(recipe); } else if (focal) { @@ -152,8 +151,8 @@ export const pathForTag = (tag: string) => export const pathForCamera = ({ make, model }: Camera) => `${PREFIX_CAMERA}/${parameterize(make)}/${parameterize(model)}`; -export const pathForFilmSimulation = (simulation: FilmSimulation) => - `${PREFIX_FILM_SIMULATION}/${simulation}`; +export const pathForFilm = (film: FilmSimulation) => + `${PREFIX_FILM}/${film}`; export const pathForLens = ({ make, model }: Lens) => make @@ -178,8 +177,8 @@ export const absolutePathForCamera= (camera: Camera) => export const absolutePathForLens= (lens: Lens) => `${BASE_URL}${pathForLens(lens)}`; -export const absolutePathForFilmSimulation = (simulation: FilmSimulation) => - `${BASE_URL}${pathForFilmSimulation(simulation)}`; +export const absolutePathForFilm = (film: FilmSimulation) => + `${BASE_URL}${pathForFilm(film)}`; export const absolutePathForRecipe = (recipe: string) => `${BASE_URL}${pathForRecipe(recipe)}`; @@ -199,9 +198,8 @@ export const absolutePathForCameraImage= (camera: Camera) => export const absolutePathForLensImage= (lens: Lens) => `${absolutePathForLens(lens)}/image`; -export const absolutePathForFilmSimulationImage = - (simulation: FilmSimulation) => - `${absolutePathForFilmSimulation(simulation)}/image`; +export const absolutePathForFilmImage = (film: FilmSimulation) => + `${absolutePathForFilm(film)}/image`; export const absolutePathForRecipeImage = (recipe: string) => `${absolutePathForRecipe(recipe)}/image`; @@ -230,13 +228,13 @@ export const isPathCamera = (pathname = '') => export const isPathCameraPhoto = (pathname = '') => new RegExp(`^${PREFIX_CAMERA}/[^/]+/[^/]+/[^/]+/?$`).test(pathname); -// film/[simulation] -export const isPathFilmSimulation = (pathname = '') => - new RegExp(`^${PREFIX_FILM_SIMULATION}/[^/]+/?$`).test(pathname); +// film/[film] +export const isPathFilm = (pathname = '') => + new RegExp(`^${PREFIX_FILM}/[^/]+/?$`).test(pathname); -// film/[simulation]/[photoId] -export const isPathFilmSimulationPhoto = (pathname = '') => - new RegExp(`^${PREFIX_FILM_SIMULATION}/[^/]+/[^/]+/?$`).test(pathname); +// film/[film]/[photoId] +export const isPathFilmPhoto = (pathname = '') => + new RegExp(`^${PREFIX_FILM}/[^/]+/[^/]+/?$`).test(pathname); // focal/[focal] export const isPathFocalLength = (pathname = '') => @@ -299,8 +297,8 @@ export const getPathComponents = (pathname = ''): { new RegExp(`^${PREFIX_TAG}/[^/]+/([^/]+)`))?.[1]; const photoIdFromCamera = pathname.match( new RegExp(`^${PREFIX_CAMERA}/[^/]+/[^/]+/([^/]+)`))?.[1]; - const photoIdFromFilmSimulation = pathname.match( - new RegExp(`^${PREFIX_FILM_SIMULATION}/[^/]+/([^/]+)`))?.[1]; + const photoIdFromFilm = pathname.match( + new RegExp(`^${PREFIX_FILM}/[^/]+/([^/]+)`))?.[1]; const photoIdFromFocalLength = pathname.match( new RegExp(`^${PREFIX_FOCAL_LENGTH}/[0-9]+mm/([^/]+)`))?.[1]; const tag = pathname.match( @@ -309,8 +307,8 @@ export const getPathComponents = (pathname = ''): { new RegExp(`^${PREFIX_CAMERA}/([^/]+)`))?.[1]; const cameraModel = pathname.match( new RegExp(`^${PREFIX_CAMERA}/[^/]+/([^/]+)`))?.[1]; - const simulation = pathname.match( - new RegExp(`^${PREFIX_FILM_SIMULATION}/([^/]+)`))?.[1] as FilmSimulation; + const film = pathname.match( + new RegExp(`^${PREFIX_FILM}/([^/]+)`))?.[1] as FilmSimulation; const focalString = pathname.match( new RegExp(`^${PREFIX_FOCAL_LENGTH}/([0-9]+)mm`))?.[1]; @@ -325,12 +323,12 @@ export const getPathComponents = (pathname = ''): { photoIdFromPhoto || photoIdFromTag || photoIdFromCamera || - photoIdFromFilmSimulation || + photoIdFromFilm || photoIdFromFocalLength ), tag, camera, - film: simulation, + film, focal, }; }; @@ -340,7 +338,7 @@ export const getEscapePath = (pathname?: string) => { photoId, tag, camera, - film: simulation, + film, focal, } = getPathComponents(pathname); @@ -348,7 +346,7 @@ export const getEscapePath = (pathname?: string) => { (photoId && isPathPhoto(pathname)) || (tag && isPathTag(pathname)) || (camera && isPathCamera(pathname)) || - (simulation && isPathFilmSimulation(pathname)) || + (film && isPathFilm(pathname)) || (focal && isPathFocalLength(pathname)) ) { return PATH_ROOT; @@ -356,8 +354,8 @@ export const getEscapePath = (pathname?: string) => { return pathForTag(tag); } else if (camera && isPathCameraPhoto(pathname)) { return pathForCamera(camera); - } else if (simulation && isPathFilmSimulationPhoto(pathname)) { - return pathForFilmSimulation(simulation); + } else if (film && isPathFilmPhoto(pathname)) { + return pathForFilm(film); } else if (focal && isPathFocalLengthPhoto(pathname)) { return pathForFocalLength(focal); } diff --git a/src/category/data.ts b/src/category/data.ts index 30c646e4..f4b6e8f3 100644 --- a/src/category/data.ts +++ b/src/category/data.ts @@ -1,13 +1,13 @@ import { getUniqueCameras, - getUniqueFilmSimulations, + getUniqueFilms, getUniqueFocalLengths, getUniqueLenses, getUniqueRecipes, getUniqueTags, } from '@/photo/db/query'; import { - SHOW_FILM_SIMULATIONS, + SHOW_FILMS, SHOW_FOCAL_LENGTHS, SHOW_LENSES, SHOW_RECIPES, @@ -40,8 +40,8 @@ export const getDataForCategories = () => [ .then(sortCategoriesByCount) .catch(() => []) : [], - SHOW_FILM_SIMULATIONS - ? getUniqueFilmSimulations() + SHOW_FILMS + ? getUniqueFilms() .then(sortCategoriesByCount) .catch(() => []) : [], @@ -58,7 +58,7 @@ export const getCountsForCategories = async () => { lenses, tags, recipes, - filmSimulations, + films, focalLengths, ] = await Promise.all(getDataForCategories()); @@ -79,8 +79,8 @@ export const getCountsForCategories = async () => { acc[recipe.recipe] = recipe.count; return acc; }, {} as Record), - filmSimulations: filmSimulations.reduce((acc, filmSimulation) => { - acc[filmSimulation.film] = filmSimulation.count; + films: films.reduce((acc, film) => { + acc[film.film] = film.count; return acc; }, {} as Record), focalLengths: focalLengths.reduce((acc, focalLength) => { diff --git a/src/category/index.ts b/src/category/index.ts index 37097f18..698330cc 100644 --- a/src/category/index.ts +++ b/src/category/index.ts @@ -1,7 +1,7 @@ import { Photo } from '../photo'; import { Camera, Cameras } from '@/camera'; import { PhotoDateRange } from '../photo'; -import { FilmSimulation, FilmSimulations } from '@/film'; +import { FilmSimulation, Films } from '@/film'; import { Lens, Lenses } from '@/lens'; import { Tags } from '@/tag'; import { FocalLengths } from '@/focal'; @@ -48,7 +48,7 @@ export interface PhotoSetCategories { lenses: Lenses tags: Tags recipes: Recipes - films: FilmSimulations + films: Films focalLengths: FocalLengths } diff --git a/src/category/useCategoryCounts.ts b/src/category/useCategoryCounts.ts index 75e9bbf6..1d5a02f1 100644 --- a/src/category/useCategoryCounts.ts +++ b/src/category/useCategoryCounts.ts @@ -4,6 +4,7 @@ import { Camera } from '@/camera'; import { Lens } from '@/lens'; import { useAppState } from '@/state/AppState'; import { useCallback } from 'react'; +import { FujifilmSimulation } from '@/platforms/fujifilm/simulation'; export default function useCategoryCounts() { const { categoriesWithCounts } = useAppState(); @@ -28,9 +29,9 @@ export default function useCategoryCounts() { return recipeCounts[recipe]; }, [categoriesWithCounts]); - const getFilmSimulationCount = useCallback((simulation: string) => { - const filmSimulationCounts = categoriesWithCounts?.filmSimulations ?? {}; - return filmSimulationCounts[simulation]; + const getFilmCount = useCallback((film: FujifilmSimulation) => { + const filmCounts = categoriesWithCounts?.films ?? {}; + return filmCounts[film]; }, [categoriesWithCounts]); const getFocalLengthCount = useCallback((focalLength: number) => { @@ -43,7 +44,7 @@ export default function useCategoryCounts() { getLensCount, getTagCount, getRecipeCount, - getFilmSimulationCount, + getFilmCount, getFocalLengthCount, }; } diff --git a/src/category/useCategoryCountsForPhoto.ts b/src/category/useCategoryCountsForPhoto.ts index 86b50620..b059ffdb 100644 --- a/src/category/useCategoryCountsForPhoto.ts +++ b/src/category/useCategoryCountsForPhoto.ts @@ -10,7 +10,7 @@ export default function useCategoryCountsForPhoto(photo: Photo) { getLensCount, getTagCount, getRecipeCount, - getFilmSimulationCount, + getFilmCount, getFocalLengthCount, } = useCategoryCounts(); @@ -25,21 +25,20 @@ export default function useCategoryCountsForPhoto(photo: Photo) { return acc; }, {} as Record), recipeCount: photo.recipeTitle ? getRecipeCount(photo.recipeTitle) : 0, - simulationCount: - photo.filmSimulation ? getFilmSimulationCount(photo.filmSimulation) : 0, + filmCount: photo.film ? getFilmCount(photo.film) : 0, focalCount: photo.focalLength ? getFocalLengthCount(photo.focalLength) : 0, }), [ getCameraCount, getLensCount, getRecipeCount, - getFilmSimulationCount, + getFilmCount, getFocalLengthCount, getTagCount, camera, lens, photo.tags, photo.recipeTitle, - photo.filmSimulation, + photo.film, photo.focalLength, ]); diff --git a/src/cmdk/CommandKClient.tsx b/src/cmdk/CommandKClient.tsx index 7240f8a4..aaddd55d 100644 --- a/src/cmdk/CommandKClient.tsx +++ b/src/cmdk/CommandKClient.tsx @@ -25,7 +25,7 @@ import { PATH_ROOT, PATH_SIGN_IN, pathForCamera, - pathForFilmSimulation, + pathForFilm, pathForFocalLength, pathForLens, pathForPhoto, @@ -333,13 +333,13 @@ export default function CommandKClient({ })), }; case 'films': return { - heading: 'Film Simulations', + heading: 'Films', accessory: , items: films.map(({ film, count }) => ({ label: labelForFilm(film).medium, annotation: formatCount(count), annotationAria: formatCountDescriptive(count), - path: pathForFilmSimulation(film), + path: pathForFilm(film), })), }; case 'focal-lengths': return { diff --git a/src/film/FilmHeader.tsx b/src/film/FilmHeader.tsx index 7af43c1f..ee2b14f6 100644 --- a/src/film/FilmHeader.tsx +++ b/src/film/FilmHeader.tsx @@ -1,17 +1,17 @@ import { Photo, PhotoDateRange } from '@/photo'; -import { FilmSimulation, descriptionForFilmSimulationPhotos } from '.'; +import { FilmSimulation, descriptionForFilmPhotos } from '.'; import PhotoHeader from '@/photo/PhotoHeader'; import PhotoFilm from '@/film/PhotoFilm'; export default function FilmHeader({ - simulation, + film, photos, selectedPhoto, indexNumber, count, dateRange, }: { - simulation: FilmSimulation + film: FilmSimulation photos: Photo[] selectedPhoto?: Photo indexNumber?: number @@ -20,9 +20,9 @@ export default function FilmHeader({ }) { return ( } - entityDescription={descriptionForFilmSimulationPhotos( + film={film} + entity={} + entityDescription={descriptionForFilmPhotos( photos, undefined, count, dateRange)} photos={photos} selectedPhoto={selectedPhoto} diff --git a/src/film/FilmOGTile.tsx b/src/film/FilmOGTile.tsx index e08ea744..19f7843a 100644 --- a/src/film/FilmOGTile.tsx +++ b/src/film/FilmOGTile.tsx @@ -1,19 +1,19 @@ import { Photo, PhotoDateRange } from '@/photo'; import { - absolutePathForFilmSimulationImage, - pathForFilmSimulation, + absolutePathForFilmImage, + pathForFilm, } from '@/app/paths'; import OGTile from '@/components/OGTile'; import { FilmSimulation, - descriptionForFilmSimulationPhotos, - titleForFilmSimulation, + descriptionForFilmPhotos, + titleForFilm, } from '.'; export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed'; export default function FilmOGTile({ - simulation, + film, photos, loadingState: loadingStateExternal, riseOnHover, @@ -23,7 +23,7 @@ export default function FilmOGTile({ count, dateRange, }: { - simulation: FilmSimulation + film: FilmSimulation photos: Photo[] loadingState?: OGLoadingState onLoad?: () => void @@ -35,11 +35,11 @@ export default function FilmOGTile({ }) { return ( - + ); }; diff --git a/src/film/PhotoFilm.tsx b/src/film/PhotoFilm.tsx index 17172c1a..3b6136ac 100644 --- a/src/film/PhotoFilm.tsx +++ b/src/film/PhotoFilm.tsx @@ -1,6 +1,6 @@ import { labelForFilm } from '@/platforms/fujifilm/simulation'; import PhotoFilmIcon from './PhotoFilmIcon'; -import { pathForFilmSimulation } from '@/app/paths'; +import { pathForFilm } from '@/app/paths'; import { FilmSimulation } from '.'; import { FujifilmRecipe } from '@/platforms/fujifilm/recipe'; import EntityLink, { @@ -9,27 +9,27 @@ import EntityLink, { import clsx from 'clsx/lite'; export default function PhotoFilm({ - simulation, + film, type = 'icon-last', badged = true, contrast = 'low', countOnHover, ...props }: { - simulation: FilmSimulation + film: FilmSimulation countOnHover?: number recipe?: FujifilmRecipe } & EntityLinkExternalProps) { - const { small, medium, large } = labelForFilm(simulation); + const { small, medium, large } = labelForFilm(film); return ( } - title={`Film Simulation: ${large}`} + title={`Film: ${large}`} type={type} badged={badged} contrast={contrast} diff --git a/src/film/PhotoFilmIcon.tsx b/src/film/PhotoFilmIcon.tsx index 7bd4a737..c7db5dbf 100644 --- a/src/film/PhotoFilmIcon.tsx +++ b/src/film/PhotoFilmIcon.tsx @@ -7,12 +7,12 @@ const INTRINSIC_WIDTH = 28; const INTRINSIC_HEIGHT = 16; export default function PhotoFilmIcon({ - simulation, + film, height = INTRINSIC_HEIGHT, className, style, }: { - simulation?: FilmSimulation + film?: FilmSimulation height?: number className?: string style?: CSSProperties @@ -21,9 +21,9 @@ export default function PhotoFilmIcon({ { // Self-calling switch function and non-fragment groups // necessary for ImageResponse compatibility - switch (simulation) { + switch (film) { case 'monochrome': return diff --git a/src/film/data.ts b/src/film/data.ts index b9179198..227f5f9b 100644 --- a/src/film/data.ts +++ b/src/film/data.ts @@ -4,14 +4,14 @@ import { } from '@/photo/cache'; import { FilmSimulation } from '.'; -export const getPhotosFilmSimulationDataCached = ({ - simulation, +export const getPhotosFilmDataCached = ({ + film, limit, }: { - simulation: FilmSimulation, + film: FilmSimulation, limit?: number, }) => Promise.all([ - getPhotosCached({ film: simulation, limit }), - getPhotosMetaCached({ film: simulation }), + getPhotosCached({ film, limit }), + getPhotosMetaCached({ film }), ]); diff --git a/src/film/index.ts b/src/film/index.ts index 98ad1925..b360e70f 100644 --- a/src/film/index.ts +++ b/src/film/index.ts @@ -5,8 +5,8 @@ import { photoQuantityText, } from '@/photo'; import { - absolutePathForFilmSimulation, - absolutePathForFilmSimulationImage, + absolutePathForFilm, + absolutePathForFilmImage, } from '@/app/paths'; import { FujifilmSimulation, @@ -15,27 +15,27 @@ import { export type FilmSimulation = FujifilmSimulation; -export type FilmSimulationWithCount = { +export type FilmWithCount = { film: FilmSimulation count: number } -export type FilmSimulations = FilmSimulationWithCount[] +export type Films = FilmWithCount[] export const sortFilms = ( - films: FilmSimulations, + films: Films, ) => films.sort(sortFilmsWithCount); export const sortFilmsWithCount = ( - a: FilmSimulationWithCount, - b: FilmSimulationWithCount, + a: FilmWithCount, + b: FilmWithCount, ) => { const aLabel = labelForFilm(a.film).large; const bLabel = labelForFilm(b.film).large; return aLabel.localeCompare(bLabel); }; -export const titleForFilmSimulation = ( +export const titleForFilm = ( film: FilmSimulation, photos: Photo[], explicitCount?: number, @@ -44,12 +44,12 @@ export const titleForFilmSimulation = ( photoQuantityText(explicitCount ?? photos.length), ].join(' '); -export const shareTextForFilmSimulation = ( +export const shareTextForFilm = ( film: FilmSimulation, ) => `Photos shot on Fujifilm ${labelForFilm(film).large}`; -export const descriptionForFilmSimulationPhotos = ( +export const descriptionForFilmPhotos = ( photos: Photo[], dateBased?: boolean, explicitCount?: number, @@ -63,22 +63,22 @@ export const descriptionForFilmSimulationPhotos = ( explicitDateRange, ); -export const generateMetaForFilmSimulation = ( +export const generateMetaForFilm = ( film: FilmSimulation, photos: Photo[], explicitCount?: number, explicitDateRange?: PhotoDateRange, ) => ({ - url: absolutePathForFilmSimulation(film), - title: titleForFilmSimulation(film, photos, explicitCount), - description: descriptionForFilmSimulationPhotos( + url: absolutePathForFilm(film), + title: titleForFilm(film, photos, explicitCount), + description: descriptionForFilmPhotos( photos, true, explicitCount, explicitDateRange, ), - images: absolutePathForFilmSimulationImage(film), + images: absolutePathForFilmImage(film), }); -export const photoHasFilmSimulationData = (photo: Photo) => - Boolean(photo.filmSimulation); +export const photoHasFilmData = (photo: Photo) => + Boolean(photo.film); diff --git a/src/image-response/FilmImageResponse.tsx b/src/image-response/FilmImageResponse.tsx index 56287002..68bb0cf5 100644 --- a/src/image-response/FilmImageResponse.tsx +++ b/src/image-response/FilmImageResponse.tsx @@ -11,13 +11,13 @@ import { FilmSimulation } from '@/film'; import { NextImageSize } from '@/platforms/next-image'; export default function FilmImageResponse({ - simulation, + film, photos, width, height, fontFamily, }: { - simulation: FilmSimulation, + film: FilmSimulation, photos: Photo[] width: NextImageSize height: number @@ -37,11 +37,11 @@ export default function FilmImageResponse({ height, fontFamily, icon: , - title: labelForFilm(simulation).medium.toLocaleUpperCase(), + title: labelForFilm(film).medium.toLocaleUpperCase(), }} /> ); diff --git a/src/image-response/RecipeImageResponse.tsx b/src/image-response/RecipeImageResponse.tsx index a0540cce..f3caddf1 100644 --- a/src/image-response/RecipeImageResponse.tsx +++ b/src/image-response/RecipeImageResponse.tsx @@ -27,13 +27,13 @@ export default function RecipeImageResponse({ }) { const { recipeData, - filmSimulation, + film, } = getPhotoWithRecipeFromPhotos(photos) ?? {}; - let recipeLines = recipeData && filmSimulation + let recipeLines = recipeData && film ? generateRecipeText({ recipe: recipeData, - simulation: filmSimulation, + film, }, true) : []; @@ -109,10 +109,10 @@ export default function RecipeImageResponse({ flexGrow: 1, }}> {text} - {isStringFilmSimulation(text) && filmSimulation && + {isStringFilmSimulation(text) && film &&
diff --git a/src/photo/InfinitePhotoScroll.tsx b/src/photo/InfinitePhotoScroll.tsx index cc9ebcfc..0b2394b3 100644 --- a/src/photo/InfinitePhotoScroll.tsx +++ b/src/photo/InfinitePhotoScroll.tsx @@ -29,10 +29,12 @@ export default function InfinitePhotoScroll({ initialOffset, itemsPerPage, sortBy, - tag, camera, lens, - film: simulation, + tag, + recipe, + film, + focal, wrapMoreButtonInGrid, useCachedPhotos = true, includeHiddenPhotos, @@ -73,7 +75,9 @@ export default function InfinitePhotoScroll({ camera, lens, tag, - film: simulation, + recipe, + film, + focal, }, warmOnly) , [ useCachedPhotos, @@ -84,7 +88,9 @@ export default function InfinitePhotoScroll({ camera, lens, tag, - simulation, + recipe, + film, + focal, ]); const { data, isLoading, isValidating, error, mutate, size, setSize } = diff --git a/src/photo/PhotoDetailPage.tsx b/src/photo/PhotoDetailPage.tsx index 6f529bc5..f67c0414 100644 --- a/src/photo/PhotoDetailPage.tsx +++ b/src/photo/PhotoDetailPage.tsx @@ -22,7 +22,7 @@ export default function PhotoDetailPage({ tag, camera, lens, - film: simulation, + film, recipe, focal, indexNumber, @@ -77,9 +77,9 @@ export default function PhotoDetailPage({ count={count} dateRange={dateRange} />; - } else if (simulation) { + } else if (film) { customHeader = } diff --git a/src/photo/PhotoGridSidebar.tsx b/src/photo/PhotoGridSidebar.tsx index 095dbf20..72116450 100644 --- a/src/photo/PhotoGridSidebar.tsx +++ b/src/photo/PhotoGridSidebar.tsx @@ -48,7 +48,7 @@ export default function PhotoGridSidebar({ cameras, lenses, tags, - films: simulations, + films, recipes, focalLengths, } = categories; @@ -192,17 +192,17 @@ export default function PhotoGridSidebar({ /> : null; - const filmsContent = simulations.length > 0 + const filmsContent = films.length > 0 ? } maxItems={maxItemsPerCategory} - items={simulations - .map(({ film: simulation, count }) => + items={films + .map(({ film, count }) => 0; const showRecipeContent = showRecipe && shouldShowRecipeDataForPhoto(photo); const showRecipeButton = shouldShowRecipeDataForPhoto(photo); - const showSimulationContent = showSimulation && - shouldShowFilmSimulationDataForPhoto(photo); + const showFilmContent = showFilm && shouldShowFilmDataForPhoto(photo); useVisible({ ref, onVisible }); @@ -168,7 +167,7 @@ export default function PhotoLarge({ showLensContent || showTagsContent || showRecipeContent || - showSimulationContent || + showFilmContent || showExifContent; const hasNonDateContent = @@ -226,12 +225,12 @@ export default function PhotoLarge({ {(shouldShowRecipeOverlay || shouldDebugRecipeOverlays) && photo.recipeData && - photo.filmSimulation && + photo.film && {photo.isoFormatted}
  • {photo.exposureCompensationFormatted ?? '0ev'}
  • - {(showRecipeButton || showSimulationContent) && + {(showRecipeButton || showFilmContent) &&
    - {showSimulationContent && photo.filmSimulation && + {showFilmContent && photo.film && } {showRecipeButton && @@ -415,7 +414,7 @@ export default function PhotoLarge({ 'px-[4px] py-[2.5px] my-[-3px]', 'translate-y-[2px]', 'hover:bg-dim active:bg-main', - !showSimulation && 'translate-x-[-2px]', + !showFilm && 'translate-x-[-2px]', )}> {shouldShowRecipeOverlay ? @@ -464,8 +463,8 @@ export default function PhotoLarge({ tag={shouldShareTag ? primaryTag : undefined} camera={shouldShareCamera ? camera : undefined} lens={shouldShareLens ? lens : undefined} - film={shouldShareSimulation - ? photo.filmSimulation + film={shouldShareFilm + ? photo.film : undefined} recipe={shouldShareRecipe ? recipeTitle diff --git a/src/photo/actions.ts b/src/photo/actions.ts index 5950f553..b3843331 100644 --- a/src/photo/actions.ts +++ b/src/photo/actions.ts @@ -315,13 +315,13 @@ export const renamePhotoTagGloballyAction = async (formData: FormData) => export const getPhotosNeedingRecipeTitleCountAction = async ( recipeData: string, - simulation: FilmSimulation, + film: FilmSimulation, photoIdToExclude?: string, ) => runAuthenticatedAdminServerAction(async () => await getPhotosNeedingRecipeTitleCount( recipeData, - simulation, + film, photoIdToExclude, ), ); diff --git a/src/photo/cache.ts b/src/photo/cache.ts index e46ee873..98a49565 100644 --- a/src/photo/cache.ts +++ b/src/photo/cache.ts @@ -10,7 +10,7 @@ import { getUniqueCameras, getUniqueTags, getUniqueTagsHidden, - getUniqueFilmSimulations, + getUniqueFilms, getPhotosNearId, getPhotosMostRecentUpdate, getPhotosMeta, @@ -29,7 +29,7 @@ import { PATH_GRID, PATH_ROOT, PREFIX_CAMERA, - PREFIX_FILM_SIMULATION, + PREFIX_FILM, PREFIX_FOCAL_LENGTH, PREFIX_LENS, PREFIX_RECIPE, @@ -45,7 +45,7 @@ const KEY_PHOTO = 'photo'; const KEY_CAMERAS = 'cameras'; const KEY_LENSES = 'lenses'; const KEY_TAGS = 'tags'; -const KEY_FILM_SIMULATIONS = 'film-simulations'; +const KEY_FILMS = 'films'; const KEY_RECIPES = 'recipes'; const KEY_FOCAL_LENGTHS = 'focal-lengths'; // Type keys @@ -109,8 +109,8 @@ export const revalidateCamerasKey = () => export const revalidateLensesKey = () => revalidateTag(KEY_LENSES); -export const revalidateFilmSimulationsKey = () => - revalidateTag(KEY_FILM_SIMULATIONS); +export const revalidateFilmsKey = () => + revalidateTag(KEY_FILMS); export const revalidateFocalLengthsKey = () => revalidateTag(KEY_FOCAL_LENGTHS); @@ -120,7 +120,7 @@ export const revalidateAllKeys = () => { revalidateTagsKey(); revalidateCamerasKey(); revalidateLensesKey(); - revalidateFilmSimulationsKey(); + revalidateFilmsKey(); revalidateRecipesKey(); revalidateFocalLengthsKey(); }; @@ -140,7 +140,7 @@ export const revalidatePhoto = (photoId: string) => { revalidateTagsKey(); revalidateCamerasKey(); revalidateLensesKey(); - revalidateFilmSimulationsKey(); + revalidateFilmsKey(); revalidateRecipesKey(); revalidateFocalLengthsKey(); // Paths @@ -151,7 +151,7 @@ export const revalidatePhoto = (photoId: string) => { revalidatePath(PREFIX_TAG, 'layout'); revalidatePath(PREFIX_CAMERA, 'layout'); revalidatePath(PREFIX_LENS, 'layout'); - revalidatePath(PREFIX_FILM_SIMULATION, 'layout'); + revalidatePath(PREFIX_FILM, 'layout'); revalidatePath(PREFIX_RECIPE, 'layout'); revalidatePath(PREFIX_FOCAL_LENGTH, 'layout'); revalidatePath(PATH_ADMIN, 'layout'); @@ -231,10 +231,10 @@ export const getUniqueLensesCached = [KEY_PHOTOS, KEY_LENSES], ); -export const getUniqueFilmSimulationsCached = +export const getUniqueFilmsCached = unstable_cache( - getUniqueFilmSimulations, - [KEY_PHOTOS, KEY_FILM_SIMULATIONS], + getUniqueFilms, + [KEY_PHOTOS, KEY_FILMS], ); export const getUniqueRecipesCached = diff --git a/src/photo/db/index.ts b/src/photo/db/index.ts index e1b1da2c..f15d954c 100644 --- a/src/photo/db/index.ts +++ b/src/photo/db/index.ts @@ -47,7 +47,7 @@ export const getWheresFromOptions = ( tag, camera, lens, - film: simulation, + film, recipe, focal, } = options; @@ -108,9 +108,9 @@ export const getWheresFromOptions = ( wheres.push(`$${valuesIndex++}=ANY(tags)`); wheresValues.push(tag); } - if (simulation) { - wheres.push(`film_simulation=$${valuesIndex++}`); - wheresValues.push(simulation); + if (film) { + wheres.push(`film=$${valuesIndex++}`); + wheresValues.push(film); } if (recipe) { wheres.push(`recipe_title=$${valuesIndex++}`); diff --git a/src/photo/db/migration.ts b/src/photo/db/migration.ts index 8693e3f3..2dbeb765 100644 --- a/src/photo/db/migration.ts +++ b/src/photo/db/migration.ts @@ -50,6 +50,27 @@ export const MIGRATIONS: Migration[] = [{ ALTER TABLE photos ADD COLUMN IF NOT EXISTS recipe_title VARCHAR(255) `, +}, { + label: '05: Universal Film', + fields: ['film'], + run: () => sql` + DO $$ + BEGIN + IF EXISTS( + SELECT 1 + FROM information_schema.columns + WHERE table_name='photos' + AND column_name='film_simulation' + ) + THEN + ALTER TABLE photos + RENAME COLUMN film_simulation TO film; + ELSE + ALTER TABLE photos + ADD COLUMN IF NOT EXISTS film VARCHAR(255); + END IF; + END $$; + `, }]; export const migrationForError = (e: any) => diff --git a/src/photo/db/query.ts b/src/photo/db/query.ts index 86c8c59d..9af7bf0c 100644 --- a/src/photo/db/query.ts +++ b/src/photo/db/query.ts @@ -13,7 +13,7 @@ import { } from '@/photo'; import { Cameras, createCameraKey } from '@/camera'; import { Tags } from '@/tag'; -import { FilmSimulation, FilmSimulations } from '@/film'; +import { FilmSimulation, Films } from '@/film'; import { ADMIN_SQL_DEBUG_ENABLED } from '@/app/config'; import { GetPhotosOptions, @@ -53,7 +53,7 @@ const createPhotosTable = () => location_name VARCHAR(255), latitude DOUBLE PRECISION, longitude DOUBLE PRECISION, - film_simulation VARCHAR(255), + film VARCHAR(255), recipe_title VARCHAR(255), recipe_data JSONB, priority_order REAL, @@ -160,7 +160,7 @@ export const insertPhoto = (photo: PhotoDbInsert) => location_name, latitude, longitude, - film_simulation, + film, recipe_title, recipe_data, priority_order, @@ -191,7 +191,7 @@ export const insertPhoto = (photo: PhotoDbInsert) => ${photo.locationName}, ${photo.latitude}, ${photo.longitude}, - ${photo.filmSimulation}, + ${photo.film}, ${photo.recipeTitle}, ${photo.recipeData}, ${photo.priorityOrder}, @@ -225,7 +225,7 @@ export const updatePhoto = (photo: PhotoDbInsert) => location_name=${photo.locationName}, latitude=${photo.latitude}, longitude=${photo.longitude}, - film_simulation=${photo.filmSimulation}, + film=${photo.film}, recipe_title=${photo.recipeTitle}, recipe_data=${photo.recipeData}, priority_order=${photo.priorityOrder || null}, @@ -367,14 +367,14 @@ export const getUniqueRecipes = async () => export const getRecipeTitleForData = async ( data: string | object, - simulation: FilmSimulation, + film: FilmSimulation, ) => // Includes legacy check on pre-stringified JSON safelyQueryPhotos(() => sql` SELECT recipe_title FROM photos WHERE hidden IS NOT TRUE AND recipe_data=${typeof data === 'string' ? data : JSON.stringify(data)} - AND film_simulation=${simulation} + AND film=${film} LIMIT 1 ` .then(({ rows }) => rows[0]?.recipe_title as string | undefined) @@ -382,7 +382,7 @@ export const getRecipeTitleForData = async ( export const getPhotosNeedingRecipeTitleCount = async ( data: string, - simulation: FilmSimulation, + film: FilmSimulation, photoIdToExclude?: string, ) => safelyQueryPhotos(() => sql` @@ -390,7 +390,7 @@ export const getPhotosNeedingRecipeTitleCount = async ( FROM photos WHERE recipe_title IS NULL AND recipe_data=${data} - AND film_simulation=${simulation} + AND film=${film} AND id <> ${photoIdToExclude} `.then(({ rows }) => parseInt(rows[0].count, 10)) , 'getPhotosNeedingRecipeTitleCount'); @@ -398,29 +398,29 @@ export const getPhotosNeedingRecipeTitleCount = async ( export const updateAllMatchingRecipeTitles = ( title: string, data: string, - simulation: FilmSimulation, + film: FilmSimulation, ) => safelyQueryPhotos(() => sql` UPDATE photos SET recipe_title=${title} WHERE recipe_title IS NULL AND recipe_data=${data} - AND film_simulation=${simulation} + AND film=${film} `, 'updateAllMatchingRecipeTitles'); -export const getUniqueFilmSimulations = async () => +export const getUniqueFilms = async () => safelyQueryPhotos(() => sql` - SELECT DISTINCT film_simulation, COUNT(*) + SELECT DISTINCT film, COUNT(*) FROM photos - WHERE hidden IS NOT TRUE AND film_simulation IS NOT NULL - GROUP BY film_simulation - ORDER BY film_simulation ASC - `.then(({ rows }): FilmSimulations => rows - .map(({ film_simulation, count }) => ({ - film: film_simulation as FilmSimulation, + WHERE hidden IS NOT TRUE AND film IS NOT NULL + GROUP BY film + ORDER BY film ASC + `.then(({ rows }): Films => rows + .map(({ film, count }) => ({ + film: film as FilmSimulation, count: parseInt(count, 10), }))) - , 'getUniqueFilmSimulations'); + , 'getUniqueFilms'); export const getUniqueFocalLengths = async () => safelyQueryPhotos(() => sql` diff --git a/src/photo/form/ApplyRecipesGloballyCheckbox.tsx b/src/photo/form/ApplyRecipesGloballyCheckbox.tsx index 3f87eaba..6bd5f7ce 100644 --- a/src/photo/form/ApplyRecipesGloballyCheckbox.tsx +++ b/src/photo/form/ApplyRecipesGloballyCheckbox.tsx @@ -8,7 +8,7 @@ export default function ApplyRecipeTitleGloballyCheckbox({ recipeTitle, hasRecipeTitleChanged, recipeData, - simulation, + film, onMatchResults, ...props }: ComponentProps & { @@ -16,7 +16,7 @@ export default function ApplyRecipeTitleGloballyCheckbox({ recipeTitle?: string hasRecipeTitleChanged?: boolean recipeData?: string - simulation?: FilmSimulation + film?: FilmSimulation onMatchResults: (didFindMatchingPhotos: boolean) => void }) { const [matchingPhotosCount, setMatchingPhotosCount] = useState(); @@ -24,14 +24,14 @@ export default function ApplyRecipeTitleGloballyCheckbox({ const loading = matchingPhotosCount === undefined; useEffect(() => { - if (recipeTitle && hasRecipeTitleChanged && recipeData && simulation) { + if (recipeTitle && hasRecipeTitleChanged && recipeData && film) { setMatchingPhotosCount(undefined); - getPhotosNeedingRecipeTitleCountAction(recipeData, simulation, photoId) + getPhotosNeedingRecipeTitleCountAction(recipeData, film, photoId) .then(setMatchingPhotosCount); } else { setMatchingPhotosCount(0); } - }, [recipeTitle, hasRecipeTitleChanged, recipeData, simulation, photoId]); + }, [recipeTitle, hasRecipeTitleChanged, recipeData, film, photoId]); useEffect(() => { onMatchResults((matchingPhotosCount ?? 0) > 0); diff --git a/src/photo/form/PhotoForm.tsx b/src/photo/form/PhotoForm.tsx index cf2dfc36..8ea391a0 100644 --- a/src/photo/form/PhotoForm.tsx +++ b/src/photo/form/PhotoForm.tsx @@ -414,7 +414,7 @@ export default function PhotoForm({ hasRecipeTitleChanged={ changedFormKeys.includes('recipeTitle')} recipeData={formData.recipeData} - simulation={formData.filmSimulation as FilmSimulation} + film={formData.film as FilmSimulation} onMatchResults={onMatchResults} {...fieldProps} />; diff --git a/src/photo/form/index.ts b/src/photo/form/index.ts index 9c5603bd..19cada9b 100644 --- a/src/photo/form/index.ts +++ b/src/photo/form/index.ts @@ -119,8 +119,8 @@ const FORM_METADATA = ( aspectRatio: { label: 'aspect ratio', readOnly: true }, make: { label: 'camera make' }, model: { label: 'camera model' }, - filmSimulation: { - label: 'fujifilm simulation', + film: { + label: 'film', selectOptions: FILM_SIMULATION_FORM_INPUT_OPTIONS, selectOptionsDefaultLabel: 'Unknown', shouldHide: ({ make }) => make !== MAKE_FUJIFILM, @@ -274,7 +274,7 @@ export const convertPhotoToFormData = (photo: Photo): PhotoFormData => { export const convertExifToFormData = ( data: ExifData, - filmSimulation?: FilmSimulation, + film?: FilmSimulation, recipeData?: FujifilmRecipe, ): Omit< Record, @@ -298,7 +298,7 @@ export const convertExifToFormData = ( !GEO_PRIVACY_ENABLED ? data.tags?.GPSLatitude?.toString() : undefined, longitude: !GEO_PRIVACY_ENABLED ? data.tags?.GPSLongitude?.toString() : undefined, - filmSimulation, + film, recipeData: JSON.stringify(recipeData), ...data.tags?.DateTimeOriginal && { takenAt: convertTimestampWithOffsetToPostgresString( @@ -345,7 +345,7 @@ export const convertFormDataToPhotoDbInsert = ( return { ...(photoForm as PhotoFormData & { - filmSimulation?: FilmSimulation + film?: FilmSimulation recipeData?: FujifilmRecipe }), ...!photoForm.id && { id: generateNanoid() }, diff --git a/src/photo/index.ts b/src/photo/index.ts index 72413883..1b0d6a33 100644 --- a/src/photo/index.ts +++ b/src/photo/index.ts @@ -1,11 +1,11 @@ import { formatFocalLength } from '@/focal'; import { getNextImageUrlForRequest } from '@/platforms/next-image'; -import { FilmSimulation, photoHasFilmSimulationData } from '@/film'; +import { FilmSimulation, photoHasFilmData } from '@/film'; import { HIGH_DENSITY_GRID, IS_PREVIEW, SHOW_EXIF_DATA, - SHOW_FILM_SIMULATIONS, + SHOW_FILMS, SHOW_LENSES, SHOW_RECIPES, } from '@/app/config'; @@ -65,7 +65,7 @@ export interface PhotoExif { exposureCompensation?: number latitude?: number longitude?: number - filmSimulation?: FilmSimulation + film?: FilmSimulation recipeData?: string takenAt?: string takenAtNaive?: string @@ -329,10 +329,10 @@ export const shouldShowRecipeDataForPhoto = (photo: Photo) => SHOW_RECIPES && photoHasRecipeData(photo); -export const shouldShowFilmSimulationDataForPhoto = (photo: Photo) => +export const shouldShowFilmDataForPhoto = (photo: Photo) => SHOW_EXIF_DATA && - SHOW_FILM_SIMULATIONS && - photoHasFilmSimulationData(photo); + SHOW_FILMS && + photoHasFilmData(photo); export const shouldShowExifDataForPhoto = (photo: Photo) => SHOW_EXIF_DATA && photoHasExifData(photo); diff --git a/src/photo/server.ts b/src/photo/server.ts index 0bdc80e6..22ab8376 100644 --- a/src/photo/server.ts +++ b/src/photo/server.ts @@ -58,7 +58,7 @@ export const extractImageDataFromBlobPath = async ( const extension = getExtensionFromStorageUrl(url); let exifData: ExifData | undefined; - let filmSimulation: FilmSimulation | undefined; + let film: FilmSimulation | undefined; let recipe: FujifilmRecipe | undefined; let blurData: string | undefined; let imageResizedBase64: string | undefined; @@ -89,7 +89,7 @@ export const extractImageDataFromBlobPath = async ( const exifDataBinary = parser.parse(); const makerNote = exifDataBinary.tags?.MakerNote; if (Buffer.isBuffer(makerNote)) { - filmSimulation = getFujifilmSimulationFromMakerNote(makerNote); + film = getFujifilmSimulationFromMakerNote(makerNote); recipe = getFujifilmRecipeFromMakerNote(makerNote); } } @@ -124,7 +124,7 @@ export const extractImageDataFromBlobPath = async ( url, }, ...generateBlurData && { blurData }, - ...convertExifToFormData(exifData, filmSimulation, recipe), + ...convertExifToFormData(exifData, film, recipe), }, }, imageResizedBase64, @@ -206,10 +206,10 @@ export const convertFormDataToPhotoDbInsertAndLookupRecipeTitle = Promise> => { const photo = convertFormDataToPhotoDbInsert(...args); - if (photo.recipeData && !photo.recipeTitle && photo.filmSimulation) { + if (photo.recipeData && !photo.recipeTitle && photo.film) { const recipeTitle = await getRecipeTitleForData( photo.recipeData, - photo.filmSimulation, + photo.film, ); if (recipeTitle) { photo.recipeTitle = recipeTitle; @@ -229,12 +229,12 @@ export const propagateRecipeTitleIfNecessary = async ( formData.get('recipeTitle') && photo.recipeTitle && photo.recipeData && - photo.filmSimulation + photo.film ) { await updateAllMatchingRecipeTitles( photo.recipeTitle, photo.recipeData, - photo.filmSimulation, + photo.film, ); } }; diff --git a/src/platforms/fujifilm/simulation.ts b/src/platforms/fujifilm/simulation.ts index 45d45287..df387d6c 100644 --- a/src/platforms/fujifilm/simulation.ts +++ b/src/platforms/fujifilm/simulation.ts @@ -222,8 +222,8 @@ const ALL_POSSIBLE_FILM_SIMULATION_LABELS = Object large.toLocaleLowerCase(), ]); -export const isStringFilmSimulation = (simulation: string) => - ALL_POSSIBLE_FILM_SIMULATION_LABELS.includes(simulation.toLocaleLowerCase()); +export const isStringFilmSimulation = (film: string) => + ALL_POSSIBLE_FILM_SIMULATION_LABELS.includes(film.toLocaleLowerCase()); export const labelForFilm = (film: FujifilmSimulation) => FILM_SIMULATION_LABELS[film]; diff --git a/src/recipe/PhotoRecipeOGTile.tsx b/src/recipe/PhotoRecipeOGTile.tsx deleted file mode 100644 index 4b1568e2..00000000 --- a/src/recipe/PhotoRecipeOGTile.tsx +++ /dev/null @@ -1,143 +0,0 @@ -import { FujifilmRecipe } from '@/platforms/fujifilm/recipe'; -import { FilmSimulation } from '@/film'; -import PhotoFilm from '@/film/PhotoFilm'; -import clsx from 'clsx/lite'; -import { ReactNode, RefObject } from 'react'; -import { addSign, formatWhiteBalance } from '.'; - -export default function PhotoRecipeOGTile({ - recipe, - simulation, - iso, - exposure, -}: { - ref?: RefObject - recipe: FujifilmRecipe - simulation: FilmSimulation - iso?: string - exposure?: string -}) { - const { - dynamicRange, - whiteBalance, - highISONoiseReduction, - noiseReductionBasic, - highlight, - shadow, - color, - sharpness, - clarity, - colorChromeEffect, - colorChromeFXBlue, - grainEffect, - bwAdjustment, - bwMagentaGreen, - } = recipe; - - const whiteBalanceTypeFormatted = formatWhiteBalance(recipe); - - const renderRow = (children: ReactNode, className?: string) => -
    - {children} -
    ; - - const renderDataSquare = ( - value: ReactNode, - label?: string, - className?: string, - ) => ( -
    -
    - {typeof value === 'number' ? addSign(value) : value} -
    - {label &&
    - {label} -
    } -
    - ); - - return ( -
    -
    - {renderRow(<> -
    - KODAK PORTRA 500 -
    - - , 'flex items-center gap-4')} - {renderRow(<> - {renderDataSquare(`DR${dynamicRange.development}`)} - {renderDataSquare(iso)} - {renderDataSquare(exposure ?? '0ev')} - )} - {renderRow(<> - {renderDataSquare( - whiteBalanceTypeFormatted.toUpperCase(), - `R${addSign(whiteBalance?.red)} / B${addSign(whiteBalance?.blue)}`, - )} - {renderDataSquare( - highISONoiseReduction ?? noiseReductionBasic ?? 'OFF', - 'ISO NR', - )} - {renderDataSquare(highlight, 'Highlight')} - {renderDataSquare(shadow, 'Shadow')} - )} - {renderRow(<> - {renderDataSquare(color, 'Color')} - {renderDataSquare(sharpness, 'Sharpness')} - {renderDataSquare(clarity, 'Clarity')} - )} - {renderRow(<> - {renderDataSquare( - colorChromeEffect?.toLocaleUpperCase() ?? 'N/A', - 'Color Chrome', - )} - {renderDataSquare( - colorChromeFXBlue?.toLocaleUpperCase() ?? 'N/A', - 'FX Blue', - )} - )} - {renderRow(<> - {renderDataSquare( - grainEffect.roughness.toLocaleUpperCase(), - grainEffect.size === 'large' - ? 'Large Grain' - : grainEffect.size === 'small' - ? 'Small Grain' - : 'Grain', - )} - {renderDataSquare(bwAdjustment ?? 0, 'BW ADJ')} - {renderDataSquare(bwMagentaGreen ?? 0, 'BW M/G')} - )} -
    -
    - ); -} diff --git a/src/recipe/PhotoRecipeOverlay.tsx b/src/recipe/PhotoRecipeOverlay.tsx index 876784e1..1a140874 100644 --- a/src/recipe/PhotoRecipeOverlay.tsx +++ b/src/recipe/PhotoRecipeOverlay.tsx @@ -25,7 +25,7 @@ export default function PhotoRecipeOverlay({ ref, title, recipe, - simulation, + film, onClose, }: RecipeProps & { ref?: RefObject @@ -122,7 +122,7 @@ export default function PhotoRecipeOverlay({ label={`${title ? `${formatRecipe(title).toLocaleUpperCase()} recipe` : 'Recipe'}`} - text={generateRecipeText({ title, recipe, simulation }).join('\n')} + text={generateRecipeText({ title, recipe, film }).join('\n')} iconSize={17} className={clsx( 'translate-y-[0.5px]', @@ -147,10 +147,10 @@ export default function PhotoRecipeOverlay({
    {renderDataSquare(
    - {labelForFilm(simulation).medium.toLocaleUpperCase()} + {labelForFilm(film).medium.toLocaleUpperCase()} diff --git a/src/recipe/RecipeHeader.tsx b/src/recipe/RecipeHeader.tsx index 451467c6..0613238a 100644 --- a/src/recipe/RecipeHeader.tsx +++ b/src/recipe/RecipeHeader.tsx @@ -32,11 +32,11 @@ export default function RecipeHeader({ contrast="high" recipeOnClick={() => ( photo?.recipeData && - photo?.filmSimulation + photo?.film ) ? setRecipeModalProps?.({ title: photo.recipeTitle, recipe: photo.recipeData, - simulation: photo.filmSimulation, + film: photo.film, iso: photo.isoFormatted, exposure: photo.exposureTimeFormatted, }) diff --git a/src/recipe/index.ts b/src/recipe/index.ts index e28c062a..0d6f102d 100644 --- a/src/recipe/index.ts +++ b/src/recipe/index.ts @@ -20,7 +20,7 @@ export type Recipes = RecipeWithCount[] export interface RecipeProps { title?: string recipe: FujifilmRecipe - simulation: FilmSimulation + film: FilmSimulation iso?: string exposure?: string } @@ -57,12 +57,12 @@ export const descriptionForRecipePhotos = ( export const generateRecipeText = ({ title, recipe, - simulation, + film, }: RecipeProps, abbreviate?: boolean, ) => { const lines = [ - `${labelForFilm(simulation).small.toLocaleUpperCase()}`, + `${labelForFilm(film).small.toLocaleUpperCase()}`, // eslint-disable-next-line max-len `${formatWhiteBalance(recipe).toLocaleUpperCase()} ${formatWhiteBalanceColor(recipe)}`, ]; @@ -133,7 +133,7 @@ export const generateMetaForRecipe = ( }); const photoHasRecipe = (photo?: Photo) => - photo?.filmSimulation && photo?.recipeData; + photo?.film && photo?.recipeData; export const getPhotoWithRecipeFromPhotos = ( photos: Photo[], diff --git a/src/share/ShareModals.tsx b/src/share/ShareModals.tsx index 92dd1895..ddf26a95 100644 --- a/src/share/ShareModals.tsx +++ b/src/share/ShareModals.tsx @@ -20,7 +20,7 @@ export default function ShareModals() { camera, lens, tag, - film: simulation, + film, recipe, focal, } = shareModalProps; @@ -30,7 +30,7 @@ export default function ShareModals() { photo, tag, camera, - film: simulation, + film, recipe, focal, }} />; @@ -42,8 +42,8 @@ export default function ShareModals() { return ; } else if (lens) { return ; - } else if (simulation) { - return ; + } else if (film) { + return ; } else if (recipe) { return ; } else if (focal !== undefined) { diff --git a/src/share/index.ts b/src/share/index.ts index fb33b224..701967e6 100644 --- a/src/share/index.ts +++ b/src/share/index.ts @@ -2,7 +2,7 @@ import { Photo } from '@/photo'; import { PhotoSetAttributes, PhotoSetCategory } from '@/category'; import { absolutePathForCameraImage, - absolutePathForFilmSimulationImage, + absolutePathForFilmImage, absolutePathForFocalLengthImage, absolutePathForLensImage, absolutePathForPhotoImage, @@ -21,7 +21,7 @@ export const getSharePathFromShareModalProps = ({ lens, tag, recipe, - film: simulation, + film, focal, }: ShareModalProps) => { if (photo) { @@ -34,8 +34,8 @@ export const getSharePathFromShareModalProps = ({ return absolutePathForTagImage(tag); } else if (recipe) { return absolutePathForRecipeImage(recipe); - } else if (simulation) { - return absolutePathForFilmSimulationImage(simulation); + } else if (film) { + return absolutePathForFilmImage(film); } else if (focal) { return absolutePathForFocalLengthImage(focal); }