'use client'; import { Photo, altTextForPhoto, doesPhotoNeedBlurCompatibility, shouldShowCameraDataForPhoto, shouldShowExifDataForPhoto, shouldShowLensDataForPhoto, shouldShowRecipeDataForPhoto, titleForPhoto, } from '.'; import AppGrid from '@/components/AppGrid'; import ImageLarge from '@/components/image/ImageLarge'; import { clsx } from 'clsx/lite'; import Link from 'next/link'; import { pathForFocalLength, pathForPhoto } from '@/app/paths'; import PhotoTags from '@/tag/PhotoTags'; import ShareButton from '@/share/ShareButton'; import DownloadButton from '@/components/DownloadButton'; import PhotoCamera from '../camera/PhotoCamera'; import { cameraFromPhoto } from '@/camera'; import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation'; import { sortTagsArray } from '@/tag'; import DivDebugBaselineGrid from '@/components/DivDebugBaselineGrid'; import PhotoLink from './PhotoLink'; import { SHOULD_PREFETCH_ALL_LINKS, ALLOW_PUBLIC_DOWNLOADS, SHOW_TAKEN_AT_TIME, } from '@/app/config'; import AdminPhotoMenuClient from '@/admin/AdminPhotoMenuClient'; import { RevalidatePhoto } from './InfinitePhotoScroll'; import { useMemo, useRef } from 'react'; import useVisible from '@/utility/useVisible'; import PhotoDate from './PhotoDate'; import { useAppState } from '@/state/AppState'; import { LuExpand } from 'react-icons/lu'; import LoaderButton from '@/components/primitives/LoaderButton'; import Tooltip from '@/components/Tooltip'; import ZoomControls, { ZoomControlsRef } from '@/components/image/ZoomControls'; import { TbChecklist } from 'react-icons/tb'; import { IoCloseSharp } from 'react-icons/io5'; import { AnimatePresence } from 'framer-motion'; import useRecipeOverlay from '../recipe/useRecipeOverlay'; import PhotoRecipeOverlay from '@/recipe/PhotoRecipeOverlay'; import PhotoRecipe from '@/recipe/PhotoRecipe'; import PhotoLens from '@/lens/PhotoLens'; import { lensFromPhoto } from '@/lens'; export default function PhotoLarge({ photo, className, primaryTag, priority, prefetch = SHOULD_PREFETCH_ALL_LINKS, prefetchRelatedLinks = SHOULD_PREFETCH_ALL_LINKS, revalidatePhoto, showTitle = true, showTitleAsH1, showCamera = true, showLens = true, showSimulation = true, showRecipe = true, showZoomControls: showZoomControlsProp = true, shouldZoomOnFKeydown = true, shouldShare = true, shouldShareCamera, shouldShareLens, shouldShareTag, shouldShareSimulation, shouldShareRecipe, shouldShareFocalLength, includeFavoriteInAdminMenu, onVisible, }: { photo: Photo className?: string primaryTag?: string priority?: boolean prefetch?: boolean prefetchRelatedLinks?: boolean revalidatePhoto?: RevalidatePhoto showTitle?: boolean showTitleAsH1?: boolean showCamera?: boolean showLens?: boolean showSimulation?: boolean showRecipe?: boolean showZoomControls?: boolean shouldZoomOnFKeydown?: boolean shouldShare?: boolean shouldShareCamera?: boolean shouldShareLens?: boolean shouldShareTag?: boolean shouldShareSimulation?: boolean shouldShareRecipe?: boolean shouldShareFocalLength?: boolean includeFavoriteInAdminMenu?: boolean onVisible?: () => void }) { const ref = useRef(null); const zoomControlsRef = useRef(null); const { areZoomControlsShown, arePhotosMatted, shouldDebugRecipeOverlays, isUserSignedIn, } = useAppState(); const showZoomControls = showZoomControlsProp && areZoomControlsShown; const refRecipe = useRef(null); const refRecipeButton = useRef(null); const refTriggers = useMemo(() => [refRecipeButton], []); const { shouldShowRecipeOverlay, toggleRecipeOverlay, hideRecipeOverlay, } = useRecipeOverlay({ ref: refRecipe, refTriggers, }); const tags = sortTagsArray(photo.tags, primaryTag); const camera = cameraFromPhoto(photo); const lens = lensFromPhoto(photo); const { recipeTitle } = photo; const showExifContent = shouldShowExifDataForPhoto(photo); const showCameraContent = showCamera && shouldShowCameraDataForPhoto(photo); const showLensContent = showLens && shouldShowLensDataForPhoto(photo); const showRecipeContent = showRecipe && shouldShowRecipeDataForPhoto(photo); const showRecipeButton = shouldShowRecipeDataForPhoto(photo); const showTagsContent = tags.length > 0; useVisible({ ref, onVisible }); const hasTitle = showTitle && Boolean(photo.title); const hasTitleContent = hasTitle || Boolean(photo.caption); const hasMetaContent = showCameraContent || showLensContent || showTagsContent || showRecipeContent || showExifContent; const hasNonDateContent = hasTitleContent || hasMetaContent; const renderPhotoLink = ; // Restrict width for landscape photos // (portrait photos are always height restricted) const matteContentWidthForAspectRatio = photo.aspectRatio > 3 / 2 + 0.1 ? 'w-[90%]' : photo.aspectRatio >= 1 ? 'w-[80%]' : undefined; const largePhotoContent =
{(shouldShowRecipeOverlay || shouldDebugRecipeOverlays) && photo.recipeData && photo.filmSimulation && }
; const largePhotoContainerClassName = clsx(arePhotosMatted && 'flex items-center justify-center aspect-3/2 bg-gray-100', ); return ( {largePhotoContent} : {largePhotoContent} } contentSide={ {/* Meta */}
{hasTitle && (showTitleAsH1 ?

{renderPhotoLink}

: renderPhotoLink)}
{photo.caption &&
{photo.caption}
} {( showCameraContent || showLensContent || showRecipeContent || showTagsContent ) &&
{(showCameraContent || showLensContent) &&
{showCameraContent && } {showLensContent && }
} {showRecipeContent && recipeTitle && } {showTagsContent && }
}
{/* EXIF Data */}
{showExifContent && <>
  • {photo.focalLength && {photo.focalLengthFormatted} } {( photo.focalLengthIn35MmFormatFormatted && // eslint-disable-next-line max-len photo.focalLengthIn35MmFormatFormatted !== photo.focalLengthFormatted ) && <> {' '} {photo.focalLengthIn35MmFormatFormatted} }
  • {photo.fNumberFormatted}
  • {photo.exposureTimeFormatted}
  • {photo.isoFormatted}
  • {photo.exposureCompensationFormatted ?? '0ev'}
{(showSimulation || showRecipeButton) &&
{showSimulation && photo.filmSimulation && } {showRecipeButton && }
} }
{showZoomControls && } onClick={() => zoomControlsRef.current?.open()} styleAs="link" className="text-medium translate-y-[0.25px]" hideFocusOutline />} {shouldShare && } {ALLOW_PUBLIC_DOWNLOADS && }
} /> ); };