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 &&
-
-
}
>
}