@@ -2139,39 +2139,68 @@ export function ChatPage({
2139
2139
return ;
2140
2140
}
2141
2141
2142
+ // Immediately add files with uploading state for instant feedback
2143
+ const tempFileDescriptors : FileDescriptor [ ] = acceptedFiles . map ( ( file ) => ( {
2144
+ id : `temp-${ Date . now ( ) } -${ Math . random ( ) } ` ,
2145
+ name : file . name ,
2146
+ type : file . type . startsWith ( "image/" ) ? ChatFileType . IMAGE : ChatFileType . PLAIN_TEXT ,
2147
+ isUploading : true ,
2148
+ } ) ) ;
2149
+
2150
+ setCurrentMessageFiles ( ( prev ) => [ ...prev , ...tempFileDescriptors ] ) ;
2142
2151
updateChatState ( "uploading" , currentSessionId ( ) ) ;
2143
2152
2144
- for ( let file of acceptedFiles ) {
2145
- const formData = new FormData ( ) ;
2146
- formData . append ( "files" , file ) ;
2147
- const response : FileResponse [ ] = await uploadFile ( formData , null ) ;
2148
-
2149
- if ( response . length > 0 && response [ 0 ] !== undefined ) {
2150
- const uploadedFile = response [ 0 ] ;
2151
-
2152
- const newFileDescriptor : FileDescriptor = {
2153
- // Use file_id (storage ID) if available, otherwise fallback to DB id
2154
- // Ensure it's a string as FileDescriptor expects
2155
- id : uploadedFile . file_id
2156
- ? String ( uploadedFile . file_id )
2157
- : String ( uploadedFile . id ) ,
2158
- type : uploadedFile . chat_file_type
2159
- ? uploadedFile . chat_file_type
2160
- : ChatFileType . PLAIN_TEXT ,
2161
- name : uploadedFile . name ,
2162
- isUploading : false , // Mark as successfully uploaded
2163
- } ;
2153
+ try {
2154
+ const uploadedFileDescriptors : FileDescriptor [ ] = [ ] ;
2155
+
2156
+ for ( let file of acceptedFiles ) {
2157
+ const formData = new FormData ( ) ;
2158
+ formData . append ( "files" , file ) ;
2159
+ const response : FileResponse [ ] = await uploadFile ( formData , null ) ;
2160
+
2161
+ if ( response . length > 0 && response [ 0 ] !== undefined ) {
2162
+ const uploadedFile = response [ 0 ] ;
2163
+
2164
+ const newFileDescriptor : FileDescriptor = {
2165
+ // Use file_id (storage ID) if available, otherwise fallback to DB id
2166
+ // Ensure it's a string as FileDescriptor expects
2167
+ id : uploadedFile . file_id
2168
+ ? String ( uploadedFile . file_id )
2169
+ : String ( uploadedFile . id ) ,
2170
+ type : uploadedFile . chat_file_type
2171
+ ? uploadedFile . chat_file_type
2172
+ : ChatFileType . PLAIN_TEXT ,
2173
+ name : uploadedFile . name ,
2174
+ isUploading : false , // Mark as successfully uploaded
2175
+ } ;
2164
2176
2165
- setCurrentMessageFiles ( ( prev ) => [ ...prev , newFileDescriptor ] ) ;
2166
- } else {
2167
- setPopup ( {
2168
- type : "error" ,
2169
- message : "Failed to upload file" ,
2170
- } ) ;
2177
+ uploadedFileDescriptors . push ( newFileDescriptor ) ;
2178
+ } else {
2179
+ setPopup ( {
2180
+ type : "error" ,
2181
+ message : `Failed to upload file: ${ file . name } ` ,
2182
+ } ) ;
2183
+ }
2171
2184
}
2172
- }
2173
2185
2174
- updateChatState ( "input" , currentSessionId ( ) ) ;
2186
+ // Replace temp files with actual uploaded files
2187
+ setCurrentMessageFiles ( ( prev ) => {
2188
+ const filtered = prev . filter ( ( f ) => ! f . id . startsWith ( "temp-" ) ) ;
2189
+ return [ ...filtered , ...uploadedFileDescriptors ] ;
2190
+ } ) ;
2191
+
2192
+ } catch ( error ) {
2193
+ console . error ( "Error uploading files:" , error ) ;
2194
+ setPopup ( {
2195
+ type : "error" ,
2196
+ message : "Failed to upload files" ,
2197
+ } ) ;
2198
+
2199
+ // Remove temp files on error
2200
+ setCurrentMessageFiles ( ( prev ) => prev . filter ( ( f ) => ! f . id . startsWith ( "temp-" ) ) ) ;
2201
+ } finally {
2202
+ updateChatState ( "input" , currentSessionId ( ) ) ;
2203
+ }
2175
2204
} ;
2176
2205
2177
2206
// Used to maintain a "time out" for history sidebar so our existing refs can have time to process change
0 commit comments