mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
perf: clean tab drag passthrough cleanup from effect (#3710)
* perf: clean tab drag passthrough cleanup from effect * test: cover tab drag root cleanup wiring Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com> Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const setTabGroupSplitRatioMock = vi.fn()
|
||||
const recordFeatureInteractionMock = vi.fn()
|
||||
const setDragRootNodeMock = vi.fn()
|
||||
const useAppStoreMock = vi.fn(
|
||||
(
|
||||
selector: (state: {
|
||||
@@ -37,7 +38,8 @@ vi.mock('./useTabDragSplit', () => ({
|
||||
onDragMove: vi.fn(),
|
||||
onDragOver: vi.fn(),
|
||||
onDragStart: vi.fn(),
|
||||
sensors: []
|
||||
sensors: [],
|
||||
setDragRootNode: setDragRootNodeMock
|
||||
})
|
||||
}))
|
||||
|
||||
@@ -47,6 +49,7 @@ describe('TabGroupSplitLayout', () => {
|
||||
beforeEach(() => {
|
||||
setTabGroupSplitRatioMock.mockClear()
|
||||
recordFeatureInteractionMock.mockClear()
|
||||
setDragRootNodeMock.mockClear()
|
||||
useAppStoreMock.mockClear()
|
||||
})
|
||||
|
||||
@@ -101,6 +104,19 @@ describe('TabGroupSplitLayout', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('wires the split layout root to drag cleanup ownership', () => {
|
||||
const element = TabGroupSplitLayout({
|
||||
layout: { type: 'leaf', groupId: 'group-1' },
|
||||
worktreeId: 'wt-1',
|
||||
focusedGroupId: 'group-1',
|
||||
isWorktreeActive: true
|
||||
})
|
||||
|
||||
const layoutWrapper = element.props.children[0]
|
||||
|
||||
expect(layoutWrapper.props.ref).toBe(setDragRootNodeMock)
|
||||
})
|
||||
|
||||
it('only reserves top-right header space for the floating explorer toggle', () => {
|
||||
const element = TabGroupSplitLayout({
|
||||
layout: {
|
||||
|
||||
@@ -238,7 +238,10 @@ export default function TabGroupSplitLayout({
|
||||
state. The leftmost pane suppresses its own `border-l` via
|
||||
`touchesLeftEdge`, so the seam is always exactly 1px — previously
|
||||
both painted and stacked into a 2px bar below the drag strip. */}
|
||||
<div className="flex flex-col flex-1 min-w-0 min-h-0 overflow-hidden border-l border-border">
|
||||
<div
|
||||
ref={dragSplit.setDragRootNode}
|
||||
className="flex flex-col flex-1 min-w-0 min-h-0 overflow-hidden border-l border-border"
|
||||
>
|
||||
<div
|
||||
className="h-[4px] shrink-0 bg-card"
|
||||
style={{ WebkitAppRegion: 'drag' } as React.CSSProperties}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* oxlint-disable max-lines -- Why: the drag-split hook co-locates drop-zone
|
||||
* resolution, same-group reordering, and cross-group handoff so state
|
||||
* transitions stay readable in one place. */
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import {
|
||||
closestCenter,
|
||||
pointerWithin,
|
||||
@@ -204,6 +204,7 @@ export function useTabDragSplit({
|
||||
onDragOver: (event: DragOverEvent) => void
|
||||
onDragStart: (event: DragStartEvent) => void
|
||||
sensors: ReturnType<typeof useSensors>
|
||||
setDragRootNode: (node: HTMLDivElement | null) => void
|
||||
} {
|
||||
const reorderUnifiedTabs = useAppStore((state) => state.reorderUnifiedTabs)
|
||||
const dropUnifiedTab = useAppStore((state) => state.dropUnifiedTab)
|
||||
@@ -235,7 +236,17 @@ export function useTabDragSplit({
|
||||
releaseWebviewDragPassthroughRef.current = acquireWebviewsDragPassthrough()
|
||||
}, [releaseWebviewDragPassthrough])
|
||||
|
||||
useEffect(() => () => releaseWebviewDragPassthrough(), [releaseWebviewDragPassthrough])
|
||||
const setDragRootNode = useCallback(
|
||||
(node: HTMLDivElement | null): void => {
|
||||
if (node) {
|
||||
return
|
||||
}
|
||||
// Why: this root owns the dnd-kit gesture that temporarily puts browser
|
||||
// webviews in pointer passthrough, so root teardown must release it.
|
||||
releaseWebviewDragPassthrough()
|
||||
},
|
||||
[releaseWebviewDragPassthrough]
|
||||
)
|
||||
|
||||
const clearDragState = useCallback(() => {
|
||||
releaseWebviewDragPassthrough()
|
||||
@@ -465,6 +476,7 @@ export function useTabDragSplit({
|
||||
onDragMove,
|
||||
onDragOver,
|
||||
onDragStart,
|
||||
sensors
|
||||
sensors,
|
||||
setDragRootNode
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user