chore: add fallback loading strategy for video previews
This commit is contained in:
@@ -10,6 +10,7 @@ import { PreviewableTextFileTypes, RequiresNativeFilePreview } from './isFilePre
|
|||||||
import TextPreview from './TextPreview'
|
import TextPreview from './TextPreview'
|
||||||
import { parseFileName } from '@standardnotes/filepicker'
|
import { parseFileName } from '@standardnotes/filepicker'
|
||||||
import { sanitizeFileName } from '@standardnotes/ui-services'
|
import { sanitizeFileName } from '@standardnotes/ui-services'
|
||||||
|
import VideoPreview from './VideoPreview'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -89,11 +90,7 @@ const PreviewComponent: FunctionComponent<Props> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (file.mimeType.startsWith('video/')) {
|
if (file.mimeType.startsWith('video/')) {
|
||||||
return (
|
return <VideoPreview file={file} filesController={application.filesController} objectUrl={objectUrl} />
|
||||||
<video className="h-full w-full" controls autoPlay>
|
|
||||||
<source src={objectUrl} type={file.mimeType} />
|
|
||||||
</video>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.mimeType.startsWith('audio/')) {
|
if (file.mimeType.startsWith('audio/')) {
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { FilesController } from '@/Controllers/FilesController'
|
||||||
|
import { NoPreviewIllustration } from '@standardnotes/icons'
|
||||||
|
import { FileItem } from '@standardnotes/snjs'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import Button from '../Button/Button'
|
||||||
|
import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
file: FileItem
|
||||||
|
filesController: FilesController
|
||||||
|
objectUrl: string
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some formats require using the <source/> tag with the type attribute
|
||||||
|
* because we use object URLs. However some formats seem to only work
|
||||||
|
* when not using the <source/> tag.
|
||||||
|
* We show an error message if neither works.
|
||||||
|
*/
|
||||||
|
const VideoPreview = ({ file, filesController, objectUrl }: Props) => {
|
||||||
|
const [showError, setShowError] = useState(false)
|
||||||
|
const [shouldTryFallback, setShouldTryFallback] = useState(false)
|
||||||
|
|
||||||
|
if (showError) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-grow flex-col items-center justify-center">
|
||||||
|
<NoPreviewIllustration className="mb-4 h-30 w-30" />
|
||||||
|
<div className="mb-2 text-base font-bold">This video can't be previewed.</div>
|
||||||
|
<div className="mb-4 max-w-[35ch] text-center text-sm text-passive-0">
|
||||||
|
To view this file, download it and open it using another application.
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
primary
|
||||||
|
onClick={() => {
|
||||||
|
filesController
|
||||||
|
.handleFileAction({
|
||||||
|
type: FileItemActionType.DownloadFile,
|
||||||
|
payload: { file },
|
||||||
|
})
|
||||||
|
.catch(console.error)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldTryFallback) {
|
||||||
|
return (
|
||||||
|
<video
|
||||||
|
className="h-full w-full"
|
||||||
|
controls
|
||||||
|
autoPlay
|
||||||
|
src={objectUrl}
|
||||||
|
onError={() => {
|
||||||
|
setShowError(true)
|
||||||
|
setShouldTryFallback(false)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<video
|
||||||
|
className="h-full w-full"
|
||||||
|
controls
|
||||||
|
autoPlay
|
||||||
|
onError={() => {
|
||||||
|
setShouldTryFallback(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<source src={objectUrl} type={file.mimeType} />
|
||||||
|
</video>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default VideoPreview
|
||||||
Reference in New Issue
Block a user