import { WebApplication } from '@/Application/WebApplication' import { concatenateUint8Arrays } from '@/Utils' import { ApplicationEvent, FileDownloadProgress, FileItem, fileProgressToHumanReadableString, } from '@standardnotes/snjs' import { useEffect, useMemo, useState } from 'react' import Spinner from '@/Components/Spinner/Spinner' import FilePreviewError from './FilePreviewError' import { isFileTypePreviewable } from './isFilePreviewable' import PreviewComponent from './PreviewComponent' import Button from '../Button/Button' import { ProtectedIllustration } from '@standardnotes/icons' import { ImageZoomLevelProps } from './ImageZoomLevelProps' type Props = { application: WebApplication file: FileItem isEmbeddedInSuper?: boolean } & ImageZoomLevelProps const FilePreview = ({ file, application, isEmbeddedInSuper = false, imageZoomLevel, setImageZoomLevel }: Props) => { const [isAuthorized, setIsAuthorized] = useState(application.isAuthorizedToRenderItem(file)) const isFilePreviewable = useMemo(() => { return isFileTypePreviewable(file.mimeType) }, [file.mimeType]) const [isDownloading, setIsDownloading] = useState(true) const [downloadProgress, setDownloadProgress] = useState() const [downloadedBytes, setDownloadedBytes] = useState() useEffect(() => { setIsAuthorized(application.isAuthorizedToRenderItem(file)) }, [file.protected, application, file]) useEffect(() => { const disposer = application.addEventObserver(async (event) => { if (event === ApplicationEvent.UnprotectedSessionBegan) { setIsAuthorized(true) } else if (event === ApplicationEvent.UnprotectedSessionExpired) { setIsAuthorized(application.isAuthorizedToRenderItem(file)) } }) return disposer }, [application, file]) useEffect(() => { if (!isFilePreviewable || !isAuthorized) { setIsDownloading(false) setDownloadProgress(undefined) setDownloadedBytes(undefined) return } const downloadFileForPreview = async () => { if (downloadedBytes) { return } setIsDownloading(true) try { const chunks: Uint8Array[] = [] setDownloadProgress(undefined) const error = await application.files.downloadFile(file, async (decryptedChunk, progress) => { chunks.push(decryptedChunk) if (progress) { setDownloadProgress(progress) } }) if (!error) { const finalDecryptedBytes = concatenateUint8Arrays(chunks) setDownloadedBytes(finalDecryptedBytes) } } catch (error) { console.error(error) } finally { setIsDownloading(false) } } void downloadFileForPreview() }, [application.files, downloadedBytes, file, isFilePreviewable, isAuthorized]) if (!isAuthorized) { const hasProtectionSources = application.hasProtectionSources() return (
This file is protected.

{hasProtectionSources ? 'Authenticate to view this file.' : 'Add a passcode or create an account to require authentication to view this file.'}

{!hasProtectionSources && ( )}
) } return isDownloading ? (
{downloadProgress && (
{Math.floor(downloadProgress.percentComplete)}%
)}
{downloadProgress ? ( {fileProgressToHumanReadableString(downloadProgress, file.name, { showPercent: false })} ) : ( Loading... )}
) : downloadedBytes ? ( ) : ( { setDownloadedBytes(undefined) }} isFilePreviewable={isFilePreviewable} /> ) } export default FilePreview