feat: show download progress in file preview modal (#1011)

This commit is contained in:
Aman Harwara
2022-05-05 19:45:39 +05:30
committed by GitHub
parent bb4fd2449a
commit 2c807e2b80
3 changed files with 23 additions and 11 deletions

View File

@@ -2,7 +2,7 @@ import { WebApplication } from '@/UIModels/Application'
import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays' import { concatenateUint8Arrays } from '@/Utils/ConcatenateUint8Arrays'
import { DialogContent, DialogOverlay } from '@reach/dialog' import { DialogContent, DialogOverlay } from '@reach/dialog'
import { SNFile } from '@standardnotes/snjs' import { SNFile } from '@standardnotes/snjs'
import { NoPreviewIllustration } from '@standardnotes/stylekit' import { addToast, NoPreviewIllustration, ToastType } from '@standardnotes/stylekit'
import { FunctionComponent } from 'preact' import { FunctionComponent } from 'preact'
import { useCallback, useEffect, useRef, useState } from 'preact/hooks' import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
import { getFileIconComponent } from '@/Components/AttachedFilesPopover/PopoverFileItem' import { getFileIconComponent } from '@/Components/AttachedFilesPopover/PopoverFileItem'
@@ -28,6 +28,7 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
const [objectUrl, setObjectUrl] = useState<string>() const [objectUrl, setObjectUrl] = useState<string>()
const [isFilePreviewable, setIsFilePreviewable] = useState(false) const [isFilePreviewable, setIsFilePreviewable] = useState(false)
const [isLoadingFile, setIsLoadingFile] = useState(true) const [isLoadingFile, setIsLoadingFile] = useState(true)
const [fileDownloadProgress, setFileDownloadProgress] = useState(0)
const [showFileInfoPanel, setShowFileInfoPanel] = useState(false) const [showFileInfoPanel, setShowFileInfoPanel] = useState(false)
const currentFileIdRef = useRef<string>() const currentFileIdRef = useRef<string>()
const closeButtonRef = useRef<HTMLButtonElement>(null) const closeButtonRef = useRef<HTMLButtonElement>(null)
@@ -35,8 +36,12 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
const getObjectUrl = useCallback(async () => { const getObjectUrl = useCallback(async () => {
try { try {
const chunks: Uint8Array[] = [] const chunks: Uint8Array[] = []
await application.files.downloadFile(file, async (decryptedChunk: Uint8Array) => { setFileDownloadProgress(0)
await application.files.downloadFile(file, async (decryptedChunk, progress) => {
chunks.push(decryptedChunk) chunks.push(decryptedChunk)
if (progress) {
setFileDownloadProgress(Math.round(progress.percentComplete))
}
}) })
const finalDecryptedBytes = concatenateUint8Arrays(chunks) const finalDecryptedBytes = concatenateUint8Arrays(chunks)
setObjectUrl( setObjectUrl(
@@ -150,6 +155,10 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
className="mr-4" className="mr-4"
onClick={() => { onClick={() => {
application.getArchiveService().downloadData(objectUrl, file.name) application.getArchiveService().downloadData(objectUrl, file.name)
addToast({
type: ToastType.Success,
message: 'Successfully downloaded file',
})
}} }}
> >
Download Download
@@ -168,7 +177,13 @@ export const FilePreviewModal: FunctionComponent<Props> = ({ application, files,
<div className="flex flex-grow min-h-0"> <div className="flex flex-grow min-h-0">
<div className="flex flex-grow items-center justify-center relative max-w-full"> <div className="flex flex-grow items-center justify-center relative max-w-full">
{isLoadingFile ? ( {isLoadingFile ? (
<div className="sk-spinner w-5 h-5 spinner-info"></div> <div className="flex flex-col items-center">
<div className="flex items-center">
<div className="sk-spinner w-5 h-5 spinner-info mr-3"></div>
<div className="text-base font-semibold">{fileDownloadProgress}%</div>
</div>
<span className="mt-3">Loading file...</span>
</div>
) : objectUrl ? ( ) : objectUrl ? (
<PreviewComponent file={file} objectUrl={objectUrl} /> <PreviewComponent file={file} objectUrl={objectUrl} />
) : ( ) : (

View File

@@ -42,13 +42,11 @@ export class FilesState {
} }
if (progress) { if (progress) {
const progressPercent = Number.isInteger(progress.percentComplete) const progressPercent = Math.floor(progress.percentComplete)
? progress.percentComplete
: progress.percentComplete.toFixed(2)
updateToast(downloadingToastId, { updateToast(downloadingToastId, {
message: `Downloading file "${file.name}" (${progressPercent}%)`, 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) => { const onChunk = async (chunk: Uint8Array, index: number, isLast: boolean) => {
await this.application.files.pushBytesForUpload(operation, chunk, index, isLast) await this.application.files.pushBytesForUpload(operation, chunk, index, isLast)
const progress = operation.getProgress().percentComplete const progress = Math.round(operation.getProgress().percentComplete)
const formattedProgress = Number.isInteger(progress) ? progress : progress.toFixed(2)
updateToast(toastId, { updateToast(toastId, {
message: `Uploading file "${file.name}" (${formattedProgress}%)`, message: `Uploading file "${file.name}" (${progress}%)`,
progress, progress,
}) })
} }

View File

@@ -51,7 +51,7 @@ module Web
img_src: ["'self'", '* data:', 'blob:'], img_src: ["'self'", '* data:', 'blob:'],
manifest_src: %w('self'), manifest_src: %w('self'),
media_src: %w('self' blob: *.standardnotes.com), media_src: %w('self' blob: *.standardnotes.com),
object_src: %w('self'), object_src: %w('self' blob: *.standardnotes.com),
plugin_types: %w(), plugin_types: %w(),
script_src: %w('self' 'unsafe-inline' 'unsafe-eval'), script_src: %w('self' 'unsafe-inline' 'unsafe-eval'),
style_src: %w(* 'unsafe-inline'), style_src: %w(* 'unsafe-inline'),