Generalize film type and labeling strategy

This commit is contained in:
Sam Becker 2025-04-01 21:08:36 -05:00
parent 087a5e223c
commit f9db50e41a
29 changed files with 92 additions and 95 deletions

View File

@ -14,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;
@ -58,7 +57,7 @@ export default async function UploadPage({ params }: Params) {
formDataFromExif?.recipeData && formDataFromExif.film
? getRecipeTitleForData(
formDataFromExif.recipeData,
formDataFromExif.film as FilmSimulation,
formDataFromExif.film,
)
: undefined,
]);

View File

@ -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:
</div>
<PhotoFilm
film={FILM_SIMULATION_FORM_INPUT_OPTIONS[index].value}
film={FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS[index].value}
type="icon-first"
/>
<div className="mt-4 text-dim relative">

View File

@ -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 (
<div className="space-y-1 my-12">
{FILM_SIMULATION_FORM_INPUT_OPTIONS.map(({ value }) =>
{FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS.map(({ value }) =>
<div key={value}>
<PhotoFilm
film={value}

View File

@ -11,7 +11,6 @@ import {
absolutePathForPhotoImage,
} from '@/app/paths';
import PhotoDetailPage from '@/photo/PhotoDetailPage';
import { FilmSimulation } from '@/film';
import {
getPhotosMetaCached,
getPhotosNearIdCached,
@ -20,7 +19,7 @@ import { cache } from 'react';
const getPhotosNearIdCachedCached = cache((
photoId: string,
film: FilmSimulation,
film: string,
) =>
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({

View File

@ -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;

View File

@ -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({

View File

@ -2,7 +2,6 @@ import { Photo } from '@/photo';
import { PhotoSetCategory } from '@/category';
import { BASE_URL, GRID_HOMEPAGE_ENABLED } from './config';
import { Camera } from '@/camera';
import { FilmSimulation } from '@/film';
import { parameterize } from '@/utility/string';
import { TAG_HIDDEN } from '@/tag';
import { Lens } from '@/lens';
@ -151,7 +150,7 @@ export const pathForTag = (tag: string) =>
export const pathForCamera = ({ make, model }: Camera) =>
`${PREFIX_CAMERA}/${parameterize(make)}/${parameterize(model)}`;
export const pathForFilm = (film: FilmSimulation) =>
export const pathForFilm = (film: string) =>
`${PREFIX_FILM}/${film}`;
export const pathForLens = ({ make, model }: Lens) =>
@ -177,7 +176,7 @@ export const absolutePathForCamera= (camera: Camera) =>
export const absolutePathForLens= (lens: Lens) =>
`${BASE_URL}${pathForLens(lens)}`;
export const absolutePathForFilm = (film: FilmSimulation) =>
export const absolutePathForFilm = (film: string) =>
`${BASE_URL}${pathForFilm(film)}`;
export const absolutePathForRecipe = (recipe: string) =>
@ -198,7 +197,7 @@ export const absolutePathForCameraImage= (camera: Camera) =>
export const absolutePathForLensImage= (lens: Lens) =>
`${absolutePathForLens(lens)}/image`;
export const absolutePathForFilmImage = (film: FilmSimulation) =>
export const absolutePathForFilmImage = (film: string) =>
`${absolutePathForFilm(film)}/image`;
export const absolutePathForRecipeImage = (recipe: string) =>
@ -308,7 +307,7 @@ export const getPathComponents = (pathname = ''): {
const cameraModel = pathname.match(
new RegExp(`^${PREFIX_CAMERA}/[^/]+/([^/]+)`))?.[1];
const film = pathname.match(
new RegExp(`^${PREFIX_FILM}/([^/]+)`))?.[1] as FilmSimulation;
new RegExp(`^${PREFIX_FILM}/([^/]+)`))?.[1] as string;
const focalString = pathname.match(
new RegExp(`^${PREFIX_FOCAL_LENGTH}/([0-9]+)mm`))?.[1];

View File

@ -1,7 +1,7 @@
import { Photo } from '../photo';
import { Camera, Cameras } from '@/camera';
import { PhotoDateRange } from '../photo';
import { FilmSimulation, Films } from '@/film';
import { Films } from '@/film';
import { Lens, Lenses } from '@/lens';
import { Tags } from '@/tag';
import { FocalLengths } from '@/focal';
@ -39,7 +39,7 @@ export interface PhotoSetCategory {
lens?: Lens
tag?: string
recipe?: string
film?: FilmSimulation
film?: string
focal?: number
}

View File

@ -59,7 +59,6 @@ import * as VisuallyHidden from '@radix-ui/react-visually-hidden';
import InsightsIndicatorDot from '@/admin/insights/InsightsIndicatorDot';
import { PhotoSetCategories } from '@/category';
import { formatCameraText } from '@/camera';
import { labelForFilm } from '@/platforms/fujifilm/simulation';
import { formatFocalLength } from '@/focal';
import { formatRecipe } from '@/recipe';
import IconLens from '../components/icons/IconLens';
@ -73,6 +72,7 @@ import IconFilm from '../components/icons/IconFilm';
import IconLock from '../components/icons/IconLock';
import useVisualViewportHeight from '@/utility/useVisualViewport';
import useMaskedScroll from '../components/useMaskedScroll';
import { labelForFilm } from '@/film';
const DIALOG_TITLE = 'Global Command-K Menu';
const DIALOG_DESCRIPTION = 'For searching photos, views, and settings';

View File

@ -1,5 +1,5 @@
import { Photo, PhotoDateRange } from '@/photo';
import { FilmSimulation, descriptionForFilmPhotos } from '.';
import { descriptionForFilmPhotos } from '.';
import PhotoHeader from '@/photo/PhotoHeader';
import PhotoFilm from '@/film/PhotoFilm';
@ -11,7 +11,7 @@ export default function FilmHeader({
count,
dateRange,
}: {
film: FilmSimulation
film: string
photos: Photo[]
selectedPhoto?: Photo
indexNumber?: number

View File

@ -4,11 +4,7 @@ import {
pathForFilm,
} from '@/app/paths';
import OGTile from '@/components/OGTile';
import {
FilmSimulation,
descriptionForFilmPhotos,
titleForFilm,
} from '.';
import { descriptionForFilmPhotos, titleForFilm } from '.';
export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
@ -23,7 +19,7 @@ export default function FilmOGTile({
count,
dateRange,
}: {
film: FilmSimulation
film: string
photos: Photo[]
loadingState?: OGLoadingState
onLoad?: () => void

View File

@ -1,6 +1,5 @@
import { Photo, PhotoDateRange } from '@/photo';
import FilmHeader from './FilmHeader';
import { FilmSimulation } from '.';
import PhotoGridContainer from '@/photo/PhotoGridContainer';
export default function FilmOverview({
@ -10,7 +9,7 @@ export default function FilmOverview({
dateRange,
animateOnFirstLoadOnly,
}: {
film: FilmSimulation,
film: string,
photos: Photo[],
count: number,
dateRange?: PhotoDateRange,

View File

@ -2,7 +2,7 @@ import { absolutePathForFilm } from '@/app/paths';
import { PhotoSetAttributes } from '../category';
import ShareModal from '@/share/ShareModal';
import FilmOGTile from './FilmOGTile';
import { FilmSimulation, shareTextForFilm } from '.';
import { shareTextForFilm } from '.';
export default function FilmShareModal({
film,
@ -10,7 +10,7 @@ export default function FilmShareModal({
count,
dateRange,
}: {
film: FilmSimulation
film: string
} & PhotoSetAttributes) {
return (
<ShareModal

View File

@ -1,12 +1,11 @@
import { labelForFilm } from '@/platforms/fujifilm/simulation';
import PhotoFilmIcon from './PhotoFilmIcon';
import { pathForFilm } from '@/app/paths';
import { FilmSimulation } from '.';
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
import EntityLink, {
EntityLinkExternalProps,
} from '@/components/primitives/EntityLink';
import clsx from 'clsx/lite';
import { labelForFilm } from '.';
export default function PhotoFilm({
film,
@ -16,7 +15,7 @@ export default function PhotoFilm({
countOnHover,
...props
}: {
film: FilmSimulation
film: string
countOnHover?: number
recipe?: FujifilmRecipe
} & EntityLinkExternalProps) {

View File

@ -1,7 +1,6 @@
/* eslint-disable max-len */
import { labelForFilm } from '@/platforms/fujifilm/simulation';
import { CSSProperties, useMemo } from 'react';
import { FilmSimulation } from '.';
import { labelForFilm } from '.';
const INTRINSIC_WIDTH = 28;
const INTRINSIC_WIDTH_FALLBACK = 16;
@ -17,7 +16,7 @@ export default function PhotoFilmIcon({
className,
style,
}: {
film?: FilmSimulation
film?: string
height?: number
className?: string
style?: CSSProperties

View File

@ -2,13 +2,12 @@ import {
getPhotosCached,
getPhotosMetaCached,
} from '@/photo/cache';
import { FilmSimulation } from '.';
export const getPhotosFilmDataCached = ({
film,
limit,
}: {
film: FilmSimulation,
film: string,
limit?: number,
}) =>
Promise.all([

View File

@ -9,24 +9,36 @@ import {
absolutePathForFilmImage,
} from '@/app/paths';
import {
FILM_SIMULATION_FORM_INPUT_OPTIONS,
FujifilmSimulation,
labelForFilm,
FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS,
labelForFujifilmSimulation,
} from '@/platforms/fujifilm/simulation';
import { formatCount } from '@/utility/string';
import { deparameterize, formatCount } from '@/utility/string';
import { formatCountDescriptive } from '@/utility/string';
import { AnnotatedTag } from '@/photo/form';
import PhotoFilmIcon from './PhotoFilmIcon';
export type FilmSimulation = FujifilmSimulation;
export type FilmWithCount = {
film: FilmSimulation
film: string
count: number
}
export type Films = FilmWithCount[]
export const labelForFilm = (film: string) => {
// Use Fujifilm simulation text when recognized
const simulationLabel = labelForFujifilmSimulation(film as any);
if (simulationLabel) {
return simulationLabel;
} else {
const filmFormatted = deparameterize(film);
return {
small: filmFormatted,
medium: filmFormatted,
large: filmFormatted,
};
}
};
export const sortFilms = (
films: Films,
) => films.sort(sortFilmsWithCount);
@ -41,7 +53,7 @@ export const sortFilmsWithCount = (
};
export const titleForFilm = (
film: FilmSimulation,
film: string,
photos: Photo[],
explicitCount?: number,
) => [
@ -50,9 +62,9 @@ export const titleForFilm = (
].join(' ');
export const shareTextForFilm = (
film: FilmSimulation,
film: string,
) =>
`Photos shot on Fujifilm ${labelForFilm(film).large}`;
`Photos shot on ${labelForFilm(film).large}`;
export const descriptionForFilmPhotos = (
photos: Photo[],
@ -69,7 +81,7 @@ export const descriptionForFilmPhotos = (
);
export const generateMetaForFilm = (
film: FilmSimulation,
film: string,
photos: Photo[],
explicitCount?: number,
explicitDateRange?: PhotoDateRange,
@ -93,13 +105,13 @@ export const convertFilmsForForm = (
includeAllFujifilmSimulations?: boolean,
): AnnotatedTag[] => {
const films = includeAllFujifilmSimulations
? FILM_SIMULATION_FORM_INPUT_OPTIONS
? FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS
.map(({ value }) => ({ value } as AnnotatedTag))
: [];
_films.forEach(({ film, count }) => {
const index = films.findIndex(f => f.value === film);
const fujifilmSimulation = FILM_SIMULATION_FORM_INPUT_OPTIONS
const fujifilmSimulation = FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS
.find(f => f.value === film);
const meta = {
annotation: formatCount(count),

View File

@ -2,13 +2,10 @@ import { Photo } from '../photo';
import ImageCaption from './components/ImageCaption';
import ImagePhotoGrid from './components/ImagePhotoGrid';
import ImageContainer from './components/ImageContainer';
import {
labelForFilm,
} from '@/platforms/fujifilm/simulation';
import PhotoFilmIcon from
'@/film/PhotoFilmIcon';
import { FilmSimulation } from '@/film';
import { NextImageSize } from '@/platforms/next-image';
import { labelForFilm } from '@/film';
export default function FilmImageResponse({
film,
@ -17,7 +14,7 @@ export default function FilmImageResponse({
height,
fontFamily,
}: {
film: FilmSimulation,
film: string,
photos: Photo[]
width: NextImageSize
height: number

View File

@ -6,7 +6,9 @@ import type { NextImageSize } from '@/platforms/next-image';
import { formatTag } from '@/tag';
import { generateRecipeText, getPhotoWithRecipeFromPhotos } from '@/recipe';
import PhotoFilmIcon from '@/film/PhotoFilmIcon';
import { isStringFilmSimulationLabel } from '@/platforms/fujifilm/simulation';
import {
isStringFujifilmSimulationLabel,
} from '@/platforms/fujifilm/simulation';
import IconRecipe from '@/components/icons/IconRecipe';
const MAX_RECIPE_LINES = 8;
@ -109,7 +111,7 @@ export default function RecipeImageResponse({
flexGrow: 1,
}}>
{text}
{isStringFilmSimulationLabel(text) && film &&
{isStringFujifilmSimulationLabel(text) && film &&
<div tw="flex">
<PhotoFilmIcon
film={film}

View File

@ -60,7 +60,6 @@ import { convertUploadToPhoto } from './storage';
import { UrlAddStatus } from '@/admin/AdminUploadsClient';
import { convertStringToArray } from '@/utility/string';
import { after } from 'next/server';
import { FilmSimulation } from '@/film';
// Private actions
@ -315,7 +314,7 @@ export const renamePhotoTagGloballyAction = async (formData: FormData) =>
export const getPhotosNeedingRecipeTitleCountAction = async (
recipeData: string,
film: FilmSimulation,
film: string,
photoIdToExclude?: string,
) =>
runAuthenticatedAdminServerAction(async () =>

View File

@ -13,7 +13,7 @@ import {
} from '@/photo';
import { Cameras, createCameraKey } from '@/camera';
import { Tags } from '@/tag';
import { FilmSimulation, Films } from '@/film';
import { Films } from '@/film';
import { ADMIN_SQL_DEBUG_ENABLED } from '@/app/config';
import {
GetPhotosOptions,
@ -380,7 +380,7 @@ export const getUniqueRecipes = async () =>
export const getRecipeTitleForData = async (
data: string | object,
film: FilmSimulation,
film: string,
) =>
// Includes legacy check on pre-stringified JSON
safelyQueryPhotos(() => sql`
@ -395,7 +395,7 @@ export const getRecipeTitleForData = async (
export const getPhotosNeedingRecipeTitleCount = async (
data: string,
film: FilmSimulation,
film: string,
photoIdToExclude?: string,
) =>
safelyQueryPhotos(() => sql`
@ -411,7 +411,7 @@ export const getPhotosNeedingRecipeTitleCount = async (
export const updateAllMatchingRecipeTitles = (
title: string,
data: string,
film: FilmSimulation,
film: string,
) =>
safelyQueryPhotos(() => sql`
UPDATE photos
@ -430,7 +430,7 @@ export const getUniqueFilms = async () =>
ORDER BY film ASC
`.then(({ rows }): Films => rows
.map(({ film, count }) => ({
film: film as FilmSimulation,
film,
count: parseInt(count, 10),
})))
, 'getUniqueFilms');

View File

@ -1,7 +1,6 @@
import FieldSetWithStatus from '@/components/FieldSetWithStatus';
import { ComponentProps, useEffect, useState } from 'react';
import { getPhotosNeedingRecipeTitleCountAction } from '../actions';
import { FilmSimulation } from '@/film';
export default function ApplyRecipeTitleGloballyCheckbox({
photoId,
@ -16,7 +15,7 @@ export default function ApplyRecipeTitleGloballyCheckbox({
recipeTitle?: string
hasRecipeTitleChanged?: boolean
recipeData?: string
film?: FilmSimulation
film?: string
onMatchResults: (didFindMatchingPhotos: boolean) => void
}) {
const [matchingPhotosCount, setMatchingPhotosCount] = useState<number>();

View File

@ -41,7 +41,7 @@ import ErrorNote from '@/components/ErrorNote';
import { convertRecipesForForm, Recipes } from '@/recipe';
import deepEqual from 'fast-deep-equal/es6/react';
import ApplyRecipeTitleGloballyCheckbox from './ApplyRecipesGloballyCheckbox';
import { convertFilmsForForm, Films, FilmSimulation } from '@/film';
import { convertFilmsForForm, Films } from '@/film';
import IconFavs from '@/components/icons/IconFavs';
import IconHidden from '@/components/icons/IconHidden';
import { isMakeFujifilm } from '@/platforms/fujifilm';
@ -431,7 +431,7 @@ export default function PhotoForm({
hasRecipeTitleChanged={
changedFormKeys.includes('recipeTitle')}
recipeData={formData.recipeData}
film={formData.film as FilmSimulation}
film={formData.film}
onMatchResults={onMatchResults}
{...fieldProps}
/>;

View File

@ -16,12 +16,12 @@ import {
import { roundToNumber } from '@/utility/number';
import { convertStringToArray, parameterize } from '@/utility/string';
import { generateNanoid } from '@/utility/nanoid';
import { FilmSimulation } from '@/film';
import { GEO_PRIVACY_ENABLED } from '@/app/config';
import { TAG_FAVS, getValidationMessageForTags } from '@/tag';
import { MAKE_FUJIFILM } from '@/platforms/fujifilm';
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
import { ReactNode } from 'react';
import { FujifilmSimulation } from '@/platforms/fujifilm/simulation';
type VirtualFields =
'favorite' |
@ -276,7 +276,7 @@ export const convertPhotoToFormData = (photo: Photo): PhotoFormData => {
export const convertExifToFormData = (
data: ExifData,
film?: FilmSimulation,
film?: FujifilmSimulation,
recipeData?: FujifilmRecipe,
): Omit<
Record<keyof PhotoExif, string | undefined>,
@ -347,7 +347,7 @@ export const convertFormDataToPhotoDbInsert = (
return {
...(photoForm as PhotoFormData & {
film?: FilmSimulation
film?: FujifilmSimulation
recipeData?: FujifilmRecipe
}),
...!photoForm.id && { id: generateNanoid() },

View File

@ -1,6 +1,6 @@
import { formatFocalLength } from '@/focal';
import { getNextImageUrlForRequest } from '@/platforms/next-image';
import { FilmSimulation, photoHasFilmData } from '@/film';
import { photoHasFilmData } from '@/film';
import {
HIGH_DENSITY_GRID,
IS_PREVIEW,
@ -22,6 +22,7 @@ import camelcaseKeys from 'camelcase-keys';
import { isBefore } from 'date-fns';
import type { Metadata } from 'next';
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
import { FujifilmSimulation } from '@/platforms/fujifilm/simulation';
// INFINITE SCROLL: FEED
export const INFINITE_SCROLL_FEED_INITIAL =
@ -65,7 +66,7 @@ export interface PhotoExif {
exposureCompensation?: number
latitude?: number
longitude?: number
film?: FilmSimulation
film?: FujifilmSimulation
recipeData?: string
takenAt?: string
takenAtNaive?: string

View File

@ -7,11 +7,11 @@ import {
convertFormDataToPhotoDbInsert,
} from '@/photo/form';
import {
FujifilmSimulation,
getFujifilmSimulationFromMakerNote,
} from '@/platforms/fujifilm/simulation';
import { ExifData, ExifParserFactory } from 'ts-exif-parser';
import { PhotoFormData } from './form';
import { FilmSimulation } from '@/film';
import sharp, { Sharp } from 'sharp';
import {
GEO_PRIVACY_ENABLED,
@ -58,7 +58,7 @@ export const extractImageDataFromBlobPath = async (
const extension = getExtensionFromStorageUrl(url);
let exifData: ExifData | undefined;
let film: FilmSimulation | undefined;
let film: FujifilmSimulation | undefined;
let recipe: FujifilmRecipe | undefined;
let blurData: string | undefined;
let imageResizedBase64: string | undefined;

View File

@ -80,7 +80,7 @@ interface FujifilmSimulationLabel {
large: string
}
const FILM_SIMULATION_LABELS: Record<
const FUJIFILM_SIMULATION_LABELS: Record<
FujifilmSimulation,
FujifilmSimulationLabel
> = {
@ -206,30 +206,30 @@ const FILM_SIMULATION_LABELS: Record<
},
};
export const FILM_SIMULATION_FORM_INPUT_OPTIONS = Object
.entries(FILM_SIMULATION_LABELS)
export const FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS = Object
.entries(FUJIFILM_SIMULATION_LABELS)
.map(([value, label]) => (
{ value, label: label.large } as
{ value: FujifilmSimulation, label: string }
))
.sort((a, b) => a.label.localeCompare(b.label));
const ALL_POSSIBLE_FILM_SIMULATION_LABELS = Object
.values(FILM_SIMULATION_LABELS)
const ALL_POSSIBLE_FUJIFILM_SIMULATION_LABELS = Object
.values(FUJIFILM_SIMULATION_LABELS)
.flatMap(({ small, medium, large }) => [
small.toLocaleLowerCase(),
medium.toLocaleLowerCase(),
large.toLocaleLowerCase(),
]);
export const isStringFilmSimulation = (film?: string) =>
film && Object.keys(FILM_SIMULATION_LABELS).includes(film);
export const isStringFujifilmSimulation = (film?: string) =>
film && Object.keys(FUJIFILM_SIMULATION_LABELS).includes(film);
export const isStringFilmSimulationLabel = (film: string) =>
ALL_POSSIBLE_FILM_SIMULATION_LABELS.includes(film.toLocaleLowerCase());
export const isStringFujifilmSimulationLabel = (film: string) =>
ALL_POSSIBLE_FUJIFILM_SIMULATION_LABELS.includes(film.toLocaleLowerCase());
export const labelForFilm = (film: FujifilmSimulation) =>
FILM_SIMULATION_LABELS[film];
export const labelForFujifilmSimulation = (film: FujifilmSimulation) =>
FUJIFILM_SIMULATION_LABELS[film];
export const getFujifilmSimulationFromMakerNote = (
bytes: Buffer,

View File

@ -15,11 +15,11 @@ import {
generateRecipeText,
RecipeProps,
} from '.';
import { labelForFilm } from '@/platforms/fujifilm/simulation';
import { TbChecklist } from 'react-icons/tb';
import CopyButton from '@/components/CopyButton';
import { pathForRecipe } from '@/app/paths';
import LinkWithStatus from '@/components/LinkWithStatus';
import { labelForFilm } from '@/film';
export default function PhotoRecipeOverlay({
ref,

View File

@ -7,8 +7,7 @@ import {
formatCountDescriptive,
} from '@/utility/string';
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
import { FilmSimulation } from '@/film';
import { labelForFilm } from '@/platforms/fujifilm/simulation';
import { labelForFilm } from '@/film';
export type RecipeWithCount = {
recipe: string
@ -20,7 +19,7 @@ export type Recipes = RecipeWithCount[]
export interface RecipeProps {
title?: string
recipe: FujifilmRecipe
film: FilmSimulation
film: string
iso?: string
exposure?: string
}