From 04c971f6235b22c155455026a238377a5bc18bee Mon Sep 17 00:00:00 2001 From: npeter83 Date: Sun, 14 Jun 2026 18:40:12 +0200 Subject: [PATCH] feat(feed): resume progress bar, play/continue/restart, in-progress filter Video cards show a resume progress bar for started-but-unfinished videos and a hover overlay: Play on every card, Continue + Restart on in-progress ones. The in-app player now resumes from (and checkpoints to) the server position instead of localStorage, accepts an explicit startAt (Restart -> 0), and refreshes the feed on close so the card bar reflects the session. Sidebar gains an 'In progress' show filter. --- frontend/src/components/Feed.tsx | 20 +++++-- frontend/src/components/PlayerModal.tsx | 43 ++++++++------- frontend/src/components/Sidebar.tsx | 1 + frontend/src/components/VideoCard.tsx | 71 +++++++++++++++++++++++-- frontend/src/lib/api.ts | 9 ++++ 5 files changed, 114 insertions(+), 30 deletions(-) diff --git a/frontend/src/components/Feed.tsx b/frontend/src/components/Feed.tsx index b29955d..bbdd000 100644 --- a/frontend/src/components/Feed.tsx +++ b/frontend/src/components/Feed.tsx @@ -16,6 +16,9 @@ function matchesView(status: string, show: string): boolean { case "saved": return status === "saved"; case "unwatched": + case "in_progress": + // (in_progress is further narrowed server-side by resume position; here we only + // need to drop a card once it's optimistically marked watched/hidden.) return status !== "watched" && status !== "hidden"; default: return status !== "hidden"; // all @@ -36,9 +39,17 @@ export default function Feed({ onOpenWizard: () => void; }) { const [overrides, setOverrides] = useState>({}); - const [activeVideo, setActiveVideo] = useState