@@ -21,7 +21,8 @@ import { useChatState } from "../hooks/chat/useChatState";
2121import { usePermissions } from "../hooks/chat/usePermissions" ;
2222import { usePermissionMode } from "../hooks/chat/usePermissionMode" ;
2323import { useAbortController } from "../hooks/chat/useAbortController" ;
24- import { useAutoHistoryLoader } from "../hooks/useHistoryLoader" ;
24+ import { useAutoCachedHistoryLoader } from "../hooks/useCachedHistoryLoader" ;
25+ import { useSessionCache } from "../hooks/useSessionCache" ;
2526import { normalizeWindowsPath } from "../utils/pathUtils" ;
2627import type { StreamingContext } from "../hooks/streaming/useMessageProcessor" ;
2728import { SettingsButton } from "./SettingsButton" ;
@@ -95,20 +96,36 @@ export function SplitView() {
9596 encodedName : string ,
9697 ) => {
9798 const updatedProjects = [ ...projects ] ;
98- updatedProjects [ projectIndex ] . loadingSessions = true ;
99+ const project = updatedProjects [ projectIndex ] ;
100+ project . loadingSessions = true ;
99101 setProjects ( updatedProjects ) ;
100102
101103 try {
102104 const response = await fetch ( getHistoriesUrl ( encodedName ) ) ;
103105 if ( response . ok ) {
104106 const data = await response . json ( ) ;
105- updatedProjects [ projectIndex ] . sessions = data . conversations || [ ] ;
107+ const sessions = data . conversations || [ ] ;
108+ project . sessions = sessions ;
109+
110+ // Preload the most recent 3 sessions for faster switching
111+ const recentSessions = sessions . slice ( 0 , 3 ) ;
112+ for ( const session of recentSessions ) {
113+ try {
114+ await preloadSession ( project . path , session . sessionId , encodedName ) ;
115+ } catch ( error ) {
116+ console . warn (
117+ "Failed to preload session:" ,
118+ session . sessionId ,
119+ error ,
120+ ) ;
121+ }
122+ }
106123 }
107124 } catch ( error ) {
108125 console . error ( "Failed to load sessions:" , error ) ;
109- updatedProjects [ projectIndex ] . sessions = [ ] ;
126+ project . sessions = [ ] ;
110127 } finally {
111- updatedProjects [ projectIndex ] . loadingSessions = false ;
128+ project . loadingSessions = false ;
112129 setProjects ( [ ...updatedProjects ] ) ;
113130 }
114131 } ;
@@ -188,14 +205,19 @@ export function SplitView() {
188205 const { processStreamLine } = useClaudeStreaming ( ) ;
189206 const { abortRequest, createAbortHandler } = useAbortController ( ) ;
190207 const { permissionMode, setPermissionMode } = usePermissionMode ( ) ;
208+ const { preloadSession, setCachedSession, updateScrollPosition } =
209+ useSessionCache ( ) ;
191210
192211 // Load conversation history if sessionId is provided
193212 const {
194213 messages : historyMessages ,
195214 loading : historyLoading ,
196215 error : historyError ,
197216 sessionId : loadedSessionId ,
198- } = useAutoHistoryLoader (
217+ fromCache : historyFromCache ,
218+ scrollPosition : historyScrollPosition ,
219+ } = useAutoCachedHistoryLoader (
220+ selectedProject || undefined ,
199221 getEncodedName ( ) || undefined ,
200222 sessionId || undefined ,
201223 ) ;
@@ -294,9 +316,38 @@ export function SplitView() {
294316 const streamingContext : StreamingContext = {
295317 currentAssistantMessage,
296318 setCurrentAssistantMessage,
297- addMessage,
298- updateLastMessage,
299- onSessionId : setCurrentSessionId ,
319+ addMessage : ( msg : ChatMessage ) => {
320+ addMessage ( msg ) ;
321+ // Update cache when new messages are added during streaming
322+ if ( currentSessionId && selectedProject ) {
323+ const updatedMessages = [ ...messages , msg ] ;
324+ setCachedSession (
325+ selectedProject ,
326+ currentSessionId ,
327+ updatedMessages ,
328+ ) ;
329+ }
330+ } ,
331+ updateLastMessage : ( msg : ChatMessage ) => {
332+ updateLastMessage ( msg ) ;
333+ // Update cache when messages are updated during streaming
334+ if ( currentSessionId && selectedProject ) {
335+ const updatedMessages = [ ...messages ] ;
336+ updatedMessages [ updatedMessages . length - 1 ] = msg ;
337+ setCachedSession (
338+ selectedProject ,
339+ currentSessionId ,
340+ updatedMessages ,
341+ ) ;
342+ }
343+ } ,
344+ onSessionId : ( sessionId : string ) => {
345+ setCurrentSessionId ( sessionId ) ;
346+ // Cache the conversation when we get a session ID
347+ if ( selectedProject && messages . length > 0 ) {
348+ setCachedSession ( selectedProject , sessionId , messages ) ;
349+ }
350+ } ,
300351 shouldShowInitMessage : ( ) => ! hasShownInitMessage ,
301352 onInitMessageShown : ( ) => setHasShownInitMessage ( true ) ,
302353 get hasReceivedInit ( ) {
@@ -407,6 +458,16 @@ export function SplitView() {
407458 closePermissionRequest ( ) ;
408459 } , [ closePermissionRequest ] ) ;
409460
461+ // Handle scroll position changes to update cache
462+ const handleScrollPositionChange = useCallback (
463+ ( position : number ) => {
464+ if ( selectedProject && currentSessionId ) {
465+ updateScrollPosition ( selectedProject , currentSessionId , position ) ;
466+ }
467+ } ,
468+ [ selectedProject , currentSessionId , updateScrollPosition ] ,
469+ ) ;
470+
410471 // Create permission data for inline permission interface
411472 const permissionData = permissionRequest
412473 ? {
@@ -603,8 +664,15 @@ export function SplitView() {
603664 { getProjectDisplayName ( selectedProject ) }
604665 </ h1 >
605666 { currentSessionId && (
606- < div className = "text-sm text-slate-500 dark:text-slate-400 font-mono" >
607- Session: { currentSessionId . substring ( 0 , 8 ) } ...
667+ < div className = "text-sm text-slate-500 dark:text-slate-400 font-mono flex items-center gap-2" >
668+ < span >
669+ Session: { currentSessionId . substring ( 0 , 8 ) } ...
670+ </ span >
671+ { historyFromCache && (
672+ < span className = "text-xs bg-green-100 dark:bg-green-900/20 text-green-700 dark:text-green-400 px-2 py-0.5 rounded-full" >
673+ cached
674+ </ span >
675+ ) }
608676 </ div >
609677 ) }
610678 </ div >
@@ -648,7 +716,15 @@ export function SplitView() {
648716 </ div >
649717 ) : (
650718 < >
651- < ChatMessages messages = { messages } isLoading = { isLoading } />
719+ < ChatMessages
720+ messages = { messages }
721+ isLoading = { isLoading }
722+ restoreScrollPosition = { historyScrollPosition }
723+ onScrollPositionChange = { handleScrollPositionChange }
724+ shouldAutoScroll = {
725+ ! historyFromCache || historyScrollPosition === undefined
726+ }
727+ />
652728 < ChatInput
653729 input = { input }
654730 isLoading = { isLoading }
0 commit comments