1
- import React , { useState } from "react" ;
1
+ import React , { useState , useEffect } from "react" ;
2
2
import {
3
3
useExternalStoreRuntime ,
4
4
ThreadMessageLike ,
9
9
import { useThreadContext , MyMessage , ThreadProvider } from "./context/ThreadContext" ;
10
10
import { Thread } from "./assistant-ui/thread" ;
11
11
import { ThreadList } from "./assistant-ui/thread-list" ;
12
+ import { chatStorage , ThreadData as StoredThreadData } from "../utils/chatStorage" ;
12
13
13
14
// Define thread data interfaces to match ExternalStoreThreadData requirements
14
15
interface RegularThreadData {
@@ -44,6 +45,108 @@ function ChatWithThreads() {
44
45
const [ threadList , setThreadList ] = useState < ThreadData [ ] > ( [
45
46
{ threadId : "default" , status : "regular" , title : "New Chat" } as RegularThreadData ,
46
47
] ) ;
48
+ const [ isInitialized , setIsInitialized ] = useState ( false ) ;
49
+
50
+ // Load data from persistent storage on component mount
51
+ useEffect ( ( ) => {
52
+ const loadData = async ( ) => {
53
+ try {
54
+ await chatStorage . initialize ( ) ;
55
+
56
+ // Load all threads from storage
57
+ const storedThreads = await chatStorage . getAllThreads ( ) ;
58
+ if ( storedThreads . length > 0 ) {
59
+ // Convert stored threads to UI format
60
+ const uiThreads : ThreadData [ ] = storedThreads . map ( stored => ( {
61
+ threadId : stored . threadId ,
62
+ status : stored . status as "regular" | "archived" ,
63
+ title : stored . title ,
64
+ } ) ) ;
65
+ setThreadList ( uiThreads ) ;
66
+
67
+ // Load messages for each thread
68
+ const threadMessages = new Map < string , MyMessage [ ] > ( ) ;
69
+ for ( const thread of storedThreads ) {
70
+ const messages = await chatStorage . getMessages ( thread . threadId ) ;
71
+ threadMessages . set ( thread . threadId , messages ) ;
72
+ }
73
+
74
+ // Ensure default thread exists
75
+ if ( ! threadMessages . has ( "default" ) ) {
76
+ threadMessages . set ( "default" , [ ] ) ;
77
+ }
78
+
79
+ setThreads ( threadMessages ) ;
80
+
81
+ // Set current thread to the most recently updated one
82
+ const latestThread = storedThreads . sort ( ( a , b ) => b . updatedAt - a . updatedAt ) [ 0 ] ;
83
+ if ( latestThread ) {
84
+ setCurrentThreadId ( latestThread . threadId ) ;
85
+ }
86
+ } else {
87
+ // Initialize with default thread
88
+ const defaultThread : StoredThreadData = {
89
+ threadId : "default" ,
90
+ status : "regular" ,
91
+ title : "New Chat" ,
92
+ createdAt : Date . now ( ) ,
93
+ updatedAt : Date . now ( ) ,
94
+ } ;
95
+ await chatStorage . saveThread ( defaultThread ) ;
96
+ }
97
+
98
+ setIsInitialized ( true ) ;
99
+ } catch ( error ) {
100
+ console . error ( "Failed to load chat data:" , error ) ;
101
+ setIsInitialized ( true ) ; // Continue with default state
102
+ }
103
+ } ;
104
+
105
+ loadData ( ) ;
106
+ } , [ setCurrentThreadId , setThreads ] ) ;
107
+
108
+ // Save thread data whenever threadList changes
109
+ useEffect ( ( ) => {
110
+ if ( ! isInitialized ) return ;
111
+
112
+ const saveThreads = async ( ) => {
113
+ try {
114
+ for ( const thread of threadList ) {
115
+ const storedThread : StoredThreadData = {
116
+ threadId : thread . threadId ,
117
+ status : thread . status ,
118
+ title : thread . title ,
119
+ createdAt : Date . now ( ) , // In real app, preserve original createdAt
120
+ updatedAt : Date . now ( ) ,
121
+ } ;
122
+ await chatStorage . saveThread ( storedThread ) ;
123
+ }
124
+ } catch ( error ) {
125
+ console . error ( "Failed to save threads:" , error ) ;
126
+ }
127
+ } ;
128
+
129
+ saveThreads ( ) ;
130
+ } , [ threadList , isInitialized ] ) ;
131
+
132
+ // Save messages whenever threads change
133
+ useEffect ( ( ) => {
134
+ if ( ! isInitialized ) return ;
135
+
136
+ const saveMessages = async ( ) => {
137
+ try {
138
+ for ( const [ threadId , messages ] of threads . entries ( ) ) {
139
+ await chatStorage . saveMessages ( messages , threadId ) ;
140
+ }
141
+ } catch ( error ) {
142
+ console . error ( "Failed to save messages:" , error ) ;
143
+ }
144
+ } ;
145
+
146
+ saveMessages ( ) ;
147
+ } , [ threads , isInitialized ] ) ;
148
+
149
+
47
150
48
151
// Get messages for current thread
49
152
const currentMessages = threads . get ( currentThreadId ) || [ ] ;
@@ -165,18 +268,31 @@ function ChatWithThreads() {
165
268
threads : threadList . filter ( ( t ) : t is RegularThreadData => t . status === "regular" ) ,
166
269
archivedThreads : threadList . filter ( ( t ) : t is ArchivedThreadData => t . status === "archived" ) ,
167
270
168
- onSwitchToNewThread : ( ) => {
271
+ onSwitchToNewThread : async ( ) => {
169
272
const newId = `thread-${ Date . now ( ) } ` ;
170
- setThreadList ( ( prev ) => [
171
- ...prev ,
172
- {
273
+ const newThread : RegularThreadData = {
274
+ threadId : newId ,
275
+ status : "regular" ,
276
+ title : "New Chat" ,
277
+ } ;
278
+
279
+ setThreadList ( ( prev ) => [ ...prev , newThread ] ) ;
280
+ setThreads ( ( prev ) => new Map ( prev ) . set ( newId , [ ] ) ) ;
281
+ setCurrentThreadId ( newId ) ;
282
+
283
+ // Save new thread to storage
284
+ try {
285
+ const storedThread : StoredThreadData = {
173
286
threadId : newId ,
174
287
status : "regular" ,
175
288
title : "New Chat" ,
176
- } as RegularThreadData ,
177
- ] ) ;
178
- setThreads ( ( prev ) => new Map ( prev ) . set ( newId , [ ] ) ) ;
179
- setCurrentThreadId ( newId ) ;
289
+ createdAt : Date . now ( ) ,
290
+ updatedAt : Date . now ( ) ,
291
+ } ;
292
+ await chatStorage . saveThread ( storedThread ) ;
293
+ } catch ( error ) {
294
+ console . error ( "Failed to save new thread:" , error ) ;
295
+ }
180
296
} ,
181
297
182
298
onSwitchToThread : ( threadId ) => {
@@ -199,7 +315,7 @@ function ChatWithThreads() {
199
315
) ;
200
316
} ,
201
317
202
- onDelete : ( threadId ) => {
318
+ onDelete : async ( threadId ) => {
203
319
setThreadList ( ( prev ) => prev . filter ( ( t ) => t . threadId !== threadId ) ) ;
204
320
setThreads ( ( prev ) => {
205
321
const next = new Map ( prev ) ;
@@ -209,6 +325,13 @@ function ChatWithThreads() {
209
325
if ( currentThreadId === threadId ) {
210
326
setCurrentThreadId ( "default" ) ;
211
327
}
328
+
329
+ // Delete thread from storage
330
+ try {
331
+ await chatStorage . deleteThread ( threadId ) ;
332
+ } catch ( error ) {
333
+ console . error ( "Failed to delete thread from storage:" , error ) ;
334
+ }
212
335
} ,
213
336
} ;
214
337
0 commit comments