Merge main (anchored-turn chat scrolling) into perf/switch-and-scroll
Main replaced the chat timeline scroll engine while this branch was in flight, which obsoletes two of its subareas and reshapes a third: - Chat timeline: main's LegendList-based MessageList/ChatContainer win; the activation-overscan staircase targeted the removed tanstack path (LegendList provides adaptive rendering natively) and is dropped along with its test. - Scroll shadows: main's hook-based masks stay (the virtualized list owns its scroll element — there is no wrapper to hand the styling to); the viewport-wrapper ScrollShadow rewrite, its index.css replacement, its test, and the call-site viewportClassName adaptations are reverted to main. The chat OverlayScrollbar keeps this branch's disableHorizontal. - OverlayScrollbar: the direct-DOM rewrite lands, but binding now follows the live container node instead of binding once per ref object — the chat scroller remounts on every session switch, and a bind-once contract left the scrollbar attached to a dead element. - Markdown renderer: the detached-DOM cache and warm-block fast path merge with main's block-commit reveal (enter cascade), streaming code highlighting, and gutter reservation; the per-block reconcile keeps both the decoration-refresh path and the reveal cascade.
This commit is contained in:
@@ -674,6 +674,7 @@ interface UIStore {
|
||||
eventStreamStatus: EventStreamStatus;
|
||||
eventStreamHint: string | null;
|
||||
showReasoningTraces: boolean;
|
||||
streamingAutoFollowEnabled: boolean;
|
||||
sessionRecapEnabled: boolean;
|
||||
sessionSuggestionEnabled: boolean;
|
||||
sessionGoalEnabled: boolean;
|
||||
@@ -859,6 +860,7 @@ interface UIStore {
|
||||
setSettingsRemoteInstancesSelectedId: (instanceId: string | null) => void;
|
||||
setEventStreamStatus: (status: EventStreamStatus, hint?: string | null) => void;
|
||||
setShowReasoningTraces: (value: boolean) => void;
|
||||
setStreamingAutoFollowEnabled: (value: boolean) => void;
|
||||
setSessionRecapEnabled: (value: boolean) => void;
|
||||
setSessionSuggestionEnabled: (value: boolean) => void;
|
||||
setSessionGoalEnabled: (value: boolean) => void;
|
||||
@@ -1027,6 +1029,7 @@ export const useUIStore = create<UIStore>()(
|
||||
eventStreamStatus: 'idle',
|
||||
eventStreamHint: null,
|
||||
showReasoningTraces: true,
|
||||
streamingAutoFollowEnabled: true,
|
||||
sessionRecapEnabled: true,
|
||||
sessionSuggestionEnabled: true,
|
||||
sessionGoalEnabled: true,
|
||||
@@ -1759,6 +1762,10 @@ export const useUIStore = create<UIStore>()(
|
||||
set({ showReasoningTraces: value });
|
||||
},
|
||||
|
||||
setStreamingAutoFollowEnabled: (value) => {
|
||||
set({ streamingAutoFollowEnabled: value });
|
||||
},
|
||||
|
||||
setSessionRecapEnabled: (value) => {
|
||||
set({ sessionRecapEnabled: value });
|
||||
},
|
||||
@@ -2639,6 +2646,7 @@ export const useUIStore = create<UIStore>()(
|
||||
isSessionCreateDialogOpen: state.isSessionCreateDialogOpen,
|
||||
// Note: isSettingsDialogOpen intentionally NOT persisted
|
||||
showReasoningTraces: state.showReasoningTraces,
|
||||
streamingAutoFollowEnabled: state.streamingAutoFollowEnabled,
|
||||
sessionRecapEnabled: state.sessionRecapEnabled,
|
||||
sessionSuggestionEnabled: state.sessionSuggestionEnabled,
|
||||
sessionGoalEnabled: state.sessionGoalEnabled,
|
||||
|
||||
Reference in New Issue
Block a user