diff --git a/src/components/mixed/ImageLightbox.tsx b/src/components/mixed/ImageLightbox.tsx index 8cccd70..e846d32 100644 --- a/src/components/mixed/ImageLightbox.tsx +++ b/src/components/mixed/ImageLightbox.tsx @@ -1,15 +1,21 @@ 'use client' -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' +import TagSelector from '@/components/tags/TagSelector' interface Props { url: string name: string onClose: () => void + mediaKey?: string + onTagsChanged?: () => void } -export default function ImageLightbox({ url, name, onClose }: Props) { +export default function ImageLightbox({ url, name, onClose, mediaKey, onTagsChanged }: Props) { const overlayRef = useRef(null) + const [showTags, setShowTags] = useState( + () => !!mediaKey && typeof window !== 'undefined' && window.innerWidth >= 1280 + ) useEffect(() => { const handleKey = (e: KeyboardEvent) => { @@ -35,30 +41,77 @@ export default function ImageLightbox({ url, name, onClose }: Props) { onClick={handleOverlayClick} > {/* Toolbar */} -
+
{name} - +
+ {mediaKey && ( + + )} + +
- {/* Image */} - {/* eslint-disable-next-line @next/next/no-img-element */} - {name} e.stopPropagation()} - /> + {showTags ? ( +
+ {/* Image */} +
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {name} e.stopPropagation()} + /> +
+ {/* Tag panel */} +
e.stopPropagation()} + > +

+ Tags +

+ +
+
+ ) : ( + /* eslint-disable-next-line @next/next/no-img-element */ + {name} e.stopPropagation()} + /> + )}
) } diff --git a/src/components/mixed/MixedView.tsx b/src/components/mixed/MixedView.tsx index ee344a1..f5eacf9 100644 --- a/src/components/mixed/MixedView.tsx +++ b/src/components/mixed/MixedView.tsx @@ -13,8 +13,8 @@ interface Props { } type ModalState = - | { type: 'video'; url: string; name: string } - | { type: 'image'; url: string; name: string } + | { type: 'video'; url: string; name: string; mediaKey: string } + | { type: 'image'; url: string; name: string; mediaKey: string } | null type TagPanelState = { entry: FileEntry; mediaKey: string } | null @@ -80,9 +80,9 @@ export default function MixedView({ libraryId, initialPath }: Props) { } if (!entry.url) return if (entry.mediaType === 'video') { - setModal({ type: 'video', url: entry.url, name: entry.name }) + setModal({ type: 'video', url: entry.url, name: entry.name, mediaKey: mediaKeyFor(entry) }) } else if (entry.mediaType === 'image') { - setModal({ type: 'image', url: entry.url, name: entry.name }) + setModal({ type: 'image', url: entry.url, name: entry.name, mediaKey: mediaKeyFor(entry) }) } else { // Download other file types window.open(entry.url, '_blank') @@ -201,10 +201,22 @@ export default function MixedView({ libraryId, initialPath }: Props) { )} {modal?.type === 'video' && ( - setModal(null)} /> + { setFilterRefreshKey((k) => k + 1); fetchAssignments() }} + onClose={() => setModal(null)} + /> )} {modal?.type === 'image' && ( - setModal(null)} /> + { setFilterRefreshKey((k) => k + 1); fetchAssignments() }} + onClose={() => setModal(null)} + /> )} {/* Tag panel */} diff --git a/src/components/mixed/VideoPlayerModal.tsx b/src/components/mixed/VideoPlayerModal.tsx index 8098b86..02dfaa9 100644 --- a/src/components/mixed/VideoPlayerModal.tsx +++ b/src/components/mixed/VideoPlayerModal.tsx @@ -1,15 +1,21 @@ 'use client' -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' +import TagSelector from '@/components/tags/TagSelector' interface Props { url: string name: string onClose: () => void + mediaKey?: string + onTagsChanged?: () => void } -export default function VideoPlayerModal({ url, name, onClose }: Props) { +export default function VideoPlayerModal({ url, name, onClose, mediaKey, onTagsChanged }: Props) { const overlayRef = useRef(null) + const [showTags, setShowTags] = useState( + () => !!mediaKey && typeof window !== 'undefined' && window.innerWidth >= 1280 + ) useEffect(() => { const handleKey = (e: KeyboardEvent) => { @@ -35,31 +41,79 @@ export default function VideoPlayerModal({ url, name, onClose }: Props) { onClick={handleOverlayClick} > {/* Toolbar */} -
+
{name} - +
+ {mediaKey && ( + + )} + +
- {/* Video */} -
) } diff --git a/src/components/movies/MovieDetailModal.tsx b/src/components/movies/MovieDetailModal.tsx index e111ff9..4411943 100644 --- a/src/components/movies/MovieDetailModal.tsx +++ b/src/components/movies/MovieDetailModal.tsx @@ -65,7 +65,15 @@ export default function MovieDetailModal({ movie, libraryId, onClose, onTagsChan } if (playing) { - return setPlaying(false)} /> + return ( + setPlaying(false)} + /> + ) } const heroUrl = movie.backdropUrl ?? movie.posterUrl