Skip to content
Source
Sign inSign up

useFileChipShare.ts

61 lines2.4 KB

1import * as Dialog from "../../components/ui/Dialog";
2import { resolveAssetUrl } from "@t3tools/client-runtime/state/assets";
3import type { EnvironmentId, ThreadId } from "@t3tools/contracts";
4import * as Option from "effect/Option";
5import { useEffect, useRef } from "react";
6​
7import { downloadAndShareAttachment } from "../../lib/attachmentDownload";
8import { assetEnvironment } from "../../state/assets";
9import { usePreparedConnection } from "../../state/session";
10import { useAtomQueryRunner } from "../../state/use-atom-query-runner";
11import { fileChipShareSource, type FileChipTarget } from "./fileChipMenu";
12​
13export function useFileChipShare(
14 environmentId: EnvironmentId,
15 threadId: ThreadId,
16 sourceIdentifier: string,
17) {
18 const connection = usePreparedConnection(environmentId);
19 const httpBaseUrl = Option.isSome(connection) ? connection.value.httpBaseUrl : null;
20 const createUrl = useAtomQueryRunner(assetEnvironment.createUrl, {
21 refresh: true,
22 reportFailure: false,
23 });
24 const requestRef = useRef<AbortController | null>(null);
25 // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- aborts the in-flight file share download when the component unmounts
26 useEffect(() => () => requestRef.current?.abort(), []);
27​
28 return (target: FileChipTarget) => {
29 const source = fileChipShareSource(target, threadId);
30 if (!source || requestRef.current) return;
31 const request = new AbortController();
32 requestRef.current = request;
33 void (async () => {
34 if (httpBaseUrl === null) throw new Error("Reconnect to the environment and try again.");
35 const result = await createUrl({ environmentId, input: { resource: source.resource } });
36 if (request.signal.aborted) return;
37 const url =
38 result._tag === "Success" ? resolveAssetUrl(httpBaseUrl, result.value.relativeUrl) : null;
39 if (url === null) throw new Error("The file could not be loaded. Reconnect and try again.");
40 await downloadAndShareAttachment({
41 url,
42 attachment: source,
43 signal: request.signal,
44 sourceIdentifier,
45 });
46 })()
47 .catch((error: unknown) => {
48 if (!request.signal.aborted) {
49 Dialog.alert(
50 "Could not share file",
51 error instanceof Error ? error.message : "Try again.",
52 );
53 }
54 })
55 .finally(() => {
56 if (requestRef.current === request) {
57 requestRef.current = null;
58 }
59 });
60 };