import { useTranslation } from "react-i18next"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { qk } from "../../lib/queryKeys"; import { invalidateSubscription } from "../../lib/subscriptionCache"; import { api, type WatchedChannel } from "../../lib/api"; import { msg, notify, raw } from "../../lib/notifications"; import { notifyYouTubeActionError } from "../../lib/youtubeErrors"; import { useConfirm } from "../../components/ui/confirmContext"; /** Follow and take-off-the-list for a watched channel: the tab's rows and its videos dialog share * them, so the confirm, the toasts and the cache refresh are written once. */ export function useWatchedChannelActions(onOpenWizard: () => void) { const { t } = useTranslation(); const qc = useQueryClient(); const confirm = useConfirm(); const nameOf = (c: WatchedChannel) => c.title ?? c.id; const subscribe = useMutation({ mutationFn: (c: WatchedChannel) => api.subscribeChannel(c.id), onSuccess: (_data, c) => { invalidateSubscription(qc, c.id); notify({ level: "success", title: msg("channels.discovery.subscribedTitle"), message: msg("channels.discovery.subscribedBody", { name: raw(nameOf(c)) }), meta: { kind: "channel-subscribed", channelId: c.id, channelName: nameOf(c) }, }); }, onError: (err: unknown) => notifyYouTubeActionError(err, msg("channels.discovery.subscribeFailed"), onOpenWizard), }); const restore = useMutation({ mutationFn: (c: WatchedChannel) => api.restoreWatchedChannel(c.id), meta: { failTitle: "errors.writeFailed.restoreWatchedChannel" }, onSuccess: () => qc.invalidateQueries({ queryKey: qk.watchedChannels() }), }); // Taken off the list at once, with the toast's Undo as the way back (the same bargain as hiding a // channel): the next channel steps up into its place. const dismiss = useMutation({ mutationFn: (c: WatchedChannel) => api.dismissWatchedChannel(c.id), meta: { failTitle: "errors.writeFailed.dismissWatchedChannel" }, onSuccess: (_data, c) => { void qc.invalidateQueries({ queryKey: qk.watchedChannels() }); notify({ level: "success", message: msg("channels.watched.dismissed", { name: raw(nameOf(c)) }), action: { label: t("common.undo"), onClick: () => restore.mutate(c) }, }); }, }); // Subscribing changes the user's real YouTube account and spends a little quota — confirmed, as // on the Discovery tab. Resolves whether it went ahead. const onSubscribe = async (c: WatchedChannel): Promise => { const ok = await confirm({ title: t("channels.discovery.subscribe"), message: t("channels.discovery.confirmSubscribe", { name: raw(nameOf(c)) }), confirmLabel: t("channels.discovery.subscribe"), }); if (ok) subscribe.mutate(c); return ok; }; return { onSubscribe, subscribing: subscribe.isPending, dismiss: (c: WatchedChannel) => dismiss.mutate(c), }; } export type WatchedChannelActions = ReturnType;