@@ -27,8 +27,13 @@ const Checks = ({ cl }: { cl: number }) => {
2727
2828 // Resizable panel state
2929 const containerRef = useRef < HTMLDivElement > ( null )
30+ const leftPanelRef = useRef < HTMLDivElement > ( null )
31+ const rightPanelRef = useRef < HTMLDivElement > ( null )
3032 const [ leftWidth , setLeftWidth ] = useState < number | null > ( null )
3133 const [ isDragging , setIsDragging ] = useState ( false )
34+ const scrollPositionRef = useRef < number > ( 0 )
35+ const logContainerRef = useRef < HTMLDivElement > ( null )
36+ const startWidthRef = useRef < number > ( 0 )
3237
3338 // Initialize left width based on container width
3439 useEffect ( ( ) => {
@@ -37,43 +42,110 @@ const Checks = ({ cl }: { cl: number }) => {
3742 }
3843 } , [ leftWidth ] )
3944
40- const handleMouseDown = useCallback ( ( e : React . MouseEvent ) => {
41- e . preventDefault ( )
42- setIsDragging ( true )
43- } , [ ] )
44-
45- const handleMouseMove = useCallback (
46- ( e : MouseEvent ) => {
47- if ( ! isDragging || ! containerRef . current ) return
45+ const handleMouseMove = useCallback ( ( e : MouseEvent ) => {
46+ if ( ! containerRef . current || ! leftPanelRef . current ) return
4847
49- const containerRect = containerRef . current . getBoundingClientRect ( )
50- const newLeftWidth = e . clientX - containerRect . left
51- const maxWidth = containerRect . width * MAX_LEFT_WIDTH_PERCENT
48+ // Directly manipulate DOM without triggering React re-render
49+ const containerRect = containerRef . current . getBoundingClientRect ( )
50+ const newLeftWidth = e . clientX - containerRect . left
51+ const maxWidth = containerRect . width * MAX_LEFT_WIDTH_PERCENT
52+ const clampedWidth = Math . max ( MIN_LEFT_WIDTH , Math . min ( newLeftWidth , maxWidth ) )
5253
53- setLeftWidth ( Math . max ( MIN_LEFT_WIDTH , Math . min ( newLeftWidth , maxWidth ) ) )
54- } ,
55- [ isDragging ]
56- )
54+ // Update DOM directly for smooth dragging
55+ leftPanelRef . current . style . width = `${ clampedWidth } px`
56+ } , [ ] )
5757
5858 const handleMouseUp = useCallback ( ( ) => {
59+ // Remove event listeners
60+ document . removeEventListener ( 'mousemove' , handleMouseMove )
61+ document . removeEventListener ( 'mouseup' , handleMouseUp )
62+ document . body . style . cursor = ''
63+ document . body . style . userSelect = ''
64+
65+ // Show right panel immediately using DOM
66+ if ( rightPanelRef . current ) {
67+ rightPanelRef . current . style . display = 'block'
68+ }
69+
70+ // Update React state only once when dragging ends
71+ if ( leftPanelRef . current ) {
72+ const finalWidth = leftPanelRef . current . offsetWidth
73+
74+ setLeftWidth ( finalWidth )
75+ }
5976 setIsDragging ( false )
77+ // eslint-disable-next-line react-hooks/exhaustive-deps
6078 } , [ ] )
6179
62- useEffect ( ( ) => {
63- if ( isDragging ) {
80+ const handleMouseDown = useCallback (
81+ ( e : React . MouseEvent ) => {
82+ e . preventDefault ( )
83+
84+ // Immediately hide right panel using DOM (no re-render)
85+ if ( rightPanelRef . current ) {
86+ rightPanelRef . current . style . display = 'none'
87+ }
88+
89+ // Save scroll position
90+ if ( logContainerRef . current ) {
91+ const lazyLogElement = logContainerRef . current . querySelector ( '.react-lazylog' )
92+
93+ if ( lazyLogElement ) {
94+ scrollPositionRef . current = lazyLogElement . scrollTop
95+ }
96+ }
97+
98+ // Save current width
99+ if ( leftPanelRef . current ) {
100+ startWidthRef . current = leftPanelRef . current . offsetWidth
101+ }
102+
103+ // Update state asynchronously (won't block dragging)
104+ requestAnimationFrame ( ( ) => {
105+ setIsDragging ( true )
106+ } )
107+
108+ // Add event listeners immediately
64109 document . addEventListener ( 'mousemove' , handleMouseMove )
65110 document . addEventListener ( 'mouseup' , handleMouseUp )
66111 document . body . style . cursor = 'col-resize'
67112 document . body . style . userSelect = 'none'
113+ } ,
114+ [ handleMouseMove , handleMouseUp ]
115+ )
116+
117+ useEffect ( ( ) => {
118+ if ( ! isDragging ) {
119+ // Restore scroll position after dragging ends
120+ if ( logContainerRef . current && scrollPositionRef . current > 0 ) {
121+ // Use requestAnimationFrame to ensure DOM is updated
122+ requestAnimationFrame ( ( ) => {
123+ const lazyLogElement = logContainerRef . current ?. querySelector ( '.react-lazylog' )
124+
125+ if ( lazyLogElement ) {
126+ lazyLogElement . scrollTop = scrollPositionRef . current
127+ }
128+ } )
129+ }
68130 }
131+ } , [ isDragging ] )
69132
70- return ( ) => {
71- document . removeEventListener ( 'mousemove' , handleMouseMove )
72- document . removeEventListener ( 'mouseup' , handleMouseUp )
73- document . body . style . cursor = ''
74- document . body . style . userSelect = ''
133+ // Reset scroll position when buildid changes
134+ useEffect ( ( ) => {
135+ // Clear saved scroll position when switching to a different build
136+ scrollPositionRef . current = 0
137+
138+ // Reset scroll to top for new build
139+ if ( logContainerRef . current ) {
140+ requestAnimationFrame ( ( ) => {
141+ const lazyLogElement = logContainerRef . current ?. querySelector ( '.react-lazylog' )
142+
143+ if ( lazyLogElement ) {
144+ lazyLogElement . scrollTop = 0
145+ }
146+ } )
75147 }
76- } , [ isDragging , handleMouseMove , handleMouseUp ] )
148+ } , [ buildid ] )
77149
78150 useEffect ( ( ) => {
79151 if ( ! tasks || tasks . length === 0 ) return
@@ -264,8 +336,8 @@ const Checks = ({ cl }: { cl: number }) => {
264336
265337 if ( status === 'success' && logsMap [ buildid ] && eventSourcesRef . current [ buildid ] ) {
266338 return (
267- < div className = 'h-full select-text [&_*]:select-text' >
268- < LazyLog extraLines = { 1 } text = { logsMap [ buildid ] } stream enableSearch caseInsensitive follow />
339+ < div ref = { logContainerRef } className = 'h-full select-text [&_*]:select-text' >
340+ < LazyLog key = { buildid } extraLines = { 1 } text = { logsMap [ buildid ] } stream enableSearch caseInsensitive />
269341 </ div >
270342 )
271343 }
@@ -288,6 +360,7 @@ const Checks = ({ cl }: { cl: number }) => {
288360 </ div >
289361 < div ref = { containerRef } className = 'flex' style = { { height : `calc(100vh - 164px)` } } >
290362 < div
363+ ref = { leftPanelRef }
291364 className = 'border-primary h-full overflow-y-auto border-r'
292365 style = { { width : leftWidth ?? '40%' , flexShrink : 0 } }
293366 >
@@ -301,7 +374,14 @@ const Checks = ({ cl }: { cl: number }) => {
301374 className = 'border-primary h-full w-1 flex-shrink-0 cursor-col-resize transition-colors hover:bg-blue-400'
302375 style = { { backgroundColor : isDragging ? '#60a5fa' : undefined } }
303376 />
304- < div className = 'flex-1' > { renderLogContent ( ) } </ div >
377+ < div ref = { rightPanelRef } className = 'flex-1' style = { { display : isDragging ? 'none' : 'block' } } >
378+ { renderLogContent ( ) }
379+ </ div >
380+ { isDragging && (
381+ < div className = 'text-tertiary flex flex-1 items-center justify-center' >
382+ < span > Resizing...</ span >
383+ </ div >
384+ ) }
305385 </ div >
306386 </ div >
307387 </ >
0 commit comments