11"use client"
22
3- import { useCallback , useState } from "react"
3+ import { useCallback , useRef , useState } from "react"
44
55import { workspaceCitationState } from "@/components/workspace-citation-state"
66import { useWorkspaceSelectedChunks } from "@/components/workspace-selected-chunks"
@@ -14,6 +14,9 @@ type FocusedChunkState = {
1414}
1515
1616type PrefetchedChunksBySourceId = Readonly < Record < string , ParsedChunkView [ ] > >
17+ type PrefetchedChunksUpdater = (
18+ current : PrefetchedChunksBySourceId ,
19+ ) => PrefetchedChunksBySourceId
1720
1821type WorkspaceCitationFocusInput = {
1922 readonly fetchChunks : ( sourceId : string ) => Promise < ParsedChunkView [ ] >
@@ -60,8 +63,15 @@ export function useWorkspaceCitationFocus({
6063 const [ fullChunkLoadingSourceId , setFullChunkLoadingSourceId ] = useState <
6164 string | null
6265 > ( null )
66+ const fullChunkRequestsBySourceIdRef = useRef <
67+ Map < string , Promise < ParsedChunkView [ ] > >
68+ > ( new Map ( ) )
69+ const fullChunkRequestedSourceIdsRef = useRef < Set < string > > ( new Set ( ) )
6370 const [ prefetchedChunksBySourceId , setPrefetchedChunksBySourceId ] =
6471 useState < PrefetchedChunksBySourceId > ( initialPrefetchedChunksBySourceId )
72+ const prefetchedChunksBySourceIdRef = useRef < PrefetchedChunksBySourceId > (
73+ initialPrefetchedChunksBySourceId ,
74+ )
6575 const {
6676 hasMoreSelectedChunks,
6777 handleLoadMoreChunks,
@@ -85,48 +95,79 @@ export function useWorkspaceCitationFocus({
8595 [ ] ,
8696 )
8797
98+ const updatePrefetchedChunksBySourceId = useCallback (
99+ ( updater : PrefetchedChunksUpdater ) : void => {
100+ const next = updater ( prefetchedChunksBySourceIdRef . current )
101+ prefetchedChunksBySourceIdRef . current = next
102+ setPrefetchedChunksBySourceId ( next )
103+ } ,
104+ [ ] ,
105+ )
106+
88107 const handleSourceSelected = useCallback (
89108 ( sourceId : string | null ) : void => {
90109 onSelectSource ( sourceId )
91- if ( sourceId ) {
92- setPrefetchedChunksBySourceId ( ( current ) =>
110+ if ( sourceId && sourceId !== selectedSourceId ) {
111+ fullChunkRequestedSourceIdsRef . current . delete ( sourceId )
112+ updatePrefetchedChunksBySourceId ( ( current ) =>
93113 workspaceCitationState . removePrefetchedChunks ( current , sourceId ) ,
94114 )
95115 }
96116 requestChunkFocus ( null )
97117 } ,
98- [ onSelectSource , requestChunkFocus ] ,
118+ [
119+ onSelectSource ,
120+ requestChunkFocus ,
121+ selectedSourceId ,
122+ updatePrefetchedChunksBySourceId ,
123+ ] ,
124+ )
125+
126+ const loadAllChunksForSource = useCallback (
127+ ( sourceId : string ) : Promise < ParsedChunkView [ ] > => {
128+ const existingRequest =
129+ fullChunkRequestsBySourceIdRef . current . get ( sourceId )
130+ if ( existingRequest ) return existingRequest
131+
132+ setFullChunkLoadingSourceId ( sourceId )
133+ const request = fetchChunks ( sourceId )
134+ . then ( ( chunks ) => {
135+ updatePrefetchedChunksBySourceId ( ( current ) =>
136+ workspaceCitationState . upsertPrefetchedChunks (
137+ current ,
138+ sourceId ,
139+ chunks ,
140+ ) ,
141+ )
142+ return chunks
143+ } )
144+ . finally ( ( ) => {
145+ fullChunkRequestsBySourceIdRef . current . delete ( sourceId )
146+ setFullChunkLoadingSourceId ( ( current ) =>
147+ current === sourceId ? null : current ,
148+ )
149+ } )
150+
151+ fullChunkRequestsBySourceIdRef . current . set ( sourceId , request )
152+ return request
153+ } ,
154+ [ fetchChunks , updatePrefetchedChunksBySourceId ] ,
99155 )
100156
101157 const handleLoadAllChunks = useCallback ( ( ) : void => {
102158 if (
103159 ! selectedSourceId ||
104- prefetchedChunksBySourceId [ selectedSourceId ] ||
105- fullChunkLoadingSourceId === selectedSourceId
160+ prefetchedChunksBySourceIdRef . current [ selectedSourceId ] ||
161+ fullChunkRequestedSourceIdsRef . current . has ( selectedSourceId ) ||
162+ fullChunkRequestsBySourceIdRef . current . has ( selectedSourceId )
106163 ) {
107164 return
108165 }
109166
110- setFullChunkLoadingSourceId ( selectedSourceId )
111- void fetchChunks ( selectedSourceId )
112- . then ( ( chunks ) => {
113- setPrefetchedChunksBySourceId ( ( current ) =>
114- workspaceCitationState . upsertPrefetchedChunks (
115- current ,
116- selectedSourceId ,
117- chunks ,
118- ) ,
119- )
120- } )
121- . finally ( ( ) => {
122- setFullChunkLoadingSourceId ( ( current ) =>
123- current === selectedSourceId ? null : current ,
124- )
125- } )
167+ fullChunkRequestedSourceIdsRef . current . add ( selectedSourceId )
168+ void loadAllChunksForSource ( selectedSourceId )
126169 } , [
127- fetchChunks ,
128- fullChunkLoadingSourceId ,
129- prefetchedChunksBySourceId ,
170+ loadAllChunksForSource ,
130171 selectedSourceId ,
131172 ] )
132173
@@ -157,15 +198,16 @@ export function useWorkspaceCitationFocus({
157198 }
158199
159200 if ( ! workspaceCitationState . hasExactCitationTargetHint ( citation ) ) {
160- setPrefetchedChunksBySourceId ( ( current ) =>
201+ fullChunkRequestedSourceIdsRef . current . delete ( source . id )
202+ updatePrefetchedChunksBySourceId ( ( current ) =>
161203 workspaceCitationState . removePrefetchedChunks ( current , source . id ) ,
162204 )
163205 if ( selectedSourceId !== source . id ) onSelectSource ( source . id )
164206 requestChunkFocus ( null )
165207 return
166208 }
167209
168- const cachedChunks = prefetchedChunksBySourceId [ source . id ]
210+ const cachedChunks = prefetchedChunksBySourceIdRef . current [ source . id ]
169211 if ( cachedChunks ) {
170212 const cachedFocusId =
171213 workspaceCitationState . getLoadedCitationChunkId ( {
@@ -175,7 +217,7 @@ export function useWorkspaceCitationFocus({
175217 selectedChunks : cachedChunks ,
176218 hasMoreSelectedChunks : false ,
177219 } )
178- setPrefetchedChunksBySourceId ( ( current ) =>
220+ updatePrefetchedChunksBySourceId ( ( current ) =>
179221 workspaceCitationState . upsertPrefetchedChunks (
180222 current ,
181223 source . id ,
@@ -188,14 +230,7 @@ export function useWorkspaceCitationFocus({
188230 }
189231
190232 requestChunkFocus ( null )
191- const chunks = await fetchChunks ( source . id )
192- setPrefetchedChunksBySourceId ( ( current ) =>
193- workspaceCitationState . upsertPrefetchedChunks (
194- current ,
195- source . id ,
196- chunks ,
197- ) ,
198- )
233+ const chunks = await loadAllChunksForSource ( source . id )
199234 const prefetchedChunkId =
200235 workspaceCitationState . getLoadedCitationChunkId ( {
201236 citation,
@@ -213,14 +248,14 @@ export function useWorkspaceCitationFocus({
213248 }
214249 } ,
215250 [
216- fetchChunks ,
217251 hasMoreSelectedChunks ,
252+ loadAllChunksForSource ,
218253 onSelectSource ,
219- prefetchedChunksBySourceId ,
220254 requestChunkFocus ,
221255 selectedChunks ,
222256 selectedSourceId ,
223257 sources ,
258+ updatePrefetchedChunksBySourceId ,
224259 ] ,
225260 )
226261
0 commit comments