diff --git a/backend/routers/stats.py b/backend/routers/stats.py index 5cc263d..a19829d 100644 --- a/backend/routers/stats.py +++ b/backend/routers/stats.py @@ -140,7 +140,7 @@ def get_stats( text(""" SELECT COUNT(*) AS n FROM user_videos WHERE user_id = :uid AND watched = 0 - AND watch_progress_seconds > 0 + AND (watch_progress_seconds > 0 OR last_watched_at IS NOT NULL) """), {"uid": uid}, ).mappings().first() diff --git a/frontend/src/components/VideoPlayer.jsx b/frontend/src/components/VideoPlayer.jsx index 7f32e1d..8ce2dcb 100644 --- a/frontend/src/components/VideoPlayer.jsx +++ b/frontend/src/components/VideoPlayer.jsx @@ -126,6 +126,16 @@ export default function VideoPlayer() { } }, [dlStatus?.status]); // eslint-disable-line react-hooks/exhaustive-deps + // Record a "clicked" impression as soon as we have the video id — even if the + // user closes immediately before playback starts. + const clickedRef = useRef(false); + useEffect(() => { + if (video?.id && !clickedRef.current && !video.is_watched) { + clickedRef.current = true; + updateProgress(video.id, { watch_progress_seconds: video.watch_progress_seconds ?? 0 }); + } + }, [video?.id]); // eslint-disable-line react-hooks/exhaustive-deps + // ── Trigger download on open ────────────────────────────────────────────── const downloadMut = useMutation({ mutationFn: (ytId) => createDownload(ytId),