40 lines · 1.3 KB
import { downloadDataExport, requestDataExport } from "~/fns/account-data";
import { useAction } from "~/hooks/use-action";

/** Safari and Firefox cancel a download whose blob URL is revoked before it starts. */
const REVOKE_DELAY_MS = 60_000;

function saveFile(filename: string, body: string): void {
  const url = URL.createObjectURL(new Blob([body], { type: "application/json" }));
  const anchor = document.createElement("a");
  anchor.href = url;
  anchor.download = filename;
  document.body.appendChild(anchor);
  anchor.click();
  anchor.remove();
  setTimeout(() => URL.revokeObjectURL(url), REVOKE_DELAY_MS);
}

/** Request a once-a-day account archive and save it as a JSON file. */
export function useDataExport() {
  const request = useAction(requestDataExport);
  const download = useAction(downloadDataExport, { invalidate: false });

  async function save(id: string): Promise<void> {
    const result = await download.run({ data: { id } });
    if (result) saveFile(result.filename, result.body);
  }

  async function create(): Promise<void> {
    const meta = await request.run(undefined);
    if (meta) await save(meta.id);
  }

  return {
    create,
    save,
    pending: request.pending || download.pending,
    error: request.error ?? download.error,
  };
}