feat(download): show a toast + button check when a file is saved
The desktop (Tauri) app has no native download UI, so FileSaver.saveAs saved files silently — no visual or audio confirmation. Users re-clicked because nothing said it worked (one report: 5 copies of the same file). Add a small useSaveFile() hook that saves AND raises a 'Downloaded <filename>' toast, and route every download call site through it (file attachments, image viewer, PDF viewer, plus the recovery-key / key-backup exports). The file-message download button also shows a green check on success. Toast system extended with an optional iconSrc so system toasts render an icon instead of an avatar/initials, and an empty roomName is no longer rendered. Tests: createDownloadToast covered; 701/701 pass; typecheck + build clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -14,10 +14,10 @@ import {
|
||||
TooltipProvider,
|
||||
as,
|
||||
} from 'folds';
|
||||
import FileSaver from 'file-saver';
|
||||
import { EncryptedAttachmentInfo } from 'browser-encrypt-attachment';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import { IFileInfo } from '../../../../types/matrix/common';
|
||||
import { useSaveFile } from '../../../hooks/useSaveFile';
|
||||
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { bytesToSize } from '../../../utils/common';
|
||||
@@ -252,6 +252,7 @@ export type DownloadFileProps = {
|
||||
export function DownloadFile({ body, mimeType, url, info, encInfo }: DownloadFileProps) {
|
||||
const mx = useMatrixClient();
|
||||
const useAuthentication = useMediaAuthentication();
|
||||
const saveFile = useSaveFile();
|
||||
|
||||
const [downloadState, download] = useAsyncCallback(
|
||||
useCallback(async () => {
|
||||
@@ -262,9 +263,9 @@ export function DownloadFile({ body, mimeType, url, info, encInfo }: DownloadFil
|
||||
: await downloadMedia(mediaUrl);
|
||||
|
||||
const fileURL = URL.createObjectURL(fileContent);
|
||||
FileSaver.saveAs(fileURL, body);
|
||||
saveFile(fileURL, body);
|
||||
return fileURL;
|
||||
}, [mx, url, useAuthentication, mimeType, encInfo, body]),
|
||||
}, [mx, url, useAuthentication, mimeType, encInfo, body, saveFile]),
|
||||
);
|
||||
|
||||
return downloadState.status === AsyncStatus.Error ? (
|
||||
@@ -277,7 +278,7 @@ export function DownloadFile({ body, mimeType, url, info, encInfo }: DownloadFil
|
||||
size="400"
|
||||
onClick={() =>
|
||||
downloadState.status === AsyncStatus.Success
|
||||
? FileSaver.saveAs(downloadState.data, body)
|
||||
? saveFile(downloadState.data, body)
|
||||
: download()
|
||||
}
|
||||
disabled={downloadState.status === AsyncStatus.Loading}
|
||||
|
||||
Reference in New Issue
Block a user