diff --git a/app/assets/javascripts/Components/Files/FilePreviewModal.tsx b/app/assets/javascripts/Components/Files/FilePreviewModal.tsx index 18abf9dd6..9d66ff812 100644 --- a/app/assets/javascripts/Components/Files/FilePreviewModal.tsx +++ b/app/assets/javascripts/Components/Files/FilePreviewModal.tsx @@ -2,7 +2,7 @@ import { WebApplication } from '@/UIModels/Application' import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays' import { DialogContent, DialogOverlay } from '@reach/dialog' import { SNFile } from '@standardnotes/snjs' -import { NoPreviewIllustration } from '@standardnotes/stylekit' +import { addToast, NoPreviewIllustration, ToastType } from '@standardnotes/stylekit' import { FunctionComponent } from 'preact' import { useCallback, useEffect, useRef, useState } from 'preact/hooks' import { getFileIconComponent } from '@/Components/AttachedFilesPopover/PopoverFileItem' @@ -28,6 +28,7 @@ export const FilePreviewModal: FunctionComponent = ({ application, files, const [objectUrl, setObjectUrl] = useState() const [isFilePreviewable, setIsFilePreviewable] = useState(false) const [isLoadingFile, setIsLoadingFile] = useState(true) + const [fileDownloadProgress, setFileDownloadProgress] = useState(0) const [showFileInfoPanel, setShowFileInfoPanel] = useState(false) const currentFileIdRef = useRef() const closeButtonRef = useRef(null) @@ -35,8 +36,12 @@ export const FilePreviewModal: FunctionComponent = ({ application, files, const getObjectUrl = useCallback(async () => { try { const chunks: Uint8Array[] = [] - await application.files.downloadFile(file, async (decryptedChunk: Uint8Array) => { + setFileDownloadProgress(0) + await application.files.downloadFile(file, async (decryptedChunk, progress) => { chunks.push(decryptedChunk) + if (progress) { + setFileDownloadProgress(Math.round(progress.percentComplete)) + } }) const finalDecryptedBytes = concatenateUint8Arrays(chunks) setObjectUrl( @@ -150,6 +155,10 @@ export const FilePreviewModal: FunctionComponent = ({ application, files, className="mr-4" onClick={() => { application.getArchiveService().downloadData(objectUrl, file.name) + addToast({ + type: ToastType.Success, + message: 'Successfully downloaded file', + }) }} > Download @@ -168,7 +177,13 @@ export const FilePreviewModal: FunctionComponent = ({ application, files,
{isLoadingFile ? ( -
+
+
+
+
{fileDownloadProgress}%
+
+ Loading file... +
) : objectUrl ? ( ) : ( diff --git a/app/assets/javascripts/UIModels/AppState/FilesState.ts b/app/assets/javascripts/UIModels/AppState/FilesState.ts index 3fdd3f079..aad700e3a 100644 --- a/app/assets/javascripts/UIModels/AppState/FilesState.ts +++ b/app/assets/javascripts/UIModels/AppState/FilesState.ts @@ -42,13 +42,11 @@ export class FilesState { } if (progress) { - const progressPercent = Number.isInteger(progress.percentComplete) - ? progress.percentComplete - : progress.percentComplete.toFixed(2) + const progressPercent = Math.floor(progress.percentComplete) updateToast(downloadingToastId, { message: `Downloading file "${file.name}" (${progressPercent}%)`, - progress: progress.percentComplete, + progress: progressPercent, }) } }) @@ -136,10 +134,9 @@ export class FilesState { const onChunk = async (chunk: Uint8Array, index: number, isLast: boolean) => { await this.application.files.pushBytesForUpload(operation, chunk, index, isLast) - const progress = operation.getProgress().percentComplete - const formattedProgress = Number.isInteger(progress) ? progress : progress.toFixed(2) + const progress = Math.round(operation.getProgress().percentComplete) updateToast(toastId, { - message: `Uploading file "${file.name}" (${formattedProgress}%)`, + message: `Uploading file "${file.name}" (${progress}%)`, progress, }) } diff --git a/config/application.rb b/config/application.rb index 4ba820593..44305e849 100644 --- a/config/application.rb +++ b/config/application.rb @@ -51,7 +51,7 @@ module Web img_src: ["'self'", '* data:', 'blob:'], manifest_src: %w('self'), media_src: %w('self' blob: *.standardnotes.com), - object_src: %w('self'), + object_src: %w('self' blob: *.standardnotes.com), plugin_types: %w(), script_src: %w('self' 'unsafe-inline' 'unsafe-eval'), style_src: %w(* 'unsafe-inline'),