From 94fc5c9806eaeecef750ee3b88720eb0f838fb79 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Fri, 19 Jun 2026 11:18:28 +0200 Subject: [PATCH] feat(discovery): total-videos column + subscribe confirmation Add a "Videos" column (channel total uploads, already in the discovery response) to the Discover-from-playlists table, and guard the Subscribe button with a confirm dialog warning it changes the real YouTube account and spends quota (mirrors the unsubscribe guard). Strings added in EN/HU/DE. --- frontend/src/components/ChannelDiscovery.tsx | 28 +++++++++++++++++++- frontend/src/i18n/locales/de/channels.json | 2 ++ frontend/src/i18n/locales/en/channels.json | 2 ++ frontend/src/i18n/locales/hu/channels.json | 2 ++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/ChannelDiscovery.tsx b/frontend/src/components/ChannelDiscovery.tsx index ce0d9cf..62deae1 100644 --- a/frontend/src/components/ChannelDiscovery.tsx +++ b/frontend/src/components/ChannelDiscovery.tsx @@ -7,6 +7,7 @@ import { notify } from "../lib/notifications"; import Tooltip from "./Tooltip"; import ChannelLink from "./ChannelLink"; import DataTable, { type Column } from "./DataTable"; +import { useConfirm } from "./ConfirmProvider"; // The Channel manager's "Discovery" tab: channels that turn up in the user's playlists but // that they don't subscribe to. Subscribing here only creates the subscription + enriches @@ -20,6 +21,7 @@ export default function ChannelDiscovery({ }) { const { t } = useTranslation(); const qc = useQueryClient(); + const confirm = useConfirm(); const query = useQuery({ queryKey: ["discovered-channels"], @@ -60,6 +62,17 @@ export default function ChannelDiscovery({ }, }); + // Subscribing changes the user's real YouTube account and spends a little quota — confirm + // first (mirrors the unsubscribe guard in the Subscriptions tab). + const onSubscribe = async (c: DiscoveredChannel) => { + const ok = await confirm({ + title: t("channels.discovery.subscribe"), + message: t("channels.discovery.confirmSubscribe", { name: c.title ?? c.id }), + confirmLabel: t("channels.discovery.subscribe"), + }); + if (ok) subscribe.mutate(c); + }; + const rows = query.data ?? []; const columns: Column[] = [ @@ -87,6 +100,19 @@ export default function ChannelDiscovery({ ), }, + { + key: "videos", + header: t("channels.discovery.cols.totalVideos"), + align: "right", + nowrap: true, + sortable: true, + sortValue: (c) => c.video_count ?? -1, + render: (c) => ( + + {c.video_count != null ? formatViews(c.video_count) : "—"} + + ), + }, { key: "inPlaylists", header: t("channels.discovery.cols.inPlaylists"), @@ -123,7 +149,7 @@ export default function ChannelDiscovery({ } >