mirror of
https://github.com/stablyai/orca.git
synced 2026-10-24 16:03:45 +00:00
refactor(sidebar): group worktree-list files by domain
Follow-up to #14465 / #14467. Keep the landed extract and reorganize the flat worktree-list dump into drag/, headers/, reveal/, rows/, scroll/, and viewport/. Fold tiny modules into their owners, move leftover sidebar-root files into the module, and retarget imports and source-path tests. Layout-only; no behavior change.
This commit is contained in:
@@ -235,8 +235,8 @@ inline src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx
|
||||
inline src/renderer/src/components/sidebar/WorktreeContextMenu.tsx
|
||||
inline src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts
|
||||
inline src/renderer/src/components/sidebar/use-workspace-kanban-area-selection.ts
|
||||
inline src/renderer/src/components/sidebar/worktree-list-groups.test.ts
|
||||
inline src/renderer/src/components/sidebar/worktree-list-groups.ts
|
||||
inline src/renderer/src/components/sidebar/worktree-list/rows/groups.test.ts
|
||||
inline src/renderer/src/components/sidebar/worktree-list/rows/groups.ts
|
||||
inline src/renderer/src/components/stats/usage-overview-model.ts
|
||||
inline src/renderer/src/components/status-bar/ResourceUsageStatusSegment.tsx
|
||||
inline src/renderer/src/components/status-bar/StatusBar.tsx
|
||||
|
||||
@@ -4334,9 +4334,9 @@
|
||||
"oracle": "Start with Active Server=Local desktop, connect and navigate Windows 2, then reveal a local terminal and assert it succeeds while the persisted preference remains local before and after restart. Repeat transient routing and selected-runtime Add Project operations with exact-ID host decoys and completion reordering. Separately pair the real web client to an isolated headed host, then make its sole still-listed runtime compatibility-blocked and unavailable. Require a null authoritative selection, a disabled host option, and disabled Browse, Clone, and Create actions with no local fallback. Repeat against headless serve. Run the byte-identical selector/action contract on latest main, candidate, and candidate with the eligibility seam disabled.",
|
||||
"commands": [
|
||||
"pnpm exec vitest run --config config/vitest.config.ts src/main/ipc/settings.test.ts src/main/ipc/runtime-environments.test.ts src/renderer/src/store/slices/settings.test.ts src/renderer/src/store/slices/browser.test.ts src/renderer/src/components/settings/browser-session-host-selection.test.ts src/renderer/src/components/settings/RuntimeEnvironmentsPane.test.ts src/renderer/src/components/status-bar/SshStatusSegment.test.ts src/renderer/src/components/sidebar/use-add-repo-host-selection.test.ts src/renderer/src/hooks/useIpcEvents.test.ts src/renderer/src/web/web-preload-api.test.ts --maxWorkers=1",
|
||||
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list-host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts --maxWorkers=1",
|
||||
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list/viewport/host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts --maxWorkers=1",
|
||||
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/use-add-repo-host-selection.test.ts src/renderer/src/components/sidebar/add-repo-browse-authority.test.ts src/renderer/src/components/sidebar/AddRepoDialogStepContent.test.tsx src/renderer/src/components/sidebar/AddRepoStartSteps.test.tsx src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/runtime/runtime-server-directory-browser.test.ts src/renderer/src/store/slices/repos-paired-runtime-add.test.ts --maxWorkers=1",
|
||||
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list-host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts src/renderer/src/runtime/web-runtime-session.test.ts --maxWorkers=1",
|
||||
"pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list/viewport/host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts src/renderer/src/runtime/web-runtime-session.test.ts --maxWorkers=1",
|
||||
"pnpm run ensure:electron-runtime && npx playwright test tests/e2e/pr11346-selected-runtime-add.spec.ts --config tests/playwright.config.ts --project electron-headful --workers=1 --reporter=line",
|
||||
"pnpm run ensure:electron-runtime && npx playwright test tests/e2e/pr11346-selected-runtime-add.spec.ts --config tests/playwright.config.ts --project electron-headless --workers=1 --reporter=line",
|
||||
"SKIP_BUILD=1 ORCA_E2E_WEB_CLIENT=1 ORCA_E2E_FORCE_HEADFUL=1 pnpm exec playwright test tests/e2e/paired-web-add-project-unavailable-host.spec.ts --config tests/playwright.config.ts --project electron-headful --workers=1 --reporter=line",
|
||||
@@ -4366,7 +4366,7 @@
|
||||
"src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts",
|
||||
"src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts",
|
||||
"src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts",
|
||||
"src/renderer/src/components/sidebar/worktree-list-host-filtering.test.ts",
|
||||
"src/renderer/src/components/sidebar/worktree-list/viewport/host-filtering.test.ts",
|
||||
"src/renderer/src/lib/resolved-worktree-execution-host.test.ts",
|
||||
"src/renderer/src/lib/worktree-runtime-owner.test.ts",
|
||||
"src/renderer/src/store/selectors.test.ts",
|
||||
@@ -4559,7 +4559,7 @@
|
||||
"date": "2026-07-30",
|
||||
"runner": "local",
|
||||
"platform": "macos",
|
||||
"command": "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list-host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts --maxWorkers=1",
|
||||
"command": "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list/viewport/host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts --maxWorkers=1",
|
||||
"result": "passed",
|
||||
"durationSeconds": 8.77,
|
||||
"summary": "Nineteen files and 386 tests passed after rebasing onto 94cf2f1422f30fc309cb47c5e864a831d516fa8b, including exact-ID repo/worktree/group/folder host identity in both catalog orders, fail-closed active-repo selection when a runtime row is unavailable, selected runtime and SSH owner capture through final Add/Clone/Create/folder activation, direct-SSH authoritative pruning, reversed catalog responses, reconnect generation fencing, local-after-runtime isolation, and missing-catalog worktree routing."
|
||||
@@ -4586,7 +4586,7 @@
|
||||
"date": "2026-07-31",
|
||||
"runner": "local",
|
||||
"platform": "macos",
|
||||
"command": "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list-host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts src/renderer/src/runtime/web-runtime-session.test.ts --maxWorkers=1",
|
||||
"command": "pnpm exec vitest run --config config/vitest.config.ts src/renderer/src/components/sidebar/AddProjectFromFolderDialog.test.tsx src/renderer/src/components/sidebar/NonGitFolderDialog.test.tsx src/renderer/src/components/sidebar/AddRepoDialog.default-checkout.test.ts src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts src/renderer/src/components/sidebar/project-added-default-checkout.test.ts src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.test.ts src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts src/renderer/src/components/sidebar/useAddRepoCloneFlow.test.ts src/renderer/src/components/sidebar/useCreateRepo.default-checkout.test.ts src/renderer/src/components/sidebar/worktree-list/viewport/host-filtering.test.ts src/renderer/src/lib/resolved-worktree-execution-host.test.ts src/renderer/src/lib/worktree-runtime-owner.test.ts src/renderer/src/store/selectors.test.ts src/renderer/src/store/slices/repos-all-hosts-folder-workspaces.test.ts src/renderer/src/store/slices/repos-project-groups.test.ts src/renderer/src/store/slices/repos-selected-owner-routing.test.ts src/renderer/src/store/slices/selected-host-active-workspace-identity.test.ts src/renderer/src/store/slices/worktrees.test.ts src/renderer/src/runtime/web-runtime-session.test.ts --maxWorkers=1",
|
||||
"result": "passed",
|
||||
"durationSeconds": 7.1,
|
||||
"summary": "Twenty files and 430 tests passed on current main integration, including explicit runtime-owner preservation for terminal and browser session activation."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Worktree } from './workspace-list-sections'
|
||||
|
||||
// Why: matches desktop's PR_GROUP_META naming from worktree-list-groups.ts.
|
||||
// Why: matches desktop's PR_GROUP_META naming from worktree-list/rows/groups.ts.
|
||||
// no PR/draft/unknown -> "In Progress", open -> "In Review", merged -> "Done", closed -> "Closed"
|
||||
export type PRGroupKey = 'done' | 'in-review' | 'in-progress' | 'closed'
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ import { getPaletteHostBadge, type PaletteHostBadge } from '@/components/cmd-j/p
|
||||
import PaletteFilterMenu from '@/components/cmd-j/PaletteFilterMenu'
|
||||
import PaletteFilterChips from '@/components/cmd-j/PaletteFilterChips'
|
||||
import { buildPaletteFilterModel } from '@/components/cmd-j/palette-filter-options'
|
||||
import { getProjectGroupExecutionHostIdForRows } from '@/components/sidebar/worktree-list-host-filtering'
|
||||
import { getProjectGroupExecutionHostIdForRows } from '@/components/sidebar/worktree-list/viewport/host-filtering'
|
||||
import {
|
||||
buildPaletteFilterPredicate,
|
||||
EMPTY_PALETTE_FILTER,
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import {
|
||||
getProjectHeaderRevealTarget,
|
||||
type ProjectGroupingModel
|
||||
} from '../sidebar/worktree-list-groups'
|
||||
} from '../sidebar/worktree-list/rows/groups'
|
||||
import type { SidebarHostOption } from '../sidebar/sidebar-host-options'
|
||||
import { buildPaletteFilterOptionSearchText } from './palette-filter-option-list'
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
getProjectGroupHeaderKey,
|
||||
getProjectHeaderRevealTarget,
|
||||
type ProjectGroupingModel
|
||||
} from '../sidebar/worktree-list-groups'
|
||||
} from '../sidebar/worktree-list/rows/groups'
|
||||
|
||||
export type CmdJProjectGroupResult = {
|
||||
id: string
|
||||
|
||||
@@ -31,6 +31,9 @@ const HOVER_REVEAL_FILES = [
|
||||
resolve(__dirname, 'sidebar/WorkspaceKanbanStatusLane.tsx'),
|
||||
resolve(__dirname, 'sidebar/WorktreeCardPorts.tsx'),
|
||||
resolve(__dirname, 'sidebar/WorktreeList.tsx'),
|
||||
resolve(__dirname, 'sidebar/worktree-list/headers/HostSectionHeader.tsx'),
|
||||
resolve(__dirname, 'sidebar/worktree-list/headers/SectionHeader.tsx'),
|
||||
resolve(__dirname, 'sidebar/worktree-list/rows/item-row.tsx'),
|
||||
resolve(__dirname, 'status-bar/ResourceUsageStatusSegment.tsx'),
|
||||
resolve(__dirname, 'status-bar/ports-status-popover-rows.tsx'),
|
||||
resolve(__dirname, 'tab-bar/TabBarQuickCommandsMenu.tsx')
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { AiVaultScope, AiVaultSession } from '../../../../shared/ai-vault-t
|
||||
import type { AiVaultResumeStartup } from '@/lib/ai-vault-resume-command'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { getActiveStickyHeaderIndexForScroll } from '../sidebar/worktree-list-virtual-rows'
|
||||
import { getActiveStickyHeaderIndexForScroll } from '../sidebar/worktree-list/viewport/virtual-rows'
|
||||
import { VaultGroupHeader } from './AiVaultPanelControls'
|
||||
import { EmptyState, SessionLoadingState } from './AiVaultSessionListStates'
|
||||
import { VaultSessionRow } from './AiVaultSessionRow'
|
||||
|
||||
@@ -10,7 +10,7 @@ import { folderWorkspaceKey, worktreeWorkspaceKey } from '../../../../shared/wor
|
||||
import {
|
||||
LINEAGE_CHILDREN_INLINE_OFFSET,
|
||||
getLineageChildrenInlineStyle
|
||||
} from '@/components/sidebar/worktree-list-indentation'
|
||||
} from '@/components/sidebar/worktree-list/rows/indentation'
|
||||
|
||||
type MockStoreState = {
|
||||
activeWorktreeId: string | null
|
||||
|
||||
@@ -2,7 +2,7 @@ import WorktreeCard from '@/components/sidebar/WorktreeCard'
|
||||
import {
|
||||
getLineageChildrenInlineStyle,
|
||||
getLineageNestedRowGeometry
|
||||
} from '@/components/sidebar/worktree-list-indentation'
|
||||
} from '@/components/sidebar/worktree-list/rows/indentation'
|
||||
import { useAppStore } from '@/store'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Range } from '@tanstack/react-virtual'
|
||||
import {
|
||||
getActiveStickyHeaderIndex,
|
||||
getPreviousStickyHeaderIndex
|
||||
} from '../sidebar/worktree-list-virtual-rows'
|
||||
} from '../sidebar/worktree-list/viewport/virtual-rows'
|
||||
|
||||
export const VAULT_GROUP_HEADER_ROW_HEIGHT = 32
|
||||
export const VAULT_SESSION_ROW_HEIGHT = 98
|
||||
|
||||
@@ -4,7 +4,7 @@ import { act } from 'react'
|
||||
import { createRoot, type Root } from 'react-dom/client'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { SidebarGroupByToggle } from './SidebarGroupByToggle'
|
||||
import type { WorktreeGroupBy } from './worktree-list-groups'
|
||||
import type { WorktreeGroupBy } from './worktree-list/rows/groups'
|
||||
|
||||
const roots: Root[] = []
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
|
||||
import type { WorktreeGroupBy } from './worktree-list-groups'
|
||||
import type { WorktreeGroupBy } from './worktree-list/rows/groups'
|
||||
import { GROUP_BY_OPTIONS } from './sidebar-workspace-option-items'
|
||||
|
||||
type SidebarGroupByToggleProps = {
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { WorktreeLineage } from '../../../../shared/worktree/lineage-types'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import { folderWorkspaceKey } from '../../../../shared/workspace-scope'
|
||||
import { getPinnedWorktreeRevealCollapsedGroupKeys } from './worktree-list/sidebar-row-reveal-ancestors'
|
||||
import { getPinnedWorktreeRevealCollapsedGroupKeys } from './worktree-list/reveal/ancestors'
|
||||
import { cloneDefaultWorkspaceStatuses } from '../../../../shared/workspace-statuses'
|
||||
|
||||
const mockStore = vi.hoisted(() => ({
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
LINEAGE_IMMEDIATE_PARENT_STEP,
|
||||
LINEAGE_NESTED_ROW_SURFACE_INSET,
|
||||
WORKTREE_CARD_SURFACE_MARGIN
|
||||
} from './worktree-list-indentation'
|
||||
} from './worktree-list/rows/indentation'
|
||||
|
||||
globalThis.IS_REACT_ACT_ENVIRONMENT = true
|
||||
|
||||
|
||||
@@ -14,29 +14,29 @@ import {
|
||||
getSettingsFocusedExecutionHostId
|
||||
} from '../../../../shared/execution-host'
|
||||
import { getActiveSidebarWorkspaceId } from '../../../../shared/workspace-scope'
|
||||
import { getPinnedWorktreeDisplayPolicy } from './worktree-list-groups'
|
||||
import { selectWorktreeListReviewCacheInputs } from './worktree-list-review-cache-inputs'
|
||||
import { getPinnedWorktreeDisplayPolicy } from './worktree-list/rows/groups'
|
||||
import { selectWorktreeListReviewCacheInputs } from './worktree-list/viewport/review-cache-inputs'
|
||||
import type { VirtualizedScrollAnchor } from '@/hooks/useVirtualizedScrollAnchor'
|
||||
import { SidebarWorktreeListDialogs } from './worktree-list/SidebarWorktreeListDialogs'
|
||||
import { SidebarWorktreeListEmptyState } from './worktree-list/SidebarWorktreeListEmptyState'
|
||||
import { VirtualizedWorktreeViewport } from './worktree-list/VirtualizedWorktreeViewport'
|
||||
import { markSidebarWorktreeActiveImmediately } from './worktree-list/worktree-option-dom'
|
||||
import { VirtualizedWorktreeViewport } from './worktree-list/viewport/VirtualizedWorktreeViewport'
|
||||
import { markSidebarWorktreeActiveImmediately } from './worktree-list/option-dom'
|
||||
import {
|
||||
EMPTY_PROJECT_GROUPS,
|
||||
NOOP_WORKSPACE_BOARD_DRAG_PREVIEW_CALLBACK
|
||||
} from './worktree-list/virtualized-worktree-viewport-props'
|
||||
} from './worktree-list/viewport/viewport-props'
|
||||
import { useAgentSendTargetWorktreeId } from './worktree-list/use-agent-send-target-worktree'
|
||||
import { useEffectiveCollapsedGroups } from './worktree-list/use-effective-collapsed-groups'
|
||||
import { useProjectGroupDialogs } from './worktree-list/use-project-group-dialogs'
|
||||
import { useSidebarExternalWorktreeCards } from './worktree-list/use-sidebar-external-worktree-cards'
|
||||
import { useSidebarHostVisibleScope } from './worktree-list/use-sidebar-host-visible-scope'
|
||||
import { useSidebarRevealRequests } from './worktree-list/use-sidebar-reveal-requests'
|
||||
import { useSidebarRevealRequests } from './worktree-list/reveal/use-requests'
|
||||
import { useSidebarSectionRows } from './worktree-list/use-sidebar-section-rows'
|
||||
import { useSidebarWorktreeFilters } from './worktree-list/use-sidebar-worktree-filters'
|
||||
import { useSidebarWorktreeSelection } from './worktree-list/use-sidebar-worktree-selection'
|
||||
import { useSidebarWorktreeSortOrder } from './worktree-list/use-sidebar-worktree-sort-order'
|
||||
import { useVisibleSidebarWorktrees } from './worktree-list/use-visible-sidebar-worktrees'
|
||||
import { useWorktreeStatusMutations } from './worktree-list/use-worktree-status-mutations'
|
||||
import { useWorktreeStatusMutations } from './worktree-list/use-status-mutations'
|
||||
|
||||
type WorktreeListProps = {
|
||||
scrollOffsetRef: React.MutableRefObject<number>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import type { WorktreeGroupBy } from './worktree-list-groups'
|
||||
import type { WorktreeGroupBy } from './worktree-list/rows/groups'
|
||||
|
||||
export function getEmptyProjectPlaceholderRepoIds(args: {
|
||||
groupBy: WorktreeGroupBy
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import { PINNED_GROUP_KEY, type Row } from './worktree-list-groups'
|
||||
import { PINNED_GROUP_KEY, type Row } from './worktree-list/rows/groups'
|
||||
import { addHostSectionRows, type HostSectionRow } from './host-section-rows'
|
||||
|
||||
function repo(id: string, connectionId?: string | null): Repo {
|
||||
|
||||
@@ -14,7 +14,7 @@ import type { SshConnectionStatus } from '../../../../shared/ssh-types'
|
||||
import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { Row } from './worktree-list-groups'
|
||||
import type { Row } from './worktree-list/rows/groups'
|
||||
|
||||
export type HostHeaderRow = {
|
||||
type: 'host-header'
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
effectiveExternalWorktreeVisibility,
|
||||
isLegacyRepoForExternalWorktreeVisibility
|
||||
} from '../../../../shared/worktree/ownership'
|
||||
import type { ImportedWorktreesCardCandidate } from './worktree-list-groups'
|
||||
import type { ImportedWorktreesCardCandidate } from './worktree-list/rows/groups'
|
||||
|
||||
export function getHiddenImportedWorktrees(
|
||||
detected: DetectedWorktreeListResult | undefined
|
||||
|
||||
@@ -8,7 +8,7 @@ import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { DetectedWorktreeListResult, Worktree } from '../../../../shared/worktree/types'
|
||||
import { getNewExternalWorktreeInboxWorktrees } from '../../../../shared/external-worktree-inbox'
|
||||
import { isGitRepoKind } from '../../../../shared/repo-kind'
|
||||
import type { NewExternalWorktreesInboxCandidate } from './worktree-list-groups'
|
||||
import type { NewExternalWorktreesInboxCandidate } from './worktree-list/rows/groups'
|
||||
|
||||
export function buildNewExternalWorktreesInboxCandidates(args: {
|
||||
repos: readonly Repo[]
|
||||
|
||||
@@ -4,14 +4,14 @@ import { describe, expect, it } from 'vitest'
|
||||
|
||||
function readWorktreeListSource(): string {
|
||||
return readFileSync(
|
||||
fileURLToPath(new URL('./worktree-list/worktree-section-header-row.tsx', import.meta.url)),
|
||||
fileURLToPath(new URL('./worktree-list/headers/SectionHeader.tsx', import.meta.url)),
|
||||
'utf8'
|
||||
)
|
||||
}
|
||||
|
||||
function readHeaderDragSource(): string {
|
||||
return readFileSync(
|
||||
fileURLToPath(new URL('./worktree-list/use-worktree-sidebar-header-drag.ts', import.meta.url)),
|
||||
fileURLToPath(new URL('./worktree-list/drag/use-header-drag.ts', import.meta.url)),
|
||||
'utf8'
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
getSidebarOrderedProjectGroupHeaderIdsByBucket,
|
||||
mapSidebarProjectGroupDropIndexToSiblingInsertIndex
|
||||
} from './project-group-header-drop'
|
||||
import type { Row } from './worktree-list-groups'
|
||||
import type { Row } from './worktree-list/rows/groups'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
computeWorktreeSidebarHeaderDropPreview,
|
||||
type WorktreeSidebarHeaderDropPreview
|
||||
} from './worktree-sidebar-header-drop-preview'
|
||||
import type { Row } from './worktree-list-groups'
|
||||
import type { Row } from './worktree-list/rows/groups'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
|
||||
export type ProjectGroupHeaderDragBucketKey = string
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
mapSidebarProjectHeaderDropIndexToSiblingInsertIndex,
|
||||
mapSidebarRepoDropIndexToAllRepoInsertAt
|
||||
} from './project-header-drop'
|
||||
import type { Row } from './worktree-list-groups'
|
||||
import type { Row } from './worktree-list/rows/groups'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
|
||||
describe('getProjectHeaderDragBucketKey', () => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
computeWorktreeSidebarHeaderDropPreview,
|
||||
type WorktreeSidebarHeaderDropPreview
|
||||
} from './worktree-sidebar-header-drop-preview'
|
||||
import type { Row } from './worktree-list-groups'
|
||||
import type { Row } from './worktree-list/rows/groups'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
|
||||
export type ProjectHeaderDragBucketKey = string
|
||||
|
||||
@@ -7,18 +7,18 @@ import {
|
||||
} from '../../../../shared/execution-host'
|
||||
import { getRepoMapFromState, getWorktreeMapFromState } from '@/store/selectors'
|
||||
import { getProjectHostSetupProjectionFromState } from '@/store/project-host-setup-selector'
|
||||
import { buildRows, getPinnedWorktreeDisplayPolicy } from './worktree-list-groups'
|
||||
import { buildRows, getPinnedWorktreeDisplayPolicy } from './worktree-list/rows/groups'
|
||||
import { addHostSectionRows } from './host-section-rows'
|
||||
import { orderHostSectionOptions } from './host-section-order'
|
||||
import { buildSidebarHostOptions } from './sidebar-host-options'
|
||||
import { getLogicalRepoOrderRankById } from './project-header-drop'
|
||||
import { getRenderedWorktreesInSidebarOrder } from './worktree-sidebar-row-preference'
|
||||
import { selectWorktreeListReviewCacheInputs } from './worktree-list-review-cache-inputs'
|
||||
import { selectWorktreeListReviewCacheInputs } from './worktree-list/viewport/review-cache-inputs'
|
||||
import {
|
||||
filterFolderWorkspacesForVisibleHosts,
|
||||
filterProjectGroupsForVisibleHosts,
|
||||
getVisibleSidebarHostIdSet
|
||||
} from './worktree-list-host-filtering'
|
||||
} from './worktree-list/viewport/host-filtering'
|
||||
|
||||
const EMPTY_REPO_ID_SET: ReadonlySet<string> = Object.freeze(new Set<string>())
|
||||
const EMPTY_IMPORTED_BY_REPO = Object.freeze(new Map()) as never
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react'
|
||||
import {
|
||||
getFlushWorktreeCardPaddingLeft,
|
||||
getNewCardStyleParentContentMarginLeft
|
||||
} from './worktree-list-indentation'
|
||||
} from './worktree-list/rows/indentation'
|
||||
import {
|
||||
hasWorktreeCardDetails,
|
||||
WorktreeCardDetailsHover,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { WorktreeDragGroup } from './worktree-manual-order'
|
||||
import { ALL_GROUP_KEY, PINNED_GROUP_KEY } from './worktree-list-groups'
|
||||
import { ALL_GROUP_KEY, PINNED_GROUP_KEY } from './worktree-list/rows/groups'
|
||||
|
||||
export type WorktreeDragUnitGroup = WorktreeDragGroup & {
|
||||
units: { worktreeId: string; worktreeIds: string[] }[]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { estimateRenderRowSize, type RenderRow } from './worktree-list-virtual-rows'
|
||||
import { estimateRenderRowSize, type RenderRow } from './worktree-list/viewport/virtual-rows'
|
||||
|
||||
function getEstimatedRenderRowStarts(
|
||||
rows: readonly RenderRow[],
|
||||
|
||||
@@ -132,9 +132,7 @@ describe('getCyclableWorktreeIds', () => {
|
||||
describe('WorktreeList keyboard cycling', () => {
|
||||
it('cycles over the rendered rows instead of rebuilding a parallel layout', () => {
|
||||
const source = readFileSync(
|
||||
fileURLToPath(
|
||||
new URL('./worktree-list/use-worktree-list-keyboard-navigation.ts', import.meta.url)
|
||||
),
|
||||
fileURLToPath(new URL('./worktree-list/viewport/use-keyboard.ts', import.meta.url)),
|
||||
'utf8'
|
||||
)
|
||||
const navigateWorktree = source.slice(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { HostSectionRow } from './host-section-rows'
|
||||
import type { PinnedWorktreeDisplayPolicy, WorktreeRow } from './worktree-list-groups'
|
||||
import type { PinnedWorktreeDisplayPolicy, WorktreeRow } from './worktree-list/rows/groups'
|
||||
import { getPreferredWorktreeRows } from './worktree-sidebar-row-preference'
|
||||
|
||||
/** Worktree ids in sidebar order, taken from the rows the sidebar actually
|
||||
|
||||
+7
-7
@@ -2,13 +2,13 @@ import type React from 'react'
|
||||
import type {
|
||||
WorkspaceStatus,
|
||||
WorkspaceStatusDefinition
|
||||
} from '../../../../../shared/worktree/types'
|
||||
import type { WorktreeDragGroup } from '../worktree-manual-order'
|
||||
import type { WorktreeDragUnitGroup } from '../worktree-drag-units'
|
||||
import type { WorktreeSidebarDropPreview } from '../worktree-sidebar-drop-preview'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from './virtualized-worktree-viewport-props'
|
||||
import type { WorktreeStatusDropRequest } from './use-worktree-drag-session'
|
||||
import type { WorktreeSidebarLineageDropTarget } from './worktree-row-drag-state'
|
||||
} from '../../../../../../shared/worktree/types'
|
||||
import type { WorktreeDragGroup } from '../../worktree-manual-order'
|
||||
import type { WorktreeDragUnitGroup } from '../../worktree-drag-units'
|
||||
import type { WorktreeSidebarDropPreview } from '../../worktree-sidebar-drop-preview'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from '../viewport/viewport-props'
|
||||
import type { WorktreeStatusDropRequest } from './use-session'
|
||||
import type { WorktreeSidebarLineageDropTarget } from './row-state'
|
||||
|
||||
// The shared surface every drop path (pointer, native drag, document capture) commits through.
|
||||
export type WorktreeDropCommitContext = {
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
import { ALL_GROUP_KEY, PINNED_GROUP_KEY } from '../worktree-list-groups'
|
||||
import type { HostSectionRow } from '../host-section-rows'
|
||||
import type { WorktreeDragGroup } from '../worktree-manual-order'
|
||||
import { ALL_GROUP_KEY, PINNED_GROUP_KEY } from '../rows/groups'
|
||||
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> {
|
||||
+9
-15
@@ -3,21 +3,15 @@ import {
|
||||
getWorkspaceKanbanSidebarDropTarget,
|
||||
isWorkspaceKanbanSidebarDropPointInBoard,
|
||||
resolveWorkspaceKanbanSidebarFullLaneDropIndex
|
||||
} from '../workspace-kanban-sidebar-drop'
|
||||
import { resolveWorkspaceKanbanCardDropCommitTarget } from '../workspace-kanban-card-pointer-drag-dom'
|
||||
import { getFullDropIndexForWorktreeDragUnit } from '../worktree-drag-units'
|
||||
import { resolveWorktreeSidebarStatusDropCommitTarget } from '../worktree-sidebar-drop-preview'
|
||||
import {
|
||||
getPointerDropStatusTarget,
|
||||
shouldPreferSidebarStatusDropTarget
|
||||
} from './pointer-drop-status-target'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from './virtualized-worktree-viewport-props'
|
||||
import type { WorktreeSidebarStatusDropTarget } from '../worktree-sidebar-drop-preview'
|
||||
import {
|
||||
NO_WORKTREE_SIDEBAR_DROP_TARGET,
|
||||
type WorktreePointerDrag
|
||||
} from './worktree-row-drag-state'
|
||||
} from '../../workspace-kanban-sidebar-drop'
|
||||
import { resolveWorkspaceKanbanCardDropCommitTarget } from '../../workspace-kanban-card-pointer-drag-dom'
|
||||
import { getFullDropIndexForWorktreeDragUnit } from '../../worktree-drag-units'
|
||||
import { resolveWorktreeSidebarStatusDropCommitTarget } from '../../worktree-sidebar-drop-preview'
|
||||
import { getPointerDropStatusTarget, shouldPreferSidebarStatusDropTarget } from './status-target'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from '../viewport/viewport-props'
|
||||
import type { WorktreeSidebarStatusDropTarget } from '../../worktree-sidebar-drop-preview'
|
||||
import { NO_WORKTREE_SIDEBAR_DROP_TARGET, type WorktreePointerDrag } from './row-state'
|
||||
|
||||
type PointerDropCommitArgs = {
|
||||
event: PointerEvent
|
||||
+6
-9
@@ -1,17 +1,14 @@
|
||||
import type React from 'react'
|
||||
import type { WorkspaceStatus } from '../../../../../shared/worktree/types'
|
||||
import type { WorkspaceStatus } from '../../../../../../shared/worktree/types'
|
||||
import {
|
||||
clearWorkspaceKanbanSidebarDropTargetVisual,
|
||||
hasWorkspaceKanbanSidebarDropBoard,
|
||||
isWorkspaceKanbanSidebarDropPointInBoard,
|
||||
updateWorkspaceKanbanSidebarDropTargetVisual
|
||||
} from '../workspace-kanban-sidebar-drop'
|
||||
import { updateSidebarDragPreviewPosition } from '../worktree-sidebar-pointer-drag-dom'
|
||||
import {
|
||||
getPointerDropStatusTarget,
|
||||
shouldPreferSidebarStatusDropTarget
|
||||
} from './pointer-drop-status-target'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
} from '../../workspace-kanban-sidebar-drop'
|
||||
import { updateSidebarDragPreviewPosition } from '../../worktree-sidebar-pointer-drag-dom'
|
||||
import { getPointerDropStatusTarget, shouldPreferSidebarStatusDropTarget } from './status-target'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import {
|
||||
applyWorktreeDropPreview,
|
||||
clearWorktreeDropPreview,
|
||||
@@ -20,7 +17,7 @@ import {
|
||||
type WorktreePointerDrag,
|
||||
type WorktreeRowDragState,
|
||||
type WorktreeSidebarLineageDropTarget
|
||||
} from './worktree-row-drag-state'
|
||||
} from './row-state'
|
||||
|
||||
export type WorktreePointerDragFrameArgs = {
|
||||
drag: WorktreePointerDrag
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
import type { WorkspaceKanbanCardTrackedDropTarget } from '../workspace-kanban-card-pointer-drag-dom'
|
||||
import type { WorktreeSidebarDragRect } from '../worktree-sidebar-drag-autoscroll'
|
||||
import type { WorkspaceKanbanCardTrackedDropTarget } from '../../workspace-kanban-card-pointer-drag-dom'
|
||||
import type { WorktreeSidebarDragRect } from '../../worktree-sidebar-drag-autoscroll'
|
||||
import type {
|
||||
WorktreeSidebarDropPreview,
|
||||
WorktreeSidebarStatusDropTarget,
|
||||
WorktreeSidebarTrackedStatusDropTarget
|
||||
} from '../worktree-sidebar-drop-preview'
|
||||
} from '../../worktree-sidebar-drop-preview'
|
||||
|
||||
export type WorktreeRowDragState = {
|
||||
draggingWorktreeId: string | null
|
||||
+5
-8
@@ -1,14 +1,11 @@
|
||||
import type {
|
||||
WorkspaceStatus,
|
||||
WorkspaceStatusDefinition
|
||||
} from '../../../../../shared/worktree/types'
|
||||
import { getWorkspaceStatusFromGroupKey } from '../workspace-status'
|
||||
import { getWorktreeLineageDropTargetId } from '../worktree-lineage-drag-drop'
|
||||
import type { WorktreeSidebarStatusDropTarget } from '../worktree-sidebar-drop-preview'
|
||||
import {
|
||||
NO_WORKTREE_SIDEBAR_DROP_TARGET,
|
||||
type WorktreeSidebarLineageDropTarget
|
||||
} from './worktree-row-drag-state'
|
||||
} from '../../../../../../shared/worktree/types'
|
||||
import { getWorkspaceStatusFromGroupKey } from '../../workspace-status'
|
||||
import { getWorktreeLineageDropTargetId } from '../../worktree-lineage-drag-drop'
|
||||
import type { WorktreeSidebarStatusDropTarget } from '../../worktree-sidebar-drop-preview'
|
||||
import { NO_WORKTREE_SIDEBAR_DROP_TARGET, type WorktreeSidebarLineageDropTarget } from './row-state'
|
||||
|
||||
export function getPointerDropStatusTarget(args: {
|
||||
container: HTMLElement
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
import { useEffect } from 'react'
|
||||
import type React from 'react'
|
||||
import { getFullDropIndexForWorktreeDragUnit } from '../worktree-drag-units'
|
||||
import type { WorktreeSidebarDragSession } from '../worktree-sidebar-drag-autoscroll'
|
||||
import { getPointerDropStatusTarget } from './pointer-drop-status-target'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import { NO_WORKTREE_SIDEBAR_DROP_TARGET } from './worktree-row-drag-state'
|
||||
import { getFullDropIndexForWorktreeDragUnit } from '../../worktree-drag-units'
|
||||
import type { WorktreeSidebarDragSession } from '../../worktree-sidebar-drag-autoscroll'
|
||||
import { getPointerDropStatusTarget } from './status-target'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import { NO_WORKTREE_SIDEBAR_DROP_TARGET } from './row-state'
|
||||
|
||||
// Why: a drop that lands outside the sidebar still belongs to the in-flight session, so the
|
||||
// capture-phase document listeners commit or abandon it before anything else sees the event.
|
||||
+14
-14
@@ -1,23 +1,23 @@
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import type React from 'react'
|
||||
import { useAppStore } from '@/store'
|
||||
import type { ProjectGroup } from '../../../../../shared/project-group-types'
|
||||
import type { ProjectOrderBy } from '../../../../../shared/ui-chrome-types'
|
||||
import type { Repo } from '../../../../../shared/repo-types'
|
||||
import type { ExecutionHostId } from '../../../../../shared/execution-host'
|
||||
import type { HostHeaderRow, HostSectionRow } from '../host-section-rows'
|
||||
import type { Row, WorktreeGroupBy } from '../worktree-list-groups'
|
||||
import type { RenderRow } from '../worktree-list-virtual-rows'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { ProjectOrderBy } from '../../../../../../shared/ui-chrome-types'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { ExecutionHostId } from '../../../../../../shared/execution-host'
|
||||
import type { HostHeaderRow, HostSectionRow } from '../../host-section-rows'
|
||||
import type { Row, WorktreeGroupBy } from '../rows/groups'
|
||||
import type { RenderRow } from '../viewport/virtual-rows'
|
||||
import {
|
||||
getProjectGroupHeaderSectionEndByGroupId,
|
||||
getRepoHeaderSectionEndByRepoId
|
||||
} from '../worktree-header-section-boundaries'
|
||||
import { useHostHeaderDrag } from '../host-header-drag'
|
||||
import { useRepoHeaderDrag } from '../project-header-drag'
|
||||
import { getSidebarOrderedRepoHeaderIdsByBucket } from '../project-header-drop'
|
||||
import { useProjectGroupHeaderDrag } from '../project-group-header-drag'
|
||||
import { getSidebarOrderedProjectGroupHeaderIdsByBucket } from '../project-group-header-drop'
|
||||
import { USER_SCROLL_MEASUREMENT_ADJUSTMENT_SUPPRESS_MS } from './worktree-sidebar-scroll-tuning'
|
||||
} from '../../worktree-header-section-boundaries'
|
||||
import { useHostHeaderDrag } from '../../host-header-drag'
|
||||
import { useRepoHeaderDrag } from '../../project-header-drag'
|
||||
import { getSidebarOrderedRepoHeaderIdsByBucket } from '../../project-header-drop'
|
||||
import { useProjectGroupHeaderDrag } from '../../project-group-header-drag'
|
||||
import { getSidebarOrderedProjectGroupHeaderIdsByBucket } from '../../project-group-header-drop'
|
||||
import { USER_SCROLL_MEASUREMENT_ADJUSTMENT_SUPPRESS_MS } from '../scroll/tuning'
|
||||
|
||||
export type WorktreeSidebarHeaderDrag = ReturnType<typeof useWorktreeSidebarHeaderDrag>
|
||||
|
||||
+8
-8
@@ -2,14 +2,14 @@ import { useCallback, useMemo } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { useAppStore } from '@/store'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import type { Repo } from '../../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../../shared/worktree/types'
|
||||
import type { WorktreeLineage } from '../../../../../shared/worktree/lineage-types'
|
||||
import { isEligibleWorktreeParent } from '../worktree-parent-candidates'
|
||||
import { getCyclicProjectedWorktreeLineageIds } from '../worktree-lineage-projection'
|
||||
import { getReorderedWorktreeIdsToUnnest } from '../worktree-lineage-drag-drop'
|
||||
import type { WorktreeDragGroup } from '../worktree-manual-order'
|
||||
import type { WorktreeSidebarLineageDropTarget } from './worktree-row-drag-state'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import type { WorktreeLineage } from '../../../../../../shared/worktree/lineage-types'
|
||||
import { isEligibleWorktreeParent } from '../../worktree-parent-candidates'
|
||||
import { getCyclicProjectedWorktreeLineageIds } from '../../worktree-lineage-projection'
|
||||
import { getReorderedWorktreeIdsToUnnest } from '../../worktree-lineage-drag-drop'
|
||||
import type { WorktreeDragGroup } from '../../worktree-manual-order'
|
||||
import type { WorktreeSidebarLineageDropTarget } from './row-state'
|
||||
|
||||
export type WorktreeLineageDropCommit = ReturnType<typeof useWorktreeLineageDropCommit>
|
||||
|
||||
+6
-6
@@ -1,11 +1,11 @@
|
||||
import { useCallback } from 'react'
|
||||
import type React from 'react'
|
||||
import { getWorktreeSidebarDragAutoscroll } from '../worktree-sidebar-drag-autoscroll'
|
||||
import { getPointerDropStatusTarget } from './pointer-drop-status-target'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import type { WorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import type { WorktreeDragSession } from './use-worktree-drag-session'
|
||||
import { applyWorktreeDropPreview, clearWorktreeDropPreview } from './worktree-row-drag-state'
|
||||
import { getWorktreeSidebarDragAutoscroll } from '../../worktree-sidebar-drag-autoscroll'
|
||||
import { getPointerDropStatusTarget } from './status-target'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import type { WorktreeDragRuntime } from './use-runtime'
|
||||
import type { WorktreeDragSession } from './use-session'
|
||||
import { applyWorktreeDropPreview, clearWorktreeDropPreview } from './row-state'
|
||||
|
||||
// The HTML5 drag equivalent of pointer autoscroll: the browser gives no move events while
|
||||
// hovering the edge, so re-derive the drop preview from the last known point each frame.
|
||||
+10
-10
@@ -1,20 +1,20 @@
|
||||
import { useCallback } from 'react'
|
||||
import type React from 'react'
|
||||
import { getWorkspaceKanbanSidebarDropTarget } from '../workspace-kanban-sidebar-drop'
|
||||
import { getFullDropIndexForWorktreeDragUnit } from '../worktree-drag-units'
|
||||
import { getWorktreeSidebarDragRectsForGroup } from '../worktree-sidebar-drag-autoscroll'
|
||||
import { getWorktreeSidebarDragGrab } from '../worktree-sidebar-drag-geometry'
|
||||
import { getPointerDropStatusTarget } from './pointer-drop-status-target'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import type { WorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import type { WorktreeDragSession } from './use-worktree-drag-session'
|
||||
import { useWorktreeNativeDragAutoscroll } from './use-worktree-native-drag-autoscroll'
|
||||
import { getWorkspaceKanbanSidebarDropTarget } from '../../workspace-kanban-sidebar-drop'
|
||||
import { getFullDropIndexForWorktreeDragUnit } from '../../worktree-drag-units'
|
||||
import { getWorktreeSidebarDragRectsForGroup } from '../../worktree-sidebar-drag-autoscroll'
|
||||
import { getWorktreeSidebarDragGrab } from '../../worktree-sidebar-drag-geometry'
|
||||
import { getPointerDropStatusTarget } from './status-target'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import type { WorktreeDragRuntime } from './use-runtime'
|
||||
import type { WorktreeDragSession } from './use-session'
|
||||
import { useWorktreeNativeDragAutoscroll } from './use-native-autoscroll'
|
||||
import {
|
||||
applyWorktreeDropPreview,
|
||||
clearWorktreeDropPreview,
|
||||
EMPTY_WORKTREE_DRAG_PREVIEW_OFFSETS,
|
||||
NO_WORKTREE_SIDEBAR_DROP_TARGET
|
||||
} from './worktree-row-drag-state'
|
||||
} from './row-state'
|
||||
|
||||
// The HTML5 drag path used by cards that start a native dragstart (board <-> sidebar transfers).
|
||||
export function useWorktreeNativeDrag(args: {
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
import { useCallback } from 'react'
|
||||
import type React from 'react'
|
||||
import { getWorktreeSidebarDragAutoscroll } from '../worktree-sidebar-drag-autoscroll'
|
||||
import type { WorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import type { WorktreeDragSession } from './use-worktree-drag-session'
|
||||
import type { WorktreePointerDrag } from './worktree-row-drag-state'
|
||||
import { getWorktreeSidebarDragAutoscroll } from '../../worktree-sidebar-drag-autoscroll'
|
||||
import type { WorktreeDragRuntime } from './use-runtime'
|
||||
import type { WorktreeDragSession } from './use-session'
|
||||
import type { WorktreePointerDrag } from './row-state'
|
||||
|
||||
// Scrolls the sidebar while a pointer drag hovers near its top or bottom edge, refreshing
|
||||
// the drag session on every scrolled frame so the insertion line stays on the right row.
|
||||
+14
-17
@@ -1,26 +1,23 @@
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import type React from 'react'
|
||||
import type { WorkspaceStatus, Worktree } from '../../../../../shared/worktree/types'
|
||||
import { hasWorkspaceKanbanSidebarDropBoard } from '../workspace-kanban-sidebar-drop'
|
||||
import type { WorkspaceStatus, Worktree } from '../../../../../../shared/worktree/types'
|
||||
import { hasWorkspaceKanbanSidebarDropBoard } from '../../workspace-kanban-sidebar-drop'
|
||||
import {
|
||||
createSidebarDragPreview,
|
||||
isSidebarPointerDragBlocked,
|
||||
setSidebarPointerDragDocumentStyles
|
||||
} from '../worktree-sidebar-pointer-drag-dom'
|
||||
import { getWorktreeSidebarDragRectsForGroup } from '../worktree-sidebar-drag-autoscroll'
|
||||
import { getWorktreeSidebarDragGrab } from '../worktree-sidebar-drag-geometry'
|
||||
import { NOOP_WORKSPACE_BOARD_DRAG_PREVIEW_CALLBACK } from './virtualized-worktree-viewport-props'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from './virtualized-worktree-viewport-props'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import type { WorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import type { WorktreeDragSession } from './use-worktree-drag-session'
|
||||
import { useWorktreePointerDragAutoscroll } from './use-worktree-pointer-drag-autoscroll'
|
||||
import { useWorktreePointerDragWindowEvents } from './use-worktree-pointer-drag-window-events'
|
||||
import { flushWorktreePointerDragFrame } from './worktree-pointer-drag-flush'
|
||||
import {
|
||||
EMPTY_WORKTREE_DRAG_PREVIEW_OFFSETS,
|
||||
type WorktreePointerDrag
|
||||
} from './worktree-row-drag-state'
|
||||
} from '../../worktree-sidebar-pointer-drag-dom'
|
||||
import { getWorktreeSidebarDragRectsForGroup } from '../../worktree-sidebar-drag-autoscroll'
|
||||
import { getWorktreeSidebarDragGrab } from '../../worktree-sidebar-drag-geometry'
|
||||
import { NOOP_WORKSPACE_BOARD_DRAG_PREVIEW_CALLBACK } from '../viewport/viewport-props'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from '../viewport/viewport-props'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import type { WorktreeDragRuntime } from './use-runtime'
|
||||
import type { WorktreeDragSession } from './use-session'
|
||||
import { useWorktreePointerDragAutoscroll } from './use-pointer-autoscroll'
|
||||
import { useWorktreePointerDragWindowEvents } from './use-pointer-window-events'
|
||||
import { flushWorktreePointerDragFrame } from './pointer-flush'
|
||||
import { EMPTY_WORKTREE_DRAG_PREVIEW_OFFSETS, type WorktreePointerDrag } from './row-state'
|
||||
|
||||
export function useWorktreePointerDrag(args: {
|
||||
ctx: WorktreeDropCommitContext
|
||||
+6
-6
@@ -1,10 +1,10 @@
|
||||
import { useEffect } from 'react'
|
||||
import type { WorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from './virtualized-worktree-viewport-props'
|
||||
import { commitWorktreePointerDrop } from './worktree-pointer-drag-commit'
|
||||
import { SIDEBAR_POINTER_DRAG_THRESHOLD_PX } from './worktree-sidebar-scroll-tuning'
|
||||
import type { WorktreePointerDrag } from './worktree-row-drag-state'
|
||||
import type { WorktreeDragRuntime } from './use-runtime'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from '../viewport/viewport-props'
|
||||
import { commitWorktreePointerDrop } from './pointer-commit'
|
||||
import { SIDEBAR_POINTER_DRAG_THRESHOLD_PX } from '../scroll/tuning'
|
||||
import type { WorktreePointerDrag } from './row-state'
|
||||
|
||||
// Pointer drags escape the row that started them, so move/up/cancel are tracked on the
|
||||
// window in capture phase.
|
||||
+6
-6
@@ -1,18 +1,18 @@
|
||||
import { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import type React from 'react'
|
||||
import type { WorkspaceStatus } from '../../../../../shared/worktree/types'
|
||||
import { clearWorkspaceKanbanSidebarDropTargetVisual } from '../workspace-kanban-sidebar-drop'
|
||||
import { setSidebarPointerDragDocumentStyles } from '../worktree-sidebar-pointer-drag-dom'
|
||||
import type { WorkspaceStatus } from '../../../../../../shared/worktree/types'
|
||||
import { clearWorkspaceKanbanSidebarDropTargetVisual } from '../../workspace-kanban-sidebar-drop'
|
||||
import { setSidebarPointerDragDocumentStyles } from '../../worktree-sidebar-pointer-drag-dom'
|
||||
import type {
|
||||
WorktreeSidebarDragPoint,
|
||||
WorktreeSidebarDragSession
|
||||
} from '../worktree-sidebar-drag-autoscroll'
|
||||
import type { WorktreeSidebarDropAnchor } from '../worktree-sidebar-drag-geometry'
|
||||
} from '../../worktree-sidebar-drag-autoscroll'
|
||||
import type { WorktreeSidebarDropAnchor } from '../../worktree-sidebar-drag-geometry'
|
||||
import {
|
||||
WORKTREE_ROW_DRAG_INITIAL_STATE,
|
||||
type WorktreePointerDrag,
|
||||
type WorktreeRowDragState
|
||||
} from './worktree-row-drag-state'
|
||||
} from './row-state'
|
||||
|
||||
export type WorktreeDragRuntime = ReturnType<typeof useWorktreeDragRuntime>
|
||||
|
||||
+12
-12
@@ -1,29 +1,29 @@
|
||||
import { useCallback, useMemo, useRef } from 'react'
|
||||
import type React from 'react'
|
||||
import type { WorkspaceStatus } from '../../../../../shared/worktree/types'
|
||||
import type { HostSectionRow } from '../host-section-rows'
|
||||
import { PINNED_GROUP_KEY } from '../worktree-list-groups'
|
||||
import { WORKTREE_SIDEBAR_VIRTUAL_ROW_GAP } from '../worktree-list-virtual-rows'
|
||||
import { getWorkspaceStatusGroupKey } from '../workspace-status'
|
||||
import { expandDraggedWorktreeIdsForVisibleLineage } from '../worktree-manual-order'
|
||||
import { getWorktreeDragUnitGroups } from '../worktree-drag-units'
|
||||
import type { WorkspaceStatus } from '../../../../../../shared/worktree/types'
|
||||
import type { HostSectionRow } from '../../host-section-rows'
|
||||
import { PINNED_GROUP_KEY } from '../rows/groups'
|
||||
import { WORKTREE_SIDEBAR_VIRTUAL_ROW_GAP } from '../viewport/virtual-rows'
|
||||
import { getWorkspaceStatusGroupKey } from '../../workspace-status'
|
||||
import { expandDraggedWorktreeIdsForVisibleLineage } from '../../worktree-manual-order'
|
||||
import { getWorktreeDragUnitGroups } from '../../worktree-drag-units'
|
||||
import {
|
||||
getWorktreeSidebarDragRectsForGroup,
|
||||
refreshWorktreeSidebarDragSession,
|
||||
type WorktreeSidebarDragRect,
|
||||
type WorktreeSidebarDragSession
|
||||
} from '../worktree-sidebar-drag-autoscroll'
|
||||
} from '../../worktree-sidebar-drag-autoscroll'
|
||||
import {
|
||||
shouldReevaluateWorktreeSidebarDropAnchor,
|
||||
type WorktreeSidebarDragGrab,
|
||||
type WorktreeSidebarDropAnchor
|
||||
} from '../worktree-sidebar-drag-geometry'
|
||||
} from '../../worktree-sidebar-drag-geometry'
|
||||
import {
|
||||
computeWorktreeSidebarDropPreview,
|
||||
type WorktreeSidebarDropPreview
|
||||
} from '../worktree-sidebar-drop-preview'
|
||||
import { getWorktreeDragGroups, getWorktreeDragIndexes } from './worktree-drag-groups'
|
||||
import type { WorktreeItemRow } from './render-row-item-rows'
|
||||
} from '../../worktree-sidebar-drop-preview'
|
||||
import { getWorktreeDragGroups, getWorktreeDragIndexes } from './groups'
|
||||
import type { WorktreeItemRow } from '../rows/renderable-rows'
|
||||
|
||||
export type WorktreeStatusDropRequest = {
|
||||
pointerY: number
|
||||
+8
-8
@@ -1,13 +1,13 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import type React from 'react'
|
||||
import type { WorkspaceStatus } from '../../../../../shared/worktree/types'
|
||||
import type { HostSectionRow } from '../host-section-rows'
|
||||
import { PINNED_GROUP_KEY, type WorktreeGroupBy } from '../worktree-list-groups'
|
||||
import { hasWorkspaceDragData, readWorkspaceDragDataIds } from '../workspace-status'
|
||||
import { useWorkspaceStatusDocumentDrop } from '../use-workspace-status-drop'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import type { WorktreeDragSession } from './use-worktree-drag-session'
|
||||
import type { WorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import type { WorkspaceStatus } from '../../../../../../shared/worktree/types'
|
||||
import type { HostSectionRow } from '../../host-section-rows'
|
||||
import { PINNED_GROUP_KEY, type WorktreeGroupBy } from '../rows/groups'
|
||||
import { hasWorkspaceDragData, readWorkspaceDragDataIds } from '../../workspace-status'
|
||||
import { useWorkspaceStatusDocumentDrop } from '../../use-workspace-status-drop'
|
||||
import type { WorktreeDropCommitContext } from './drop-commit-context'
|
||||
import type { WorktreeDragSession } from './use-session'
|
||||
import type { WorktreeDragRuntime } from './use-runtime'
|
||||
|
||||
// Drag-and-drop onto a status section header or a status-grouped row, including the
|
||||
// document-level fallback used when the pointer leaves the sidebar mid-drag.
|
||||
+1
-1
@@ -9,7 +9,7 @@ import {
|
||||
import {
|
||||
isConfirmedStaleFolderPathStatus,
|
||||
type FolderWorkspacePathStatus
|
||||
} from '../../../../../shared/folder-workspace-path-status'
|
||||
} from '../../../../../../shared/folder-workspace-path-status'
|
||||
|
||||
export function FolderPathStatusIndicator({
|
||||
status
|
||||
+2
-2
@@ -3,8 +3,8 @@ import { AlertTriangle, ChevronDown, Loader2, Server, ServerOff } from 'lucide-r
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import type { HostHeaderRow } from '../host-section-rows'
|
||||
import { HostSectionHeaderMenu } from '../HostSectionHeaderMenu'
|
||||
import type { HostHeaderRow } from '../../host-section-rows'
|
||||
import { HostSectionHeaderMenu } from '../../HostSectionHeaderMenu'
|
||||
|
||||
function formatSectionActivityLabel(count: number, label: string): string {
|
||||
return `${count} ${label}${count === 1 ? '' : 's'}`
|
||||
+15
-15
@@ -5,24 +5,24 @@ import { cn } from '@/lib/utils'
|
||||
import type { AppState } from '@/store/types'
|
||||
import { RepoIconGlyph } from '@/components/repo/repo-icon'
|
||||
import { RepoForkIndicator } from '@/components/repo/repo-fork-indicator'
|
||||
import type { FolderWorkspacePathStatus } from '../../../../../shared/folder-workspace-path-status'
|
||||
import { isConfirmedStaleFolderPathStatus } from '../../../../../shared/folder-workspace-path-status'
|
||||
import type { ProjectGroup } from '../../../../../shared/project-group-types'
|
||||
import type { FolderWorkspacePathStatus } from '../../../../../../shared/folder-workspace-path-status'
|
||||
import { isConfirmedStaleFolderPathStatus } from '../../../../../../shared/folder-workspace-path-status'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type {
|
||||
WorkspaceStatus,
|
||||
WorkspaceStatusDefinition
|
||||
} from '../../../../../shared/worktree/types'
|
||||
import type { GroupHeaderRow, WorktreeGroupBy } from '../worktree-list-groups'
|
||||
import { PINNED_GROUP_KEY } from '../worktree-list-groups'
|
||||
import { getWorkspaceStatusFromGroupKey } from '../workspace-status'
|
||||
import { getVirtualRowTransform } from '../worktree-list-virtual-rows'
|
||||
import { resolveProjectGroupHeaderColor } from '../project-header-color'
|
||||
import { getRepoHeaderCreateState } from '../repo-header-create-state'
|
||||
import { ProjectHeaderActions } from '../ProjectHeaderActions'
|
||||
} from '../../../../../../shared/worktree/types'
|
||||
import type { GroupHeaderRow, WorktreeGroupBy } from '../rows/groups'
|
||||
import { PINNED_GROUP_KEY } from '../rows/groups'
|
||||
import { getWorkspaceStatusFromGroupKey } from '../../workspace-status'
|
||||
import { getVirtualRowTransform } from '../viewport/virtual-rows'
|
||||
import { resolveProjectGroupHeaderColor } from '../../project-header-color'
|
||||
import { getRepoHeaderCreateState } from '../../repo-header-create-state'
|
||||
import { ProjectHeaderActions } from '../../ProjectHeaderActions'
|
||||
import {
|
||||
getProjectGroupHeaderPaddingLeft,
|
||||
WORKTREE_SECTION_HEADER_PADDING_LEFT
|
||||
} from '../worktree-list-indentation'
|
||||
} from '../rows/indentation'
|
||||
import { FolderPathStatusIndicator } from './FolderPathStatusIndicator'
|
||||
import {
|
||||
ProjectGroupCreateWorkspaceButton,
|
||||
@@ -36,9 +36,9 @@ import {
|
||||
import {
|
||||
handleRepoHeaderCollapseAffordancePointerDown,
|
||||
shouldIgnoreRepoHeaderToggle
|
||||
} from './repo-header-event-guards'
|
||||
import type { WorktreeSidebarHeaderDrag } from './use-worktree-sidebar-header-drag'
|
||||
import { getWorktreeOptionId } from './worktree-option-dom'
|
||||
} from './event-guards'
|
||||
import type { WorktreeSidebarHeaderDrag } from '../drag/use-header-drag'
|
||||
import { getWorktreeOptionId } from '../option-dom'
|
||||
|
||||
export type SectionHeaderRowContext = {
|
||||
groupBy: WorktreeGroupBy
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import type React from 'react'
|
||||
import { isRepoHeaderActionTarget } from '../project-header-drag'
|
||||
import { isRepoHeaderActionTarget } from '../../project-header-drag'
|
||||
|
||||
export function stopRepoHeaderKeyboardToggle(event: React.KeyboardEvent<HTMLElement>): void {
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
+4
-4
@@ -11,14 +11,14 @@ import {
|
||||
import { cn } from '@/lib/utils'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { getFolderWorkspacePathStatusDescription } from '@/lib/folder-workspace-path-status'
|
||||
import type { ProjectGroup } from '../../../../../shared/project-group-types'
|
||||
import type { FolderWorkspacePathStatus } from '../../../../../shared/folder-workspace-path-status'
|
||||
import { REPO_HEADER_ACTION_BUTTON_CLASS } from '../repo-header-action-button-class'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { FolderWorkspacePathStatus } from '../../../../../../shared/folder-workspace-path-status'
|
||||
import { REPO_HEADER_ACTION_BUTTON_CLASS } from '../../repo-header-action-button-class'
|
||||
import {
|
||||
handleRepoHeaderActionPointerDown,
|
||||
stopRepoHeaderKeyboardToggle,
|
||||
stopRepoHeaderMenuEvent
|
||||
} from './repo-header-event-guards'
|
||||
} from './event-guards'
|
||||
|
||||
export function ProjectGroupHeaderMenu({
|
||||
groupId,
|
||||
+23
-8
@@ -25,21 +25,36 @@ import {
|
||||
import { cn } from '@/lib/utils'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { getRepositoryIconSectionId } from '@/components/settings/repository-settings-targets'
|
||||
import type { ProjectGroup } from '../../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../../shared/repo-types'
|
||||
import type { WorktreeVisibilityDefaults } from '../../../../../shared/global-settings-types'
|
||||
import { isGitRepoKind } from '../../../../../shared/repo-kind'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { WorktreeVisibilityDefaults } from '../../../../../../shared/global-settings-types'
|
||||
import { isGitRepoKind } from '../../../../../../shared/repo-kind'
|
||||
import {
|
||||
effectiveExternalWorktreeVisibility,
|
||||
isLegacyRepoForExternalWorktreeVisibility
|
||||
} from '../../../../../../shared/worktree/ownership'
|
||||
import {
|
||||
REPO_HEADER_ACTION_BUTTON_CLASS,
|
||||
REPO_HEADER_ACTION_REVEAL_CLASS
|
||||
} from '../repo-header-action-button-class'
|
||||
import type { getRepoHeaderCreateState } from '../repo-header-create-state'
|
||||
} from '../../repo-header-action-button-class'
|
||||
import type { getRepoHeaderCreateState } from '../../repo-header-create-state'
|
||||
import {
|
||||
handleRepoHeaderActionPointerDown,
|
||||
stopRepoHeaderKeyboardToggle,
|
||||
stopRepoHeaderMenuEvent
|
||||
} from './repo-header-event-guards'
|
||||
import { getWorktreeVisibilityMenuLabel } from './worktree-visibility-menu-label'
|
||||
} from './event-guards'
|
||||
|
||||
function getWorktreeVisibilityMenuLabel(
|
||||
repo: Repo,
|
||||
visibilityDefaults?: WorktreeVisibilityDefaults
|
||||
): string {
|
||||
const visibility = effectiveExternalWorktreeVisibility(
|
||||
repo,
|
||||
isLegacyRepoForExternalWorktreeVisibility(repo),
|
||||
visibilityDefaults
|
||||
)
|
||||
return visibility === 'show' ? 'Hide non-Orca worktrees' : 'Show hidden worktrees'
|
||||
}
|
||||
|
||||
export type RepoHeaderProjectActions = {
|
||||
getWorktreeVisibilityDefaults: (repo: Repo) => WorktreeVisibilityDefaults | undefined
|
||||
-9
@@ -1,9 +0,0 @@
|
||||
import type { Row } from '../worktree-list-groups'
|
||||
import type { ImportedWorktreeCardActionState } from '../imported-worktrees-card-actions'
|
||||
|
||||
export function canKeepImportedWorktreesHidden(
|
||||
row: Extract<Row, { type: 'imported-worktrees-card' }>,
|
||||
actionState: ImportedWorktreeCardActionState | undefined
|
||||
): boolean {
|
||||
return row.placement === 'repo-group' && actionState?.forceVisible !== true
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { PINNED_GROUP_KEY } from '../worktree-list-groups'
|
||||
import type { HostSectionRow } from '../host-section-rows'
|
||||
|
||||
export type WorktreeItemRow = Extract<HostSectionRow, { type: 'item' }>
|
||||
export type FolderWorkspaceItemRow = Extract<HostSectionRow, { type: 'folder-workspace' }>
|
||||
|
||||
export function isWorktreeItemRow(row: HostSectionRow): row is WorktreeItemRow {
|
||||
return row.type === 'item'
|
||||
}
|
||||
|
||||
export function isPinnedWorktreeRow(row: WorktreeItemRow): boolean {
|
||||
return row.sectionKey === PINNED_GROUP_KEY
|
||||
}
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
import type { ProjectGroup } from '../../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../../shared/worktree/types'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import {
|
||||
getProjectGroupHeaderKey,
|
||||
PINNED_GROUP_KEY,
|
||||
type ProjectGroupingModel
|
||||
} from '../worktree-list-groups'
|
||||
} from '../rows/groups'
|
||||
|
||||
function getProjectIdFromHeaderRowKey(rowKey: string): string | null {
|
||||
if (!rowKey.startsWith('project:')) {
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import { folderWorkspaceKey } from '../../../../shared/workspace-scope'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import { folderWorkspaceKey } from '../../../../../../shared/workspace-scope'
|
||||
import {
|
||||
getFolderWorkspaceRevealGroupKeys,
|
||||
getKnownSidebarWorktreeById,
|
||||
sidebarWorkspaceStillExists
|
||||
} from './worktree-list-folder-reveal'
|
||||
import { getProjectGroupHeaderKey } from './worktree-list-groups'
|
||||
} from './folder-reveal'
|
||||
import { getProjectGroupHeaderKey } from '../rows/groups'
|
||||
|
||||
function makeFolderWorkspace(overrides: Partial<FolderWorkspace> = {}): FolderWorkspace {
|
||||
return {
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import { folderWorkspaceToWorktree } from '../../../../shared/folder-workspace-worktree'
|
||||
import { parseWorkspaceKey } from '../../../../shared/workspace-scope'
|
||||
import { getProjectGroupHeaderKey } from './worktree-list-groups'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import { folderWorkspaceToWorktree } from '../../../../../../shared/folder-workspace-worktree'
|
||||
import { parseWorkspaceKey } from '../../../../../../shared/workspace-scope'
|
||||
import { getProjectGroupHeaderKey } from '../rows/groups'
|
||||
|
||||
function findFolderWorkspaceByKey(
|
||||
worktreeId: string,
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { revealElementInScrollContainer } from '../worktree-sidebar-reveal'
|
||||
import { getMountedWorktreeOptions, getWorktreeOptionId } from './worktree-option-dom'
|
||||
import { revealElementInScrollContainer } from '../../worktree-sidebar-reveal'
|
||||
import { getMountedWorktreeOptions, getWorktreeOptionId } from '../option-dom'
|
||||
|
||||
export function revealMountedWorktreeElement(
|
||||
container: HTMLElement,
|
||||
+12
-12
@@ -2,24 +2,24 @@ import type React from 'react'
|
||||
import type { Virtualizer } from '@tanstack/react-virtual'
|
||||
import type { AppState } from '@/store/types'
|
||||
import type { PendingSidebarRowReveal, PendingSidebarWorktreeReveal } from '@/store/slices/ui'
|
||||
import type { FolderWorkspace } from '../../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../../shared/repo-types'
|
||||
import type { WorkspaceStatusDefinition, Worktree } from '../../../../../shared/worktree/types'
|
||||
import type { WorktreeLineage } from '../../../../../shared/worktree/lineage-types'
|
||||
import type { ExecutionHostId } from '../../../../../shared/execution-host'
|
||||
import { getWorktreeExecutionHostId } from '../../../../../shared/execution-host'
|
||||
import type { RenderRow } from '../worktree-list-virtual-rows'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { WorkspaceStatusDefinition, Worktree } from '../../../../../../shared/worktree/types'
|
||||
import type { WorktreeLineage } from '../../../../../../shared/worktree/lineage-types'
|
||||
import type { ExecutionHostId } from '../../../../../../shared/execution-host'
|
||||
import { getWorktreeExecutionHostId } from '../../../../../../shared/execution-host'
|
||||
import type { RenderRow } from '../viewport/virtual-rows'
|
||||
import {
|
||||
getGroupKeysForWorktree,
|
||||
getLineageGroupKey,
|
||||
type PinnedWorktreeDisplayPolicy,
|
||||
type ProjectGroupingModel,
|
||||
type WorktreeGroupBy
|
||||
} from '../worktree-list-groups'
|
||||
import { getWorktreeLineageAncestors } from '../worktree-lineage-projection'
|
||||
import { getFolderWorkspaceRevealGroupKeys } from '../worktree-list-folder-reveal'
|
||||
import { getPinnedWorktreeRevealCollapsedGroupKeys } from './sidebar-row-reveal-ancestors'
|
||||
} from '../rows/groups'
|
||||
import { getWorktreeLineageAncestors } from '../../worktree-lineage-projection'
|
||||
import { getFolderWorkspaceRevealGroupKeys } from './folder-reveal'
|
||||
import { getPinnedWorktreeRevealCollapsedGroupKeys } from './ancestors'
|
||||
|
||||
export const MAX_REVEAL_RETRIES = 8
|
||||
|
||||
+7
-7
@@ -2,21 +2,21 @@ import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { useAppStore } from '@/store'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { getRenderRowOptionId } from './active-descendant-option'
|
||||
import { getRenderRowOptionId } from '../viewport/active-descendant-option'
|
||||
import {
|
||||
findPreferredRenderRowIndexForWorktree,
|
||||
getRenderRowSidebarKey,
|
||||
rowKeyMatchesRenderRow
|
||||
} from './render-row-worktree-lookup'
|
||||
import { revealMountedSidebarRowElement, revealMountedWorktreeElement } from './mounted-row-reveal'
|
||||
import { getSidebarRowRevealAncestorKeys } from './sidebar-row-reveal-ancestors'
|
||||
import { sidebarWorkspaceStillExists } from '../worktree-list-folder-reveal'
|
||||
import { resolvePendingSidebarReveal } from './worktree-sidebar-scroll-tuning'
|
||||
} from '../rows/render-row-lookup'
|
||||
import { revealMountedSidebarRowElement, revealMountedWorktreeElement } from './mounted-row'
|
||||
import { getSidebarRowRevealAncestorKeys } from './ancestors'
|
||||
import { sidebarWorkspaceStillExists } from './folder-reveal'
|
||||
import { resolvePendingSidebarReveal } from '../scroll/tuning'
|
||||
import {
|
||||
expandGroupsForWorktreeReveal,
|
||||
MAX_REVEAL_RETRIES,
|
||||
type PendingSidebarRevealArgs
|
||||
} from './pending-sidebar-reveal-inputs'
|
||||
} from './pending-inputs'
|
||||
|
||||
// Drives the store's two pending reveal requests (a worktree card, or any sidebar row)
|
||||
// from "expand the ancestors" through "scroll the mounted element into view".
|
||||
+4
-4
@@ -4,10 +4,10 @@ import {
|
||||
SCROLL_TO_CURRENT_WORKSPACE_REVEAL_REQUEST_EVENT,
|
||||
type ScrollToCurrentWorkspaceRevealRequestDetail
|
||||
} from '@/lib/scroll-to-current-workspace-status'
|
||||
import type { FolderWorkspace } from '../../../../../shared/folder-workspace-types'
|
||||
import type { Worktree } from '../../../../../shared/worktree/types'
|
||||
import type { WorktreeGroupBy } from '../worktree-list-groups'
|
||||
import { getKnownSidebarWorktreeById } from '../worktree-list-folder-reveal'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import type { WorktreeGroupBy } from '../rows/groups'
|
||||
import { getKnownSidebarWorktreeById } from './folder-reveal'
|
||||
|
||||
// Turns a "show me the current workspace" request into whatever the sidebar must change
|
||||
// first — grouping mode, active filters — before the viewport can scroll to it.
|
||||
+14
-14
@@ -1,23 +1,23 @@
|
||||
import React from 'react'
|
||||
import type { VirtualItem } from '@tanstack/react-virtual'
|
||||
import type { AppState } from '@/store/types'
|
||||
import type { Repo } from '../../../../../shared/repo-types'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type {
|
||||
WorkspaceLineage,
|
||||
WorktreeLineage
|
||||
} from '../../../../../shared/worktree/lineage-types'
|
||||
import type { Worktree } from '../../../../../shared/worktree/types'
|
||||
import type { FolderWorkspacePathStatus } from '../../../../../shared/folder-workspace-path-status'
|
||||
import { isConfirmedStaleFolderPathStatus } from '../../../../../shared/folder-workspace-path-status'
|
||||
import { folderWorkspaceToWorktree } from '../../../../../shared/folder-workspace-worktree'
|
||||
import WorktreeCard from '../WorktreeCard'
|
||||
import type { WorktreeGroupBy } from '../worktree-list-groups'
|
||||
import { getVirtualRowTransform } from '../worktree-list-virtual-rows'
|
||||
import { getFolderWorkspaceRowGeometry } from '../worktree-list-indentation'
|
||||
import { getFolderWorkspaceCardPrDisplay } from '../folder-workspace-card-pr-display'
|
||||
import { FolderPathStatusIndicator } from './FolderPathStatusIndicator'
|
||||
import type { FolderWorkspaceItemRow } from './render-row-item-rows'
|
||||
import { getWorktreeOptionId } from './worktree-option-dom'
|
||||
} from '../../../../../../shared/worktree/lineage-types'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import type { FolderWorkspacePathStatus } from '../../../../../../shared/folder-workspace-path-status'
|
||||
import { isConfirmedStaleFolderPathStatus } from '../../../../../../shared/folder-workspace-path-status'
|
||||
import { folderWorkspaceToWorktree } from '../../../../../../shared/folder-workspace-worktree'
|
||||
import WorktreeCard from '../../WorktreeCard'
|
||||
import type { WorktreeGroupBy } from './groups'
|
||||
import { getVirtualRowTransform } from '../viewport/virtual-rows'
|
||||
import { getFolderWorkspaceRowGeometry } from './indentation'
|
||||
import { getFolderWorkspaceCardPrDisplay } from '../../folder-workspace-card-pr-display'
|
||||
import { FolderPathStatusIndicator } from '../headers/FolderPathStatusIndicator'
|
||||
import type { FolderWorkspaceItemRow } from './renderable-rows'
|
||||
import { getWorktreeOptionId } from '../option-dom'
|
||||
|
||||
export type FolderWorkspaceRowContext = {
|
||||
groupBy: WorktreeGroupBy
|
||||
+13
-13
@@ -2,8 +2,8 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { getExecutionHostLabel } from '../../../../shared/execution-host'
|
||||
import { projectHostSetupProjectionFromRepos } from '../../../../shared/project-host-setup-projection'
|
||||
import { getExecutionHostLabel } from '../../../../../../shared/execution-host'
|
||||
import { projectHostSetupProjectionFromRepos } from '../../../../../../shared/project-host-setup-projection'
|
||||
import {
|
||||
ALL_GROUP_META,
|
||||
buildRows,
|
||||
@@ -14,18 +14,18 @@ import {
|
||||
getPRGroupKey,
|
||||
PINNED_GROUP_KEY,
|
||||
type PendingCreationRef
|
||||
} from './worktree-list-groups'
|
||||
} from './groups'
|
||||
import {
|
||||
REPO_HEADER_ACTION_BUTTON_CLASS,
|
||||
REPO_HEADER_ACTION_REVEAL_CLASS
|
||||
} from './repo-header-action-button-class'
|
||||
import { getWorktreeLineageAncestors } from './worktree-lineage-projection'
|
||||
import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { Project, ProjectHostSetup } from '../../../../shared/project-types'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { WorktreeLineage } from '../../../../shared/worktree/lineage-types'
|
||||
import type { DetectedWorktree, Worktree } from '../../../../shared/worktree/types'
|
||||
} from '../../repo-header-action-button-class'
|
||||
import { getWorktreeLineageAncestors } from '../../worktree-lineage-projection'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { Project, ProjectHostSetup } from '../../../../../../shared/project-types'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { WorktreeLineage } from '../../../../../../shared/worktree/lineage-types'
|
||||
import type { DetectedWorktree, Worktree } from '../../../../../../shared/worktree/types'
|
||||
|
||||
const LOCAL_HOST_LABEL = getExecutionHostLabel('local')
|
||||
|
||||
@@ -60,12 +60,12 @@ const worktree: Worktree = {
|
||||
const repoMap = new Map([[repo.id, repo]])
|
||||
|
||||
function readWorktreeListSource(): string {
|
||||
return readFileSync(fileURLToPath(new URL('./WorktreeList.tsx', import.meta.url)), 'utf8')
|
||||
return readFileSync(fileURLToPath(new URL('../../WorktreeList.tsx', import.meta.url)), 'utf8')
|
||||
}
|
||||
|
||||
function readSectionHeaderRowSource(): string {
|
||||
return readFileSync(
|
||||
fileURLToPath(new URL('./worktree-list/worktree-section-header-row.tsx', import.meta.url)),
|
||||
fileURLToPath(new URL('../headers/SectionHeader.tsx', import.meta.url)),
|
||||
'utf8'
|
||||
)
|
||||
}
|
||||
+22
-19
@@ -1,36 +1,39 @@
|
||||
/* eslint-disable max-lines -- Why: sidebar row construction keeps every grouping mode in one pure module so reveal, virtualized rendering, and tests share the same flat row contract. */
|
||||
import { CircleX, FolderTree, List, Pin } from 'lucide-react'
|
||||
import type React from 'react'
|
||||
import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { Project, ProjectHostSetup } from '../../../../shared/project-types'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { ProjectOrderBy } from '../../../../shared/ui-chrome-types'
|
||||
import type { WorktreeLineage } from '../../../../shared/worktree/lineage-types'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { Project, ProjectHostSetup } from '../../../../../../shared/project-types'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { ProjectOrderBy } from '../../../../../../shared/ui-chrome-types'
|
||||
import type { WorktreeLineage } from '../../../../../../shared/worktree/lineage-types'
|
||||
import type {
|
||||
DetectedWorktree,
|
||||
WorkspaceStatusDefinition,
|
||||
Worktree
|
||||
} from '../../../../shared/worktree/types'
|
||||
import { branchName } from '../../lib/git-utils'
|
||||
} from '../../../../../../shared/worktree/types'
|
||||
import { branchName } from '../../../../lib/git-utils'
|
||||
import {
|
||||
getWorkspaceStatus,
|
||||
getWorkspaceStatusFromGroupKey,
|
||||
getWorkspaceStatusGroupKey,
|
||||
getWorkspaceStatusVisualMeta
|
||||
} from './workspace-status'
|
||||
} from '../../workspace-status'
|
||||
import {
|
||||
ConductorDoneIcon,
|
||||
ConductorProgressIcon,
|
||||
ConductorReviewIcon
|
||||
} from './workspace-status-icons'
|
||||
} from '../../workspace-status-icons'
|
||||
import {
|
||||
getEffectiveProjectGroupManualRank,
|
||||
UNGROUPED_PROJECT_GROUP_KEY
|
||||
} from '../../../../shared/project-groups'
|
||||
import { cloneDefaultWorkspaceStatuses } from '../../../../shared/workspace-statuses'
|
||||
import type { AppState } from '../../store/types'
|
||||
import { getGitHubPRCacheKey, getLegacyGitHubPRCacheKey } from '../../store/slices/github-cache-key'
|
||||
} from '../../../../../../shared/project-groups'
|
||||
import { cloneDefaultWorkspaceStatuses } from '../../../../../../shared/workspace-statuses'
|
||||
import type { AppState } from '../../../../store/types'
|
||||
import {
|
||||
getGitHubPRCacheKey,
|
||||
getLegacyGitHubPRCacheKey
|
||||
} from '../../../../store/slices/github-cache-key'
|
||||
import { getRepoDisplayLabelKey, getRepoDisplayLabelsByPath } from '@/lib/repo-display-labels'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import {
|
||||
@@ -40,18 +43,18 @@ import {
|
||||
getWorktreeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../../shared/execution-host'
|
||||
import { parseWslUncPath } from '../../../../shared/wsl-paths'
|
||||
} from '../../../../../../shared/execution-host'
|
||||
import { parseWslUncPath } from '../../../../../../shared/wsl-paths'
|
||||
import {
|
||||
isWindowsAbsolutePathLike,
|
||||
normalizeRuntimePathForComparison
|
||||
} from '../../../../shared/cross-platform-path'
|
||||
} from '../../../../../../shared/cross-platform-path'
|
||||
import {
|
||||
getCyclicProjectedWorktreeLineageIds,
|
||||
getLineageRenderInfo
|
||||
} from './worktree-lineage-projection'
|
||||
} from '../../worktree-lineage-projection'
|
||||
|
||||
export { getLineageRenderInfo } from './worktree-lineage-projection'
|
||||
export { getLineageRenderInfo } from '../../worktree-lineage-projection'
|
||||
|
||||
export { branchName }
|
||||
|
||||
+7
-7
@@ -1,11 +1,11 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { canKeepImportedWorktreesHidden } from './worktree-list/imported-worktrees-card-visibility'
|
||||
import { getRenderRowKey } from './worktree-list-virtual-rows'
|
||||
import { getWorktreeDragGroups, getWorktreeDragIndexes } from './worktree-list/worktree-drag-groups'
|
||||
import { renderRowContainsWorktree } from './worktree-list/render-row-worktree-lookup'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../shared/worktree/types'
|
||||
import type { Row } from './worktree-list-groups'
|
||||
import { canKeepImportedWorktreesHidden } from './notice-rows'
|
||||
import { getRenderRowKey } from '../viewport/virtual-rows'
|
||||
import { getWorktreeDragGroups, getWorktreeDragIndexes } from '../drag/groups'
|
||||
import { renderRowContainsWorktree } from './render-row-lookup'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import type { Row } from './groups'
|
||||
|
||||
const repo: Repo = {
|
||||
id: 'repo-1',
|
||||
+1
-1
@@ -20,7 +20,7 @@ import {
|
||||
getProjectGroupHeaderPaddingLeft,
|
||||
getWorktreeCardContentIndent,
|
||||
getWorktreeCardSurfaceInset
|
||||
} from './worktree-list-indentation'
|
||||
} from './indentation'
|
||||
|
||||
function getFlushCardContentStart(args: {
|
||||
surfaceInset: number
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { AppState } from '@/store/types'
|
||||
import type { Worktree } from '../../../../../shared/worktree/types'
|
||||
import WorktreeCard, { type ActiveSurfaceVariant } from '../WorktreeCard'
|
||||
import { PINNED_GROUP_KEY, type WorktreeGroupBy } from '../worktree-list-groups'
|
||||
import type { Worktree } from '../../../../../../shared/worktree/types'
|
||||
import WorktreeCard, { type ActiveSurfaceVariant } from '../../WorktreeCard'
|
||||
import { PINNED_GROUP_KEY, type WorktreeGroupBy } from './groups'
|
||||
import {
|
||||
getFolderBackedRepoWorktreeCardContentIndent,
|
||||
getFolderBackedRepoWorktreeCardSurfaceInset,
|
||||
@@ -12,12 +12,12 @@ import {
|
||||
getWorktreeCardContentIndent,
|
||||
getWorktreeCardSurfaceInset,
|
||||
LINEAGE_CHILDREN_INLINE_OFFSET
|
||||
} from '../worktree-list-indentation'
|
||||
import type { LineageToggleHandler } from '../worktree-lineage-toggle-handler-cache'
|
||||
import { stopNestedWorktreeCardBubble } from './repo-header-event-guards'
|
||||
import type { WorktreeItemRow } from './render-row-item-rows'
|
||||
import { getWorktreeOptionId } from './worktree-option-dom'
|
||||
import type { WorktreePointerDrag, WorktreeRowDragState } from './worktree-row-drag-state'
|
||||
} from './indentation'
|
||||
import type { LineageToggleHandler } from '../../worktree-lineage-toggle-handler-cache'
|
||||
import { stopNestedWorktreeCardBubble } from '../headers/event-guards'
|
||||
import type { WorktreeItemRow } from './renderable-rows'
|
||||
import { getWorktreeOptionId } from '../option-dom'
|
||||
import type { WorktreePointerDrag, WorktreeRowDragState } from '../drag/row-state'
|
||||
|
||||
export type WorktreeItemRowContext = {
|
||||
settings: AppState['settings']
|
||||
+14
-8
@@ -1,13 +1,19 @@
|
||||
import React from 'react'
|
||||
import type { VirtualItem } from '@tanstack/react-virtual'
|
||||
import type { Row } from '../worktree-list-groups'
|
||||
import { getVirtualRowTransform } from '../worktree-list-virtual-rows'
|
||||
import { PendingWorktreeRow } from '../PendingWorktreeRow'
|
||||
import ImportedWorktreesVisibilityLine from '../ImportedWorktreesVisibilityLine'
|
||||
import NewExternalWorktreesInboxLine from '../NewExternalWorktreesInboxLine'
|
||||
import type { ImportedWorktreeCardActionState } from '../imported-worktrees-card-actions'
|
||||
import type { NewExternalWorktreesInboxActionState } from '../new-external-worktrees-inbox-actions'
|
||||
import { canKeepImportedWorktreesHidden } from './imported-worktrees-card-visibility'
|
||||
import type { Row } from './groups'
|
||||
import { getVirtualRowTransform } from '../viewport/virtual-rows'
|
||||
import { PendingWorktreeRow } from '../../PendingWorktreeRow'
|
||||
import ImportedWorktreesVisibilityLine from '../../ImportedWorktreesVisibilityLine'
|
||||
import NewExternalWorktreesInboxLine from '../../NewExternalWorktreesInboxLine'
|
||||
import type { ImportedWorktreeCardActionState } from '../../imported-worktrees-card-actions'
|
||||
import type { NewExternalWorktreesInboxActionState } from '../../new-external-worktrees-inbox-actions'
|
||||
|
||||
export function canKeepImportedWorktreesHidden(
|
||||
row: Extract<Row, { type: 'imported-worktrees-card' }>,
|
||||
actionState: ImportedWorktreeCardActionState | undefined
|
||||
): boolean {
|
||||
return row.placement === 'repo-group' && actionState?.forceVisible !== true
|
||||
}
|
||||
|
||||
type NoticeRowFrameProps = {
|
||||
vItem: VirtualItem
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
import { folderWorkspaceKey } from '../../../../../shared/workspace-scope'
|
||||
import type { RenderRow } from '../worktree-list-virtual-rows'
|
||||
import type { PinnedWorktreeDisplayPolicy } from '../worktree-list-groups'
|
||||
import { isPinnedWorktreeRow, type WorktreeItemRow } from './render-row-item-rows'
|
||||
import { folderWorkspaceKey } from '../../../../../../shared/workspace-scope'
|
||||
import type { RenderRow } from '../viewport/virtual-rows'
|
||||
import type { PinnedWorktreeDisplayPolicy } from './groups'
|
||||
import { isPinnedWorktreeRow, type WorktreeItemRow } from './renderable-rows'
|
||||
|
||||
export function getRenderRowSidebarKey(row: RenderRow): string | null {
|
||||
if (row.type === 'header') {
|
||||
+14
-4
@@ -1,7 +1,17 @@
|
||||
import { getLineageGroupKey } from '../worktree-list-groups'
|
||||
import type { HostSectionRow } from '../host-section-rows'
|
||||
import type { RenderRow } from '../worktree-list-virtual-rows'
|
||||
import { isWorktreeItemRow, type WorktreeItemRow } from './render-row-item-rows'
|
||||
import { getLineageGroupKey, PINNED_GROUP_KEY } from './groups'
|
||||
import type { HostSectionRow } from '../../host-section-rows'
|
||||
import type { RenderRow } from '../viewport/virtual-rows'
|
||||
|
||||
export type WorktreeItemRow = Extract<HostSectionRow, { type: 'item' }>
|
||||
export type FolderWorkspaceItemRow = Extract<HostSectionRow, { type: 'folder-workspace' }>
|
||||
|
||||
export function isWorktreeItemRow(row: HostSectionRow): row is WorktreeItemRow {
|
||||
return row.type === 'item'
|
||||
}
|
||||
|
||||
export function isPinnedWorktreeRow(row: WorktreeItemRow): boolean {
|
||||
return row.sectionKey === PINNED_GROUP_KEY
|
||||
}
|
||||
|
||||
// Collapse a parent and its visible lineage descendants into one virtual row so the card renders them inline.
|
||||
export function buildRenderableRows(rows: HostSectionRow[]): RenderRow[] {
|
||||
+15
-15
@@ -1,20 +1,20 @@
|
||||
import type React from 'react'
|
||||
import type { AppState } from '@/store/types'
|
||||
import type { ProjectGroup } from '../../../../../shared/project-group-types'
|
||||
import type { RenderRow } from '../worktree-list-virtual-rows'
|
||||
import type { LineageToggleHandler } from '../worktree-lineage-toggle-handler-cache'
|
||||
import type { SidebarRevealHighlight } from './use-sidebar-reveal-highlight'
|
||||
import type { WorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import type { WorktreeDragSession } from './use-worktree-drag-session'
|
||||
import type { useFolderWorkspacePathStatusRows } from './use-folder-workspace-path-status-rows'
|
||||
import type { usePrimaryActiveWorktreeRow } from './use-primary-active-worktree-row'
|
||||
import type { useWorkspaceStatusRowDrag } from './use-workspace-status-row-drag'
|
||||
import type { useWorktreeNativeDrag } from './use-worktree-native-drag'
|
||||
import type { WorktreeSidebarHeaderDrag } from './use-worktree-sidebar-header-drag'
|
||||
import type { WorktreeListVirtualizer } from './use-worktree-list-virtualizer'
|
||||
import type { VirtualizedWorktreeViewportProps } from './virtualized-worktree-viewport-props'
|
||||
import type { WorktreeVirtualRowContext } from './worktree-virtual-row-dispatch'
|
||||
import { getRepoOwnerWorktreeVisibilityDefaults } from '../../../store/worktree-visibility-defaults-by-host'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import type { RenderRow } from '../viewport/virtual-rows'
|
||||
import type { LineageToggleHandler } from '../../worktree-lineage-toggle-handler-cache'
|
||||
import type { SidebarRevealHighlight } from '../reveal/use-highlight'
|
||||
import type { WorktreeDragRuntime } from '../drag/use-runtime'
|
||||
import type { WorktreeDragSession } from '../drag/use-session'
|
||||
import type { useFolderWorkspacePathStatusRows } from '../viewport/use-folder-path-statuses'
|
||||
import type { usePrimaryActiveWorktreeRow } from '../viewport/use-active-row'
|
||||
import type { useWorkspaceStatusRowDrag } from '../drag/use-status-row-drag'
|
||||
import type { useWorktreeNativeDrag } from '../drag/use-native-drag'
|
||||
import type { WorktreeSidebarHeaderDrag } from '../drag/use-header-drag'
|
||||
import type { WorktreeListVirtualizer } from '../viewport/use-virtualizer'
|
||||
import type { VirtualizedWorktreeViewportProps } from '../viewport/viewport-props'
|
||||
import type { WorktreeVirtualRowContext } from './virtual-row-dispatch'
|
||||
import { getRepoOwnerWorktreeVisibilityDefaults } from '../../../../store/worktree-visibility-defaults-by-host'
|
||||
|
||||
type BuildArgs = {
|
||||
props: VirtualizedWorktreeViewportProps
|
||||
+14
-17
@@ -4,38 +4,35 @@ import { cn } from '@/lib/utils'
|
||||
import type {
|
||||
WorkspaceStatus,
|
||||
WorkspaceStatusDefinition
|
||||
} from '../../../../../shared/worktree/types'
|
||||
import { getWorkspaceStatus } from '../workspace-status'
|
||||
import type { WorktreeGroupBy } from '../worktree-list-groups'
|
||||
} from '../../../../../../shared/worktree/types'
|
||||
import { getWorkspaceStatus } from '../../workspace-status'
|
||||
import type { WorktreeGroupBy } from './groups'
|
||||
import {
|
||||
getVirtualRowTransform,
|
||||
shouldUseHeaderTopSpacing,
|
||||
type RenderRow
|
||||
} from '../worktree-list-virtual-rows'
|
||||
import type { ImportedWorktreeCardActionState } from '../imported-worktrees-card-actions'
|
||||
import type { NewExternalWorktreesInboxActionState } from '../new-external-worktrees-inbox-actions'
|
||||
import type { useHostHeaderDrag } from '../host-header-drag'
|
||||
import { HostSectionHeader } from './HostSectionHeader'
|
||||
import {
|
||||
renderFolderWorkspaceVirtualRow,
|
||||
type FolderWorkspaceRowContext
|
||||
} from './folder-workspace-virtual-row'
|
||||
} from '../viewport/virtual-rows'
|
||||
import type { ImportedWorktreeCardActionState } from '../../imported-worktrees-card-actions'
|
||||
import type { NewExternalWorktreesInboxActionState } from '../../new-external-worktrees-inbox-actions'
|
||||
import type { useHostHeaderDrag } from '../../host-header-drag'
|
||||
import { HostSectionHeader } from '../headers/HostSectionHeader'
|
||||
import { renderFolderWorkspaceVirtualRow, type FolderWorkspaceRowContext } from './folder-row'
|
||||
import {
|
||||
renderImportedWorktreesVirtualRow,
|
||||
renderNewExternalWorktreesInboxVirtualRow,
|
||||
renderPendingCreationVirtualRow
|
||||
} from './worktree-notice-virtual-rows'
|
||||
} from './notice-rows'
|
||||
import {
|
||||
renderWorktreeItemRow,
|
||||
renderWorktreeLineageDescendants,
|
||||
type WorktreeItemRowContext
|
||||
} from './worktree-list-item-row'
|
||||
} from './item-row'
|
||||
import {
|
||||
renderWorktreeSectionHeaderRow,
|
||||
type SectionHeaderRowContext
|
||||
} from './worktree-section-header-row'
|
||||
import { getWorktreeVirtualRowTransform } from './virtual-row-dom-attributes'
|
||||
import type { WorktreeRowDragState } from './worktree-row-drag-state'
|
||||
} from '../headers/SectionHeader'
|
||||
import { getWorktreeVirtualRowTransform } from '../viewport/virtual-rows'
|
||||
import type { WorktreeRowDragState } from '../drag/row-state'
|
||||
|
||||
export type WorktreeVirtualRowContext = {
|
||||
renderRows: RenderRow[]
|
||||
+1
-1
@@ -7,7 +7,7 @@ import {
|
||||
reduceHardScrollUpOnIdle,
|
||||
reduceHardScrollUpOnScroll,
|
||||
reduceHardScrollUpOnWheel
|
||||
} from './worktree-list-hard-scroll-up'
|
||||
} from './hard-scroll-up'
|
||||
|
||||
const DEEP = {
|
||||
scrollTop: 1200,
|
||||
+5
-5
@@ -3,19 +3,19 @@ import {
|
||||
countRecordKeysByReference,
|
||||
resolvePendingSidebarReveal,
|
||||
shouldAdjustWorktreeSidebarMeasuredRowScroll
|
||||
} from './worktree-list/worktree-sidebar-scroll-tuning'
|
||||
} from './tuning'
|
||||
import {
|
||||
getScrollTopToRevealBounds,
|
||||
WORKTREE_SIDEBAR_REVEAL_TOP_INSET
|
||||
} from './worktree-sidebar-reveal'
|
||||
} from '../../worktree-sidebar-reveal'
|
||||
import {
|
||||
extractWorktreeVirtualRowIndexes,
|
||||
estimateRenderRowSize,
|
||||
GROUP_HEADER_ROW_HEIGHT,
|
||||
getActiveStickyHeaderIndexForScroll
|
||||
} from './worktree-list-virtual-rows'
|
||||
import type { Repo } from '../../../../shared/repo-types'
|
||||
import type { Row } from './worktree-list-groups'
|
||||
} from '../viewport/virtual-rows'
|
||||
import type { Repo } from '../../../../../../shared/repo-types'
|
||||
import type { Row } from '../rows/groups'
|
||||
|
||||
const repo: Repo = {
|
||||
id: 'repo-1',
|
||||
+5
@@ -40,3 +40,8 @@ export function resolvePendingSidebarReveal(args: {
|
||||
}
|
||||
return args.targetWorktreeStillExists ? 'keep-pending' : 'clear'
|
||||
}
|
||||
|
||||
export function installWorktreeVisibleRefreshVisibilityListener(onChange: () => void): () => void {
|
||||
document.addEventListener('visibilitychange', onChange)
|
||||
return () => document.removeEventListener('visibilitychange', onChange)
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
// @vitest-environment happy-dom
|
||||
import { act, renderHook } from '@testing-library/react'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useWorktreeListScrollToTop } from './use-worktree-list-scroll-to-top'
|
||||
import { HARD_SCROLL_UP } from './worktree-list-hard-scroll-up'
|
||||
import { useWorktreeListScrollToTop } from './use-scroll-to-top'
|
||||
import { HARD_SCROLL_UP } from './hard-scroll-up'
|
||||
|
||||
let clockMs = 0
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
import { act, cleanup, renderHook } from '@testing-library/react'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { useWorktreeListScrollToTop } from './use-worktree-list-scroll-to-top'
|
||||
import { useWorktreeListScrollToTop } from './use-scroll-to-top'
|
||||
|
||||
function createScroller(): HTMLElement {
|
||||
const element = document.createElement('div')
|
||||
+1
-1
@@ -7,7 +7,7 @@ import {
|
||||
reduceHardScrollUpOnScroll,
|
||||
reduceHardScrollUpOnWheel,
|
||||
type HardScrollUpDetectorState
|
||||
} from './worktree-list-hard-scroll-up'
|
||||
} from './hard-scroll-up'
|
||||
|
||||
function readViewport(element: HTMLElement): { scrollTop: number; maxScroll: number } {
|
||||
const maxScroll = Math.max(0, element.scrollHeight - element.clientHeight)
|
||||
+3
-3
@@ -1,15 +1,15 @@
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import type React from 'react'
|
||||
import { SUPPRESS_WORKTREE_LIST_SCROLL_ADJUSTMENT_EVENT } from '../WorktreeCardAgents'
|
||||
import { SUPPRESS_WORKTREE_LIST_SCROLL_ADJUSTMENT_EVENT } from '../../WorktreeCardAgents'
|
||||
import {
|
||||
createPendingRevealScroll,
|
||||
isRevealScrollSettling,
|
||||
type PendingRevealScroll
|
||||
} from '../worktree-sidebar-reveal-scroll-settle'
|
||||
} from '../../worktree-sidebar-reveal-scroll-settle'
|
||||
import {
|
||||
EXPANDING_CARD_MEASUREMENT_ADJUSTMENT_SUPPRESS_MS,
|
||||
USER_SCROLL_MEASUREMENT_ADJUSTMENT_SUPPRESS_MS
|
||||
} from './worktree-sidebar-scroll-tuning'
|
||||
} from './tuning'
|
||||
|
||||
export type WorktreeSidebarScrollSuppression = ReturnType<
|
||||
typeof useWorktreeSidebarScrollSuppression
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { installWorktreeVisibleRefreshVisibilityListener } from './worktree-list/worktree-visible-refresh-listener'
|
||||
import { installWorktreeVisibleRefreshVisibilityListener } from './tuning'
|
||||
|
||||
describe('installWorktreeVisibleRefreshVisibilityListener', () => {
|
||||
beforeEach(() => {
|
||||
@@ -1,19 +0,0 @@
|
||||
export function isEditableTarget(target: EventTarget | null): boolean {
|
||||
if (!(target instanceof HTMLElement)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// xterm's hidden input textarea isn't a real text field; treating it as one would block sidebar shortcuts.
|
||||
if (target.classList.contains('xterm-helper-textarea')) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (target.isContentEditable) {
|
||||
return true
|
||||
}
|
||||
|
||||
return (
|
||||
target.closest('input, textarea, select, [contenteditable=""], [contenteditable="true"]') !==
|
||||
null
|
||||
)
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
import type { AppState } from '@/store/types'
|
||||
|
||||
// Why: selectors that opt out of a slice must return one stable reference, or every store tick looks like a change.
|
||||
export const EMPTY_AGENT_STATUS_BY_PANE_KEY: AppState['agentStatusByPaneKey'] = {}
|
||||
export const EMPTY_WORKTREE_ID_SET: ReadonlySet<string> = new Set()
|
||||
export const EMPTY_TABS_BY_WORKTREE: AppState['tabsByWorktree'] = {}
|
||||
export const EMPTY_TERMINAL_LAYOUTS_BY_TAB_ID: AppState['terminalLayoutsByTabId'] = {}
|
||||
export const EMPTY_PTY_IDS_BY_TAB_ID: AppState['ptyIdsByTabId'] = {}
|
||||
export const EMPTY_RUNTIME_PANE_TITLES_BY_TAB_ID: AppState['runtimePaneTitlesByTabId'] = {}
|
||||
@@ -1,13 +1,14 @@
|
||||
import { useMemo } from 'react'
|
||||
import { useAppStore } from '@/store'
|
||||
import type { AppState } from '@/store/types'
|
||||
import { deriveRunningAgentSendTargets } from '@/lib/running-agent-targets'
|
||||
import {
|
||||
EMPTY_AGENT_STATUS_BY_PANE_KEY,
|
||||
EMPTY_PTY_IDS_BY_TAB_ID,
|
||||
EMPTY_RUNTIME_PANE_TITLES_BY_TAB_ID,
|
||||
EMPTY_TABS_BY_WORKTREE,
|
||||
EMPTY_TERMINAL_LAYOUTS_BY_TAB_ID
|
||||
} from './stable-empty-store-slices'
|
||||
|
||||
// Why: selectors that opt out of a slice must return one stable reference, or every store tick looks like a change.
|
||||
const EMPTY_AGENT_STATUS_BY_PANE_KEY: AppState['agentStatusByPaneKey'] = {}
|
||||
const EMPTY_TABS_BY_WORKTREE: AppState['tabsByWorktree'] = {}
|
||||
const EMPTY_TERMINAL_LAYOUTS_BY_TAB_ID: AppState['terminalLayoutsByTabId'] = {}
|
||||
const EMPTY_PTY_IDS_BY_TAB_ID: AppState['ptyIdsByTabId'] = {}
|
||||
const EMPTY_RUNTIME_PANE_TITLES_BY_TAB_ID: AppState['runtimePaneTitlesByTabId'] = {}
|
||||
|
||||
// The agent send picker forces its target workspace visible, but only while a running
|
||||
// agent there can actually receive the message.
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
PINNED_GROUP_KEY,
|
||||
type ProjectGroupingModel,
|
||||
type WorktreeGroupBy
|
||||
} from '../worktree-list-groups'
|
||||
} from './rows/groups'
|
||||
import { getWorktreeLineageAncestors } from '../worktree-lineage-projection'
|
||||
|
||||
// While the agent send picker targets a workspace, force open every section that hides it.
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
filterFolderWorkspacesForVisibleHosts,
|
||||
filterProjectGroupsForVisibleHosts,
|
||||
getVisibleSidebarHostIdSet
|
||||
} from '../worktree-list-host-filtering'
|
||||
} from './viewport/host-filtering'
|
||||
|
||||
// Narrows repos, project groups, and folder workspaces to the hosts (and devices) the
|
||||
// current host filter admits.
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
type ProjectGroupingModel,
|
||||
type Row,
|
||||
type WorktreeGroupBy
|
||||
} from '../worktree-list-groups'
|
||||
} from './rows/groups'
|
||||
import { getLogicalRepoOrderRankById } from '../project-header-drop'
|
||||
import { getEmptyProjectPlaceholderRepoIds } from '../empty-project-placeholder-repos'
|
||||
import { addHostSectionRows } from '../host-section-rows'
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from 'reac
|
||||
import type React from 'react'
|
||||
import type { Worktree } from '../../../../../shared/worktree/types'
|
||||
import type { HostSectionRow } from '../host-section-rows'
|
||||
import type { PinnedWorktreeDisplayPolicy } from '../worktree-list-groups'
|
||||
import type { PinnedWorktreeDisplayPolicy } from './rows/groups'
|
||||
import { getRenderedWorktreesInSidebarOrder } from '../worktree-sidebar-row-preference'
|
||||
import { setVisibleWorktreeIds } from '../visible-worktrees'
|
||||
import {
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import {
|
||||
type WorktreeAttention
|
||||
} from '../smart-attention'
|
||||
import { useReusedArrayIdentity } from './use-reused-array-identity'
|
||||
import { SORT_SETTLE_MS } from './worktree-sidebar-scroll-tuning'
|
||||
import { SORT_SETTLE_MS } from './scroll/tuning'
|
||||
|
||||
function trackSmartClassDistribution(attention: ReadonlyMap<string, WorktreeAttention>): void {
|
||||
let class1 = 0
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ import {
|
||||
} from '../worktree-manual-order'
|
||||
import { buildWorkspaceKanbanSidebarDropUpdates } from '../workspace-kanban-sidebar-drop'
|
||||
import type { SortBy } from '../smart-sort'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from './virtualized-worktree-viewport-props'
|
||||
import type { WorktreeStatusDropAtIndexArgs } from './viewport/viewport-props'
|
||||
|
||||
function buildRankByWorktreeId(
|
||||
groups: readonly WorktreeDragGroup[],
|
||||
@@ -17,9 +17,10 @@ import {
|
||||
} from '../visible-worktree-activity-inputs'
|
||||
import type { SortBy } from '../smart-sort'
|
||||
import type { SidebarWorktreeFilters } from './use-sidebar-worktree-filters'
|
||||
import { EMPTY_WORKTREE_ID_SET } from './stable-empty-store-slices'
|
||||
import { useReusedArrayIdentity } from './use-reused-array-identity'
|
||||
|
||||
const EMPTY_WORKTREE_ID_SET: ReadonlySet<string> = new Set()
|
||||
|
||||
// Applies every sidebar filter to the sorted id stream. Flatten/filter/sort goes through the
|
||||
// shared utility so card order matches Cmd+1–9 numbering.
|
||||
export function useVisibleSidebarWorktrees(args: {
|
||||
|
||||
+27
-30
@@ -1,37 +1,34 @@
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react'
|
||||
import { useAppStore } from '@/store'
|
||||
import { translate } from '@/i18n/i18n'
|
||||
import { WorktreeSidebarDropIndicator } from '../WorktreeSidebarDropIndicator'
|
||||
import { WorktreeListScrollToTopButton } from '../WorktreeListScrollToTopButton'
|
||||
import { useWorktreeListScrollToTop } from '../use-worktree-list-scroll-to-top'
|
||||
import { WorktreeSidebarDropIndicator } from '../../WorktreeSidebarDropIndicator'
|
||||
import { WorktreeListScrollToTopButton } from '../../WorktreeListScrollToTopButton'
|
||||
import { useWorktreeListScrollToTop } from '../scroll/use-scroll-to-top'
|
||||
import { getActiveDescendantOptionId } from './active-descendant-option'
|
||||
import { buildRenderableRows } from './renderable-rows'
|
||||
import { useFolderWorkspacePathStatusRows } from './use-folder-workspace-path-status-rows'
|
||||
import { useGroupToggleWithScrollAnchor } from './use-group-toggle-with-scroll-anchor'
|
||||
import { usePendingSidebarReveal } from './use-pending-sidebar-reveal'
|
||||
import { usePrimaryActiveWorktreeRow } from './use-primary-active-worktree-row'
|
||||
import { useSidebarRevealHighlight } from './use-sidebar-reveal-highlight'
|
||||
import { useVirtualRowMeasurementSync } from './use-virtual-row-measurement-sync'
|
||||
import { useVisiblePrRefreshReporting } from './use-visible-pr-refresh-reporting'
|
||||
import { useWorkspaceStatusRowDrag } from './use-workspace-status-row-drag'
|
||||
import { useWorktreeDragRuntime } from './use-worktree-drag-runtime'
|
||||
import { useWorktreeDragSession } from './use-worktree-drag-session'
|
||||
import { useWorktreeDocumentDrop } from './use-worktree-document-drop'
|
||||
import { useWorktreeLineageDropCommit } from './use-worktree-lineage-drop-commit'
|
||||
import { useWorktreeListKeyboardNavigation } from './use-worktree-list-keyboard-navigation'
|
||||
import { useWorktreeListVirtualizer } from './use-worktree-list-virtualizer'
|
||||
import { useWorktreeNativeDrag } from './use-worktree-native-drag'
|
||||
import { useWorktreePointerDrag } from './use-worktree-pointer-drag'
|
||||
import { useWorktreeSidebarHeaderDrag } from './use-worktree-sidebar-header-drag'
|
||||
import { useWorktreeSidebarScrollSuppression } from './use-worktree-sidebar-scroll-suppression'
|
||||
import {
|
||||
EMPTY_PROJECT_GROUPS,
|
||||
type VirtualizedWorktreeViewportProps
|
||||
} from './virtualized-worktree-viewport-props'
|
||||
import { WORKTREE_SIDEBAR_SCROLL_STYLE } from './worktree-sidebar-scroll-tuning'
|
||||
import type { WorktreeDropCommitContext } from './worktree-drop-commit-context'
|
||||
import { buildWorktreeVirtualRowContext } from './worktree-virtual-row-context'
|
||||
import { renderWorktreeVirtualRow } from './worktree-virtual-row-dispatch'
|
||||
import { buildRenderableRows } from '../rows/renderable-rows'
|
||||
import { useFolderWorkspacePathStatusRows } from './use-folder-path-statuses'
|
||||
import { useGroupToggleWithScrollAnchor } from './use-group-toggle'
|
||||
import { usePendingSidebarReveal } from '../reveal/use-pending'
|
||||
import { usePrimaryActiveWorktreeRow } from './use-active-row'
|
||||
import { useSidebarRevealHighlight } from '../reveal/use-highlight'
|
||||
import { useVirtualRowMeasurementSync } from './use-row-measurement'
|
||||
import { useVisiblePrRefreshReporting } from './use-visible-review-refresh'
|
||||
import { useWorkspaceStatusRowDrag } from '../drag/use-status-row-drag'
|
||||
import { useWorktreeDragRuntime } from '../drag/use-runtime'
|
||||
import { useWorktreeDragSession } from '../drag/use-session'
|
||||
import { useWorktreeDocumentDrop } from '../drag/use-document-drop'
|
||||
import { useWorktreeLineageDropCommit } from '../drag/use-lineage-drop-commit'
|
||||
import { useWorktreeListKeyboardNavigation } from './use-keyboard'
|
||||
import { useWorktreeListVirtualizer } from './use-virtualizer'
|
||||
import { useWorktreeNativeDrag } from '../drag/use-native-drag'
|
||||
import { useWorktreePointerDrag } from '../drag/use-pointer-drag'
|
||||
import { useWorktreeSidebarHeaderDrag } from '../drag/use-header-drag'
|
||||
import { useWorktreeSidebarScrollSuppression } from '../scroll/use-suppression'
|
||||
import { EMPTY_PROJECT_GROUPS, type VirtualizedWorktreeViewportProps } from './viewport-props'
|
||||
import { WORKTREE_SIDEBAR_SCROLL_STYLE } from '../scroll/tuning'
|
||||
import type { WorktreeDropCommitContext } from '../drag/drop-commit-context'
|
||||
import { buildWorktreeVirtualRowContext } from '../rows/virtual-row-context'
|
||||
import { renderWorktreeVirtualRow } from '../rows/virtual-row-dispatch'
|
||||
|
||||
export const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewport(
|
||||
props: VirtualizedWorktreeViewportProps
|
||||
+6
-6
@@ -1,9 +1,9 @@
|
||||
import { folderWorkspaceKey } from '../../../../../shared/workspace-scope'
|
||||
import type { RenderRow } from '../worktree-list-virtual-rows'
|
||||
import type { PinnedWorktreeDisplayPolicy } from '../worktree-list-groups'
|
||||
import { isPinnedWorktreeRow } from './render-row-item-rows'
|
||||
import { getRenderRowWorktreeItem, renderRowContainsWorktree } from './render-row-worktree-lookup'
|
||||
import { getWorktreeOptionId } from './worktree-option-dom'
|
||||
import { folderWorkspaceKey } from '../../../../../../shared/workspace-scope'
|
||||
import type { RenderRow } from './virtual-rows'
|
||||
import type { PinnedWorktreeDisplayPolicy } from '../rows/groups'
|
||||
import { isPinnedWorktreeRow } from '../rows/renderable-rows'
|
||||
import { getRenderRowWorktreeItem, renderRowContainsWorktree } from '../rows/render-row-lookup'
|
||||
import { getWorktreeOptionId } from '../option-dom'
|
||||
|
||||
export function getRenderRowOptionId(
|
||||
row: RenderRow | undefined,
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { FolderWorkspace } from '../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import type { FolderWorkspace } from '../../../../../../shared/folder-workspace-types'
|
||||
import type { ProjectGroup } from '../../../../../../shared/project-group-types'
|
||||
import {
|
||||
getFolderPathStatusRouteOptionsForRows,
|
||||
getFolderWorkspaceExecutionHostIdForRows,
|
||||
getProjectGroupExecutionHostIdForRows,
|
||||
getRuntimeEnvironmentIdForFolderPathStatusHost
|
||||
} from './worktree-list-host-filtering'
|
||||
} from './host-filtering'
|
||||
|
||||
function group(overrides: Partial<ProjectGroup> = {}): ProjectGroup {
|
||||
return {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user