mirror of
https://github.com/stablyai/orca
synced 2026-04-21 14:17:16 +00:00
refactor: extract scheduleSplitScrollRestore to stay under max-lines lint
Moves the two-phase scroll restoration schedule (double-rAF + 200ms timeout) into pane-split-scroll.ts so both pane-manager.ts and pane-tree-ops.ts stay under the 300-line oxlint limit.
This commit is contained in:
parent
0072d409e6
commit
fa88f76b3c
2 changed files with 44 additions and 35 deletions
|
|
@ -33,9 +33,9 @@ import {
|
|||
safeFit,
|
||||
fitAllPanesInternal,
|
||||
captureScrollState,
|
||||
restoreScrollState,
|
||||
refitPanesUnder
|
||||
} from './pane-tree-ops'
|
||||
import { scheduleSplitScrollRestore } from './pane-split-scroll'
|
||||
|
||||
export type { PaneManagerOptions, PaneStyleOptions, ManagedPane, DropZone }
|
||||
|
||||
|
|
@ -129,40 +129,12 @@ export class PaneManager {
|
|||
void this.options.onPaneCreated?.(this.toPublic(newPane))
|
||||
this.options.onLayoutChanged?.()
|
||||
|
||||
// Why: reparenting the container resets the viewport scroll position
|
||||
// immediately (browser clears scrollTop on DOM move). The early
|
||||
// double-rAF restore fires after the first fit settles (~2 frames /
|
||||
// ~32ms) to minimise the visible flash. The lock stays in place so
|
||||
// intermediate fits don't interfere. The later 200ms timeout is the
|
||||
// authoritative final restore that also clears the lock — it catches
|
||||
// any late async reflows (ResizeObserver 150ms debounce, WebGL
|
||||
// context-loss rAFs) that might shift the position after the early
|
||||
// restore.
|
||||
const existingPaneId = existing.id
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (this.destroyed) {
|
||||
return
|
||||
}
|
||||
const live = this.panes.get(existingPaneId)
|
||||
if (live?.pendingSplitScrollState) {
|
||||
restoreScrollState(live.terminal, scrollState)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.destroyed) {
|
||||
return
|
||||
}
|
||||
const live = this.panes.get(existingPaneId)
|
||||
if (!live) {
|
||||
return
|
||||
}
|
||||
live.pendingSplitScrollState = null
|
||||
restoreScrollState(live.terminal, scrollState)
|
||||
}, 200)
|
||||
scheduleSplitScrollRestore(
|
||||
(id) => this.panes.get(id),
|
||||
existing.id,
|
||||
scrollState,
|
||||
() => this.destroyed
|
||||
)
|
||||
|
||||
return this.toPublic(newPane)
|
||||
}
|
||||
|
|
|
|||
37
src/renderer/src/lib/pane-manager/pane-split-scroll.ts
Normal file
37
src/renderer/src/lib/pane-manager/pane-split-scroll.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
import type { ManagedPaneInternal, ScrollState } from './pane-manager-types'
|
||||
import { restoreScrollState } from './pane-tree-ops'
|
||||
|
||||
// Why: reparenting a terminal container during split resets the viewport
|
||||
// scroll position (browser clears scrollTop on DOM move). This schedules a
|
||||
// two-phase restore: an early double-rAF (~32ms) to minimise the visible
|
||||
// flash, plus a 200ms authoritative restore that also clears the scroll lock.
|
||||
export function scheduleSplitScrollRestore(
|
||||
getPaneById: (id: number) => ManagedPaneInternal | undefined,
|
||||
paneId: number,
|
||||
scrollState: ScrollState,
|
||||
isDestroyed: () => boolean
|
||||
): void {
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (isDestroyed()) {
|
||||
return
|
||||
}
|
||||
const live = getPaneById(paneId)
|
||||
if (live?.pendingSplitScrollState) {
|
||||
restoreScrollState(live.terminal, scrollState)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
setTimeout(() => {
|
||||
if (isDestroyed()) {
|
||||
return
|
||||
}
|
||||
const live = getPaneById(paneId)
|
||||
if (!live) {
|
||||
return
|
||||
}
|
||||
live.pendingSplitScrollState = null
|
||||
restoreScrollState(live.terminal, scrollState)
|
||||
}, 200)
|
||||
}
|
||||
Loading…
Reference in a new issue