feat(feed): a card's menu filters the feed by its channel, and back

Under "Open the channel" a video card's menu (the right-click on its
channel name included) adds the channel to the feed's channel filter, or,
when it is already in, takes it out. Channels OR together, so it widens a
filter that names others, as "Show in feed" does. Not on a channel page,
whose view is that channel already, nor in a live YouTube search or on Home.
This commit is contained in:
2026-10-09 00:44:46 +02:00
parent ece74a42ab
commit 4f076b5d45
6 changed files with 98 additions and 4 deletions
@@ -55,3 +55,52 @@ describe("the video menu's download row", () => {
expect(none().note).toBeUndefined();
});
});
// The feed's channel filter from a card (owner): under "Open the channel", a row that adds the card's
// channel to the filter, or takes it out again when it is already in.
describe("the video menu's channel-filter row", () => {
const menu = (ids: string[] | null) => {
vi.spyOn(api, "downloadIndex").mockResolvedValue({});
const set = vi.fn();
const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } });
const wrapper = ({ children }: { children: ReactNode }) => (
<QueryClientProvider client={qc}>{children}</QueryClientProvider>
);
const { result } = renderHook(
() =>
useVideoActions(
{
onState: vi.fn(),
onToggleSave: vi.fn(),
channelFilter: ids ? { ids, set } : undefined,
},
true,
),
{ wrapper },
);
const items = result.current.items({ ...video, channel_id: "UCa" }, null);
return { items, set };
};
it("adds the channel to a filter that names others, right under Open the channel", () => {
const { items, set } = menu(["UCz"]);
const at = items.findIndex((i) => i.id === "channel");
const row = items[at + 1]!;
expect(row.id).toBe("channel-filter");
expect(row.label).toBe("card.menu.channelFilterAdd");
row.onSelect?.();
expect(set).toHaveBeenCalledWith(["UCz", "UCa"]);
});
it("takes it out again when it is in", () => {
const { items, set } = menu(["UCz", "UCa"]);
const row = items.find((i) => i.id === "channel-filter")!;
expect(row.label).toBe("card.menu.channelFilterRemove");
row.onSelect?.();
expect(set).toHaveBeenCalledWith(["UCz"]);
});
it("is absent where the host gives no filter (a channel page, Home, a live search)", () => {
expect(menu(null).items.some((i) => i.id === "channel-filter")).toBe(false);
});
});