diff --git a/client/src/components/VideosView.jsx b/client/src/components/VideosView.jsx index 33ca18a..4a736de 100644 --- a/client/src/components/VideosView.jsx +++ b/client/src/components/VideosView.jsx @@ -1,11 +1,33 @@ -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect } from 'react'; import { fetchVideos } from '../api/photos.js'; +// ── Grouping (mirrors Timeline.jsx) ─────────────────────────────────────────── + +function groupByMonth(videos) { + const groups = []; + let current = null; + for (const v of videos) { + const key = v.date_taken ? v.date_taken.slice(0, 7) : 'undated'; + if (!current || current.key !== key) { + current = { key, label: monthLabel(v.date_taken), videos: [] }; + groups.push(current); + } + current.videos.push(v); + } + return groups; +} + +function monthLabel(d) { + if (!d) return 'Undated'; + return new Date(d).toLocaleDateString('en-US', { month: 'long', year: 'numeric' }); +} + +// ── Helpers ─────────────────────────────────────────────────────────────────── + function fmtDuration(s) { - if (!s) return null; + if (s == null) return null; const m = Math.floor(s / 60); - const sec = Math.floor(s % 60).toString().padStart(2, '0'); - return `${m}:${sec}`; + return `${m}:${Math.floor(s % 60).toString().padStart(2, '0')}`; } function fmtDate(d) { @@ -15,16 +37,17 @@ function fmtDate(d) { function fmtSize(b) { if (!b) return null; - if (b < 1048576) return `${(b / 1024).toFixed(0)} KB`; + if (b < 1048576) return `${(b / 1024).toFixed(0)} KB`; if (b < 1073741824) return `${(b / 1048576).toFixed(1)} MB`; return `${(b / 1073741824).toFixed(2)} GB`; } +// ── Component ───────────────────────────────────────────────────────────────── + export default function VideosView() { - const [videos, setVideos] = useState(null); + const [videos, setVideos] = useState(null); const [playing, setPlaying] = useState(null); - const [error, setError] = useState(null); - const videoRef = useRef(null); + const [error, setError] = useState(null); useEffect(() => { fetchVideos() @@ -32,7 +55,6 @@ export default function VideosView() { .catch(e => setError(e.message)); }, []); - // Keyboard: Esc to close player useEffect(() => { if (!playing) return; const onKey = (e) => { if (e.key === 'Escape') setPlaying(null); }; @@ -40,113 +62,76 @@ export default function VideosView() { return () => window.removeEventListener('keydown', onKey); }, [playing]); - if (error) return
{error}
; - if (!videos) returnLoading…
; + if (error) return{error}
; + if (!videos) returnLoading…
; - const noVideos = videos.length === 0; + if (videos.length === 0) { + return ( +No videos indexed yet.
+Add a folder with .mp4, .mov, or .m4v files and rescan.
+No videos indexed yet.
-Add a folder containing .mp4, .mov, or .m4v files and rescan.
-