82 lines
2.4 KiB
TypeScript
82 lines
2.4 KiB
TypeScript
import { WebApplication } from '@/Application/Application'
|
|
import { concatenateUint8Arrays } from '@/Utils'
|
|
import { FileItem } from '@standardnotes/snjs'
|
|
import { useEffect, useMemo, useState } from 'react'
|
|
import FilePreviewError from './FilePreviewError'
|
|
import { isFileTypePreviewable } from './isFilePreviewable'
|
|
import PreviewComponent from './PreviewComponent'
|
|
|
|
type Props = {
|
|
application: WebApplication
|
|
file: FileItem
|
|
}
|
|
|
|
const FilePreview = ({ file, application }: Props) => {
|
|
const isFilePreviewable = useMemo(() => {
|
|
return isFileTypePreviewable(file.mimeType)
|
|
}, [file.mimeType])
|
|
|
|
const [isDownloading, setIsDownloading] = useState(true)
|
|
const [downloadProgress, setDownloadProgress] = useState(0)
|
|
const [downloadedBytes, setDownloadedBytes] = useState<Uint8Array>()
|
|
|
|
useEffect(() => {
|
|
if (!isFilePreviewable) {
|
|
setIsDownloading(false)
|
|
setDownloadProgress(0)
|
|
setDownloadedBytes(undefined)
|
|
return
|
|
}
|
|
|
|
const downloadFileForPreview = async () => {
|
|
if (downloadedBytes) {
|
|
return
|
|
}
|
|
|
|
setIsDownloading(true)
|
|
|
|
try {
|
|
const chunks: Uint8Array[] = []
|
|
setDownloadProgress(0)
|
|
await application.files.downloadFile(file, async (decryptedChunk, progress) => {
|
|
chunks.push(decryptedChunk)
|
|
if (progress) {
|
|
setDownloadProgress(Math.round(progress.percentComplete))
|
|
}
|
|
})
|
|
const finalDecryptedBytes = concatenateUint8Arrays(chunks)
|
|
setDownloadedBytes(finalDecryptedBytes)
|
|
} catch (error) {
|
|
console.error(error)
|
|
} finally {
|
|
setIsDownloading(false)
|
|
}
|
|
}
|
|
|
|
void downloadFileForPreview()
|
|
}, [application.files, downloadedBytes, file, isFilePreviewable])
|
|
|
|
return isDownloading ? (
|
|
<div className="flex flex-col justify-center items-center flex-grow">
|
|
<div className="flex items-center">
|
|
<div className="sk-spinner w-5 h-5 spinner-info mr-3"></div>
|
|
<div className="text-base font-semibold">{downloadProgress}%</div>
|
|
</div>
|
|
<span className="mt-3">Loading file...</span>
|
|
</div>
|
|
) : downloadedBytes ? (
|
|
<PreviewComponent file={file} bytes={downloadedBytes} />
|
|
) : (
|
|
<FilePreviewError
|
|
file={file}
|
|
filesController={application.getViewControllerManager().filesController}
|
|
tryAgainCallback={() => {
|
|
setDownloadedBytes(undefined)
|
|
}}
|
|
isFilePreviewable={isFilePreviewable}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export default FilePreview
|