32 lines · 1.2 KB
import { useMutation } from "@tanstack/react-query";
import { useRouter } from "@tanstack/react-router";
import { setKnownAvatarKey } from "~/lib/avatar-version";
import { errorMessage } from "~/lib/error-message";

async function postAvatar(account: string, file: File): Promise<void> {
  const response = await fetch(`/settings/avatar?account=${encodeURIComponent(account)}`, {
    method: "POST",
    headers: { "content-type": file.type, "x-gitfor-csrf": "1" },
    body: file,
  });
  if (!response.ok) throw new Error((await response.text()) || "Upload failed");
  const { url } = (await response.json().catch(() => ({}))) as { url?: string };
  const key = url?.match(/^\/avatars\/([^/?]+)$/)?.[1];
  if (key) setKnownAvatarKey(account, key);
}

/** Avatars go to a raw Worker route (binary body) rather than a server function. */
export function useAvatarUpload(account: string) {
  const router = useRouter();
  const mutation = useMutation({
    mutationFn: (file: File) => postAvatar(account, file),
    onSuccess: () => router.invalidate({ sync: true }),
  });

  return {
    upload: (file: File) => mutation.mutateAsync(file).catch(() => undefined),
    pending: mutation.isPending,
    error: mutation.isError ? errorMessage(mutation.error) : null,
  };
}