diff --git a/src/admin/AdminPhotoMenuClient.tsx b/src/admin/AdminPhotoMenuClient.tsx index 60b902a7..ee792f59 100644 --- a/src/admin/AdminPhotoMenuClient.tsx +++ b/src/admin/AdminPhotoMenuClient.tsx @@ -25,7 +25,7 @@ export default function AdminPhotoMenuClient({ const isFav = isPhotoFav(photo); const path = usePathname(); const shouldRedirectFav = isPathFavs(path) && isFav; - const shouldRedirectDelete = pathForPhoto(photo.id) === path; + const shouldRedirectDelete = pathForPhoto({ photo: photo.id }) === path; return ( isUserSignedIn diff --git a/src/admin/AdminPhotosTable.tsx b/src/admin/AdminPhotosTable.tsx index 34dcf7de..15d6c6fc 100644 --- a/src/admin/AdminPhotosTable.tsx +++ b/src/admin/AdminPhotosTable.tsx @@ -45,7 +45,7 @@ export default function AdminPhotosTable({
diff --git a/src/app/film/[simulation]/[photoId]/layout.tsx b/src/app/film/[simulation]/[photoId]/layout.tsx index 4773e8da..4219e838 100644 --- a/src/app/film/[simulation]/[photoId]/layout.tsx +++ b/src/app/film/[simulation]/[photoId]/layout.tsx @@ -41,7 +41,7 @@ export async function generateMetadata({ const title = titleForPhoto(photo); const description = descriptionForPhoto(photo); const images = absolutePathForPhotoImage(photo); - const url = absolutePathForPhoto(photo, simulation); + const url = absolutePathForPhoto({ photo, simulation }); return { title, diff --git a/src/app/focal/[focal]/image/route.tsx b/src/app/focal/[focal]/image/route.tsx new file mode 100644 index 00000000..22db2d06 --- /dev/null +++ b/src/app/focal/[focal]/image/route.tsx @@ -0,0 +1,41 @@ +import { getPhotosCached } from '@/photo/cache'; +import { + IMAGE_OG_DIMENSION_SMALL, + MAX_PHOTOS_TO_SHOW_PER_TAG, +} from '@/image-response'; +import { getIBMPlexMonoMedium } from '@/site/font'; +import { ImageResponse } from 'next/og'; +import { getImageResponseCacheControlHeaders } from '@/image-response/cache'; +import FocalLengthImageResponse from + '@/image-response/FocalLengthImageResponse'; +import { getFocalLengthFromString } from '@/focal'; + +export async function GET( + _: Request, + context: { params: { focal: string } }, +) { + const focal = getFocalLengthFromString(context.params.focal); + + const [ + photos, + { fontFamily, fonts }, + headers, + ] = await Promise.all([ + getPhotosCached({ limit: MAX_PHOTOS_TO_SHOW_PER_TAG, focal }), + getIBMPlexMonoMedium(), + getImageResponseCacheControlHeaders(), + ]); + + const { width, height } = IMAGE_OG_DIMENSION_SMALL; + + return new ImageResponse( + , + { width, height, fonts, headers }, + ); +} diff --git a/src/app/focal/[focal]/page.tsx b/src/app/focal/[focal]/page.tsx new file mode 100644 index 00000000..f8b01767 --- /dev/null +++ b/src/app/focal/[focal]/page.tsx @@ -0,0 +1,71 @@ +import { generateMetaForFocalLength, getFocalLengthFromString } from '@/focal'; +import FocalLengthOverview from '@/focal/FocalLengthOverview'; +import { getPhotosFocalDataCached } from '@/focal/data'; +import { INFINITE_SCROLL_GRID_PHOTO_INITIAL } from '@/photo'; +import { PATH_ROOT } from '@/site/paths'; +import type { Metadata } from 'next'; +import { redirect } from 'next/navigation'; +import { cache } from 'react'; + +const getPhotosFocalDataCachedCached = cache((focal: number) => + getPhotosFocalDataCached({ + focal, + limit: INFINITE_SCROLL_GRID_PHOTO_INITIAL, + })); + +interface FocalLengthProps { + params: { focal: string } +} + +export async function generateMetadata({ + params: { focal: focalString }, +}: FocalLengthProps): Promise { + const focal = getFocalLengthFromString(focalString); + + const [ + photos, + { count, dateRange }, + ] = await getPhotosFocalDataCachedCached(focal); + + if (photos.length === 0) { return {}; } + + const { + url, + title, + description, + images, + } = generateMetaForFocalLength(focal, photos, count, dateRange); + + return { + title, + openGraph: { + title, + description, + images, + url, + }, + twitter: { + images, + description, + card: 'summary_large_image', + }, + description, + }; +} + +export default async function TagPage({ + params: { focal: focalString }, +}:FocalLengthProps) { + const focal = getFocalLengthFromString(focalString); + + const [ + photos, + { count, dateRange }, + ] = await getPhotosFocalDataCachedCached(focal); + + if (photos.length === 0) { redirect(PATH_ROOT); } + + return ( + + ); +} diff --git a/src/app/p/[photoId]/layout.tsx b/src/app/p/[photoId]/layout.tsx index e40e7d9c..1a00868a 100644 --- a/src/app/p/[photoId]/layout.tsx +++ b/src/app/p/[photoId]/layout.tsx @@ -44,7 +44,7 @@ export async function generateMetadata({ const title = titleForPhoto(photo); const description = descriptionForPhoto(photo); const images = absolutePathForPhotoImage(photo); - const url = absolutePathForPhoto(photo); + const url = absolutePathForPhoto({ photo }); return { title, diff --git a/src/app/shot-on/[make]/[model]/[photoId]/layout.tsx b/src/app/shot-on/[make]/[model]/[photoId]/layout.tsx index 42efcca0..b2908928 100644 --- a/src/app/shot-on/[make]/[model]/[photoId]/layout.tsx +++ b/src/app/shot-on/[make]/[model]/[photoId]/layout.tsx @@ -44,11 +44,10 @@ export async function generateMetadata({ const title = titleForPhoto(photo); const description = descriptionForPhoto(photo); const images = absolutePathForPhotoImage(photo); - const url = absolutePathForPhoto( + const url = absolutePathForPhoto({ photo, - undefined, - cameraFromPhoto(photo, { make, model }), - ); + camera: cameraFromPhoto(photo, { make, model }), + }); return { title, diff --git a/src/app/tag/[tag]/[photoId]/layout.tsx b/src/app/tag/[tag]/[photoId]/layout.tsx index 5de147fd..cb8ebd85 100644 --- a/src/app/tag/[tag]/[photoId]/layout.tsx +++ b/src/app/tag/[tag]/[photoId]/layout.tsx @@ -35,7 +35,7 @@ export async function generateMetadata({ const title = titleForPhoto(photo); const description = descriptionForPhoto(photo); const images = absolutePathForPhotoImage(photo); - const url = absolutePathForPhoto(photo, tag); + const url = absolutePathForPhoto({ photo, tag }); return { title, diff --git a/src/app/tag/hidden/[photoId]/page.tsx b/src/app/tag/hidden/[photoId]/page.tsx index 954fca0c..796447c0 100644 --- a/src/app/tag/hidden/[photoId]/page.tsx +++ b/src/app/tag/hidden/[photoId]/page.tsx @@ -33,7 +33,7 @@ export async function generateMetadata({ const title = titleForPhoto(photo); const description = descriptionForPhoto(photo); - const url = absolutePathForPhoto(photo, TAG_HIDDEN); + const url = absolutePathForPhoto({ photo, tag: TAG_HIDDEN }); return { title, diff --git a/src/components/CommandKClient.tsx b/src/components/CommandKClient.tsx index 4f5af280..61d6bd10 100644 --- a/src/components/CommandKClient.tsx +++ b/src/components/CommandKClient.tsx @@ -147,7 +147,7 @@ export default function CommandKClient({ keywords: getKeywordsForPhoto(photo), annotation: , accessory: , - path: pathForPhoto(photo), + path: pathForPhoto({ photo }), })), }] : []); diff --git a/src/focal/FocalLengthHeader.tsx b/src/focal/FocalLengthHeader.tsx new file mode 100644 index 00000000..9babb486 --- /dev/null +++ b/src/focal/FocalLengthHeader.tsx @@ -0,0 +1,39 @@ +import { Photo, PhotoDateRange } from '@/photo'; +import { descriptionForFocalLengthPhotos } from '.'; +import { pathForFocalLength } from '@/site/paths'; +import PhotoSetHeader from '@/photo/PhotoSetHeader'; +import PhotoFocalLength from './PhotoFocalLength'; + +export default function FocalLengthHeader({ + focal, + photos, + selectedPhoto, + indexNumber, + count, + dateRange, +}: { + focal: number + photos: Photo[] + selectedPhoto?: Photo + indexNumber?: number + count?: number + dateRange?: PhotoDateRange +}) { + return ( + } + entityVerb="Tagged" + entityDescription={descriptionForFocalLengthPhotos( + photos, + undefined, + count, + )} + photos={photos} + selectedPhoto={selectedPhoto} + sharePath={pathForFocalLength(focal)} + indexNumber={indexNumber} + count={count} + dateRange={dateRange} + /> + ); +} diff --git a/src/focal/FocalLengthOverview.tsx b/src/focal/FocalLengthOverview.tsx new file mode 100644 index 00000000..a5d23463 --- /dev/null +++ b/src/focal/FocalLengthOverview.tsx @@ -0,0 +1,33 @@ +import { Photo, PhotoDateRange } from '@/photo'; +import PhotoGridPage from '@/photo/PhotoGridPage'; +import FocalLengthHeader from './FocalLengthHeader'; + +export default function FocalLengthOverview({ + focal, + photos, + count, + dateRange, + animateOnFirstLoadOnly, +}: { + focal: number, + photos: Photo[], + count: number, + dateRange?: PhotoDateRange, + animateOnFirstLoadOnly?: boolean, +}) { + return ( + , + animateOnFirstLoadOnly, + }} /> + ); +} diff --git a/src/focal/PhotoFocalLength.tsx b/src/focal/PhotoFocalLength.tsx new file mode 100644 index 00000000..b242e43b --- /dev/null +++ b/src/focal/PhotoFocalLength.tsx @@ -0,0 +1,31 @@ +import { pathForFocalLength } from '@/site/paths'; +import EntityLink, { + EntityLinkExternalProps, +} from '@/components/primitives/EntityLink'; +import { TbCone } from 'react-icons/tb'; +import { formatFocalLength } from '.'; + +export default function PhotoFocalLength({ + focal, + type, + badged, + contrast, + prefetch, + countOnHover, +}: { + focal: number + countOnHover?: number +} & EntityLinkExternalProps) { + return ( + } + type={type} + badged={badged} + contrast={contrast} + prefetch={prefetch} + hoverEntity={countOnHover} + /> + ); +} diff --git a/src/focal/data.ts b/src/focal/data.ts new file mode 100644 index 00000000..be5b539d --- /dev/null +++ b/src/focal/data.ts @@ -0,0 +1,17 @@ +import { + getPhotosCached, + getPhotosMetaCached, +} from '@/photo/cache'; + +export const getPhotosFocalDataCached = ({ + focal, + limit, +}: { + focal: number, + limit?: number, +}) => + Promise.all([ + getPhotosCached({ focal, limit }), + getPhotosMetaCached({ focal }), + ]); + diff --git a/src/focal/index.ts b/src/focal/index.ts index 712e8a25..9104df94 100644 --- a/src/focal/index.ts +++ b/src/focal/index.ts @@ -9,12 +9,21 @@ import { absolutePathForFocalLengthImage, } from '@/site/paths'; +export const getFocalLengthFromString = (focalString?: string) => { + const focal = focalString?.match(/^([0-9]+)mm/)?.[1]; + return focal ? parseInt(focal, 10) : 0; +}; + +export const formatFocalLength = (focal?: number) => focal ? + `${focal}mm` + : undefined; + export const titleForFocalLength = ( focal: number, photos: Photo[], explicitCount?: number, ) => [ - `${focal}mm`, + formatFocalLength(focal), photoQuantityText(explicitCount ?? photos.length), ].join(' '); diff --git a/src/image-response/FocalLengthImageResponse.tsx b/src/image-response/FocalLengthImageResponse.tsx new file mode 100644 index 00000000..498f9cfd --- /dev/null +++ b/src/image-response/FocalLengthImageResponse.tsx @@ -0,0 +1,46 @@ +import type { Photo } from '../photo'; +import ImageCaption from './components/ImageCaption'; +import ImagePhotoGrid from './components/ImagePhotoGrid'; +import ImageContainer from './components/ImageContainer'; +import type { NextImageSize } from '@/services/next-image'; +import { TbCone } from 'react-icons/tb'; +import { formatFocalLength } from '@/focal'; + +export default function FocalLengthImageResponse({ + focal, + photos, + width, + height, + fontFamily, +}: { + focal: number, + photos: Photo[] + width: NextImageSize + height: number + fontFamily: string +}) { + return ( + + + + + {formatFocalLength(focal)} + + + ); +} diff --git a/src/photo/PhotoGrid.tsx b/src/photo/PhotoGrid.tsx index 32e669d4..6dbc57f4 100644 --- a/src/photo/PhotoGrid.tsx +++ b/src/photo/PhotoGrid.tsx @@ -12,6 +12,7 @@ export default function PhotoGrid({ tag, camera, simulation, + focal, photoPriority, fast, animate = true, @@ -28,6 +29,7 @@ export default function PhotoGrid({ tag?: string camera?: Camera simulation?: FilmSimulation + focal?: number photoPriority?: boolean fast?: boolean animate?: boolean @@ -77,6 +79,7 @@ export default function PhotoGrid({ tag, camera, simulation, + focal, selected: photo.id === selectedPhoto?.id, priority: photoPriority, onVisible: index === photos.length - 1 diff --git a/src/photo/PhotoGridInfinite.tsx b/src/photo/PhotoGridInfinite.tsx index 98b43667..0b9a1428 100644 --- a/src/photo/PhotoGridInfinite.tsx +++ b/src/photo/PhotoGridInfinite.tsx @@ -13,6 +13,7 @@ export default function PhotoGridInfinite({ tag, camera, simulation, + focal, animateOnFirstLoadOnly, }: { cacheKey: string @@ -21,6 +22,7 @@ export default function PhotoGridInfinite({ tag?: string camera?: Camera simulation?: FilmSimulation + focal?: number animateOnFirstLoadOnly?: boolean }) { return ( @@ -39,6 +41,7 @@ export default function PhotoGridInfinite({ tag, camera, simulation, + focal, onLastPhotoVisible, animateOnFirstLoadOnly, }} />} diff --git a/src/photo/PhotoGridPage.tsx b/src/photo/PhotoGridPage.tsx index 4e1fdc74..eb3430f0 100644 --- a/src/photo/PhotoGridPage.tsx +++ b/src/photo/PhotoGridPage.tsx @@ -17,6 +17,7 @@ export default function PhotoGridPage({ tag, camera, simulation, + focal, animateOnFirstLoadOnly, header, sidebar, @@ -27,6 +28,7 @@ export default function PhotoGridPage({ tag?: string camera?: Camera simulation?: FilmSimulation + focal?: number animateOnFirstLoadOnly?: boolean header?: JSX.Element sidebar?: JSX.Element @@ -58,6 +60,7 @@ export default function PhotoGridPage({ tag, camera, simulation, + focal, animateOnFirstLoadOnly, onAnimationComplete, }} /> @@ -69,6 +72,7 @@ export default function PhotoGridPage({ tag, camera, simulation, + focal, animateOnFirstLoadOnly, }} />}
diff --git a/src/photo/PhotoLarge.tsx b/src/photo/PhotoLarge.tsx index 92862170..e7e7c561 100644 --- a/src/photo/PhotoLarge.tsx +++ b/src/photo/PhotoLarge.tsx @@ -40,6 +40,7 @@ export default function PhotoLarge({ shouldShareTag, shouldShareCamera, shouldShareSimulation, + shouldShareFocalLength, shouldScrollOnShare, onVisible, }: { @@ -54,6 +55,7 @@ export default function PhotoLarge({ shouldShareTag?: boolean shouldShareCamera?: boolean shouldShareSimulation?: boolean + shouldShareFocalLength?: boolean shouldScrollOnShare?: boolean onVisible?: () => void }) { @@ -76,7 +78,7 @@ export default function PhotoLarge({ containerRef={ref} contentMain={ diff --git a/src/photo/PhotoLink.tsx b/src/photo/PhotoLink.tsx index bbdf02d3..34bcca38 100644 --- a/src/photo/PhotoLink.tsx +++ b/src/photo/PhotoLink.tsx @@ -15,6 +15,7 @@ export default function PhotoLink({ tag, camera, simulation, + focal, scroll, prefetch, nextPhotoAnimation, @@ -25,6 +26,7 @@ export default function PhotoLink({ tag?: string camera?: Camera simulation?: FilmSimulation + focal?: number scroll?: boolean prefetch?: boolean nextPhotoAnimation?: AnimationConfig @@ -36,7 +38,7 @@ export default function PhotoLink({ return ( photo ? { if (nextPhotoAnimation) { diff --git a/src/photo/PhotoLinks.tsx b/src/photo/PhotoLinks.tsx index 0c369464..6a7a5c1b 100644 --- a/src/photo/PhotoLinks.tsx +++ b/src/photo/PhotoLinks.tsx @@ -21,12 +21,14 @@ export default function PhotoLinks({ tag, camera, simulation, + focal, }: { photo: Photo photos: Photo[] tag?: string camera?: Camera simulation?: FilmSimulation + focal?: number }) { const router = useRouter(); @@ -47,7 +49,13 @@ export default function PhotoLinks({ if (previousPhoto) { setNextPhotoAnimation?.(ANIMATION_RIGHT); router.push( - pathForPhoto(previousPhoto, tag, camera, simulation), + pathForPhoto({ + photo: previousPhoto, + tag, + camera, + simulation, + focal, + }), { scroll: false }, ); } @@ -57,7 +65,13 @@ export default function PhotoLinks({ if (nextPhoto) { setNextPhotoAnimation?.(ANIMATION_LEFT); router.push( - pathForPhoto(nextPhoto, tag, camera, simulation), + pathForPhoto({ + photo: nextPhoto, + tag, + camera, + simulation, + focal, + }), { scroll: false }, ); } @@ -76,6 +90,7 @@ export default function PhotoLinks({ tag, camera, simulation, + focal, ]); return ( diff --git a/src/photo/PhotoMedium.tsx b/src/photo/PhotoMedium.tsx index ec666919..72fdd0a4 100644 --- a/src/photo/PhotoMedium.tsx +++ b/src/photo/PhotoMedium.tsx @@ -16,6 +16,7 @@ export default function PhotoMedium({ tag, camera, simulation, + focal, selected, priority, prefetch = SHOULD_PREFETCH_ALL_LINKS, @@ -26,6 +27,7 @@ export default function PhotoMedium({ tag?: string camera?: Camera simulation?: FilmSimulation + focal?: number selected?: boolean priority?: boolean prefetch?: boolean @@ -39,7 +41,7 @@ export default function PhotoMedium({ return ( - + ); }; diff --git a/src/photo/PhotoSmall.tsx b/src/photo/PhotoSmall.tsx index 36ef31ee..66a9819a 100644 --- a/src/photo/PhotoSmall.tsx +++ b/src/photo/PhotoSmall.tsx @@ -6,10 +6,15 @@ import { pathForPhoto } from '@/site/paths'; import { SHOULD_PREFETCH_ALL_LINKS } from '@/site/config'; import { useRef } from 'react'; import useOnVisible from '@/utility/useOnVisible'; +import { Camera } from '@/camera'; +import { FilmSimulation } from '@/simulation'; export default function PhotoSmall({ photo, tag, + camera, + simulation, + focal, selected, className, prefetch = SHOULD_PREFETCH_ALL_LINKS, @@ -17,6 +22,9 @@ export default function PhotoSmall({ }: { photo: Photo tag?: string + camera?: Camera + simulation?: FilmSimulation + focal?: number selected?: boolean className?: string prefetch?: boolean @@ -29,7 +37,7 @@ export default function PhotoSmall({ return ( { revalidateCamerasKey(); revalidateFilmSimulationsKey(); // Paths - revalidatePath(pathForPhoto(photoId), 'layout'); + revalidatePath(pathForPhoto({ photo: photoId }), 'layout'); revalidatePath(PATH_ROOT, 'layout'); revalidatePath(PATH_GRID, 'layout'); revalidatePath(PREFIX_TAG, 'layout'); diff --git a/src/photo/db/index.ts b/src/photo/db/index.ts index 8094d545..79697d6c 100644 --- a/src/photo/db/index.ts +++ b/src/photo/db/index.ts @@ -7,16 +7,17 @@ export const GENERATE_STATIC_PARAMS_LIMIT = 1000; export const PHOTO_DEFAULT_LIMIT = 100; export type GetPhotosOptions = { - sortBy?: 'createdAt' | 'takenAt' | 'priority'; - limit?: number; - offset?: number; - query?: string; - tag?: string; - camera?: Camera; - simulation?: FilmSimulation; - takenBefore?: Date; - takenAfterInclusive?: Date; - hidden?: 'exclude' | 'include' | 'only'; + sortBy?: 'createdAt' | 'takenAt' | 'priority' + limit?: number + offset?: number + query?: string + tag?: string + camera?: Camera + simulation?: FilmSimulation + focal?: number + takenBefore?: Date + takenAfterInclusive?: Date + hidden?: 'exclude' | 'include' | 'only' }; export const getWheresFromOptions = ( @@ -31,6 +32,7 @@ export const getWheresFromOptions = ( tag, camera, simulation, + focal, } = options; const wheres = [] as string[]; @@ -73,6 +75,10 @@ export const getWheresFromOptions = ( wheres.push(`film_simulation=$${valuesIndex++}`); wheresValues.push(simulation); } + if (focal) { + wheres.push(`focal_length=$${valuesIndex++}`); + wheresValues.push(focal); + } return { wheres: wheres.length > 0 diff --git a/src/photo/index.ts b/src/photo/index.ts index c9ea8bef..01b0d0b0 100644 --- a/src/photo/index.ts +++ b/src/photo/index.ts @@ -1,3 +1,4 @@ +import { formatFocalLength } from '@/focal'; import { getNextImageUrlForRequest } from '@/services/next-image'; import { FilmSimulation } from '@/simulation'; import { HIGH_DENSITY_GRID, SHOW_EXIF_DATA } from '@/site/config'; @@ -8,7 +9,6 @@ import { formatIso, formatExposureCompensation, formatExposureTime, - formatFocalLength, } from '@/utility/exif'; import camelcaseKeys from 'camelcase-keys'; import { isBefore } from 'date-fns'; diff --git a/src/site/api.ts b/src/site/api.ts index b478d183..54ba5cbe 100644 --- a/src/site/api.ts +++ b/src/site/api.ts @@ -30,7 +30,7 @@ interface PublicApiPhoto { export const formatPhotoForApi = (photo: Photo): PublicApiPhoto => ({ id: photo.id, title: photo.title, - url: absolutePathForPhoto(photo), + url: absolutePathForPhoto({ photo }), ...photo.make && { make: photo.make }, ...photo.model && { model: photo.model }, ...photo.tags.length > 0 && { tags: photo.tags }, diff --git a/src/site/paths.ts b/src/site/paths.ts index 60a8da35..a04b4335 100644 --- a/src/site/paths.ts +++ b/src/site/paths.ts @@ -63,6 +63,14 @@ export const PATHS_TO_CACHE = [ ...PATHS_ADMIN, ]; +interface PhotoPathParams { + photo: PhotoOrPhotoId + tag?: string + camera?: Camera + simulation?: FilmSimulation + focal?: number +} + // Absolute paths export const ABSOLUTE_PATH_FOR_HOME_IMAGE = `${BASE_URL}/home-image`; @@ -80,13 +88,13 @@ type PhotoOrPhotoId = Photo | string; const getPhotoId = (photoOrPhotoId: PhotoOrPhotoId) => typeof photoOrPhotoId === 'string' ? photoOrPhotoId : photoOrPhotoId.id; -export const pathForPhoto = ( - photo: PhotoOrPhotoId, - tag?: string, - camera?: Camera, - simulation?: FilmSimulation, - focal?: number, -) => +export const pathForPhoto = ({ + photo, + tag, + camera, + simulation, + focal, +}: PhotoPathParams) => typeof photo !== 'string' && photo.hidden ? `${pathForTag(TAG_HIDDEN)}/${getPhotoId(photo)}` : tag @@ -99,13 +107,8 @@ export const pathForPhoto = ( ? `${pathForFocalLength(focal)}/${getPhotoId(photo)}` : `${PREFIX_PHOTO}/${getPhotoId(photo)}`; -export const pathForPhotoShare = ( - photo: PhotoOrPhotoId, - tag?: string, - camera?: Camera, - simulation?: FilmSimulation, -) => - `${pathForPhoto(photo, tag, camera, simulation)}/${SHARE}`; +export const pathForPhotoShare = (params: PhotoPathParams) => + `${pathForPhoto(params)}/${SHARE}`; export const pathForTag = (tag: string) => `${PREFIX_TAG}/${tag}`; @@ -128,13 +131,8 @@ export const pathForFocalLength = (focal: number) => export const pathForFilmSimulationShare = (simulation: FilmSimulation) => `${pathForFilmSimulation(simulation)}/${SHARE}`; -export const absolutePathForPhoto = ( - photo: PhotoOrPhotoId, - tag?: string, - camera?: Camera, - simulation?: FilmSimulation -) => - `${BASE_URL}${pathForPhoto(photo, tag, camera, simulation)}`; +export const absolutePathForPhoto = (params: PhotoPathParams) => + `${BASE_URL}${pathForPhoto(params)}`; export const absolutePathForTag = (tag: string) => `${BASE_URL}${pathForTag(tag)}`; @@ -149,7 +147,7 @@ export const absolutePathForFocalLength = (focal: number) => `${BASE_URL}${pathForFocalLength(focal)}`; export const absolutePathForPhotoImage = (photo: PhotoOrPhotoId) => - `${absolutePathForPhoto(photo)}/image`; + `${absolutePathForPhoto({ photo })}/image`; export const absolutePathForTagImage = (tag: string) => `${absolutePathForTag(tag)}/image`; @@ -329,15 +327,15 @@ export const getEscapePath = (pathname?: string) => { ) { return PATH_GRID; } else if (photoId && isPathTagPhotoShare(pathname)) { - return pathForPhoto(photoId, tag); + return pathForPhoto({ photo: photoId, tag }); } else if (photoId && isPathCameraPhotoShare(pathname)) { - return pathForPhoto(photoId, undefined, camera); + return pathForPhoto({ photo: photoId, camera }); } else if (photoId && isPathFilmSimulationPhotoShare(pathname)) { - return pathForPhoto(photoId, undefined, undefined, simulation); + return pathForPhoto({ photo: photoId, simulation }); } else if (photoId && isPathFocalLengthPhotoShare(pathname)) { - return pathForPhoto(photoId, undefined, undefined, undefined, focal); + return pathForPhoto({ photo: photoId, focal }); } else if (photoId && isPathPhotoShare(pathname)) { - return pathForPhoto(photoId); + return pathForPhoto({ photo: photoId }); } else if (tag && ( isPathTagPhoto(pathname) || isPathTagShare(pathname) diff --git a/src/utility/exif.ts b/src/utility/exif.ts index ebc36bf9..60b10288 100644 --- a/src/utility/exif.ts +++ b/src/utility/exif.ts @@ -31,9 +31,6 @@ export const getAspectRatioFromExif = (data: ExifData): number => { } }; -export const formatFocalLength = (focalLength?: number) => - focalLength ? `${focalLength}mm` : undefined; - export const formatAperture = (aperture?: number) => aperture ? `ƒ/${aperture}` : undefined;