feat(feed): the card menu carries the card's own actions

Right-click, long-press or Shift+F10 on a feed card offered only the
comfort-shelf pin; watched, saved, hidden and the progress reset were
reachable only by hovering or Tabbing through every card.
This commit is contained in:
2026-09-19 04:51:43 +02:00
parent ef652ee5d8
commit 582c033e1c
5 changed files with 228 additions and 10 deletions
+9 -4
View File
@@ -1,7 +1,7 @@
import type { Video, VideoStatus } from "../lib/api";
import { FEED_VIEW_SPEC, type FeedView } from "../lib/feedView";
import VideoCard from "./VideoCard";
import { VideoPinMenu } from "./ComfortPinMenu";
import { FeedVideoMenu } from "./ComfortPinMenu";
import { useContextMenu } from "./ui/useContextMenu";
import VirtualGrid from "./ui/VirtualGrid";
@@ -47,8 +47,8 @@ export default function VirtualFeed({
fetchNextPage,
}: VirtualFeedProps) {
const { minCol, colMaxWidth, maxCols, thumb } = FEED_VIEW_SPEC[view];
// The comfort-shelf pin (E24 S3) lives HERE rather than in each of the feed's callers: this is the
// list, and `useContextMenu`'s contract is one menu per list. Mounting it at this level is also
// The card menu (its state actions and the comfort-shelf pin, E24 S3) lives HERE rather than in each
// of the feed's callers: this is the list, and `useContextMenu`'s contract is one menu per list. Mounting it at this level is also
// what gives the channel page the gesture for free — it renders `<Feed channelScoped>`, so it is
// the same component all the way down.
const pinMenu = useContextMenu<Video>();
@@ -82,7 +82,12 @@ export default function VirtualFeed({
/>
)}
/>
<VideoPinMenu menu={pinMenu} />
<FeedVideoMenu
menu={pinMenu}
onState={onState}
onToggleSave={onToggleSave}
onResetState={onResetState}
/>
</>
);
}