@@ -149,6 +149,7 @@ public void Update(ChatTimelineView view)
149149 var appendedEntries = ! sessionChanged
150150 && view . EntryCount > previousEntryCount
151151 && ! prependedHistory ;
152+ var shouldFollowAppendedEntries = _isFollowing || IsAtBottom ;
152153
153154 _view = view ;
154155 _rowFactory . Update ( view . Rows ) ;
@@ -184,7 +185,7 @@ public void Update(ChatTimelineView view)
184185 QueueScrollToBottom ( view . SessionId , disableAnimation : true ) ;
185186 }
186187 }
187- else if ( appendedEntries && _isFollowing )
188+ else if ( appendedEntries && shouldFollowAppendedEntries )
188189 {
189190 QueueScrollToBottom ( view . SessionId , disableAnimation : false ) ;
190191 }
@@ -214,7 +215,9 @@ public void ScrollToEnd()
214215 ResetScrollToEndState ( ) ;
215216 _suppressAutoFollow = false ;
216217 ClearSessionOffset ( _view . SessionId ) ;
217- QueueScrollToBottom ( _view . SessionId , disableAnimation : false ) ;
218+ _isFollowing = true ;
219+ _scrollToLatestButton . Visibility = Visibility . Collapsed ;
220+ EnqueueOnView ( ( ) => ForceScrollToLatest ( _view . SessionId , remainingPasses : 4 , disableAnimation : false ) ) ;
218221 }
219222
220223 private void SyncRows ( IReadOnlyList < ChatTimelineRow > desiredRows )
@@ -417,6 +420,32 @@ private void ResetScrollToEndState()
417420 _scrollToEndState = ScrollToEndState . Idle ;
418421 }
419422
423+ private void ForceScrollToLatest ( string ? sessionId , int remainingPasses , bool disableAnimation )
424+ {
425+ if ( _rows . Count == 0 )
426+ return ;
427+
428+ var latest = _itemsRepeater . GetOrCreateElement ( _rows . Count - 1 ) ;
429+ latest . StartBringIntoView ( new BringIntoViewOptions
430+ {
431+ AnimationDesired = ! disableAnimation ,
432+ VerticalAlignmentRatio = 1.0 ,
433+ } ) ;
434+
435+ EnqueueOnView ( ( ) =>
436+ {
437+ var bottom = _scrollViewer . ScrollableHeight ;
438+ _scrollViewer . ChangeView ( null , bottom , null , disableAnimation ) ;
439+ _lastVerticalOffset = bottom ;
440+ _lastScrollableHeight = _scrollViewer . ScrollableHeight ;
441+ _isFollowing = true ;
442+ ClearSessionOffset ( sessionId ) ;
443+
444+ if ( remainingPasses > 0 )
445+ ForceScrollToLatest ( sessionId , remainingPasses - 1 , disableAnimation : true ) ;
446+ } ) ;
447+ }
448+
420449 private void QueuePreservePrependOffset ( string ? sessionId , double oldOffset , double oldScrollableHeight )
421450 {
422451 _pendingPrependSessionId = sessionId ;
0 commit comments