diff --git a/src/components/FullscreenButton.tsx b/src/components/FullscreenButton.tsx new file mode 100644 index 00000000..fcbab1b6 --- /dev/null +++ b/src/components/FullscreenButton.tsx @@ -0,0 +1,54 @@ +'use client'; + +import { useEffect, RefObject } from 'react'; +import { MdFullscreen, MdFullscreenExit } from 'react-icons/md'; +import { clsx } from 'clsx/lite'; +import { useAppState } from '@/state/AppState'; +import LoaderButton from './primitives/LoaderButton'; + +export default function FullscreenButton({ + className, + imageRef, +}: { + className?: string; + imageRef: RefObject; +}) { + const { isFullscreen, setIsFullscreen } = useAppState(); + + const toggleFullscreen = async () => { + if (!document.fullscreenElement) { + await imageRef.current?.requestFullscreen(); + setIsFullscreen && setIsFullscreen(true); + } else { + await document.exitFullscreen(); + setIsFullscreen && setIsFullscreen(false); + } + }; + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'f' || event.key === 'F') { + toggleFullscreen(); + } + }; + + document.addEventListener('keydown', handleKeyDown); + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + }, [toggleFullscreen]); + + return ( + : } + spinnerColor='light-gray' + styleAs='link' + onClick={toggleFullscreen} + /> + ); +} diff --git a/src/components/image/ImageLarge.tsx b/src/components/image/ImageLarge.tsx index 18569d92..d7d178d0 100644 --- a/src/components/image/ImageLarge.tsx +++ b/src/components/image/ImageLarge.tsx @@ -13,6 +13,7 @@ export default function ImageLarge(props: ImageProps) { blurCompatibilityLevel: blurCompatibilityMode ? 'high' : 'none', width: IMAGE_WIDTH_LARGE, height: Math.round(IMAGE_WIDTH_LARGE / aspectRatio), + allowFullscreen: true, }} /> ); }; diff --git a/src/components/image/ImageWithFallback.tsx b/src/components/image/ImageWithFallback.tsx index 23457add..5d18738b 100644 --- a/src/components/image/ImageWithFallback.tsx +++ b/src/components/image/ImageWithFallback.tsx @@ -6,10 +6,12 @@ import { useAppState } from '@/state/AppState'; import { clsx} from 'clsx/lite'; import Image, { ImageProps } from 'next/image'; import { useCallback, useEffect, useRef, useState } from 'react'; +import FullscreenButton from '../FullscreenButton'; export default function ImageWithFallback(props: ImageProps & { blurCompatibilityLevel?: 'none' | 'low' | 'high' imgClassName?: string + allowFullscreen?: boolean }) { const { className, @@ -17,6 +19,7 @@ export default function ImageWithFallback(props: ImageProps & { blurDataURL, blurCompatibilityLevel = 'low', imgClassName = 'object-cover h-full', + allowFullscreen, ...rest } = props; @@ -104,6 +107,7 @@ export default function ImageWithFallback(props: ImageProps & { onLoad, onError, }} /> - + {allowFullscreen && } + ); }