diff --git a/.vscode/settings.json b/.vscode/settings.json
index ea94cecd..4a786c5d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -8,6 +8,7 @@
"Astia",
"authjs",
"camelcase",
+ "CLAR",
"cloudflarestorage",
"cmdk",
"Consolas",
diff --git a/app/admin/photos/[photoId]/edit/page.tsx b/app/admin/photos/[photoId]/edit/page.tsx
index e81de2c7..38dda275 100644
--- a/app/admin/photos/[photoId]/edit/page.tsx
+++ b/app/admin/photos/[photoId]/edit/page.tsx
@@ -1,6 +1,7 @@
import { redirect } from 'next/navigation';
import {
getPhotoNoStore,
+ getUniqueFilmsCached,
getUniqueRecipesCached,
getUniqueTagsCached,
} from '@/photo/cache';
@@ -10,7 +11,6 @@ import {
AI_TEXT_GENERATION_ENABLED,
BLUR_ENABLED,
IS_PREVIEW,
- SHOW_RECIPES,
} from '@/app/config';
import { blurImageFromUrl, resizeImageFromUrl } from '@/photo/server';
import { getNextImageUrlForManipulation } from '@/platforms/next-image';
@@ -22,16 +22,20 @@ export default async function PhotoEditPage({
}) {
const { photoId } = await params;
- const photo = await getPhotoNoStore(photoId, true);
+ const [
+ photo,
+ uniqueTags,
+ uniqueRecipes,
+ uniqueFilms,
+ ] = await Promise.all([
+ getPhotoNoStore(photoId, true),
+ getUniqueTagsCached(),
+ getUniqueRecipesCached(),
+ getUniqueFilmsCached(),
+ ]);
if (!photo) { redirect(PATH_ADMIN); }
- const uniqueTags = await getUniqueTagsCached();
-
- const uniqueRecipes = SHOW_RECIPES
- ? await getUniqueRecipesCached()
- : [];
-
const hasAiTextGeneration = AI_TEXT_GENERATION_ENABLED;
// Only generate image thumbnails when AI generation is enabled
@@ -52,6 +56,7 @@ export default async function PhotoEditPage({
photo,
uniqueTags,
uniqueRecipes,
+ uniqueFilms,
hasAiTextGeneration,
imageThumbnailBase64,
blurData,
diff --git a/app/admin/recipes/[recipe]/edit/page.tsx b/app/admin/recipes/[recipe]/edit/page.tsx
index c9db0fbd..9565cc55 100644
--- a/app/admin/recipes/[recipe]/edit/page.tsx
+++ b/app/admin/recipes/[recipe]/edit/page.tsx
@@ -45,7 +45,7 @@ export default async function RecipePageEdit({
accessory={recipeData && film &&
}
diff --git a/app/admin/uploads/[uploadPath]/page.tsx b/app/admin/uploads/[uploadPath]/page.tsx
index d55b9912..3bc007e9 100644
--- a/app/admin/uploads/[uploadPath]/page.tsx
+++ b/app/admin/uploads/[uploadPath]/page.tsx
@@ -1,7 +1,11 @@
import { PATH_ADMIN } from '@/app/paths';
import { extractImageDataFromBlobPath } from '@/photo/server';
import { redirect } from 'next/navigation';
-import { getUniqueRecipesCached, getUniqueTagsCached } from '@/photo/cache';
+import {
+ getUniqueFilmsCached,
+ getUniqueRecipesCached,
+ getUniqueTagsCached,
+} from '@/photo/cache';
import UploadPageClient from '@/photo/UploadPageClient';
import {
AI_TEXT_AUTO_GENERATED_FIELDS,
@@ -10,7 +14,6 @@ import {
} from '@/app/config';
import ErrorNote from '@/components/ErrorNote';
import { getRecipeTitleForData } from '@/photo/db/query';
-import { FilmSimulation } from '@/film';
export const maxDuration = 60;
@@ -45,14 +48,16 @@ export default async function UploadPage({ params }: Params) {
const [
uniqueTags,
uniqueRecipes,
+ uniqueFilms,
recipeTitle,
] = await Promise.all([
getUniqueTagsCached(),
getUniqueRecipesCached(),
+ getUniqueFilmsCached(),
formDataFromExif?.recipeData && formDataFromExif.film
? getRecipeTitleForData(
formDataFromExif.recipeData,
- formDataFromExif.film as FilmSimulation,
+ formDataFromExif.film,
)
: undefined,
]);
@@ -72,6 +77,7 @@ export default async function UploadPage({ params }: Params) {
formDataFromExif,
uniqueTags,
uniqueRecipes,
+ uniqueFilms,
hasAiTextGeneration,
textFieldsToAutoGenerate,
imageThumbnailBase64,
diff --git a/app/film-demo/animate/page.tsx b/app/film-demo/animate/page.tsx
index 0542cda2..7c8c8d5a 100644
--- a/app/film-demo/animate/page.tsx
+++ b/app/film-demo/animate/page.tsx
@@ -3,7 +3,7 @@
import AppGrid from '@/components/AppGrid';
import { clsx } from 'clsx/lite';
import {
- FILM_SIMULATION_FORM_INPUT_OPTIONS,
+ FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS,
} from '@/platforms/fujifilm/simulation';
import PhotoFilm from '@/film/PhotoFilm';
import { useEffect, useState } from 'react';
@@ -13,7 +13,7 @@ export default function FilmPage() {
useEffect(() => {
const interval = setInterval(() => {
- setIndex((index + 1) % FILM_SIMULATION_FORM_INPUT_OPTIONS.length);
+ setIndex((index + 1) % FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS.length);
}, 200);
return () => clearInterval(interval);
});
@@ -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 972e4143..4bb841d0 100644
--- a/app/film-demo/page.tsx
+++ b/app/film-demo/page.tsx
@@ -1,12 +1,12 @@
import {
- FILM_SIMULATION_FORM_INPUT_OPTIONS,
+ FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS,
} from '@/platforms/fujifilm/simulation';
import PhotoFilm from '@/film/PhotoFilm';
export default function FilmPage() {
return (
- {FILM_SIMULATION_FORM_INPUT_OPTIONS.map(({ value }) =>
+ {FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS.map(({ value }) =>
getPhotosNearIdCached(
photoId,
@@ -28,7 +27,7 @@ const getPhotosNearIdCachedCached = cache((
));
interface PhotoFilmProps {
- params: Promise<{ photoId: string, film: FilmSimulation }>
+ params: Promise<{ photoId: string, film: string }>
}
export async function generateMetadata({
diff --git a/app/film/[film]/image/route.tsx b/app/film/[film]/image/route.tsx
index 83a77b22..330d0355 100644
--- a/app/film/[film]/image/route.tsx
+++ b/app/film/[film]/image/route.tsx
@@ -5,7 +5,6 @@ import {
} from '@/image-response';
import FilmImageResponse from
'@/image-response/FilmImageResponse';
-import { FilmSimulation } from '@/film';
import { getIBMPlexMono } from '@/app/font';
import { ImageResponse } from 'next/og';
import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
@@ -21,7 +20,7 @@ export const generateStaticParams = staticallyGenerateCategoryIfConfigured(
export async function GET(
_: Request,
- context: { params: Promise<{ film: FilmSimulation }> },
+ context: { params: Promise<{ film: string }> },
) {
const { film } = await context.params;
diff --git a/app/film/[film]/page.tsx b/app/film/[film]/page.tsx
index 2fdff053..c521a4ea 100644
--- a/app/film/[film]/page.tsx
+++ b/app/film/[film]/page.tsx
@@ -1,6 +1,6 @@
import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo';
import { getUniqueFilms } from '@/photo/db/query';
-import { FilmSimulation, generateMetaForFilm } from '@/film';
+import { generateMetaForFilm } from '@/film';
import FilmOverview from '@/film/FilmOverview';
import { getPhotosFilmDataCached } from '@/film/data';
import { Metadata } from 'next/types';
@@ -20,7 +20,7 @@ export const generateStaticParams = staticallyGenerateCategoryIfConfigured(
);
interface FilmProps {
- params: Promise<{ film: FilmSimulation }>
+ params: Promise<{ film: string }>
}
export async function generateMetadata({
diff --git a/src/admin/AdminAppMenu.tsx b/src/admin/AdminAppMenu.tsx
index 5bdc8521..2f53d0a1 100644
--- a/src/admin/AdminAppMenu.tsx
+++ b/src/admin/AdminAppMenu.tsx
@@ -44,7 +44,7 @@ export default function AdminAppMenu({
startUpload,
setSelectedPhotoIds,
refreshAdminData,
- clearAuthStateAndRedirect,
+ clearAuthStateAndRedirectIfNecessary,
} = useAppState();
const isSelecting = selectedPhotoIds !== undefined;
@@ -148,7 +148,7 @@ export default function AdminAppMenu({
}, {
label: 'Sign Out',
icon: ,
- action: () => signOutAction().then(clearAuthStateAndRedirect),
+ action: () => signOutAction().then(clearAuthStateAndRedirectIfNecessary),
});
return (
diff --git a/src/admin/AdminShowRecipeButton.tsx b/src/admin/AdminShowRecipeButton.tsx
index bfe97689..80fd1ca8 100644
--- a/src/admin/AdminShowRecipeButton.tsx
+++ b/src/admin/AdminShowRecipeButton.tsx
@@ -1,20 +1,11 @@
'use client';
import LoaderButton from '@/components/primitives/LoaderButton';
-import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
-import { FujifilmSimulation } from '@/platforms/fujifilm/simulation';
+import { RecipeProps } from '@/recipe';
import { useAppState } from '@/state/AppState';
import { TbChecklist } from 'react-icons/tb';
-export default function AdminShowRecipeButton({
- title,
- recipe,
- film,
-}: {
- title: string
- recipe: FujifilmRecipe
- film: FujifilmSimulation
-}) {
+export default function AdminShowRecipeButton(props: RecipeProps) {
const { setRecipeModalProps } = useAppState();
return (
@@ -23,11 +14,7 @@ export default function AdminShowRecipeButton({
size={17}
className="translate-y-[1px]"
/>}
- onClick={() => setRecipeModalProps?.({
- title,
- recipe,
- film,
- })}
+ onClick={() => setRecipeModalProps?.(props)}
>
Preview
diff --git a/src/app/Footer.tsx b/src/app/Footer.tsx
index eb982578..ba9930fc 100644
--- a/src/app/Footer.tsx
+++ b/src/app/Footer.tsx
@@ -17,7 +17,7 @@ import { useAppState } from '@/state/AppState';
export default function Footer() {
const pathname = usePathname();
- const { userEmail, clearAuthStateAndRedirect } = useAppState();
+ const { userEmail, clearAuthStateAndRedirectIfNecessary } = useAppState();
const showFooter = !isPathSignIn(pathname);
@@ -49,7 +49,7 @@ export default function Footer() {
{userEmail}