import { useMutation } from "@tanstack/react-query";
import { errorMessage } from "~/lib/error-message";
import { upsellFromResponse } from "~/lib/upsell";
const MAX_FILES_PER_DROP = 5;
type UploadState = { status: "idle" } | { status: "uploading"; count: number } | { status: "error"; message: string };
async function uploadOne(owner: string, repo: string, file: File): Promise<string> {
const response = await fetch(`/${owner}/${repo}/attachments?name=${encodeURIComponent(file.name)}`, {
method: "POST",
headers: { "x-gitfor-csrf": "1", "content-type": file.type || "application/octet-stream" },
body: file,
});
const payload: { markdown?: string; error?: string } = await response.json();
upsellFromResponse(response.status, payload);
if (!response.ok || !payload.markdown) throw new Error(payload.error ?? `Upload of ${file.name} failed`);
return payload.markdown;
}
/** Uploads dropped or pasted files as repo attachments and yields markdown snippets to insert. */
export function useAttachmentUpload(owner: string | undefined, repo: string | undefined) {
const enabled = Boolean(owner && repo);
const mutation = useMutation({
mutationFn: async (files: File[]) => {
if (!owner || !repo) return [];
const snippets: string[] = [];
for (const file of files) snippets.push(await uploadOne(owner, repo, file));
return snippets;
},
});
async function upload(files: FileList | File[]): Promise<string[]> {
const list = [...files].slice(0, MAX_FILES_PER_DROP);
if (!enabled || list.length === 0) return [];
return mutation.mutateAsync(list).catch(() => []);
}
const state: UploadState = mutation.isPending
? { status: "uploading", count: mutation.variables.length }