Generalize film type and labeling strategy
This commit is contained in:
parent
087a5e223c
commit
f9db50e41a
@ -14,7 +14,6 @@ import {
|
|||||||
} from '@/app/config';
|
} from '@/app/config';
|
||||||
import ErrorNote from '@/components/ErrorNote';
|
import ErrorNote from '@/components/ErrorNote';
|
||||||
import { getRecipeTitleForData } from '@/photo/db/query';
|
import { getRecipeTitleForData } from '@/photo/db/query';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
|
|
||||||
export const maxDuration = 60;
|
export const maxDuration = 60;
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ export default async function UploadPage({ params }: Params) {
|
|||||||
formDataFromExif?.recipeData && formDataFromExif.film
|
formDataFromExif?.recipeData && formDataFromExif.film
|
||||||
? getRecipeTitleForData(
|
? getRecipeTitleForData(
|
||||||
formDataFromExif.recipeData,
|
formDataFromExif.recipeData,
|
||||||
formDataFromExif.film as FilmSimulation,
|
formDataFromExif.film,
|
||||||
)
|
)
|
||||||
: undefined,
|
: undefined,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import AppGrid from '@/components/AppGrid';
|
import AppGrid from '@/components/AppGrid';
|
||||||
import { clsx } from 'clsx/lite';
|
import { clsx } from 'clsx/lite';
|
||||||
import {
|
import {
|
||||||
FILM_SIMULATION_FORM_INPUT_OPTIONS,
|
FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS,
|
||||||
} from '@/platforms/fujifilm/simulation';
|
} from '@/platforms/fujifilm/simulation';
|
||||||
import PhotoFilm from '@/film/PhotoFilm';
|
import PhotoFilm from '@/film/PhotoFilm';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@ -13,7 +13,7 @@ export default function FilmPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
setIndex((index + 1) % FILM_SIMULATION_FORM_INPUT_OPTIONS.length);
|
setIndex((index + 1) % FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS.length);
|
||||||
}, 200);
|
}, 200);
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
});
|
});
|
||||||
@ -28,7 +28,7 @@ export default function FilmPage() {
|
|||||||
Film Simulation:
|
Film Simulation:
|
||||||
</div>
|
</div>
|
||||||
<PhotoFilm
|
<PhotoFilm
|
||||||
film={FILM_SIMULATION_FORM_INPUT_OPTIONS[index].value}
|
film={FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS[index].value}
|
||||||
type="icon-first"
|
type="icon-first"
|
||||||
/>
|
/>
|
||||||
<div className="mt-4 text-dim relative">
|
<div className="mt-4 text-dim relative">
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
FILM_SIMULATION_FORM_INPUT_OPTIONS,
|
FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS,
|
||||||
} from '@/platforms/fujifilm/simulation';
|
} from '@/platforms/fujifilm/simulation';
|
||||||
import PhotoFilm from '@/film/PhotoFilm';
|
import PhotoFilm from '@/film/PhotoFilm';
|
||||||
|
|
||||||
export default function FilmPage() {
|
export default function FilmPage() {
|
||||||
return (
|
return (
|
||||||
<div className="space-y-1 my-12">
|
<div className="space-y-1 my-12">
|
||||||
{FILM_SIMULATION_FORM_INPUT_OPTIONS.map(({ value }) =>
|
{FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS.map(({ value }) =>
|
||||||
<div key={value}>
|
<div key={value}>
|
||||||
<PhotoFilm
|
<PhotoFilm
|
||||||
film={value}
|
film={value}
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import {
|
|||||||
absolutePathForPhotoImage,
|
absolutePathForPhotoImage,
|
||||||
} from '@/app/paths';
|
} from '@/app/paths';
|
||||||
import PhotoDetailPage from '@/photo/PhotoDetailPage';
|
import PhotoDetailPage from '@/photo/PhotoDetailPage';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
import {
|
import {
|
||||||
getPhotosMetaCached,
|
getPhotosMetaCached,
|
||||||
getPhotosNearIdCached,
|
getPhotosNearIdCached,
|
||||||
@ -20,7 +19,7 @@ import { cache } from 'react';
|
|||||||
|
|
||||||
const getPhotosNearIdCachedCached = cache((
|
const getPhotosNearIdCachedCached = cache((
|
||||||
photoId: string,
|
photoId: string,
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
) =>
|
) =>
|
||||||
getPhotosNearIdCached(
|
getPhotosNearIdCached(
|
||||||
photoId,
|
photoId,
|
||||||
@ -28,7 +27,7 @@ const getPhotosNearIdCachedCached = cache((
|
|||||||
));
|
));
|
||||||
|
|
||||||
interface PhotoFilmProps {
|
interface PhotoFilmProps {
|
||||||
params: Promise<{ photoId: string, film: FilmSimulation }>
|
params: Promise<{ photoId: string, film: string }>
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import {
|
|||||||
} from '@/image-response';
|
} from '@/image-response';
|
||||||
import FilmImageResponse from
|
import FilmImageResponse from
|
||||||
'@/image-response/FilmImageResponse';
|
'@/image-response/FilmImageResponse';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
import { getIBMPlexMono } from '@/app/font';
|
import { getIBMPlexMono } from '@/app/font';
|
||||||
import { ImageResponse } from 'next/og';
|
import { ImageResponse } from 'next/og';
|
||||||
import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
|
import { getImageResponseCacheControlHeaders } from '@/image-response/cache';
|
||||||
@ -21,7 +20,7 @@ export const generateStaticParams = staticallyGenerateCategoryIfConfigured(
|
|||||||
|
|
||||||
export async function GET(
|
export async function GET(
|
||||||
_: Request,
|
_: Request,
|
||||||
context: { params: Promise<{ film: FilmSimulation }> },
|
context: { params: Promise<{ film: string }> },
|
||||||
) {
|
) {
|
||||||
const { film } = await context.params;
|
const { film } = await context.params;
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo';
|
import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo';
|
||||||
import { getUniqueFilms } from '@/photo/db/query';
|
import { getUniqueFilms } from '@/photo/db/query';
|
||||||
import { FilmSimulation, generateMetaForFilm } from '@/film';
|
import { generateMetaForFilm } from '@/film';
|
||||||
import FilmOverview from '@/film/FilmOverview';
|
import FilmOverview from '@/film/FilmOverview';
|
||||||
import { getPhotosFilmDataCached } from '@/film/data';
|
import { getPhotosFilmDataCached } from '@/film/data';
|
||||||
import { Metadata } from 'next/types';
|
import { Metadata } from 'next/types';
|
||||||
@ -20,7 +20,7 @@ export const generateStaticParams = staticallyGenerateCategoryIfConfigured(
|
|||||||
);
|
);
|
||||||
|
|
||||||
interface FilmProps {
|
interface FilmProps {
|
||||||
params: Promise<{ film: FilmSimulation }>
|
params: Promise<{ film: string }>
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { Photo } from '@/photo';
|
|||||||
import { PhotoSetCategory } from '@/category';
|
import { PhotoSetCategory } from '@/category';
|
||||||
import { BASE_URL, GRID_HOMEPAGE_ENABLED } from './config';
|
import { BASE_URL, GRID_HOMEPAGE_ENABLED } from './config';
|
||||||
import { Camera } from '@/camera';
|
import { Camera } from '@/camera';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
import { parameterize } from '@/utility/string';
|
import { parameterize } from '@/utility/string';
|
||||||
import { TAG_HIDDEN } from '@/tag';
|
import { TAG_HIDDEN } from '@/tag';
|
||||||
import { Lens } from '@/lens';
|
import { Lens } from '@/lens';
|
||||||
@ -151,7 +150,7 @@ export const pathForTag = (tag: string) =>
|
|||||||
export const pathForCamera = ({ make, model }: Camera) =>
|
export const pathForCamera = ({ make, model }: Camera) =>
|
||||||
`${PREFIX_CAMERA}/${parameterize(make)}/${parameterize(model)}`;
|
`${PREFIX_CAMERA}/${parameterize(make)}/${parameterize(model)}`;
|
||||||
|
|
||||||
export const pathForFilm = (film: FilmSimulation) =>
|
export const pathForFilm = (film: string) =>
|
||||||
`${PREFIX_FILM}/${film}`;
|
`${PREFIX_FILM}/${film}`;
|
||||||
|
|
||||||
export const pathForLens = ({ make, model }: Lens) =>
|
export const pathForLens = ({ make, model }: Lens) =>
|
||||||
@ -177,7 +176,7 @@ export const absolutePathForCamera= (camera: Camera) =>
|
|||||||
export const absolutePathForLens= (lens: Lens) =>
|
export const absolutePathForLens= (lens: Lens) =>
|
||||||
`${BASE_URL}${pathForLens(lens)}`;
|
`${BASE_URL}${pathForLens(lens)}`;
|
||||||
|
|
||||||
export const absolutePathForFilm = (film: FilmSimulation) =>
|
export const absolutePathForFilm = (film: string) =>
|
||||||
`${BASE_URL}${pathForFilm(film)}`;
|
`${BASE_URL}${pathForFilm(film)}`;
|
||||||
|
|
||||||
export const absolutePathForRecipe = (recipe: string) =>
|
export const absolutePathForRecipe = (recipe: string) =>
|
||||||
@ -198,7 +197,7 @@ export const absolutePathForCameraImage= (camera: Camera) =>
|
|||||||
export const absolutePathForLensImage= (lens: Lens) =>
|
export const absolutePathForLensImage= (lens: Lens) =>
|
||||||
`${absolutePathForLens(lens)}/image`;
|
`${absolutePathForLens(lens)}/image`;
|
||||||
|
|
||||||
export const absolutePathForFilmImage = (film: FilmSimulation) =>
|
export const absolutePathForFilmImage = (film: string) =>
|
||||||
`${absolutePathForFilm(film)}/image`;
|
`${absolutePathForFilm(film)}/image`;
|
||||||
|
|
||||||
export const absolutePathForRecipeImage = (recipe: string) =>
|
export const absolutePathForRecipeImage = (recipe: string) =>
|
||||||
@ -308,7 +307,7 @@ export const getPathComponents = (pathname = ''): {
|
|||||||
const cameraModel = pathname.match(
|
const cameraModel = pathname.match(
|
||||||
new RegExp(`^${PREFIX_CAMERA}/[^/]+/([^/]+)`))?.[1];
|
new RegExp(`^${PREFIX_CAMERA}/[^/]+/([^/]+)`))?.[1];
|
||||||
const film = pathname.match(
|
const film = pathname.match(
|
||||||
new RegExp(`^${PREFIX_FILM}/([^/]+)`))?.[1] as FilmSimulation;
|
new RegExp(`^${PREFIX_FILM}/([^/]+)`))?.[1] as string;
|
||||||
const focalString = pathname.match(
|
const focalString = pathname.match(
|
||||||
new RegExp(`^${PREFIX_FOCAL_LENGTH}/([0-9]+)mm`))?.[1];
|
new RegExp(`^${PREFIX_FOCAL_LENGTH}/([0-9]+)mm`))?.[1];
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Photo } from '../photo';
|
import { Photo } from '../photo';
|
||||||
import { Camera, Cameras } from '@/camera';
|
import { Camera, Cameras } from '@/camera';
|
||||||
import { PhotoDateRange } from '../photo';
|
import { PhotoDateRange } from '../photo';
|
||||||
import { FilmSimulation, Films } from '@/film';
|
import { Films } from '@/film';
|
||||||
import { Lens, Lenses } from '@/lens';
|
import { Lens, Lenses } from '@/lens';
|
||||||
import { Tags } from '@/tag';
|
import { Tags } from '@/tag';
|
||||||
import { FocalLengths } from '@/focal';
|
import { FocalLengths } from '@/focal';
|
||||||
@ -39,7 +39,7 @@ export interface PhotoSetCategory {
|
|||||||
lens?: Lens
|
lens?: Lens
|
||||||
tag?: string
|
tag?: string
|
||||||
recipe?: string
|
recipe?: string
|
||||||
film?: FilmSimulation
|
film?: string
|
||||||
focal?: number
|
focal?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,6 @@ import * as VisuallyHidden from '@radix-ui/react-visually-hidden';
|
|||||||
import InsightsIndicatorDot from '@/admin/insights/InsightsIndicatorDot';
|
import InsightsIndicatorDot from '@/admin/insights/InsightsIndicatorDot';
|
||||||
import { PhotoSetCategories } from '@/category';
|
import { PhotoSetCategories } from '@/category';
|
||||||
import { formatCameraText } from '@/camera';
|
import { formatCameraText } from '@/camera';
|
||||||
import { labelForFilm } from '@/platforms/fujifilm/simulation';
|
|
||||||
import { formatFocalLength } from '@/focal';
|
import { formatFocalLength } from '@/focal';
|
||||||
import { formatRecipe } from '@/recipe';
|
import { formatRecipe } from '@/recipe';
|
||||||
import IconLens from '../components/icons/IconLens';
|
import IconLens from '../components/icons/IconLens';
|
||||||
@ -73,6 +72,7 @@ import IconFilm from '../components/icons/IconFilm';
|
|||||||
import IconLock from '../components/icons/IconLock';
|
import IconLock from '../components/icons/IconLock';
|
||||||
import useVisualViewportHeight from '@/utility/useVisualViewport';
|
import useVisualViewportHeight from '@/utility/useVisualViewport';
|
||||||
import useMaskedScroll from '../components/useMaskedScroll';
|
import useMaskedScroll from '../components/useMaskedScroll';
|
||||||
|
import { labelForFilm } from '@/film';
|
||||||
|
|
||||||
const DIALOG_TITLE = 'Global Command-K Menu';
|
const DIALOG_TITLE = 'Global Command-K Menu';
|
||||||
const DIALOG_DESCRIPTION = 'For searching photos, views, and settings';
|
const DIALOG_DESCRIPTION = 'For searching photos, views, and settings';
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Photo, PhotoDateRange } from '@/photo';
|
import { Photo, PhotoDateRange } from '@/photo';
|
||||||
import { FilmSimulation, descriptionForFilmPhotos } from '.';
|
import { descriptionForFilmPhotos } from '.';
|
||||||
import PhotoHeader from '@/photo/PhotoHeader';
|
import PhotoHeader from '@/photo/PhotoHeader';
|
||||||
import PhotoFilm from '@/film/PhotoFilm';
|
import PhotoFilm from '@/film/PhotoFilm';
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ export default function FilmHeader({
|
|||||||
count,
|
count,
|
||||||
dateRange,
|
dateRange,
|
||||||
}: {
|
}: {
|
||||||
film: FilmSimulation
|
film: string
|
||||||
photos: Photo[]
|
photos: Photo[]
|
||||||
selectedPhoto?: Photo
|
selectedPhoto?: Photo
|
||||||
indexNumber?: number
|
indexNumber?: number
|
||||||
|
|||||||
@ -4,11 +4,7 @@ import {
|
|||||||
pathForFilm,
|
pathForFilm,
|
||||||
} from '@/app/paths';
|
} from '@/app/paths';
|
||||||
import OGTile from '@/components/OGTile';
|
import OGTile from '@/components/OGTile';
|
||||||
import {
|
import { descriptionForFilmPhotos, titleForFilm } from '.';
|
||||||
FilmSimulation,
|
|
||||||
descriptionForFilmPhotos,
|
|
||||||
titleForFilm,
|
|
||||||
} from '.';
|
|
||||||
|
|
||||||
export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
|
export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
|
||||||
|
|
||||||
@ -23,7 +19,7 @@ export default function FilmOGTile({
|
|||||||
count,
|
count,
|
||||||
dateRange,
|
dateRange,
|
||||||
}: {
|
}: {
|
||||||
film: FilmSimulation
|
film: string
|
||||||
photos: Photo[]
|
photos: Photo[]
|
||||||
loadingState?: OGLoadingState
|
loadingState?: OGLoadingState
|
||||||
onLoad?: () => void
|
onLoad?: () => void
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { Photo, PhotoDateRange } from '@/photo';
|
import { Photo, PhotoDateRange } from '@/photo';
|
||||||
import FilmHeader from './FilmHeader';
|
import FilmHeader from './FilmHeader';
|
||||||
import { FilmSimulation } from '.';
|
|
||||||
import PhotoGridContainer from '@/photo/PhotoGridContainer';
|
import PhotoGridContainer from '@/photo/PhotoGridContainer';
|
||||||
|
|
||||||
export default function FilmOverview({
|
export default function FilmOverview({
|
||||||
@ -10,7 +9,7 @@ export default function FilmOverview({
|
|||||||
dateRange,
|
dateRange,
|
||||||
animateOnFirstLoadOnly,
|
animateOnFirstLoadOnly,
|
||||||
}: {
|
}: {
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
photos: Photo[],
|
photos: Photo[],
|
||||||
count: number,
|
count: number,
|
||||||
dateRange?: PhotoDateRange,
|
dateRange?: PhotoDateRange,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { absolutePathForFilm } from '@/app/paths';
|
|||||||
import { PhotoSetAttributes } from '../category';
|
import { PhotoSetAttributes } from '../category';
|
||||||
import ShareModal from '@/share/ShareModal';
|
import ShareModal from '@/share/ShareModal';
|
||||||
import FilmOGTile from './FilmOGTile';
|
import FilmOGTile from './FilmOGTile';
|
||||||
import { FilmSimulation, shareTextForFilm } from '.';
|
import { shareTextForFilm } from '.';
|
||||||
|
|
||||||
export default function FilmShareModal({
|
export default function FilmShareModal({
|
||||||
film,
|
film,
|
||||||
@ -10,7 +10,7 @@ export default function FilmShareModal({
|
|||||||
count,
|
count,
|
||||||
dateRange,
|
dateRange,
|
||||||
}: {
|
}: {
|
||||||
film: FilmSimulation
|
film: string
|
||||||
} & PhotoSetAttributes) {
|
} & PhotoSetAttributes) {
|
||||||
return (
|
return (
|
||||||
<ShareModal
|
<ShareModal
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
import { labelForFilm } from '@/platforms/fujifilm/simulation';
|
|
||||||
import PhotoFilmIcon from './PhotoFilmIcon';
|
import PhotoFilmIcon from './PhotoFilmIcon';
|
||||||
import { pathForFilm } from '@/app/paths';
|
import { pathForFilm } from '@/app/paths';
|
||||||
import { FilmSimulation } from '.';
|
|
||||||
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
||||||
import EntityLink, {
|
import EntityLink, {
|
||||||
EntityLinkExternalProps,
|
EntityLinkExternalProps,
|
||||||
} from '@/components/primitives/EntityLink';
|
} from '@/components/primitives/EntityLink';
|
||||||
import clsx from 'clsx/lite';
|
import clsx from 'clsx/lite';
|
||||||
|
import { labelForFilm } from '.';
|
||||||
|
|
||||||
export default function PhotoFilm({
|
export default function PhotoFilm({
|
||||||
film,
|
film,
|
||||||
@ -16,7 +15,7 @@ export default function PhotoFilm({
|
|||||||
countOnHover,
|
countOnHover,
|
||||||
...props
|
...props
|
||||||
}: {
|
}: {
|
||||||
film: FilmSimulation
|
film: string
|
||||||
countOnHover?: number
|
countOnHover?: number
|
||||||
recipe?: FujifilmRecipe
|
recipe?: FujifilmRecipe
|
||||||
} & EntityLinkExternalProps) {
|
} & EntityLinkExternalProps) {
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
/* eslint-disable max-len */
|
/* eslint-disable max-len */
|
||||||
import { labelForFilm } from '@/platforms/fujifilm/simulation';
|
|
||||||
import { CSSProperties, useMemo } from 'react';
|
import { CSSProperties, useMemo } from 'react';
|
||||||
import { FilmSimulation } from '.';
|
import { labelForFilm } from '.';
|
||||||
|
|
||||||
const INTRINSIC_WIDTH = 28;
|
const INTRINSIC_WIDTH = 28;
|
||||||
const INTRINSIC_WIDTH_FALLBACK = 16;
|
const INTRINSIC_WIDTH_FALLBACK = 16;
|
||||||
@ -17,7 +16,7 @@ export default function PhotoFilmIcon({
|
|||||||
className,
|
className,
|
||||||
style,
|
style,
|
||||||
}: {
|
}: {
|
||||||
film?: FilmSimulation
|
film?: string
|
||||||
height?: number
|
height?: number
|
||||||
className?: string
|
className?: string
|
||||||
style?: CSSProperties
|
style?: CSSProperties
|
||||||
|
|||||||
@ -2,13 +2,12 @@ import {
|
|||||||
getPhotosCached,
|
getPhotosCached,
|
||||||
getPhotosMetaCached,
|
getPhotosMetaCached,
|
||||||
} from '@/photo/cache';
|
} from '@/photo/cache';
|
||||||
import { FilmSimulation } from '.';
|
|
||||||
|
|
||||||
export const getPhotosFilmDataCached = ({
|
export const getPhotosFilmDataCached = ({
|
||||||
film,
|
film,
|
||||||
limit,
|
limit,
|
||||||
}: {
|
}: {
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
limit?: number,
|
limit?: number,
|
||||||
}) =>
|
}) =>
|
||||||
Promise.all([
|
Promise.all([
|
||||||
|
|||||||
@ -9,24 +9,36 @@ import {
|
|||||||
absolutePathForFilmImage,
|
absolutePathForFilmImage,
|
||||||
} from '@/app/paths';
|
} from '@/app/paths';
|
||||||
import {
|
import {
|
||||||
FILM_SIMULATION_FORM_INPUT_OPTIONS,
|
FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS,
|
||||||
FujifilmSimulation,
|
labelForFujifilmSimulation,
|
||||||
labelForFilm,
|
|
||||||
} from '@/platforms/fujifilm/simulation';
|
} from '@/platforms/fujifilm/simulation';
|
||||||
import { formatCount } from '@/utility/string';
|
import { deparameterize, formatCount } from '@/utility/string';
|
||||||
import { formatCountDescriptive } from '@/utility/string';
|
import { formatCountDescriptive } from '@/utility/string';
|
||||||
import { AnnotatedTag } from '@/photo/form';
|
import { AnnotatedTag } from '@/photo/form';
|
||||||
import PhotoFilmIcon from './PhotoFilmIcon';
|
import PhotoFilmIcon from './PhotoFilmIcon';
|
||||||
|
|
||||||
export type FilmSimulation = FujifilmSimulation;
|
|
||||||
|
|
||||||
export type FilmWithCount = {
|
export type FilmWithCount = {
|
||||||
film: FilmSimulation
|
film: string
|
||||||
count: number
|
count: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Films = FilmWithCount[]
|
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 = (
|
export const sortFilms = (
|
||||||
films: Films,
|
films: Films,
|
||||||
) => films.sort(sortFilmsWithCount);
|
) => films.sort(sortFilmsWithCount);
|
||||||
@ -41,7 +53,7 @@ export const sortFilmsWithCount = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const titleForFilm = (
|
export const titleForFilm = (
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
photos: Photo[],
|
photos: Photo[],
|
||||||
explicitCount?: number,
|
explicitCount?: number,
|
||||||
) => [
|
) => [
|
||||||
@ -50,9 +62,9 @@ export const titleForFilm = (
|
|||||||
].join(' ');
|
].join(' ');
|
||||||
|
|
||||||
export const shareTextForFilm = (
|
export const shareTextForFilm = (
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
) =>
|
) =>
|
||||||
`Photos shot on Fujifilm ${labelForFilm(film).large}`;
|
`Photos shot on ${labelForFilm(film).large}`;
|
||||||
|
|
||||||
export const descriptionForFilmPhotos = (
|
export const descriptionForFilmPhotos = (
|
||||||
photos: Photo[],
|
photos: Photo[],
|
||||||
@ -69,7 +81,7 @@ export const descriptionForFilmPhotos = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
export const generateMetaForFilm = (
|
export const generateMetaForFilm = (
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
photos: Photo[],
|
photos: Photo[],
|
||||||
explicitCount?: number,
|
explicitCount?: number,
|
||||||
explicitDateRange?: PhotoDateRange,
|
explicitDateRange?: PhotoDateRange,
|
||||||
@ -93,13 +105,13 @@ export const convertFilmsForForm = (
|
|||||||
includeAllFujifilmSimulations?: boolean,
|
includeAllFujifilmSimulations?: boolean,
|
||||||
): AnnotatedTag[] => {
|
): AnnotatedTag[] => {
|
||||||
const films = includeAllFujifilmSimulations
|
const films = includeAllFujifilmSimulations
|
||||||
? FILM_SIMULATION_FORM_INPUT_OPTIONS
|
? FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS
|
||||||
.map(({ value }) => ({ value } as AnnotatedTag))
|
.map(({ value }) => ({ value } as AnnotatedTag))
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
_films.forEach(({ film, count }) => {
|
_films.forEach(({ film, count }) => {
|
||||||
const index = films.findIndex(f => f.value === film);
|
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);
|
.find(f => f.value === film);
|
||||||
const meta = {
|
const meta = {
|
||||||
annotation: formatCount(count),
|
annotation: formatCount(count),
|
||||||
|
|||||||
@ -2,13 +2,10 @@ import { Photo } from '../photo';
|
|||||||
import ImageCaption from './components/ImageCaption';
|
import ImageCaption from './components/ImageCaption';
|
||||||
import ImagePhotoGrid from './components/ImagePhotoGrid';
|
import ImagePhotoGrid from './components/ImagePhotoGrid';
|
||||||
import ImageContainer from './components/ImageContainer';
|
import ImageContainer from './components/ImageContainer';
|
||||||
import {
|
|
||||||
labelForFilm,
|
|
||||||
} from '@/platforms/fujifilm/simulation';
|
|
||||||
import PhotoFilmIcon from
|
import PhotoFilmIcon from
|
||||||
'@/film/PhotoFilmIcon';
|
'@/film/PhotoFilmIcon';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
import { NextImageSize } from '@/platforms/next-image';
|
import { NextImageSize } from '@/platforms/next-image';
|
||||||
|
import { labelForFilm } from '@/film';
|
||||||
|
|
||||||
export default function FilmImageResponse({
|
export default function FilmImageResponse({
|
||||||
film,
|
film,
|
||||||
@ -17,7 +14,7 @@ export default function FilmImageResponse({
|
|||||||
height,
|
height,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
}: {
|
}: {
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
photos: Photo[]
|
photos: Photo[]
|
||||||
width: NextImageSize
|
width: NextImageSize
|
||||||
height: number
|
height: number
|
||||||
|
|||||||
@ -6,7 +6,9 @@ import type { NextImageSize } from '@/platforms/next-image';
|
|||||||
import { formatTag } from '@/tag';
|
import { formatTag } from '@/tag';
|
||||||
import { generateRecipeText, getPhotoWithRecipeFromPhotos } from '@/recipe';
|
import { generateRecipeText, getPhotoWithRecipeFromPhotos } from '@/recipe';
|
||||||
import PhotoFilmIcon from '@/film/PhotoFilmIcon';
|
import PhotoFilmIcon from '@/film/PhotoFilmIcon';
|
||||||
import { isStringFilmSimulationLabel } from '@/platforms/fujifilm/simulation';
|
import {
|
||||||
|
isStringFujifilmSimulationLabel,
|
||||||
|
} from '@/platforms/fujifilm/simulation';
|
||||||
import IconRecipe from '@/components/icons/IconRecipe';
|
import IconRecipe from '@/components/icons/IconRecipe';
|
||||||
const MAX_RECIPE_LINES = 8;
|
const MAX_RECIPE_LINES = 8;
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ export default function RecipeImageResponse({
|
|||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
}}>
|
}}>
|
||||||
{text}
|
{text}
|
||||||
{isStringFilmSimulationLabel(text) && film &&
|
{isStringFujifilmSimulationLabel(text) && film &&
|
||||||
<div tw="flex">
|
<div tw="flex">
|
||||||
<PhotoFilmIcon
|
<PhotoFilmIcon
|
||||||
film={film}
|
film={film}
|
||||||
|
|||||||
@ -60,7 +60,6 @@ import { convertUploadToPhoto } from './storage';
|
|||||||
import { UrlAddStatus } from '@/admin/AdminUploadsClient';
|
import { UrlAddStatus } from '@/admin/AdminUploadsClient';
|
||||||
import { convertStringToArray } from '@/utility/string';
|
import { convertStringToArray } from '@/utility/string';
|
||||||
import { after } from 'next/server';
|
import { after } from 'next/server';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
|
|
||||||
// Private actions
|
// Private actions
|
||||||
|
|
||||||
@ -315,7 +314,7 @@ export const renamePhotoTagGloballyAction = async (formData: FormData) =>
|
|||||||
|
|
||||||
export const getPhotosNeedingRecipeTitleCountAction = async (
|
export const getPhotosNeedingRecipeTitleCountAction = async (
|
||||||
recipeData: string,
|
recipeData: string,
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
photoIdToExclude?: string,
|
photoIdToExclude?: string,
|
||||||
) =>
|
) =>
|
||||||
runAuthenticatedAdminServerAction(async () =>
|
runAuthenticatedAdminServerAction(async () =>
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import {
|
|||||||
} from '@/photo';
|
} from '@/photo';
|
||||||
import { Cameras, createCameraKey } from '@/camera';
|
import { Cameras, createCameraKey } from '@/camera';
|
||||||
import { Tags } from '@/tag';
|
import { Tags } from '@/tag';
|
||||||
import { FilmSimulation, Films } from '@/film';
|
import { Films } from '@/film';
|
||||||
import { ADMIN_SQL_DEBUG_ENABLED } from '@/app/config';
|
import { ADMIN_SQL_DEBUG_ENABLED } from '@/app/config';
|
||||||
import {
|
import {
|
||||||
GetPhotosOptions,
|
GetPhotosOptions,
|
||||||
@ -380,7 +380,7 @@ export const getUniqueRecipes = async () =>
|
|||||||
|
|
||||||
export const getRecipeTitleForData = async (
|
export const getRecipeTitleForData = async (
|
||||||
data: string | object,
|
data: string | object,
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
) =>
|
) =>
|
||||||
// Includes legacy check on pre-stringified JSON
|
// Includes legacy check on pre-stringified JSON
|
||||||
safelyQueryPhotos(() => sql`
|
safelyQueryPhotos(() => sql`
|
||||||
@ -395,7 +395,7 @@ export const getRecipeTitleForData = async (
|
|||||||
|
|
||||||
export const getPhotosNeedingRecipeTitleCount = async (
|
export const getPhotosNeedingRecipeTitleCount = async (
|
||||||
data: string,
|
data: string,
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
photoIdToExclude?: string,
|
photoIdToExclude?: string,
|
||||||
) =>
|
) =>
|
||||||
safelyQueryPhotos(() => sql`
|
safelyQueryPhotos(() => sql`
|
||||||
@ -411,7 +411,7 @@ export const getPhotosNeedingRecipeTitleCount = async (
|
|||||||
export const updateAllMatchingRecipeTitles = (
|
export const updateAllMatchingRecipeTitles = (
|
||||||
title: string,
|
title: string,
|
||||||
data: string,
|
data: string,
|
||||||
film: FilmSimulation,
|
film: string,
|
||||||
) =>
|
) =>
|
||||||
safelyQueryPhotos(() => sql`
|
safelyQueryPhotos(() => sql`
|
||||||
UPDATE photos
|
UPDATE photos
|
||||||
@ -430,7 +430,7 @@ export const getUniqueFilms = async () =>
|
|||||||
ORDER BY film ASC
|
ORDER BY film ASC
|
||||||
`.then(({ rows }): Films => rows
|
`.then(({ rows }): Films => rows
|
||||||
.map(({ film, count }) => ({
|
.map(({ film, count }) => ({
|
||||||
film: film as FilmSimulation,
|
film,
|
||||||
count: parseInt(count, 10),
|
count: parseInt(count, 10),
|
||||||
})))
|
})))
|
||||||
, 'getUniqueFilms');
|
, 'getUniqueFilms');
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import FieldSetWithStatus from '@/components/FieldSetWithStatus';
|
import FieldSetWithStatus from '@/components/FieldSetWithStatus';
|
||||||
import { ComponentProps, useEffect, useState } from 'react';
|
import { ComponentProps, useEffect, useState } from 'react';
|
||||||
import { getPhotosNeedingRecipeTitleCountAction } from '../actions';
|
import { getPhotosNeedingRecipeTitleCountAction } from '../actions';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
|
|
||||||
export default function ApplyRecipeTitleGloballyCheckbox({
|
export default function ApplyRecipeTitleGloballyCheckbox({
|
||||||
photoId,
|
photoId,
|
||||||
@ -16,7 +15,7 @@ export default function ApplyRecipeTitleGloballyCheckbox({
|
|||||||
recipeTitle?: string
|
recipeTitle?: string
|
||||||
hasRecipeTitleChanged?: boolean
|
hasRecipeTitleChanged?: boolean
|
||||||
recipeData?: string
|
recipeData?: string
|
||||||
film?: FilmSimulation
|
film?: string
|
||||||
onMatchResults: (didFindMatchingPhotos: boolean) => void
|
onMatchResults: (didFindMatchingPhotos: boolean) => void
|
||||||
}) {
|
}) {
|
||||||
const [matchingPhotosCount, setMatchingPhotosCount] = useState<number>();
|
const [matchingPhotosCount, setMatchingPhotosCount] = useState<number>();
|
||||||
|
|||||||
@ -41,7 +41,7 @@ import ErrorNote from '@/components/ErrorNote';
|
|||||||
import { convertRecipesForForm, Recipes } from '@/recipe';
|
import { convertRecipesForForm, Recipes } from '@/recipe';
|
||||||
import deepEqual from 'fast-deep-equal/es6/react';
|
import deepEqual from 'fast-deep-equal/es6/react';
|
||||||
import ApplyRecipeTitleGloballyCheckbox from './ApplyRecipesGloballyCheckbox';
|
import ApplyRecipeTitleGloballyCheckbox from './ApplyRecipesGloballyCheckbox';
|
||||||
import { convertFilmsForForm, Films, FilmSimulation } from '@/film';
|
import { convertFilmsForForm, Films } from '@/film';
|
||||||
import IconFavs from '@/components/icons/IconFavs';
|
import IconFavs from '@/components/icons/IconFavs';
|
||||||
import IconHidden from '@/components/icons/IconHidden';
|
import IconHidden from '@/components/icons/IconHidden';
|
||||||
import { isMakeFujifilm } from '@/platforms/fujifilm';
|
import { isMakeFujifilm } from '@/platforms/fujifilm';
|
||||||
@ -431,7 +431,7 @@ export default function PhotoForm({
|
|||||||
hasRecipeTitleChanged={
|
hasRecipeTitleChanged={
|
||||||
changedFormKeys.includes('recipeTitle')}
|
changedFormKeys.includes('recipeTitle')}
|
||||||
recipeData={formData.recipeData}
|
recipeData={formData.recipeData}
|
||||||
film={formData.film as FilmSimulation}
|
film={formData.film}
|
||||||
onMatchResults={onMatchResults}
|
onMatchResults={onMatchResults}
|
||||||
{...fieldProps}
|
{...fieldProps}
|
||||||
/>;
|
/>;
|
||||||
|
|||||||
@ -16,12 +16,12 @@ import {
|
|||||||
import { roundToNumber } from '@/utility/number';
|
import { roundToNumber } from '@/utility/number';
|
||||||
import { convertStringToArray, parameterize } from '@/utility/string';
|
import { convertStringToArray, parameterize } from '@/utility/string';
|
||||||
import { generateNanoid } from '@/utility/nanoid';
|
import { generateNanoid } from '@/utility/nanoid';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
import { GEO_PRIVACY_ENABLED } from '@/app/config';
|
import { GEO_PRIVACY_ENABLED } from '@/app/config';
|
||||||
import { TAG_FAVS, getValidationMessageForTags } from '@/tag';
|
import { TAG_FAVS, getValidationMessageForTags } from '@/tag';
|
||||||
import { MAKE_FUJIFILM } from '@/platforms/fujifilm';
|
import { MAKE_FUJIFILM } from '@/platforms/fujifilm';
|
||||||
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
import { FujifilmSimulation } from '@/platforms/fujifilm/simulation';
|
||||||
|
|
||||||
type VirtualFields =
|
type VirtualFields =
|
||||||
'favorite' |
|
'favorite' |
|
||||||
@ -276,7 +276,7 @@ export const convertPhotoToFormData = (photo: Photo): PhotoFormData => {
|
|||||||
|
|
||||||
export const convertExifToFormData = (
|
export const convertExifToFormData = (
|
||||||
data: ExifData,
|
data: ExifData,
|
||||||
film?: FilmSimulation,
|
film?: FujifilmSimulation,
|
||||||
recipeData?: FujifilmRecipe,
|
recipeData?: FujifilmRecipe,
|
||||||
): Omit<
|
): Omit<
|
||||||
Record<keyof PhotoExif, string | undefined>,
|
Record<keyof PhotoExif, string | undefined>,
|
||||||
@ -347,7 +347,7 @@ export const convertFormDataToPhotoDbInsert = (
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
...(photoForm as PhotoFormData & {
|
...(photoForm as PhotoFormData & {
|
||||||
film?: FilmSimulation
|
film?: FujifilmSimulation
|
||||||
recipeData?: FujifilmRecipe
|
recipeData?: FujifilmRecipe
|
||||||
}),
|
}),
|
||||||
...!photoForm.id && { id: generateNanoid() },
|
...!photoForm.id && { id: generateNanoid() },
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { formatFocalLength } from '@/focal';
|
import { formatFocalLength } from '@/focal';
|
||||||
import { getNextImageUrlForRequest } from '@/platforms/next-image';
|
import { getNextImageUrlForRequest } from '@/platforms/next-image';
|
||||||
import { FilmSimulation, photoHasFilmData } from '@/film';
|
import { photoHasFilmData } from '@/film';
|
||||||
import {
|
import {
|
||||||
HIGH_DENSITY_GRID,
|
HIGH_DENSITY_GRID,
|
||||||
IS_PREVIEW,
|
IS_PREVIEW,
|
||||||
@ -22,6 +22,7 @@ import camelcaseKeys from 'camelcase-keys';
|
|||||||
import { isBefore } from 'date-fns';
|
import { isBefore } from 'date-fns';
|
||||||
import type { Metadata } from 'next';
|
import type { Metadata } from 'next';
|
||||||
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
||||||
|
import { FujifilmSimulation } from '@/platforms/fujifilm/simulation';
|
||||||
|
|
||||||
// INFINITE SCROLL: FEED
|
// INFINITE SCROLL: FEED
|
||||||
export const INFINITE_SCROLL_FEED_INITIAL =
|
export const INFINITE_SCROLL_FEED_INITIAL =
|
||||||
@ -65,7 +66,7 @@ export interface PhotoExif {
|
|||||||
exposureCompensation?: number
|
exposureCompensation?: number
|
||||||
latitude?: number
|
latitude?: number
|
||||||
longitude?: number
|
longitude?: number
|
||||||
film?: FilmSimulation
|
film?: FujifilmSimulation
|
||||||
recipeData?: string
|
recipeData?: string
|
||||||
takenAt?: string
|
takenAt?: string
|
||||||
takenAtNaive?: string
|
takenAtNaive?: string
|
||||||
|
|||||||
@ -7,11 +7,11 @@ import {
|
|||||||
convertFormDataToPhotoDbInsert,
|
convertFormDataToPhotoDbInsert,
|
||||||
} from '@/photo/form';
|
} from '@/photo/form';
|
||||||
import {
|
import {
|
||||||
|
FujifilmSimulation,
|
||||||
getFujifilmSimulationFromMakerNote,
|
getFujifilmSimulationFromMakerNote,
|
||||||
} from '@/platforms/fujifilm/simulation';
|
} from '@/platforms/fujifilm/simulation';
|
||||||
import { ExifData, ExifParserFactory } from 'ts-exif-parser';
|
import { ExifData, ExifParserFactory } from 'ts-exif-parser';
|
||||||
import { PhotoFormData } from './form';
|
import { PhotoFormData } from './form';
|
||||||
import { FilmSimulation } from '@/film';
|
|
||||||
import sharp, { Sharp } from 'sharp';
|
import sharp, { Sharp } from 'sharp';
|
||||||
import {
|
import {
|
||||||
GEO_PRIVACY_ENABLED,
|
GEO_PRIVACY_ENABLED,
|
||||||
@ -58,7 +58,7 @@ export const extractImageDataFromBlobPath = async (
|
|||||||
const extension = getExtensionFromStorageUrl(url);
|
const extension = getExtensionFromStorageUrl(url);
|
||||||
|
|
||||||
let exifData: ExifData | undefined;
|
let exifData: ExifData | undefined;
|
||||||
let film: FilmSimulation | undefined;
|
let film: FujifilmSimulation | undefined;
|
||||||
let recipe: FujifilmRecipe | undefined;
|
let recipe: FujifilmRecipe | undefined;
|
||||||
let blurData: string | undefined;
|
let blurData: string | undefined;
|
||||||
let imageResizedBase64: string | undefined;
|
let imageResizedBase64: string | undefined;
|
||||||
|
|||||||
@ -80,7 +80,7 @@ interface FujifilmSimulationLabel {
|
|||||||
large: string
|
large: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const FILM_SIMULATION_LABELS: Record<
|
const FUJIFILM_SIMULATION_LABELS: Record<
|
||||||
FujifilmSimulation,
|
FujifilmSimulation,
|
||||||
FujifilmSimulationLabel
|
FujifilmSimulationLabel
|
||||||
> = {
|
> = {
|
||||||
@ -206,30 +206,30 @@ const FILM_SIMULATION_LABELS: Record<
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FILM_SIMULATION_FORM_INPUT_OPTIONS = Object
|
export const FUJIFILM_SIMULATION_FORM_INPUT_OPTIONS = Object
|
||||||
.entries(FILM_SIMULATION_LABELS)
|
.entries(FUJIFILM_SIMULATION_LABELS)
|
||||||
.map(([value, label]) => (
|
.map(([value, label]) => (
|
||||||
{ value, label: label.large } as
|
{ value, label: label.large } as
|
||||||
{ value: FujifilmSimulation, label: string }
|
{ value: FujifilmSimulation, label: string }
|
||||||
))
|
))
|
||||||
.sort((a, b) => a.label.localeCompare(b.label));
|
.sort((a, b) => a.label.localeCompare(b.label));
|
||||||
|
|
||||||
const ALL_POSSIBLE_FILM_SIMULATION_LABELS = Object
|
const ALL_POSSIBLE_FUJIFILM_SIMULATION_LABELS = Object
|
||||||
.values(FILM_SIMULATION_LABELS)
|
.values(FUJIFILM_SIMULATION_LABELS)
|
||||||
.flatMap(({ small, medium, large }) => [
|
.flatMap(({ small, medium, large }) => [
|
||||||
small.toLocaleLowerCase(),
|
small.toLocaleLowerCase(),
|
||||||
medium.toLocaleLowerCase(),
|
medium.toLocaleLowerCase(),
|
||||||
large.toLocaleLowerCase(),
|
large.toLocaleLowerCase(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const isStringFilmSimulation = (film?: string) =>
|
export const isStringFujifilmSimulation = (film?: string) =>
|
||||||
film && Object.keys(FILM_SIMULATION_LABELS).includes(film);
|
film && Object.keys(FUJIFILM_SIMULATION_LABELS).includes(film);
|
||||||
|
|
||||||
export const isStringFilmSimulationLabel = (film: string) =>
|
export const isStringFujifilmSimulationLabel = (film: string) =>
|
||||||
ALL_POSSIBLE_FILM_SIMULATION_LABELS.includes(film.toLocaleLowerCase());
|
ALL_POSSIBLE_FUJIFILM_SIMULATION_LABELS.includes(film.toLocaleLowerCase());
|
||||||
|
|
||||||
export const labelForFilm = (film: FujifilmSimulation) =>
|
export const labelForFujifilmSimulation = (film: FujifilmSimulation) =>
|
||||||
FILM_SIMULATION_LABELS[film];
|
FUJIFILM_SIMULATION_LABELS[film];
|
||||||
|
|
||||||
export const getFujifilmSimulationFromMakerNote = (
|
export const getFujifilmSimulationFromMakerNote = (
|
||||||
bytes: Buffer,
|
bytes: Buffer,
|
||||||
|
|||||||
@ -15,11 +15,11 @@ import {
|
|||||||
generateRecipeText,
|
generateRecipeText,
|
||||||
RecipeProps,
|
RecipeProps,
|
||||||
} from '.';
|
} from '.';
|
||||||
import { labelForFilm } from '@/platforms/fujifilm/simulation';
|
|
||||||
import { TbChecklist } from 'react-icons/tb';
|
import { TbChecklist } from 'react-icons/tb';
|
||||||
import CopyButton from '@/components/CopyButton';
|
import CopyButton from '@/components/CopyButton';
|
||||||
import { pathForRecipe } from '@/app/paths';
|
import { pathForRecipe } from '@/app/paths';
|
||||||
import LinkWithStatus from '@/components/LinkWithStatus';
|
import LinkWithStatus from '@/components/LinkWithStatus';
|
||||||
|
import { labelForFilm } from '@/film';
|
||||||
|
|
||||||
export default function PhotoRecipeOverlay({
|
export default function PhotoRecipeOverlay({
|
||||||
ref,
|
ref,
|
||||||
|
|||||||
@ -7,8 +7,7 @@ import {
|
|||||||
formatCountDescriptive,
|
formatCountDescriptive,
|
||||||
} from '@/utility/string';
|
} from '@/utility/string';
|
||||||
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
import { FujifilmRecipe } from '@/platforms/fujifilm/recipe';
|
||||||
import { FilmSimulation } from '@/film';
|
import { labelForFilm } from '@/film';
|
||||||
import { labelForFilm } from '@/platforms/fujifilm/simulation';
|
|
||||||
|
|
||||||
export type RecipeWithCount = {
|
export type RecipeWithCount = {
|
||||||
recipe: string
|
recipe: string
|
||||||
@ -20,7 +19,7 @@ export type Recipes = RecipeWithCount[]
|
|||||||
export interface RecipeProps {
|
export interface RecipeProps {
|
||||||
title?: string
|
title?: string
|
||||||
recipe: FujifilmRecipe
|
recipe: FujifilmRecipe
|
||||||
film: FilmSimulation
|
film: string
|
||||||
iso?: string
|
iso?: string
|
||||||
exposure?: string
|
exposure?: string
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user