A name goes in as raw(), a translated word as its own msg(): tsc now lists every value, and the ones that froze are said when shown — Watch later and an untitled channel in the pin and channel notices, a Plex season's name in its removal toast (a new seasonTitleText, which seasonTitle says).
71 lines
3.0 KiB
TypeScript
71 lines
3.0 KiB
TypeScript
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<boolean> => {
|
|
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<typeof useWatchedChannelActions>;
|