35 lines · 1.5 KB
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { getThreadSubscription, setThreadSubscription } from "~/fns/notification-settings";
import { errorMessage } from "~/lib/error-message";
import type { QueryClient } from "@tanstack/react-query";

type Thread = { owner: string; repo: string; number: number };
type Subscription = Awaited<ReturnType<typeof getThreadSubscription>>;

export const threadSubscriptionQueryKey = ({ owner, repo, number }: Thread) =>
  ["thread-subscription", owner, repo, number] as const;

export async function refreshThreadSubscription(queryClient: QueryClient, thread: Thread): Promise<void> {
  await queryClient.invalidateQueries({ queryKey: threadSubscriptionQueryKey(thread) });
}

export function useThreadSubscription(thread: Thread) {
  const queryClient = useQueryClient();
  const key = threadSubscriptionQueryKey(thread);
  const query = useQuery({ queryKey: key, queryFn: () => getThreadSubscription({ data: thread }) });
  const mutation = useMutation({
    mutationFn: (subscribed: boolean) => setThreadSubscription({ data: { ...thread, subscribed } }),
    onSuccess: (_result, subscribed) => {
      queryClient.setQueryData<Subscription>(key, { subscribed, reason: "manual" });
      return refreshThreadSubscription(queryClient, thread);
    },
  });

  const state = query.data ?? null;
  function toggle() {
    if (state) mutation.mutate(!state.subscribed);
  }

  return { state, toggle, pending: mutation.isPending, error: mutation.error ? errorMessage(mutation.error) : null };
}