From fc120bcb381b95eeaefcb8a3446e5a86e34ba03d Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:32:08 +0530 Subject: [PATCH] refactor: improve infinite scroll implementation in DocumentsTableShell by adding separate scroll references for desktop and mobile views --- .../components/DocumentsTableShell.tsx | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx index 736ea183f..914207c71 100644 --- a/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx +++ b/surfsense_web/app/dashboard/[search_space_id]/documents/(manage)/components/DocumentsTableShell.tsx @@ -178,10 +178,6 @@ function DocumentNameTooltip({ Created:{" "} {formatAbsoluteDate(doc.created_at)}

-

- Source:{" "} - {getDocumentTypeLabel(doc.document_type)} -

@@ -331,27 +327,30 @@ export function DocumentsTableShell({ const desktopSentinelRef = useRef(null); const mobileSentinelRef = useRef(null); + const desktopScrollRef = useRef(null); + const mobileScrollRef = useRef(null); useEffect(() => { if (!onLoadMore || !hasMore || loadingMore) return; - const observer = new IntersectionObserver( - (entries) => { - if (entries.some((e) => e.isIntersecting)) { - onLoadMore(); - } - }, - { root: null, rootMargin: "200px", threshold: 0 } - ); + const observers: IntersectionObserver[] = []; - if (desktopSentinelRef.current) { - observer.observe(desktopSentinelRef.current); - } - if (mobileSentinelRef.current) { - observer.observe(mobileSentinelRef.current); - } + const observe = (root: HTMLElement | null, sentinel: HTMLElement | null) => { + if (!root || !sentinel) return; + const observer = new IntersectionObserver( + (entries) => { + if (entries.some((e) => e.isIntersecting)) onLoadMore(); + }, + { root, rootMargin: "150px", threshold: 0 } + ); + observer.observe(sentinel); + observers.push(observer); + }; - return () => observer.disconnect(); + observe(desktopScrollRef.current, desktopSentinelRef.current); + observe(mobileScrollRef.current, mobileSentinelRef.current); + + return () => { for (const o of observers) o.disconnect(); }; }, [onLoadMore, hasMore, loadingMore]); const handleViewDocument = useCallback(async (doc: Document) => { @@ -589,7 +588,7 @@ export function DocumentsTableShell({ -
+
{sorted.map((doc, index) => { @@ -661,15 +660,13 @@ export function DocumentsTableShell({
{hasMore && ( -
- {loadingMore && } -
+
)}
{/* Mobile Card View */} -
+
{sorted.map((doc, index) => { const isSelected = selectedIds.has(doc.id); const canSelect = isSelectable(doc); @@ -731,9 +728,7 @@ export function DocumentsTableShell({ ); })} {hasMore && ( -
- {loadingMore && } -
+
)}