import FileSaver from 'file-saver'; import { downloadMedia } from './matrix'; import { getCurrentAccessToken } from './auth'; export type MediaSaver = (blob: Blob, filename: string) => void | Promise; let customMediaSaver: MediaSaver | null = null; const defaultMediaSaver: MediaSaver = (blob, filename) => { FileSaver.saveAs(blob, filename); }; /** * Register a platform-specific media saver (Android MediaStore, Electron dialog, etc.). * Pass null to restore the default FileSaver path. * * Platforms should call this once at startup (mobile overlay / desktop shell entry). */ export const registerMediaSaver = (saver: MediaSaver | null): void => { customMediaSaver = saver; }; /** * Persist a Blob to disk via the registered platform saver, or FileSaver by default. */ export const saveMediaBlob = async (blob: Blob, filename: string): Promise => { const saver = customMediaSaver ?? defaultMediaSaver; await saver(blob, filename); }; /** * Fetch media (auth download or blob:/data:/http URL) and save it via [saveMediaBlob]. */ export const downloadAndSaveMedia = async ( src: string, filename: string, accessToken?: string | null ): Promise => { let blob: Blob; try { if (src.startsWith('blob:') || src.startsWith('data:')) { const res = await fetch(src); if (!res.ok) throw new Error(`Failed to fetch ${src}`); blob = await res.blob(); } else { blob = await downloadMedia(src, accessToken ?? getCurrentAccessToken()); } } catch (error) { console.warn('[saveMedia] downloadMedia failed, trying fetch fallback:', error); const res = await fetch(src); if (!res.ok) throw error; blob = await res.blob(); } await saveMediaBlob(blob, filename); };