mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 08:03:12 +00:00
perf(sidebar): share one natural-worktree-id scan and drop a redundant row-key join
The natural-worktree-id Set was spelled out four times — twice in the drag groups module, once in the drag session hook, once in the drag units module — each as rows.flatMap(row => cond ? [id] : []), which allocates a throwaway array per row. All four memoize on the same rows, so they recompute together. Share one loop-based helper. use-row-measurement also built a joined string of every row key purely as an effect dependency, alongside a Set memoized on the same input. A fresh Set always changes identity, so the string could never fire the effect on its own.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { PINNED_GROUP_KEY } from './worktree-list/grouping/group-keys'
|
||||
import { getNaturalWorktreeIds } from './natural-worktree-ids'
|
||||
|
||||
const item = (id: string, sectionKey: string) => ({
|
||||
type: 'item' as const,
|
||||
sectionKey,
|
||||
worktree: { id }
|
||||
})
|
||||
|
||||
describe('getNaturalWorktreeIds', () => {
|
||||
it('collects item rows outside the pinned section', () => {
|
||||
expect([...getNaturalWorktreeIds([item('a', 'group-1'), item('b', 'group-2')])]).toEqual([
|
||||
'a',
|
||||
'b'
|
||||
])
|
||||
})
|
||||
|
||||
it('excludes a pinned duplicate that also renders in its natural group', () => {
|
||||
const rows = [item('a', PINNED_GROUP_KEY), item('a', 'group-1'), item('b', PINNED_GROUP_KEY)]
|
||||
|
||||
const ids = getNaturalWorktreeIds(rows)
|
||||
|
||||
expect(ids.has('a')).toBe(true)
|
||||
expect(ids.has('b')).toBe(false)
|
||||
})
|
||||
|
||||
it('ignores every non-item row type', () => {
|
||||
const rows = [
|
||||
{ type: 'header', key: 'k' },
|
||||
{ type: 'host-header' },
|
||||
{ type: 'imported-worktrees-card' },
|
||||
{ type: 'new-external-worktrees-inbox' },
|
||||
{ type: 'pending-creation' },
|
||||
{ type: 'folder-workspace' },
|
||||
item('a', 'group-1')
|
||||
]
|
||||
|
||||
expect([...getNaturalWorktreeIds(rows)]).toEqual(['a'])
|
||||
})
|
||||
|
||||
it('returns an empty set for no rows', () => {
|
||||
expect(getNaturalWorktreeIds([]).size).toBe(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import { PINNED_GROUP_KEY } from './worktree-list/grouping/group-keys'
|
||||
|
||||
/** The row shape both drag models share: only `item` rows carry a worktree and a section. */
|
||||
type NaturalWorktreeIdRow = { type: string } & Partial<{
|
||||
sectionKey: string
|
||||
worktree: { id: string }
|
||||
}>
|
||||
|
||||
/**
|
||||
* Ids of worktrees rendered in their own group.
|
||||
*
|
||||
* Why: a pinned duplicate of a worktree that also renders in its natural group is not its own drag
|
||||
* slot. Shared by every drag model so the rule lives in one place, and built with a loop rather
|
||||
* than `flatMap` — that allocated a throwaway array per row, four times per row-model rebuild.
|
||||
*/
|
||||
export function getNaturalWorktreeIds(rows: readonly NaturalWorktreeIdRow[]): Set<string> {
|
||||
const ids = new Set<string>()
|
||||
for (const row of rows) {
|
||||
if (row.type === 'item' && row.sectionKey !== PINNED_GROUP_KEY && row.worktree) {
|
||||
ids.add(row.worktree.id)
|
||||
}
|
||||
}
|
||||
return ids
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { WorktreeDragGroup } from './worktree-manual-order'
|
||||
import { ALL_GROUP_KEY, PINNED_GROUP_KEY } from './worktree-list/grouping/group-keys'
|
||||
import { getNaturalWorktreeIds } from './natural-worktree-ids'
|
||||
|
||||
export type WorktreeDragUnitGroup = WorktreeDragGroup & {
|
||||
units: { worktreeId: string; worktreeIds: string[] }[]
|
||||
@@ -19,11 +20,7 @@ export function getWorktreeDragUnitGroups(
|
||||
): WorktreeDragUnitGroup[] {
|
||||
const groups: WorktreeDragUnitGroup[] = []
|
||||
let current: { key: string; units: WorktreeDragUnitGroup['units'] } | null = null
|
||||
const naturalWorktreeIds = new Set(
|
||||
rows.flatMap((row) =>
|
||||
row.type === 'item' && row.sectionKey !== PINNED_GROUP_KEY ? [row.worktree.id] : []
|
||||
)
|
||||
)
|
||||
const naturalWorktreeIds = getNaturalWorktreeIds(rows)
|
||||
|
||||
for (const row of rows) {
|
||||
if (row.type === 'header') {
|
||||
|
||||
@@ -1,16 +1,8 @@
|
||||
import { ALL_GROUP_KEY, PINNED_GROUP_KEY } from '../grouping/group-keys'
|
||||
import { getNaturalWorktreeIds } from '../../natural-worktree-ids'
|
||||
import type { HostSectionRow } from '../../host-section-rows'
|
||||
import type { WorktreeDragGroup } from '../../worktree-manual-order'
|
||||
|
||||
// A pinned duplicate of a worktree that also renders in its natural group is not its own drag slot.
|
||||
function getNaturalWorktreeIds(rows: readonly HostSectionRow[]): Set<string> {
|
||||
return new Set(
|
||||
rows.flatMap((row) =>
|
||||
row.type === 'item' && row.sectionKey !== PINNED_GROUP_KEY ? [row.worktree.id] : []
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export function getWorktreeDragGroups(rows: HostSectionRow[]): WorktreeDragGroup[] {
|
||||
const groups: WorktreeDragGroup[] = []
|
||||
let current: { key: string; ids: string[] } | null = null
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
} from '../../worktree-sidebar-drop-preview'
|
||||
import { getWorktreeDragGroups, getWorktreeDragIndexes } from './groups'
|
||||
import type { WorktreeItemRow } from '../listing/renderable-rows'
|
||||
import { getNaturalWorktreeIds } from '../../natural-worktree-ids'
|
||||
|
||||
export type WorktreeStatusDropRequest = {
|
||||
pointerY: number
|
||||
@@ -48,15 +49,7 @@ export function useWorktreeDragSession(args: {
|
||||
|
||||
const worktreeDragGroups = useMemo(() => getWorktreeDragGroups(rows), [rows])
|
||||
const worktreeDragUnitGroups = useMemo(() => getWorktreeDragUnitGroups(rows), [rows])
|
||||
const naturalDragWorktreeIds = useMemo(
|
||||
() =>
|
||||
new Set(
|
||||
rows.flatMap((row) =>
|
||||
row.type === 'item' && row.sectionKey !== PINNED_GROUP_KEY ? [row.worktree.id] : []
|
||||
)
|
||||
),
|
||||
[rows]
|
||||
)
|
||||
const naturalDragWorktreeIds = useMemo(() => getNaturalWorktreeIds(rows), [rows])
|
||||
const worktreeLineageDragRows = useMemo(
|
||||
() =>
|
||||
rows
|
||||
|
||||
@@ -51,10 +51,6 @@ export function useVirtualRowMeasurementSync(args: {
|
||||
const { virtualizer, isCurrentVirtualRowElement } = virtualization
|
||||
const prCacheLen = useAppStore((s) => countRecordKeysByReference(s.prCache))
|
||||
const issueCacheLen = useAppStore((s) => countRecordKeysByReference(s.issueCache))
|
||||
const renderRowKeySignature = useMemo(
|
||||
() => renderRows.map(getRenderRowKey).join('\n'),
|
||||
[renderRows]
|
||||
)
|
||||
const activeRenderRowKeys = useMemo(() => new Set(renderRows.map(getRenderRowKey)), [renderRows])
|
||||
const lineageRowRekeys = useMemo(() => buildLineageRowRekeyMap(renderRows), [renderRows])
|
||||
const totalSize = virtualizer.getTotalSize()
|
||||
@@ -100,14 +96,7 @@ export function useVirtualRowMeasurementSync(args: {
|
||||
measureMountedRows()
|
||||
const frameId = window.requestAnimationFrame(measureMountedRows)
|
||||
return () => window.cancelAnimationFrame(frameId)
|
||||
}, [
|
||||
activeRenderRowKeys,
|
||||
prCacheLen,
|
||||
issueCacheLen,
|
||||
measureMountedRows,
|
||||
renderRowKeySignature,
|
||||
virtualizer
|
||||
])
|
||||
}, [activeRenderRowKeys, prCacheLen, issueCacheLen, measureMountedRows, virtualizer])
|
||||
|
||||
useVirtualizedScrollAnchor({
|
||||
anchorRef: scrollAnchorRef,
|
||||
|
||||
Reference in New Issue
Block a user