diff --git a/frontend/src/components/Feed.tsx b/frontend/src/components/Feed.tsx index 423be85..f66f61c 100644 --- a/frontend/src/components/Feed.tsx +++ b/frontend/src/components/Feed.tsx @@ -174,7 +174,13 @@ export default function Feed({ ? i18n.t("feed.markedWatchedNamed", { title: v.title }) : i18n.t("feed.markedWatched"), action: { label: i18n.t("feed.unwatch"), onClick: () => onState(id, "new") }, - meta: { kind: "video-watched", videoId: id, title: v?.title ?? "this video" }, + meta: { + kind: "video-watched", + videoId: id, + title: v?.title ?? "this video", + channelId: v?.channel_id ?? "", + channelName: v?.channel_title ?? "", + }, }); } else if (status === "new") { // Unhide / unwatch (from a card, the toast's Undo, or the center): quietly resolve diff --git a/frontend/src/components/NotificationsPanel.tsx b/frontend/src/components/NotificationsPanel.tsx index 2f05b4f..1715acd 100644 --- a/frontend/src/components/NotificationsPanel.tsx +++ b/frontend/src/components/NotificationsPanel.tsx @@ -1,7 +1,7 @@ import { useEffect, useSyncExternalStore } from "react"; import { useTranslation } from "react-i18next"; import { useMutation, useQueryClient } from "@tanstack/react-query"; -import { Bell, Check, CheckCheck, ExternalLink, Eye, RotateCcw, Search, Trash2, Tv, X } from "lucide-react"; +import { Activity, Bell, Check, CheckCheck, ExternalLink, Eye, RotateCcw, Search, Trash2, Tv, X } from "lucide-react"; import { api, type AppNotification, type FeedFilters } from "../lib/api"; import { useLiveQuery } from "../lib/useLiveQuery"; import { @@ -94,11 +94,12 @@ export default function NotificationsPanel({ clearMut.mutate(); } - // "Find in feed" / undo, ported from the old bell. - function locateHidden(meta: VideoHiddenMeta) { + // "Find in feed" / undo, ported from the old bell. Works for both hidden and watched + // notices — jump to the feed filtered to that state and the video's channel. + function locate(meta: VideoHiddenMeta | VideoWatchedMeta) { setFilters({ ...filters, - show: "hidden", + show: meta.kind === "video-hidden" ? "hidden" : "watched", channelId: meta.channelId || undefined, channelName: meta.channelName || undefined, }); @@ -168,6 +169,7 @@ export default function NotificationsPanel({ t={t} onRead={() => readMut.mutate(n.id)} onDismiss={() => dismissMut.mutate(n.id)} + onOpenScheduler={() => setPage("scheduler")} /> ))} @@ -184,7 +186,7 @@ export default function NotificationsPanel({ key={n.id} n={n} t={t} - onFind={locateHidden} + onFind={locate} onRevert={revertState} onFocusChannel={onFocusChannel} onRemove={() => removeClient(n.id)} @@ -204,11 +206,13 @@ function NotificationRow({ t, onRead, onDismiss, + onOpenScheduler, }: { n: AppNotification; t: (k: string, o?: any) => string; onRead: () => void; onDismiss: () => void; + onOpenScheduler: () => void; }) { // The maintenance producer ships the affected videos in `data.videos`; list a few titles. const videos: { id: string; title: string | null }[] = Array.isArray(n.data?.videos) @@ -261,6 +265,15 @@ function NotificationRow({ )} )} + {isScheduler && ( + + )}