@@ -33,10 +33,10 @@ import {
33
33
import { useAuth } from '@/lib/auth' ;
34
34
import { PaperItem } from "@/lib/schema" ;
35
35
import ReferencePaperCards from '@/components/ReferencePaperCards' ;
36
- import { Skeleton } from '@/components/ui/skeleton' ;
37
36
import Link from 'next/link' ;
38
37
import { TopicBubbles } from '@/components/TopicBubbles' ;
39
38
import { AnimatedGradientText } from "@/components/magicui/animated-gradient-text" ;
39
+ import { ChatHistorySkeleton } from "@/components/ChatHistorySkeleton" ;
40
40
41
41
interface ChatRequestBody {
42
42
user_query : string ;
@@ -73,6 +73,7 @@ function UnderstandPageContent() {
73
73
const [ statusMessage , setStatusMessage ] = useState ( '' ) ;
74
74
75
75
const [ isConversationLoading , setIsConversationLoading ] = useState ( false ) ;
76
+ const [ isSessionLoading , setIsSessionLoading ] = useState ( true ) ;
76
77
77
78
const messagesEndRef = useRef < HTMLDivElement > ( null ) ;
78
79
const inputMessageRef = useRef < HTMLTextAreaElement > ( null ) ;
@@ -129,6 +130,7 @@ function UnderstandPageContent() {
129
130
toast . error ( "Failed to load conversation history." ) ;
130
131
} finally {
131
132
setIsConversationLoading ( false ) ;
133
+ setIsSessionLoading ( false ) ; // New line
132
134
}
133
135
} , [ ] ) ;
134
136
@@ -143,6 +145,7 @@ function UnderstandPageContent() {
143
145
setMessages ( [ ] ) ;
144
146
setConversationId ( null ) ;
145
147
setIsCentered ( true ) ;
148
+ setIsSessionLoading ( false ) ;
146
149
}
147
150
} , [ searchParams , user , fetchMessages , isStreaming ] ) ;
148
151
@@ -297,19 +300,24 @@ function UnderstandPageContent() {
297
300
298
301
try {
299
302
const parsedChunk = JSON . parse ( event . trim ( ) ) ;
300
- const chunkType = parsedChunk . type ;
301
- const chunkContent = parsedChunk . content ;
302
-
303
- if ( chunkType === 'content' ) {
304
- accumulatedContent += chunkContent ;
305
- setStreamingChunks ( prev => [ ...prev , chunkContent ] ) ;
306
- } else if ( chunkType === 'references' ) {
307
- references = chunkContent ;
308
- setStreamingReferences ( chunkContent ) ;
309
- } else if ( chunkType === 'status' ) {
310
- setStatusMessage ( chunkContent ) ;
311
- } else {
312
- console . warn ( `Unknown chunk type: ${ chunkType } ` ) ;
303
+
304
+ if ( parsedChunk && typeof parsedChunk === 'object' && 'type' in parsedChunk ) {
305
+ const chunkType = parsedChunk . type ;
306
+ const chunkContent = parsedChunk . content ;
307
+
308
+ if ( chunkType === 'content' ) {
309
+ accumulatedContent += chunkContent ;
310
+ setStreamingChunks ( prev => [ ...prev , chunkContent ] ) ;
311
+ } else if ( chunkType === 'references' ) {
312
+ references = chunkContent ;
313
+ setStreamingReferences ( chunkContent ) ;
314
+ } else if ( chunkType === 'status' ) {
315
+ setStatusMessage ( chunkContent ) ;
316
+ } else {
317
+ console . warn ( `Unknown chunk type: ${ chunkType } ` ) ;
318
+ }
319
+ } else if ( parsedChunk ) {
320
+ console . warn ( 'Received unexpected chunk:' , parsedChunk ) ;
313
321
}
314
322
} catch ( error ) {
315
323
console . error ( 'Error processing event:' , error , 'Raw event:' , event ) ;
@@ -351,6 +359,22 @@ function UnderstandPageContent() {
351
359
setCurrentMessage ( e . target . value ) ;
352
360
} , [ ] ) ;
353
361
362
+ useEffect ( ( ) => {
363
+ const focusInput = ( ) => {
364
+ if ( inputMessageRef . current &&
365
+ ! isStreaming &&
366
+ papers . length > 0 &&
367
+ ! chatCreditLimitReached ) {
368
+ // Small delay to ensure DOM is ready
369
+ setTimeout ( ( ) => {
370
+ inputMessageRef . current ?. focus ( ) ;
371
+ } , 100 ) ;
372
+ }
373
+ } ;
374
+
375
+ focusInput ( ) ;
376
+ } , [ papers . length , isStreaming , chatCreditLimitReached ] ) ; // Dependencies that affect focusability
377
+
354
378
const memoizedMessages = useMemo ( ( ) => {
355
379
return messages . map ( ( msg , index ) => (
356
380
< div
@@ -417,7 +441,7 @@ function UnderstandPageContent() {
417
441
</ div >
418
442
</ div >
419
443
) ) ;
420
- } , [ messages , user , handleCitationClick ] ) ;
444
+ } , [ messages , user , handleCitationClick , papers ] ) ;
421
445
422
446
const [ isCentered , setIsCentered ] = useState ( true ) ;
423
447
@@ -435,23 +459,23 @@ function UnderstandPageContent() {
435
459
< div className = "flex flex-col w-full h-[calc(100vh-64px)]" >
436
460
< div className = { `${ isCentered ? 'flex-0' : 'flex-1' } w-full overflow-y-auto` } ref = { messagesContainerRef } >
437
461
< div className = "mx-auto max-w-3xl space-y-4 p-4 w-full" >
438
- { papers . length === 0 && messages . length === 0 && ! authLoading && (
439
- < div className = "text-center p-8" >
440
- < h2 className = "text-xl font-semibold mb-2" > No Papers Found</ h2 >
441
- < p className = "text-gray-600 dark:text-gray-400 mb-4" >
442
- You need to have at least one paper indexed to ask questions.
443
- </ p >
444
- < Button onClick = { ( ) => window . location . href = '/' } > Index a Paper</ Button >
445
- </ div >
446
- ) }
447
- { isConversationLoading && (
448
- < div className = "space-y-4" >
449
- < Skeleton className = "h-16 w-full" />
450
- < Skeleton className = "h-16 w-full" />
451
- < Skeleton className = "h-16 w-full" />
452
- </ div >
462
+ { isSessionLoading ? (
463
+ < ChatHistorySkeleton />
464
+ ) : (
465
+ < >
466
+ { papers . length === 0 && messages . length === 0 && ! authLoading && (
467
+ < div className = "text-center p-8" >
468
+ < h2 className = "text-xl font-semibold mb-2" > No Papers Found</ h2 >
469
+ < p className = "text-gray-600 dark:text-gray-400 mb-4" >
470
+ You need to have at least one paper indexed to ask questions.
471
+ </ p >
472
+ < Button onClick = { ( ) => window . location . href = '/' } > Index a Paper</ Button >
473
+ </ div >
474
+ ) }
475
+
476
+ { messages . length > 0 && memoizedMessages }
477
+ </ >
453
478
) }
454
- { messages . length > 0 && memoizedMessages }
455
479
{
456
480
isStreaming && streamingChunks . length > 0 && (
457
481
< div className = "relative group prose dark:prose-invert !max-w-full rounded-lg w-full text-primary dark:text-primary-foreground" >
@@ -559,9 +583,9 @@ function UnderstandPageContent() {
559
583
) }
560
584
</ form >
561
585
{
562
- isCentered && ! currentMessage && (
586
+ isCentered && (
563
587
< div className = "absolute bottom-0 left-0 w-full" >
564
- < TopicBubbles />
588
+ < TopicBubbles isVisible = { currentMessage . length === 0 } />
565
589
</ div >
566
590
)
567
591
}
0 commit comments