From fbd9f5e4cfada83750efe516623a83392fb60ddd Mon Sep 17 00:00:00 2001 From: Mahesh Sanikommu Date: Mon, 18 May 2026 10:15:30 -0700 Subject: [PATCH] feat(graph): auto-paginate consumer graph + loading progress chip (#966) --- apps/web/components/graph-layout-view.tsx | 1 + .../memory-graph/hooks/use-graph-api.ts | 23 ++++++++++- .../memory-graph/memory-graph-wrapper.tsx | 38 ++++++++++++++++++- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/apps/web/components/graph-layout-view.tsx b/apps/web/components/graph-layout-view.tsx index c1fc0311..0bbf6a3f 100644 --- a/apps/web/components/graph-layout-view.tsx +++ b/apps/web/components/graph-layout-view.tsx @@ -46,6 +46,7 @@ export const GraphLayoutView = memo(function GraphLayoutView({ maxNodes={undefined} canvasRef={canvasRef} onOpenDocument={onOpenDocument} + autoFetchAll /> diff --git a/apps/web/components/memory-graph/hooks/use-graph-api.ts b/apps/web/components/memory-graph/hooks/use-graph-api.ts index 7991f600..41a7d63f 100644 --- a/apps/web/components/memory-graph/hooks/use-graph-api.ts +++ b/apps/web/components/memory-graph/hooks/use-graph-api.ts @@ -1,7 +1,7 @@ "use client" import { useInfiniteQuery } from "@tanstack/react-query" -import { useMemo } from "react" +import { useEffect, useMemo } from "react" import { $fetch } from "@lib/api" import type { GraphApiDocument, @@ -15,6 +15,7 @@ interface UseGraphApiOptions { containerTags?: string[] documentIds?: string[] enabled?: boolean + autoFetchAll?: boolean } interface ApiMemoryEntry { @@ -108,7 +109,12 @@ function toGraphDocument( } export function useGraphApi(options: UseGraphApiOptions = {}) { - const { containerTags, documentIds, enabled = true } = options + const { + containerTags, + documentIds, + enabled = true, + autoFetchAll = false, + } = options const filteredDocumentIds = documentIds?.filter(Boolean) const hasDocumentIds = filteredDocumentIds != null && filteredDocumentIds.length > 0 @@ -163,6 +169,19 @@ export function useGraphApi(options: UseGraphApiOptions = {}) { enabled, }) + useEffect(() => { + if (!autoFetchAll || !enabled) return + if (!hasNextPage || isPending || isFetchingNextPage) return + fetchNextPage() + }, [ + autoFetchAll, + enabled, + hasNextPage, + isPending, + isFetchingNextPage, + fetchNextPage, + ]) + const documents = useMemo(() => { if (!data?.pages) return [] return data.pages.flatMap((page) => diff --git a/apps/web/components/memory-graph/memory-graph-wrapper.tsx b/apps/web/components/memory-graph/memory-graph-wrapper.tsx index 0b2ca826..e2881387 100644 --- a/apps/web/components/memory-graph/memory-graph-wrapper.tsx +++ b/apps/web/components/memory-graph/memory-graph-wrapper.tsx @@ -1,9 +1,11 @@ "use client" -import { useEffect, useRef, useState } from "react" +import { useEffect, useMemo, useRef, useState } from "react" +import { Loader2 } from "lucide-react" import { MemoryGraph as MemoryGraphBase } from "@supermemory/memory-graph" import type { GraphThemeColors } from "@supermemory/memory-graph" import { useGraphApi } from "./hooks/use-graph-api" +import { cn } from "@lib/utils" export interface MemoryGraphWrapperProps { children?: React.ReactNode @@ -21,6 +23,7 @@ export interface MemoryGraphWrapperProps { onSlideshowStop?: () => void canvasRef?: React.RefObject onOpenDocument?: (documentId: string) => void + autoFetchAll?: boolean } export function MemoryGraph({ @@ -32,6 +35,7 @@ export function MemoryGraph({ documentIds, maxNodes, canvasRef, + autoFetchAll = false, ...rest }: MemoryGraphWrapperProps) { const [containerSize, setContainerSize] = useState({ width: 0, height: 0 }) @@ -60,10 +64,22 @@ export function MemoryGraph({ containerTags, documentIds, enabled: containerSize.width > 0 && containerSize.height > 0, + autoFetchAll, }) + const loadedDocCount = documents.length + const loadedMemoryCount = useMemo( + () => documents.reduce((sum, doc) => sum + doc.memories.length, 0), + [documents], + ) + const showProgress = + autoFetchAll && + !apiIsLoading && + totalCount > 0 && + (hasMore || isLoadingMore || loadedDocCount < totalCount) + return ( -
+
{children} + {showProgress && ( +
+ + + {loadedMemoryCount.toLocaleString()} memories ยท{" "} + {loadedDocCount.toLocaleString()}/{totalCount.toLocaleString()}{" "} + documents + +
+ )}
) }