import { attachmentKindOf } from "@rakazo/contracts"; import { File, Paths } from "expo-file-system"; import * as Sharing from "expo-sharing"; import { captureApiRequestContext, rpc } from "./api"; import { artifactCacheFileName } from "./artifact-file"; import { t } from "./i18n"; export type MobileArtifactTarget = { botId: string } | { groupId: string }; async function cacheMobileArtifact( target: MobileArtifactTarget, artifactId: string, mimeType: string, ): Promise { const kind = attachmentKindOf(mimeType); if (kind === "video" || kind === "audio") { // Media can be hundreds of megabytes: stream it to disk instead of a base64 RPC payload. const { apiBase, headers } = await captureApiRequestContext(); return File.downloadFileAsync( `${apiBase}/api/artifacts/${encodeURIComponent(artifactId)}`, new File(Paths.cache, artifactCacheFileName(artifactId, mimeType)), { headers, idempotent: true }, ); } const artifact = await rpc<{ contentBase64: string }>("artifacts/get", { ...target, artifactId, }); const file = new File(Paths.cache, artifactCacheFileName(artifactId, mimeType)); file.create({ overwrite: true }); file.write(artifact.contentBase64, { encoding: "base64" }); return file; } export async function readMobileArtifactText( target: MobileArtifactTarget, artifactId: string, mimeType: string, ): Promise { const file = await cacheMobileArtifact(target, artifactId, mimeType); return file.text(); } export async function openMobileArtifact( target: MobileArtifactTarget, artifactId: string, name: string, mimeType: string, ): Promise { const file = await cacheMobileArtifact(target, artifactId, mimeType); if (await Sharing.isAvailableAsync()) { await Sharing.shareAsync(file.uri, { mimeType }); return; } throw new Error(t("Saved {name} locally", { name })); }