fix: remove sleep hover quick actions (#2697)
This commit is contained in:
parent
7b0a1faac1
commit
cfd758ef73
|
|
@ -149,7 +149,7 @@ describe('WorktreeCard quick actions', () => {
|
|||
expect(markup).toContain('aria-label="Delete workspace"')
|
||||
})
|
||||
|
||||
it('shows sleep as the top-right quick action for a workspace with live activity', () => {
|
||||
it('does not replace sleep with delete for a workspace with live activity', () => {
|
||||
const worktree = makeWorktree()
|
||||
tabsByWorktree = { [worktree.id]: [{ id: 'tab-1' }] }
|
||||
ptyIdsByTabId = { 'tab-1': ['pty-1'] }
|
||||
|
|
@ -158,6 +158,30 @@ describe('WorktreeCard quick actions', () => {
|
|||
<WorktreeCard worktree={worktree} repo={makeRepo()} isActive={false} />
|
||||
)
|
||||
|
||||
expect(markup).toContain('aria-label="Sleep workspace"')
|
||||
expect(markup).not.toContain('aria-label="Sleep workspace"')
|
||||
expect(markup).not.toContain('aria-label="Delete workspace"')
|
||||
})
|
||||
|
||||
it('does not show sleep as the top-right quick action for an active workspace', () => {
|
||||
const worktree = makeWorktree()
|
||||
tabsByWorktree = { [worktree.id]: [{ id: 'tab-1' }] }
|
||||
ptyIdsByTabId = { 'tab-1': ['pty-1'] }
|
||||
|
||||
const markup = renderToStaticMarkup(
|
||||
<WorktreeCard worktree={worktree} repo={makeRepo()} isActive />
|
||||
)
|
||||
|
||||
expect(markup).not.toContain('aria-label="Sleep workspace"')
|
||||
expect(markup).not.toContain('aria-label="Delete workspace"')
|
||||
})
|
||||
|
||||
it('does not show delete when the workspace is current but not selected in the sidebar', () => {
|
||||
const worktree = makeWorktree()
|
||||
|
||||
const markup = renderToStaticMarkup(
|
||||
<WorktreeCard worktree={worktree} repo={makeRepo()} isActive={false} isCurrentWorktree />
|
||||
)
|
||||
|
||||
expect(markup).not.toContain('aria-label="Delete workspace"')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import {
|
|||
ChevronDown,
|
||||
GitMerge,
|
||||
LoaderCircle,
|
||||
Moon,
|
||||
Server,
|
||||
ServerOff,
|
||||
Trash2,
|
||||
|
|
@ -47,14 +46,12 @@ import { getWorkspacePortsByWorktreeId } from '@/lib/workspace-port-groups'
|
|||
import { hasActiveWorkspaceActivity } from '@/lib/worktree-activity-state'
|
||||
import { installWindowVisibilityInterval, isWindowVisible } from '@/lib/window-visibility-interval'
|
||||
import { runWorktreeDelete } from './delete-worktree-flow'
|
||||
import { runSleepWorktree } from './sleep-worktree-flow'
|
||||
import { getWorkspaceQuickActionKind } from './worktree-card-quick-action'
|
||||
import { useMacOptionKeyPressed } from './mac-option-key-state'
|
||||
|
||||
type WorktreeCardProps = {
|
||||
worktree: Worktree
|
||||
repo: Repo | undefined
|
||||
isActive: boolean
|
||||
isCurrentWorktree?: boolean
|
||||
isActiveSurface?: boolean
|
||||
isMultiSelected?: boolean
|
||||
selectedWorktrees?: readonly Worktree[]
|
||||
|
|
@ -90,6 +87,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
|
|||
worktree,
|
||||
repo,
|
||||
isActive,
|
||||
isCurrentWorktree = isActive,
|
||||
isActiveSurface = isActive,
|
||||
isMultiSelected = false,
|
||||
selectedWorktrees,
|
||||
|
|
@ -162,7 +160,6 @@ const WorktreeCard = React.memo(function WorktreeCard({
|
|||
})
|
||||
const isSshDisconnected = sshStatus != null && sshStatus !== 'connected'
|
||||
const [showDisconnectedDialog, setShowDisconnectedDialog] = useState(false)
|
||||
const isMacOptionPressed = useMacOptionKeyPressed()
|
||||
|
||||
// Why: on restart the previously-active worktree is auto-restored without a
|
||||
// click, so the dialog never opens. Auto-show it for the active card when SSH
|
||||
|
|
@ -414,30 +411,20 @@ const WorktreeCard = React.memo(function WorktreeCard({
|
|||
},
|
||||
[worktree.id, worktree.isUnread, updateWorktreeMeta]
|
||||
)
|
||||
const quickActionKind = getWorkspaceQuickActionKind({
|
||||
hasActiveActivity,
|
||||
isDeletable: !worktree.isMainWorktree,
|
||||
isInactive: !hasActiveActivity,
|
||||
isMacOptionPressed
|
||||
})
|
||||
// Why: deleting the active/current workspace or one with live activity is a
|
||||
// disruptive hover action; keep the quick action delete-only and passive.
|
||||
const showDeleteQuickAction =
|
||||
!isCurrentWorktree && !hasActiveActivity && !worktree.isMainWorktree
|
||||
const handleWorkspaceQuickAction = useCallback(
|
||||
(event: React.MouseEvent<HTMLButtonElement>) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
if (quickActionKind === 'sleep') {
|
||||
void runSleepWorktree(worktree.id)
|
||||
} else if (quickActionKind === 'delete') {
|
||||
if (showDeleteQuickAction) {
|
||||
runWorktreeDelete(worktree.id)
|
||||
}
|
||||
},
|
||||
[quickActionKind, worktree.id]
|
||||
[showDeleteQuickAction, worktree.id]
|
||||
)
|
||||
const quickActionLabel =
|
||||
quickActionKind === 'sleep'
|
||||
? 'Sleep workspace'
|
||||
: quickActionKind === 'delete'
|
||||
? 'Delete workspace'
|
||||
: ''
|
||||
|
||||
const unreadTooltip = worktree.isUnread ? 'Mark read' : 'Mark unread'
|
||||
const childWorkspaceLabel = `${lineageChildCount} child ${
|
||||
|
|
@ -696,7 +683,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
|
|||
)}
|
||||
</div>
|
||||
|
||||
{quickActionKind && !isDeleting && (
|
||||
{showDeleteQuickAction && !isDeleting && (
|
||||
<div className="ml-auto flex shrink-0 items-center justify-center pr-1.5">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
|
|
@ -708,21 +695,15 @@ const WorktreeCard = React.memo(function WorktreeCard({
|
|||
className={cn(
|
||||
'inline-flex size-4 items-center justify-center rounded bg-transparent opacity-0 transition-colors transition-opacity',
|
||||
'group-hover:opacity-100 group-focus-within:opacity-100 focus-visible:opacity-100',
|
||||
quickActionKind === 'delete'
|
||||
? 'text-muted-foreground hover:bg-transparent hover:text-foreground focus-visible:bg-transparent focus-visible:text-foreground'
|
||||
: 'text-muted-foreground hover:bg-transparent hover:text-foreground focus-visible:bg-transparent focus-visible:text-foreground'
|
||||
'text-muted-foreground hover:bg-transparent hover:text-foreground focus-visible:bg-transparent focus-visible:text-foreground'
|
||||
)}
|
||||
aria-label={quickActionLabel}
|
||||
aria-label="Delete workspace"
|
||||
>
|
||||
{quickActionKind === 'delete' ? (
|
||||
<Trash2 className="size-3.5" />
|
||||
) : (
|
||||
<Moon className="size-3.5" />
|
||||
)}
|
||||
<Trash2 className="size-3.5" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right" sideOffset={8}>
|
||||
{quickActionKind === 'delete' ? 'Delete workspace' : 'Sleep workspace'}
|
||||
Delete workspace
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ const SIDEBAR_POINTER_DRAG_THRESHOLD_PX = 4
|
|||
type VirtualizedWorktreeViewportProps = {
|
||||
rows: Row[]
|
||||
activeWorktreeId: string | null
|
||||
currentWorktreeId: string | null
|
||||
groupBy: WorktreeGroupBy
|
||||
repoGroupOrdering: RepoGroupOrdering
|
||||
toggleGroup: (key: string) => void
|
||||
|
|
@ -519,6 +520,7 @@ function getVirtualRowKey(element: Element): string | null {
|
|||
const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewport({
|
||||
rows,
|
||||
activeWorktreeId,
|
||||
currentWorktreeId,
|
||||
groupBy,
|
||||
repoGroupOrdering,
|
||||
toggleGroup,
|
||||
|
|
@ -2120,6 +2122,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
|
|||
worktree={itemRow.worktree}
|
||||
repo={itemRow.repo}
|
||||
isActive={activeWorktreeId === itemRow.worktree.id}
|
||||
isCurrentWorktree={currentWorktreeId === itemRow.worktree.id}
|
||||
// Why: a child-active parent should look active without
|
||||
// running active-card side effects such as SSH reconnect UI.
|
||||
isActiveSurface={forceActiveSurface || activeWorktreeId === itemRow.worktree.id}
|
||||
|
|
@ -3034,6 +3037,7 @@ const WorktreeList = React.memo(function WorktreeList({
|
|||
key={viewportResetKey}
|
||||
rows={rows}
|
||||
activeWorktreeId={selectedSidebarWorktreeId}
|
||||
currentWorktreeId={activeWorktreeId}
|
||||
groupBy={groupBy}
|
||||
repoGroupOrdering={repoGroupOrdering}
|
||||
toggleGroup={toggleGroup}
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
type StoredListener = (event: KeyboardEvent) => void
|
||||
|
||||
function createWindowStub(): {
|
||||
addEventListener: ReturnType<typeof vi.fn>
|
||||
removeEventListener: ReturnType<typeof vi.fn>
|
||||
dispatch: (type: string, event: KeyboardEvent) => void
|
||||
} {
|
||||
const listeners = new Map<string, Set<StoredListener>>()
|
||||
return {
|
||||
addEventListener: vi.fn((type: string, listener: StoredListener) => {
|
||||
const bucket = listeners.get(type) ?? new Set<StoredListener>()
|
||||
bucket.add(listener)
|
||||
listeners.set(type, bucket)
|
||||
}),
|
||||
removeEventListener: vi.fn((type: string, listener: StoredListener) => {
|
||||
listeners.get(type)?.delete(listener)
|
||||
}),
|
||||
dispatch: (type, event) => {
|
||||
for (const listener of listeners.get(type) ?? []) {
|
||||
listener(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('mac option key state', () => {
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals()
|
||||
vi.resetModules()
|
||||
})
|
||||
|
||||
it('shares one window listener set across subscribers and only notifies on value changes', async () => {
|
||||
const windowStub = createWindowStub()
|
||||
vi.stubGlobal('navigator', { userAgent: 'Macintosh' })
|
||||
vi.stubGlobal('window', windowStub)
|
||||
const { getMacOptionKeySnapshot, subscribeMacOptionKey } =
|
||||
await import('./mac-option-key-state')
|
||||
const first = vi.fn()
|
||||
const second = vi.fn()
|
||||
|
||||
const unsubscribeFirst = subscribeMacOptionKey(first)
|
||||
const unsubscribeSecond = subscribeMacOptionKey(second)
|
||||
|
||||
expect(windowStub.addEventListener).toHaveBeenCalledTimes(3)
|
||||
windowStub.dispatch('keydown', { altKey: true } as KeyboardEvent)
|
||||
expect(getMacOptionKeySnapshot()).toBe(true)
|
||||
expect(first).toHaveBeenCalledTimes(1)
|
||||
expect(second).toHaveBeenCalledTimes(1)
|
||||
|
||||
windowStub.dispatch('keydown', { altKey: true } as KeyboardEvent)
|
||||
expect(first).toHaveBeenCalledTimes(1)
|
||||
expect(second).toHaveBeenCalledTimes(1)
|
||||
|
||||
unsubscribeFirst()
|
||||
expect(windowStub.removeEventListener).not.toHaveBeenCalled()
|
||||
windowStub.dispatch('keyup', { altKey: false } as KeyboardEvent)
|
||||
expect(first).toHaveBeenCalledTimes(1)
|
||||
expect(second).toHaveBeenCalledTimes(2)
|
||||
|
||||
unsubscribeSecond()
|
||||
expect(windowStub.removeEventListener).toHaveBeenCalledTimes(3)
|
||||
expect(getMacOptionKeySnapshot()).toBe(false)
|
||||
})
|
||||
|
||||
it('does not attach keyboard listeners on non-mac platforms', async () => {
|
||||
const windowStub = createWindowStub()
|
||||
vi.stubGlobal('navigator', { userAgent: 'Windows' })
|
||||
vi.stubGlobal('window', windowStub)
|
||||
const { getMacOptionKeySnapshot, subscribeMacOptionKey } =
|
||||
await import('./mac-option-key-state')
|
||||
|
||||
const unsubscribe = subscribeMacOptionKey(vi.fn())
|
||||
|
||||
expect(windowStub.addEventListener).not.toHaveBeenCalled()
|
||||
expect(getMacOptionKeySnapshot()).toBe(false)
|
||||
unsubscribe()
|
||||
})
|
||||
})
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
import { useSyncExternalStore } from 'react'
|
||||
|
||||
type OptionKeyListener = () => void
|
||||
|
||||
let optionPressed = false
|
||||
const listeners = new Set<OptionKeyListener>()
|
||||
let disposeWindowListeners: (() => void) | null = null
|
||||
|
||||
function isMacPlatform(): boolean {
|
||||
return typeof navigator !== 'undefined' && navigator.userAgent.includes('Mac')
|
||||
}
|
||||
|
||||
function setOptionPressed(nextPressed: boolean): void {
|
||||
if (optionPressed === nextPressed) {
|
||||
return
|
||||
}
|
||||
optionPressed = nextPressed
|
||||
for (const listener of listeners) {
|
||||
listener()
|
||||
}
|
||||
}
|
||||
|
||||
function startWindowListeners(): void {
|
||||
if (disposeWindowListeners || !isMacPlatform() || typeof window === 'undefined') {
|
||||
return
|
||||
}
|
||||
|
||||
const handleKeyChange = (event: KeyboardEvent): void => setOptionPressed(event.altKey)
|
||||
const handleWindowBlur = (): void => setOptionPressed(false)
|
||||
window.addEventListener('keydown', handleKeyChange, true)
|
||||
window.addEventListener('keyup', handleKeyChange, true)
|
||||
window.addEventListener('blur', handleWindowBlur)
|
||||
disposeWindowListeners = () => {
|
||||
window.removeEventListener('keydown', handleKeyChange, true)
|
||||
window.removeEventListener('keyup', handleKeyChange, true)
|
||||
window.removeEventListener('blur', handleWindowBlur)
|
||||
}
|
||||
}
|
||||
|
||||
export function subscribeMacOptionKey(listener: OptionKeyListener): () => void {
|
||||
if (!isMacPlatform()) {
|
||||
return () => undefined
|
||||
}
|
||||
listeners.add(listener)
|
||||
startWindowListeners()
|
||||
return () => {
|
||||
listeners.delete(listener)
|
||||
if (listeners.size > 0) {
|
||||
return
|
||||
}
|
||||
disposeWindowListeners?.()
|
||||
disposeWindowListeners = null
|
||||
setOptionPressed(false)
|
||||
}
|
||||
}
|
||||
|
||||
export function getMacOptionKeySnapshot(): boolean {
|
||||
return isMacPlatform() ? optionPressed : false
|
||||
}
|
||||
|
||||
export function useMacOptionKeyPressed(): boolean {
|
||||
// Why: the sidebar can render dozens of cards. One shared external store
|
||||
// avoids a global key listener per card and only re-renders on Option flips.
|
||||
return useSyncExternalStore(subscribeMacOptionKey, getMacOptionKeySnapshot, () => false)
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
export type WorktreeCardQuickActionKind = 'sleep' | 'delete' | null
|
||||
|
||||
export function getWorkspaceQuickActionKind({
|
||||
hasActiveActivity,
|
||||
isDeletable,
|
||||
isInactive,
|
||||
isMacOptionPressed
|
||||
}: {
|
||||
hasActiveActivity: boolean
|
||||
isDeletable: boolean
|
||||
isInactive: boolean
|
||||
isMacOptionPressed: boolean
|
||||
}): WorktreeCardQuickActionKind {
|
||||
if (isInactive) {
|
||||
return isDeletable ? 'delete' : null
|
||||
}
|
||||
if (hasActiveActivity) {
|
||||
return isMacOptionPressed && isDeletable ? 'delete' : 'sleep'
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
|
@ -11,7 +11,6 @@ import {
|
|||
ChevronRight,
|
||||
LoaderCircle,
|
||||
MemoryStick,
|
||||
Moon,
|
||||
RotateCw,
|
||||
Terminal,
|
||||
Trash2,
|
||||
|
|
@ -35,7 +34,6 @@ import { installWindowVisibilityInterval } from '@/lib/window-visibility-interva
|
|||
import { useAppStore } from '../../store'
|
||||
import { useWorktreeMap } from '../../store/selectors'
|
||||
import { runWorktreeDelete } from '../sidebar/delete-worktree-flow'
|
||||
import { runSleepWorktree } from '../sidebar/sleep-worktree-flow'
|
||||
import { useDaemonActions, DaemonActionDialog } from '../shared/useDaemonActions'
|
||||
import type { AppMemory, UsageValues, Worktree } from '../../../../shared/types'
|
||||
import { ORPHAN_WORKTREE_ID } from '../../../../shared/constants'
|
||||
|
|
@ -394,20 +392,20 @@ function SessionRow({
|
|||
function WorktreeRow({
|
||||
worktree,
|
||||
storeRecord,
|
||||
activeWorktreeId,
|
||||
isCollapsed,
|
||||
onToggle,
|
||||
onNavigate,
|
||||
onSleep,
|
||||
onDelete,
|
||||
onKillSession,
|
||||
navigateToTab
|
||||
}: {
|
||||
worktree: UnifiedWorktreeRow
|
||||
storeRecord: Worktree | null
|
||||
activeWorktreeId: string | null
|
||||
isCollapsed: boolean
|
||||
onToggle: () => void
|
||||
onNavigate: () => void
|
||||
onSleep: () => void
|
||||
onDelete: () => void
|
||||
onKillSession: (session: UnifiedSessionRow) => void
|
||||
navigateToTab: (tabId: string, paneKey: string | null) => void
|
||||
|
|
@ -420,10 +418,12 @@ function WorktreeRow({
|
|||
const isSynthetic =
|
||||
worktree.worktreeId === ORPHAN_WORKTREE_ID || worktree.repoId === UNATTRIBUTED_REPO_ID
|
||||
const isNavigable = !isSynthetic
|
||||
// Why: Sleep / Delete affordances act on a sidebar worktree record; without
|
||||
// Why: Delete acts on a sidebar worktree record; without
|
||||
// one (synthesized SSH rows whose worktreeId isn't in worktreeById, or
|
||||
// synthetic buckets) we hide them but keep the row clickable for navigation.
|
||||
const showWorktreeActions = !isSynthetic && storeRecord !== null
|
||||
// synthetic buckets), or for the active worktree, we hide it but keep the
|
||||
// row clickable for navigation.
|
||||
const showWorktreeActions =
|
||||
!isSynthetic && storeRecord !== null && worktree.worktreeId !== activeWorktreeId
|
||||
const isMainWorktree = storeRecord?.isMainWorktree ?? false
|
||||
const rowLabel = storeRecord?.displayName?.trim() || worktree.worktreeName
|
||||
|
||||
|
|
@ -481,25 +481,6 @@ function WorktreeRow({
|
|||
</span>
|
||||
{showWorktreeActions && (
|
||||
<div className="absolute inset-0 flex items-center justify-end gap-0.5 opacity-0 pointer-events-none transition-opacity group-hover/wtrow:opacity-100 group-hover/wtrow:pointer-events-auto group-focus-within/wtrow:opacity-100 group-focus-within/wtrow:pointer-events-auto">
|
||||
<Tooltip delayDuration={300}>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onSleep}
|
||||
aria-label={`Sleep workspace ${rowLabel}`}
|
||||
className="p-0.5 rounded text-muted-foreground hover:bg-accent hover:text-foreground transition-colors"
|
||||
>
|
||||
<Moon className="size-3" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
side="top"
|
||||
sideOffset={4}
|
||||
className="z-[70] max-w-[200px] text-pretty"
|
||||
>
|
||||
Sleep — close all panels in this workspace to free memory.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip delayDuration={300}>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
|
|
@ -555,10 +536,10 @@ function ResourceTree({
|
|||
collapsedRepos,
|
||||
toggleRepo,
|
||||
collapsedWorktrees,
|
||||
activeWorktreeId,
|
||||
toggleWorktree,
|
||||
navigateToWorktree,
|
||||
navigateToTab,
|
||||
onSleep,
|
||||
onDelete,
|
||||
onKillSession
|
||||
}: {
|
||||
|
|
@ -567,10 +548,10 @@ function ResourceTree({
|
|||
collapsedRepos: Set<string>
|
||||
toggleRepo: (repoId: string) => void
|
||||
collapsedWorktrees: Set<string>
|
||||
activeWorktreeId: string | null
|
||||
toggleWorktree: (worktreeId: string) => void
|
||||
navigateToWorktree: (worktreeId: string) => void
|
||||
navigateToTab: (tabId: string, paneKey: string | null) => void
|
||||
onSleep: (worktreeId: string) => void
|
||||
onDelete: (worktreeId: string) => void
|
||||
onKillSession: (session: UnifiedSessionRow) => void
|
||||
}): React.JSX.Element {
|
||||
|
|
@ -591,10 +572,10 @@ function ResourceTree({
|
|||
key={wt.worktreeId}
|
||||
worktree={wt}
|
||||
storeRecord={storeRecord}
|
||||
activeWorktreeId={activeWorktreeId}
|
||||
isCollapsed={collapsedWorktrees.has(wt.worktreeId)}
|
||||
onToggle={() => toggleWorktree(wt.worktreeId)}
|
||||
onNavigate={() => navigateToWorktree(wt.worktreeId)}
|
||||
onSleep={() => onSleep(wt.worktreeId)}
|
||||
onDelete={() => onDelete(wt.worktreeId)}
|
||||
onKillSession={onKillSession}
|
||||
navigateToTab={navigateToTab}
|
||||
|
|
@ -670,6 +651,7 @@ export function ResourceUsageStatusSegment({
|
|||
const openModal = useAppStore((s) => s.openModal)
|
||||
const openSpacePage = useAppStore((s) => s.openSpacePage)
|
||||
const activeView = useAppStore((s) => s.activeView)
|
||||
const activeWorktreeId = useAppStore((s) => s.activeWorktreeId)
|
||||
const workspaceSpaceScannedAt = useAppStore((s) => s.workspaceSpaceAnalysis?.scannedAt ?? null)
|
||||
const workspaceSpaceScanning = useAppStore((s) => s.workspaceSpaceScanning)
|
||||
const activeRuntimeEnvironmentId = useAppStore(
|
||||
|
|
@ -986,10 +968,6 @@ export function ResourceUsageStatusSegment({
|
|||
runWorktreeDelete(worktreeId)
|
||||
}, [])
|
||||
|
||||
const handleSleep = useCallback((id: string): void => {
|
||||
void runSleepWorktree(id)
|
||||
}, [])
|
||||
|
||||
const handleOpenWorkspaceCleanup = useCallback((): void => {
|
||||
if (runtimeEnvironmentActive) {
|
||||
return
|
||||
|
|
@ -1352,10 +1330,10 @@ export function ResourceUsageStatusSegment({
|
|||
collapsedRepos={collapsedRepos}
|
||||
toggleRepo={toggleRepo}
|
||||
collapsedWorktrees={collapsedWorktrees}
|
||||
activeWorktreeId={activeWorktreeId}
|
||||
toggleWorktree={toggleWorktree}
|
||||
navigateToWorktree={navigateToWorktree}
|
||||
navigateToTab={navigateToTab}
|
||||
onSleep={handleSleep}
|
||||
onDelete={deleteWorktree}
|
||||
onKillSession={handleKillSession}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue