11"use client" ;
22
3- import { useEffect , useState } from "react" ;
4- import { getDefaultSession } from "@inrupt/solid-client-authn-browser " ;
3+ import { useEffect , useState , useRef } from "react" ;
4+ import { getAuthenticatedSession } from "../helpers " ;
55import {
66 getSolidDataset ,
77 getContainedResourceUrlAll ,
@@ -23,6 +23,10 @@ interface UseBrowseStorageResult {
2323 error : Error | null ;
2424}
2525
26+ // In-memory cache for container contents
27+ // Key: normalized URL (with trailing slash), Value: cached files
28+ const containerCache = new Map < string , FileItemData [ ] > ( ) ;
29+
2630/**
2731 * Hook to browse/list the contents of a Solid storage container
2832 * Uses LDP to fetch and parse container contents
@@ -31,36 +35,58 @@ export function useBrowseStorage(containerUrl: string | null, refreshKey?: numbe
3135 const [ files , setFiles ] = useState < FileItemData [ ] > ( [ ] ) ;
3236 const [ isLoading , setIsLoading ] = useState ( false ) ;
3337 const [ error , setError ] = useState < Error | null > ( null ) ;
38+ const lastUrlRef = useRef < string | null > ( null ) ;
39+ const lastRefreshKeyRef = useRef < number | undefined > ( undefined ) ;
3440
3541 useEffect ( ( ) => {
3642 if ( ! containerUrl ) {
3743 setFiles ( [ ] ) ;
3844 setIsLoading ( false ) ;
45+ lastUrlRef . current = null ;
46+ return ;
47+ }
48+
49+ // Normalize URL (ensure trailing slash for consistency)
50+ const normalizedUrl = containerUrl . endsWith ( "/" ) ? containerUrl : containerUrl + "/" ;
51+
52+ // Check if we should use cached data
53+ // Use cache if: no explicit refresh requested and cache exists for this URL
54+ const shouldUseCache =
55+ refreshKey === undefined &&
56+ containerCache . has ( normalizedUrl ) ;
57+
58+ if ( shouldUseCache ) {
59+ // Use cached data immediately
60+ const cachedFiles = containerCache . get ( normalizedUrl ) ! ;
61+ setFiles ( cachedFiles ) ;
62+ setIsLoading ( false ) ;
63+ setError ( null ) ;
64+ // Update refs to track current URL
65+ lastUrlRef . current = normalizedUrl ;
66+ lastRefreshKeyRef . current = refreshKey ;
3967 return ;
4068 }
4169
42- const urlToBrowse = containerUrl ;
70+ // Update refs
71+ lastUrlRef . current = normalizedUrl ;
72+ lastRefreshKeyRef . current = refreshKey ;
4373
4474 async function browseContainer ( ) {
4575 try {
4676 setIsLoading ( true ) ;
4777 setError ( null ) ;
4878
49- const session = getDefaultSession ( ) ;
50- if ( ! session . info . isLoggedIn ) {
51- throw new Error ( "Not authenticated" ) ;
52- }
79+ const { fetch : fetchFn } = getAuthenticatedSession ( ) ;
5380
54- const url = urlToBrowse . endsWith ( "/" ) ? urlToBrowse : urlToBrowse + "/" ;
55- const sessionFetch = session . fetch || fetch ;
81+ const url = normalizedUrl ;
5682
5783 // Create a fetch function that bypasses cache when refreshKey is provided
5884 const fetchWithCacheBust = refreshKey !== undefined
5985 ? async ( input : RequestInfo | URL , init ?: RequestInit ) => {
6086 const urlWithCacheBust = typeof input === 'string'
6187 ? `${ input } ${ input . includes ( '?' ) ? '&' : '?' } _t=${ Date . now ( ) } `
6288 : input ;
63- return sessionFetch ( urlWithCacheBust , {
89+ return fetchFn ( urlWithCacheBust , {
6490 ...init ,
6591 cache : 'no-store' ,
6692 headers : {
@@ -69,7 +95,7 @@ export function useBrowseStorage(containerUrl: string | null, refreshKey?: numbe
6995 } ,
7096 } ) ;
7197 }
72- : sessionFetch ;
98+ : fetchFn ;
7399
74100 // Use @inrupt /solid-client to fetch the container dataset
75101 const containerDataset = await getSolidDataset ( url , {
@@ -170,6 +196,8 @@ export function useBrowseStorage(containerUrl: string | null, refreshKey?: numbe
170196 url : item . url
171197 } ) ) ) ;
172198
199+ // Cache the results
200+ containerCache . set ( normalizedUrl , fileItems ) ;
173201 setFiles ( fileItems ) ;
174202 } catch ( err ) {
175203 const errorMessage =
0 commit comments