@@ -8,34 +8,38 @@ const DELETE_MS = 30;
88const HOLD_MS = 1800 ;
99const GAP_MS = 300 ;
1010
11+ // Count the in-progress second so the timer reads 1s the moment it appears, not 0s
12+ const secondsSince = ( start : number ) => Math . max ( 1 , Math . ceil ( ( Date . now ( ) - start ) / 1000 ) ) ;
13+
1114interface StatusTypewriterProps {
1215 streamStartTime ?: number ;
1316}
1417
1518export const StatusTypewriter = memo ( function StatusTypewriter ( {
1619 streamStartTime,
1720} : StatusTypewriterProps ) {
18- const [ elapsed , setElapsed ] = useState ( 0 ) ;
19- const [ text , setText ] = useState ( '' ) ;
20- const [ deleting , setDeleting ] = useState ( false ) ;
21- const [ verbIndex , setVerbIndex ] = useState ( 0 ) ;
2221 // Seed from the active stream's start so the timer survives chat switches —
2322 // the indicator sits inside the chat-keyed scroller and remounts on switch.
2423 // Fall back to mount time when loading begins before the stream exists yet.
2524 const startTime = useRef ( streamStartTime ?? Date . now ( ) ) ;
25+ const [ elapsed , setElapsed ] = useState ( ( ) => secondsSince ( startTime . current ) ) ;
26+ const [ text , setText ] = useState ( '' ) ;
27+ const [ deleting , setDeleting ] = useState ( false ) ;
28+ const [ verbIndex , setVerbIndex ] = useState ( 0 ) ;
2629 // Adopt the real stream start when it arrives after mount instead of remounting
2730 // via key — a remount would restart the typewriter and replay the fade-in.
31+ // A cleared prop means a new turn is loading (queued message, stop-then-resend) —
32+ // restart the clock instead of carrying the old stream's elapsed forward.
2833 const prevStreamStart = useRef ( streamStartTime ) ;
2934 if ( prevStreamStart . current !== streamStartTime ) {
3035 prevStreamStart . current = streamStartTime ;
31- if ( streamStartTime != null ) {
32- startTime . current = streamStartTime ;
33- }
36+ startTime . current = streamStartTime ?? Date . now ( ) ;
37+ setElapsed ( secondsSince ( startTime . current ) ) ;
3438 }
3539
3640 useMountEffect ( ( ) => {
3741 const interval = setInterval ( ( ) => {
38- setElapsed ( Math . floor ( ( Date . now ( ) - startTime . current ) / 1000 ) ) ;
42+ setElapsed ( secondsSince ( startTime . current ) ) ;
3943 } , 1000 ) ;
4044
4145 return ( ) => clearInterval ( interval ) ;
@@ -88,11 +92,9 @@ export const StatusTypewriter = memo(function StatusTypewriter({
8892 />
8993 </ span >
9094
91- { elapsed > 0 && (
92- < span className = "text-xs text-text-quaternary dark:text-text-dark-quaternary" >
93- · { elapsed } s
94- </ span >
95- ) }
95+ < span className = "text-xs text-text-quaternary dark:text-text-dark-quaternary" >
96+ · { elapsed } s
97+ </ span >
9698 </ div >
9799 </ div >
98100 ) ;
0 commit comments