From eefae250ff57a19cc16808a1ec31e74f4b826b3f Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Tue, 3 Sep 2024 23:55:59 +0200 Subject: [PATCH] fix(files): avoid duplicated fetch during preview (#2254) Closes #2217 --- public/locales/en/files.json | 2 +- src/bundles/files/actions.js | 8 +++++++- src/files/file-preview/FilePreview.js | 29 ++++++++++++++++----------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/public/locales/en/files.json b/public/locales/en/files.json index 0e5179d04..d49556511 100644 --- a/public/locales/en/files.json +++ b/public/locales/en/files.json @@ -101,7 +101,7 @@ "paragraph3": "Pro tip: drag and drop a file from any other page of the Web UI to add them to the root of your MFS." } }, - "loadMore": "Load more", + "previewLimitReached": "This preview is limited to 10 KiB. Click the download button to access the full file.", "previousFolder": "Go back to previous folder", "fileLabel": "Select {type} {name} with size: {size}", "hashUnavailable": "hash unavailable", diff --git a/src/bundles/files/actions.js b/src/bundles/files/actions.js index 4f42d35e0..d81bed5ca 100644 --- a/src/bundles/files/actions.js +++ b/src/bundles/files/actions.js @@ -214,7 +214,13 @@ const actions = () => ({ ...fileFromStats({ ...stats, path }), fetched: time, type: 'file', - read: () => ipfs.cat(stats.cid), + /** + * Reads a portion of data from IPFS. + * @param {number} offset - The starting point to read from. + * @param {number} length - The number of bytes to read. + * @returns {AsyncIterable} An async generator that yields the data read from IPFS. + */ + read: (offset, length) => ipfs.cat(stats.cid, { offset, length }), name: path.split('/').pop(), size: stats.size, cid: stats.cid diff --git a/src/files/file-preview/FilePreview.js b/src/files/file-preview/FilePreview.js index 3ad629aa7..58b5f40ea 100644 --- a/src/files/file-preview/FilePreview.js +++ b/src/files/file-preview/FilePreview.js @@ -11,6 +11,8 @@ import { useDrag } from 'react-dnd' import { toString as fromUint8ArrayToString } from 'uint8arrays' import Button from '../../components/button/Button.js' +const maxPlainTextPreview = 1024 * 10 // only preview small part of huge files + const Drag = ({ name, size, cid, path, children }) => { const [, drag] = useDrag({ item: { name, size, cid, path, type: 'FILE' } @@ -29,7 +31,11 @@ const Preview = (props) => { const type = typeFromExt(name) const loadContent = useCallback(async () => { - const readBuffer = buffer || await read() + if (['audio', 'video', 'pdf', 'image'].includes(type)) { + // noop, we dont need to read() preview for these because we embed them on page + return + } + const readBuffer = buffer || await read(0, maxPlainTextPreview) if (!buffer) { setBuffer(readBuffer) } @@ -44,7 +50,7 @@ const Preview = (props) => { const hasMore = !done && new TextEncoder().encode(currentContent).length < size setHasMoreContent(hasMore) - }, [buffer, content, read, size]) + }, [buffer, content, read, size, type]) useEffect(() => { loadContent() @@ -102,21 +108,20 @@ const Preview = (props) => { : Try opening it instead with your local gateway or public gateway. - } -

) - if (size > 1024 * 1024 * 4) { - return cantPreview - } - if (content === null) { return } + // a precaution to not render too much, in case we overread + if (content.length > maxPlainTextPreview) { + return cantPreview + } + if (isBinary(name, content)) { return cantPreview } @@ -126,12 +131,12 @@ const Preview = (props) => { {content} { hasMoreContent &&
- - +

} }