58 lines · 2.6 KB
import { useState } from "react";
import { DropdownMenu } from "@cloudflare/kumo/components/dropdown";
import { getWatchLevel, setWatchLevel } from "~/fns/notification-settings";
import { useOptimisticMutation } from "~/hooks/use-optimistic-mutation";
import { Button } from "~/ui/Button";

const LEVELS = [
  { value: "participating", label: "Participating and @mentions", hint: "Only threads you're involved in" },
  { value: "all", label: "All activity", hint: "Every issue, pull request and release" },
  { value: "releases", label: "Releases only", hint: "New releases plus participating" },
  { value: "ignore", label: "Ignore", hint: "Never notify, even when mentioned" },
] as const;

type Level = (typeof LEVELS)[number]["value"] | "none";

export function WatchMenu({ owner, repo, watching }: { owner: string; repo: string; watching: boolean }) {
  const [level, setLevel] = useState<string | null>(null);
  const save = useOptimisticMutation(
    level ?? (watching ? "all" : "none"),
    (_state: string, next: Level) => next,
    async (next: Level) => {
      await setWatchLevel({ data: { owner, repo, level: next } });
      setLevel(next);
    },
  );

  async function loadLevel(open: boolean) {
    if (open && level === null) setLevel((await getWatchLevel({ data: { owner, repo } })).level);
  }

  const current = save.state;
  const selected = current === "none" ? "participating" : current;
  return (
    <DropdownMenu onOpenChange={(open) => void loadLevel(open)}>
      <DropdownMenu.Trigger render={<Button size="sm" className="min-w-24" title={save.error ?? undefined} />}>
        {current === "ignore" ? "Ignoring" : current === "none" || current === "participating" ? "Watch" : "Unwatch"} ▾
      </DropdownMenu.Trigger>
      <DropdownMenu.Content align="end" className="w-72">
        <DropdownMenu.RadioGroup
          value={selected}