@@ -34,8 +34,6 @@ import type { CollapseMode } from "@posthog/ui/features/sessions/components/new-
3434import { createIncrementalThreadGrouper } from "@posthog/ui/features/sessions/components/new-thread/incrementalThreadGrouping" ;
3535import { ToolCallGroupChip } from "@posthog/ui/features/sessions/components/new-thread/ToolCallGroupChip" ;
3636import { SessionFooter } from "@posthog/ui/features/sessions/components/SessionFooter" ;
37- import { MessageScrollbarRail } from "@posthog/ui/features/sessions/components/scrollbar-rail/MessageScrollbarRail" ;
38- import { useMessageRailMarkers } from "@posthog/ui/features/sessions/components/scrollbar-rail/useMessageRailMarkers" ;
3937import {
4038 type RenderItem ,
4139 SessionUpdateView ,
@@ -75,8 +73,8 @@ import {
7573 useCallback ,
7674 useEffect ,
7775 useMemo ,
78- useReducer ,
7976 useRef ,
77+ useState ,
8078} from "react" ;
8179import { useHotkeys } from "react-hotkeys-hook" ;
8280
@@ -108,57 +106,6 @@ export interface ConversationViewProps {
108106 promptRecallRef ?: RefObject < PromptRecallHandler | null > ;
109107}
110108
111- interface ConversationViewState {
112- showScrollButton : boolean ;
113- jumpPickerOpen : boolean ;
114- keyboardFocusedMessageId : string | null ;
115- scrollElements : {
116- scrollEl : HTMLElement | null ;
117- contentEl : HTMLElement | null ;
118- } ;
119- }
120-
121- type ConversationViewAction =
122- | { type : "set-show-scroll-button" ; value : boolean }
123- | { type : "set-jump-picker-open" ; value : boolean }
124- | { type : "set-keyboard-focused-message" ; value : string | null }
125- | {
126- type : "set-scroll-elements" ;
127- value : ConversationViewState [ "scrollElements" ] ;
128- } ;
129-
130- const INITIAL_CONVERSATION_VIEW_STATE : ConversationViewState = {
131- showScrollButton : false ,
132- jumpPickerOpen : false ,
133- keyboardFocusedMessageId : null ,
134- scrollElements : { scrollEl : null , contentEl : null } ,
135- } ;
136-
137- function conversationViewReducer (
138- state : ConversationViewState ,
139- action : ConversationViewAction ,
140- ) : ConversationViewState {
141- switch ( action . type ) {
142- case "set-show-scroll-button" :
143- return state . showScrollButton === action . value
144- ? state
145- : { ...state , showScrollButton : action . value } ;
146- case "set-jump-picker-open" :
147- return state . jumpPickerOpen === action . value
148- ? state
149- : { ...state , jumpPickerOpen : action . value } ;
150- case "set-keyboard-focused-message" :
151- return state . keyboardFocusedMessageId === action . value
152- ? state
153- : { ...state , keyboardFocusedMessageId : action . value } ;
154- case "set-scroll-elements" :
155- return state . scrollElements . scrollEl === action . value . scrollEl &&
156- state . scrollElements . contentEl === action . value . contentEl
157- ? state
158- : { ...state , scrollElements : action . value } ;
159- }
160- }
161-
162109export function ConversationView ( {
163110 events,
164111 isPromptPending,
@@ -187,10 +134,7 @@ export function ConversationView({
187134
188135 const listRef = useRef < VirtualizedListHandle > ( null ) ;
189136 const isAtBottomRef = useRef ( true ) ;
190- const [ viewState , dispatchViewState ] = useReducer (
191- conversationViewReducer ,
192- INITIAL_CONVERSATION_VIEW_STATE ,
193- ) ;
137+ const [ showScrollButton , setShowScrollButton ] = useState ( false ) ;
194138 const debugLogsCloudRuns = useSettingsStore ( ( s ) => s . debugLogsCloudRuns ) ;
195139 const showDebugLogs = debugLogsCloudRuns ;
196140
@@ -225,16 +169,14 @@ export function ConversationView({
225169 }
226170 const firstUserMessageId = firstUserMessageIdRef . current ;
227171
228- const initialItemIdsRef = useRef < Set < string > | null > ( null ) ;
229- if ( initialItemIdsRef . current === null ) {
230- initialItemIdsRef . current = new Set < string > ( ) ;
231- for ( const item of conversationItems ) {
232- if ( item . type === "user_message" ) {
233- initialItemIdsRef . current . add ( item . id ) ;
234- }
235- }
236- }
237- const initialItemIds = initialItemIdsRef . current ;
172+ const [ initialItemIds ] = useState (
173+ ( ) =>
174+ new Set (
175+ conversationItems
176+ . filter ( ( i ) => i . type === "user_message" )
177+ . map ( ( i ) => i . id ) ,
178+ ) ,
179+ ) ;
238180
239181 const pendingPermissions = usePendingPermissionsForTask ( taskId ?? "" ) ;
240182 const pendingPermissionsCount = pendingPermissions . size ;
@@ -293,10 +235,6 @@ export function ConversationView({
293235 id != null ? itemIdToRowIndexRef . current . get ( id ) : undefined ;
294236 listRef . current ?. scrollToIndex ( rowIdx ?? index ) ;
295237 } ,
296- // Search doesn't read scroll/content geometry, so these forward to the real
297- // handle purely to satisfy the (now-extended) VirtualizedListHandle shape.
298- getScrollElement : ( ) => listRef . current ?. getScrollElement ( ) ?? null ,
299- getContentElement : ( ) => listRef . current ?. getContentElement ( ) ?? null ,
300238 } ) ;
301239
302240 const search = useConversationSearch ( {
@@ -305,8 +243,10 @@ export function ConversationView({
305243 listRef : searchListRef ,
306244 } ) ;
307245
308- const { jumpPickerOpen, keyboardFocusedMessageId, scrollElements } =
309- viewState ;
246+ const [ jumpPickerOpen , setJumpPickerOpen ] = useState ( false ) ;
247+ const [ keyboardFocusedMessageId , setKeyboardFocusedMessageId ] = useState <
248+ string | null
249+ > ( null ) ;
310250
311251 const userMessages = useMemo ( ( ) => {
312252 const result : Array < { id : string ; index : number ; content : string } > = [ ] ;
@@ -352,22 +292,15 @@ export function ConversationView({
352292 if ( ! nextMessage ) return ;
353293
354294 useSettingsStore . getState ( ) . markHintLearned ( PROMPT_RECALL_HINT_KEY ) ;
355- dispatchViewState ( {
356- type : "set-keyboard-focused-message" ,
357- value : nextMessage . id ,
358- } ) ;
295+ setKeyboardFocusedMessageId ( nextMessage . id ) ;
359296 scrollToUserMessage ( nextMessage . id , nextMessage . index ) ;
360297 } ,
361298 [ keyboardFocusedMessageId , userMessages , scrollToUserMessage ] ,
362299 ) ;
363300
364301 useHotkeys (
365302 SHORTCUTS . MESSAGE_JUMP ,
366- ( ) =>
367- dispatchViewState ( {
368- type : "set-jump-picker-open" ,
369- value : ! jumpPickerOpen ,
370- } ) ,
303+ ( ) => setJumpPickerOpen ( ( prev ) => ! prev ) ,
371304 THREAD_HOTKEY_OPTIONS ,
372305 ) ;
373306
@@ -384,73 +317,34 @@ export function ConversationView({
384317 ) ;
385318
386319 const clearKeyboardFocus = useCallback ( ( ) => {
387- dispatchViewState ( { type : "set-keyboard-focused-message" , value : null } ) ;
320+ setKeyboardFocusedMessageId ( null ) ;
388321 } , [ ] ) ;
389322
390323 const handleJumpToMessage = useCallback (
391324 ( id : string ) => {
392325 const message = userMessages . find ( ( entry ) => entry . id === id ) ;
393326 if ( ! message ) return ;
394- dispatchViewState ( { type : "set-keyboard-focused-message" , value : id } ) ;
327+ setKeyboardFocusedMessageId ( id ) ;
395328 scrollToUserMessage ( id , message . index ) ;
396329 } ,
397330 [ userMessages , scrollToUserMessage ] ,
398331 ) ;
399332
400- // The scrollbar marker rail needs the VirtualizedList's scroll + content
401- // elements. Resolve them from the list ref callback so the rail renders as
402- // soon as the imperative handle is attached, without mount-time state setup.
403- const setListRef = useCallback ( ( handle : VirtualizedListHandle | null ) => {
404- listRef . current = handle ;
405- dispatchViewState ( {
406- type : "set-scroll-elements" ,
407- value : {
408- scrollEl : handle ?. getScrollElement ( ) ?? null ,
409- contentEl : handle ?. getContentElement ( ) ?? null ,
410- } ,
411- } ) ;
412- } , [ ] ) ;
413-
414- const railUserMessages = useMemo (
415- ( ) =>
416- userMessages . map ( ( m ) => ( {
417- id : m . id ,
418- content : m . content ,
419- index : m . index ,
420- } ) ) ,
421- [ userMessages ] ,
422- ) ;
423- const railMarkers = useMessageRailMarkers ( {
424- contentEl : scrollElements . contentEl ,
425- scrollEl : scrollElements . scrollEl ,
426- userMessages : railUserMessages ,
427- onJump : ( id ) => {
428- const message = userMessages . find ( ( entry ) => entry . id === id ) ;
429- if ( ! message ) return ;
430- dispatchViewState ( { type : "set-keyboard-focused-message" , value : id } ) ;
431- scrollToUserMessage ( id , message . index ) ;
432- } ,
433- activeId : keyboardFocusedMessageId ,
434- } ) ;
435-
436333 const handleScrollStateChange = useCallback ( ( isAtBottom : boolean ) => {
437334 isAtBottomRef . current = isAtBottom ;
438- dispatchViewState ( {
439- type : "set-show-scroll-button" ,
440- value : ! isAtBottom ,
441- } ) ;
335+ setShowScrollButton ( ! isAtBottom ) ;
442336 } , [ ] ) ;
443337
444338 const scrollToBottom = useCallback ( ( ) => {
445339 listRef . current ?. scrollToBottom ( ) ;
446- dispatchViewState ( { type : "set-show-scroll-button" , value : false } ) ;
340+ setShowScrollButton ( false ) ;
447341 } , [ ] ) ;
448342
449343 useEffect ( ( ) => {
450344 const handleVisibilityChange = ( ) => {
451345 if ( ! document . hidden && isAtBottomRef . current ) {
452346 listRef . current ?. scrollToBottom ( ) ;
453- dispatchViewState ( { type : "set-show-scroll-button" , value : false } ) ;
347+ setShowScrollButton ( false ) ;
454348 }
455349 } ;
456350
@@ -607,16 +501,14 @@ export function ConversationView({
607501
608502 < MessageJumpPicker
609503 open = { jumpPickerOpen }
610- onOpenChange = { ( open ) =>
611- dispatchViewState ( { type : "set-jump-picker-open" , value : open } )
612- }
504+ onOpenChange = { setJumpPickerOpen }
613505 items = { items }
614506 onJumpToMessage = { handleJumpToMessage }
615507 />
616508
617509 < SessionTaskIdProvider taskId = { taskId } >
618510 < VirtualizedList < ThreadRow >
619- ref = { setListRef }
511+ ref = { listRef }
620512 items = { threadRows }
621513 getItemKey = { getRowKey }
622514 renderItem = { renderRow }
@@ -629,8 +521,7 @@ export function ConversationView({
629521 scrollX = { scrollX }
630522 />
631523 </ SessionTaskIdProvider >
632- < MessageScrollbarRail markers = { railMarkers } />
633- { viewState . showScrollButton && (
524+ { showScrollButton && (
634525 < Box className = "absolute right-6 bottom-4 z-10" >
635526 < Tooltip >
636527 < TooltipTrigger
0 commit comments