fix: lazy load embedded files in super editor (#2043)
This commit is contained in:
@@ -6,7 +6,8 @@ import Spinner from '@/Components/Spinner/Spinner'
|
|||||||
import FilePreviewError from './FilePreviewError'
|
import FilePreviewError from './FilePreviewError'
|
||||||
import { isFileTypePreviewable } from './isFilePreviewable'
|
import { isFileTypePreviewable } from './isFilePreviewable'
|
||||||
import PreviewComponent from './PreviewComponent'
|
import PreviewComponent from './PreviewComponent'
|
||||||
import ProtectedItemOverlay from '../ProtectedItemOverlay/ProtectedItemOverlay'
|
import Button from '../Button/Button'
|
||||||
|
import { ProtectedIllustration } from '@standardnotes/icons'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
application: WebApplication
|
application: WebApplication
|
||||||
@@ -77,13 +78,28 @@ const FilePreview = ({ file, application }: Props) => {
|
|||||||
}, [application.files, downloadedBytes, file, isFilePreviewable, isAuthorized])
|
}, [application.files, downloadedBytes, file, isFilePreviewable, isAuthorized])
|
||||||
|
|
||||||
if (!isAuthorized) {
|
if (!isAuthorized) {
|
||||||
|
const hasProtectionSources = application.hasProtectionSources()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProtectedItemOverlay
|
<div className="flex flex-grow flex-col items-center justify-center">
|
||||||
showAccountMenu={application.showAccountMenu}
|
<ProtectedIllustration className="mb-4 h-30 w-30" />
|
||||||
itemType={'file'}
|
<div className="mb-2 text-base font-bold">This file is protected.</div>
|
||||||
onViewItem={() => application.protections.authorizeItemAccess(file)}
|
<p className="max-w-[35ch] text-center text-sm text-passive-0">
|
||||||
hasProtectionSources={application.hasProtectionSources()}
|
{hasProtectionSources
|
||||||
/>
|
? 'Authenticate to view this file.'
|
||||||
|
: 'Add a passcode or create an account to require authentication to view this file.'}
|
||||||
|
</p>
|
||||||
|
<div className="mt-3 flex gap-3">
|
||||||
|
{!hasProtectionSources && (
|
||||||
|
<Button primary small onClick={() => application.showAccountMenu()}>
|
||||||
|
Open account menu
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<Button primary onClick={() => application.protections.authorizeItemAccess(file)}>
|
||||||
|
{hasProtectionSources ? 'Authenticate' : 'View file'}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const FilePreviewError = ({ file, filesController, isFilePreviewable, tryAgainCa
|
|||||||
<div className="mb-2 text-base font-bold">This file can't be previewed.</div>
|
<div className="mb-2 text-base font-bold">This file can't be previewed.</div>
|
||||||
{isFilePreviewable ? (
|
{isFilePreviewable ? (
|
||||||
<>
|
<>
|
||||||
<div className="max-w-35ch mb-4 text-center text-sm text-passive-0">
|
<div className="mb-4 max-w-[35ch] text-center text-sm text-passive-0">
|
||||||
There was an error loading the file. Try again, or download the file and open it using another application.
|
There was an error loading the file. Try again, or download the file and open it using another application.
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
@@ -41,7 +41,7 @@ const FilePreviewError = ({ file, filesController, isFilePreviewable, tryAgainCa
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<div className="max-w-35ch mb-4 text-center text-sm text-passive-0">
|
<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.
|
To view this file, download it and open it using another application.
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -953,7 +953,7 @@ class NoteView extends AbstractComponent<NoteViewProps, State> {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{editorMode === 'super' && (
|
{editorMode === 'super' && (
|
||||||
<div className={classNames('blocks-editor w-full flex-grow overflow-hidden overflow-y-scroll')}>
|
<div className={classNames('blocks-editor w-full flex-grow overflow-hidden overflow-y-auto')}>
|
||||||
<SuperEditor
|
<SuperEditor
|
||||||
key={this.note.uuid}
|
key={this.note.uuid}
|
||||||
application={this.application}
|
application={this.application}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { BlockWithAlignableContents } from '@lexical/react/LexicalBlockWithAlignableContents'
|
import { BlockWithAlignableContents } from '@lexical/react/LexicalBlockWithAlignableContents'
|
||||||
import { useMemo } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { ElementFormatType, NodeKey } from 'lexical'
|
import { ElementFormatType, NodeKey } from 'lexical'
|
||||||
import { useApplication } from '@/Components/ApplicationView/ApplicationProvider'
|
import { useApplication } from '@/Components/ApplicationView/ApplicationProvider'
|
||||||
import FilePreview from '@/Components/FilePreview/FilePreview'
|
import FilePreview from '@/Components/FilePreview/FilePreview'
|
||||||
@@ -19,13 +19,47 @@ export function FileComponent({ className, format, nodeKey, fileUuid }: FileComp
|
|||||||
const application = useApplication()
|
const application = useApplication()
|
||||||
const file = useMemo(() => application.items.findItem<FileItem>(fileUuid), [application, fileUuid])
|
const file = useMemo(() => application.items.findItem<FileItem>(fileUuid), [application, fileUuid])
|
||||||
|
|
||||||
|
const [canLoad, setCanLoad] = useState(false)
|
||||||
|
|
||||||
|
const blockWrapperRef = useRef<HTMLDivElement>(null)
|
||||||
|
const blockObserver = useMemo(
|
||||||
|
() =>
|
||||||
|
new IntersectionObserver(
|
||||||
|
(entries) => {
|
||||||
|
entries.forEach((entry) => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
setCanLoad(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
threshold: 0.25,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const wrapper = blockWrapperRef.current
|
||||||
|
|
||||||
|
if (!wrapper) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
blockObserver.observe(wrapper)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
blockObserver.unobserve(wrapper)
|
||||||
|
}
|
||||||
|
}, [blockObserver])
|
||||||
|
|
||||||
if (!file) {
|
if (!file) {
|
||||||
return <div>Unable to find file {fileUuid}</div>
|
return <div>Unable to find file {fileUuid}</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BlockWithAlignableContents className={className} format={format} nodeKey={nodeKey}>
|
<BlockWithAlignableContents className={className} format={format} nodeKey={nodeKey}>
|
||||||
<FilePreview file={file} application={application} />
|
<div ref={blockWrapperRef}>{canLoad && <FilePreview file={file} application={application} />}</div>
|
||||||
</BlockWithAlignableContents>
|
</BlockWithAlignableContents>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user