All checks were successful
Trigger cinny-mobile / dispatch (push) Successful in 2s
Platforms can register a custom saver; viewers share one download/save path instead of FileSaver call sites.
56 lines
1.7 KiB
TypeScript
56 lines
1.7 KiB
TypeScript
import FileSaver from 'file-saver';
|
|
import { downloadMedia } from './matrix';
|
|
import { getCurrentAccessToken } from './auth';
|
|
|
|
export type MediaSaver = (blob: Blob, filename: string) => void | Promise<void>;
|
|
|
|
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<void> => {
|
|
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<void> => {
|
|
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);
|
|
};
|