import { invoke } from "@tauri-apps/api/tauri"; import { appWindow } from "@tauri-apps/api/window"; interface BaseHandlerData { id: number; } interface ProgressHandlerData extends BaseHandlerData { progress: number; total: number; } interface SizeHandlerData extends BaseHandlerData { size: number; } interface ResponseData { text: string; status: number; } enum UploadEvent { progress = "upload://progress", fileSize = "upload://file-size", } type EventId = `${UploadEvent}-${number}`; type ProgressHandler = (data: ProgressHandlerData) => unknown; type SizeHandler = (data: SizeHandlerData) => unknown; const handlers: Map = new Map(); const listeningMap: Map = new Map(); const getIdForEvent = (event: UploadEvent, id: number): EventId => `${event}-${id}`; async function listenToEventIfNeeded(event: UploadEvent) { if (listeningMap.get(event)) { return; } return appWindow.listen( event, ({ payload }) => { const eventId = getIdForEvent(event, payload.id); const handler = handlers.get(eventId); if (typeof handler === "function") { handler(payload); } } ); } export default async function upload( url: string, filePath: string, progressHandler?: ProgressHandler, fileSizeHandler?: SizeHandler, headers?: Record ) { const ids = new Uint32Array(1); window.crypto.getRandomValues(ids); const id = ids[0]; if (progressHandler) { const eventId = getIdForEvent(UploadEvent.progress, id); handlers.set(eventId, progressHandler); } if (fileSizeHandler) { const eventId = getIdForEvent(UploadEvent.fileSize, id); handlers.set(eventId, fileSizeHandler); } await listenToEventIfNeeded(UploadEvent.progress); await listenToEventIfNeeded(UploadEvent.fileSize); return await invoke("plugin:upload|upload", { id, url, filePath, headers: headers ?? {}, }); }