mirror of
https://github.com/stablyai/orca.git
synced 2026-10-21 00:03:46 +00:00
perf(renderer): defer terminal quick command host work
This commit is contained in:
@@ -824,26 +824,6 @@ function TerminalPane(
|
||||
: quickCommandRepoId
|
||||
? 'This Repo'
|
||||
: null
|
||||
const {
|
||||
hosts: quickCommandHosts,
|
||||
refreshRemoteHost: refreshQuickCommandRemoteHost,
|
||||
remoteHostLoadFailed: quickCommandHostLoadFailed,
|
||||
remoteHostPending: quickCommandHostOwnershipPending
|
||||
} = useTerminalQuickCommandHosts(worktreeId)
|
||||
const visibleQuickCommandHosts = quickCommandHosts.map((host) => {
|
||||
const commands = host.commands.filter(isTerminalQuickCommandComplete)
|
||||
return {
|
||||
globalCommands: commands.filter(
|
||||
(command) => getTerminalQuickCommandScope(command).type === 'global'
|
||||
),
|
||||
hostId: host.hostId,
|
||||
label: host.label,
|
||||
repoCommands: commands.filter((command) => {
|
||||
const scope = getTerminalQuickCommandScope(command)
|
||||
return scope.type === 'repo' && terminalQuickCommandMatchesRepo(command, quickCommandRepoId)
|
||||
})
|
||||
}
|
||||
})
|
||||
const quickCommandGroupId =
|
||||
useAppStore(
|
||||
(s) =>
|
||||
@@ -2569,6 +2549,32 @@ function TerminalPane(
|
||||
forceBracketedMultilineTextPaste,
|
||||
rightClickToPaste
|
||||
})
|
||||
const {
|
||||
hosts: quickCommandHosts,
|
||||
refreshRemoteHost: refreshQuickCommandRemoteHost,
|
||||
remoteHostLoadFailed: quickCommandHostLoadFailed,
|
||||
remoteHostPending: quickCommandHostOwnershipPending
|
||||
} = useTerminalQuickCommandHosts(worktreeId, contextMenu.open)
|
||||
const visibleQuickCommandHosts = useMemo(
|
||||
() =>
|
||||
quickCommandHosts.map((host) => {
|
||||
const commands = host.commands.filter(isTerminalQuickCommandComplete)
|
||||
return {
|
||||
globalCommands: commands.filter(
|
||||
(command) => getTerminalQuickCommandScope(command).type === 'global'
|
||||
),
|
||||
hostId: host.hostId,
|
||||
label: host.label,
|
||||
repoCommands: commands.filter((command) => {
|
||||
const scope = getTerminalQuickCommandScope(command)
|
||||
return (
|
||||
scope.type === 'repo' && terminalQuickCommandMatchesRepo(command, quickCommandRepoId)
|
||||
)
|
||||
})
|
||||
}
|
||||
}),
|
||||
[quickCommandHosts, quickCommandRepoId]
|
||||
)
|
||||
useEffect(() => {
|
||||
if (contextMenu.open) {
|
||||
refreshQuickCommandRemoteHost()
|
||||
|
||||
@@ -11,18 +11,23 @@ import type { RuntimeTerminalQuickCommands } from '@/store/slices/terminal-quick
|
||||
const testState = vi.hoisted(() => ({
|
||||
executionHostId: 'runtime:build' as ExecutionHostId,
|
||||
loadRuntimeTerminalQuickCommands: vi.fn(async () => {}),
|
||||
resolveExecutionHostId: vi.fn(() => 'runtime:build' as ExecutionHostId),
|
||||
runtimeEnvironments: [] as { id: string; name: string }[],
|
||||
runtimeStatusByEnvironmentId: new Map<string, { connectionGeneration?: number }>(),
|
||||
runtimeTerminalQuickCommands: new Map<string, RuntimeTerminalQuickCommands>(),
|
||||
settings: null as GlobalSettings | null
|
||||
settings: null as GlobalSettings | null,
|
||||
subscribedSelectors: [] as ((state: unknown) => unknown)[]
|
||||
}))
|
||||
|
||||
vi.mock('@/store', () => ({
|
||||
useAppStore: (selector: (state: typeof testState) => unknown) => selector(testState)
|
||||
useAppStore: (selector: (state: typeof testState) => unknown) => {
|
||||
testState.subscribedSelectors.push(selector as (state: unknown) => unknown)
|
||||
return selector(testState)
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/worktree-runtime-owner', () => ({
|
||||
getExecutionHostIdForWorktree: () => testState.executionHostId
|
||||
getExecutionHostIdForWorktree: () => testState.resolveExecutionHostId()
|
||||
}))
|
||||
|
||||
import {
|
||||
@@ -34,12 +39,16 @@ import {
|
||||
} from './use-terminal-quick-command-hosts'
|
||||
|
||||
let renderedHosts: TerminalQuickCommandHost[] = []
|
||||
let renderedExecutionHostId: ExecutionHostId = 'local'
|
||||
let refreshRemoteHost = (): void => {}
|
||||
let remoteHostLoadFailed = false
|
||||
let remoteHostPending = false
|
||||
|
||||
function Probe(): null {
|
||||
const result = useTerminalQuickCommandHosts('worktree-1')
|
||||
function Probe({ enabled = true }: { enabled?: boolean }): null {
|
||||
const result = useTerminalQuickCommandHosts('worktree-1', enabled)
|
||||
renderedExecutionHostId = result.executionHostId
|
||||
renderedHosts = result.hosts
|
||||
refreshRemoteHost = result.refreshRemoteHost
|
||||
remoteHostLoadFailed = result.remoteHostLoadFailed
|
||||
remoteHostPending = result.remoteHostPending
|
||||
return null
|
||||
@@ -51,10 +60,13 @@ describe('useTerminalQuickCommandHosts', () => {
|
||||
beforeEach(() => {
|
||||
testState.executionHostId = 'runtime:build'
|
||||
testState.loadRuntimeTerminalQuickCommands.mockClear()
|
||||
testState.resolveExecutionHostId.mockClear()
|
||||
testState.resolveExecutionHostId.mockImplementation(() => testState.executionHostId)
|
||||
testState.runtimeEnvironments = [{ id: 'build', name: 'Build Server' }]
|
||||
testState.runtimeStatusByEnvironmentId = new Map([['build', { connectionGeneration: 4 }]])
|
||||
testState.runtimeTerminalQuickCommands = new Map()
|
||||
testState.settings = getDefaultSettings('/tmp')
|
||||
testState.subscribedSelectors = []
|
||||
renderedHosts = []
|
||||
remoteHostLoadFailed = false
|
||||
remoteHostPending = false
|
||||
@@ -75,6 +87,37 @@ describe('useTerminalQuickCommandHosts', () => {
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
it('skips host resolution and remote loading while disabled', async () => {
|
||||
await act(async () => root.render(createElement(Probe, { enabled: false })))
|
||||
|
||||
const disabledHosts = renderedHosts
|
||||
expect(testState.subscribedSelectors).toHaveLength(1)
|
||||
for (let write = 0; write < 1_000; write += 1) {
|
||||
testState.subscribedSelectors[0](testState)
|
||||
}
|
||||
refreshRemoteHost()
|
||||
|
||||
expect(renderedExecutionHostId).toBe('local')
|
||||
expect(renderedHosts).toEqual([])
|
||||
expect(remoteHostLoadFailed).toBe(false)
|
||||
expect(remoteHostPending).toBe(false)
|
||||
expect(testState.resolveExecutionHostId).not.toHaveBeenCalled()
|
||||
expect(testState.loadRuntimeTerminalQuickCommands).not.toHaveBeenCalled()
|
||||
|
||||
testState.executionHostId = 'runtime:other'
|
||||
await act(async () => root.render(createElement(Probe, { enabled: false })))
|
||||
|
||||
expect(renderedHosts).toBe(disabledHosts)
|
||||
expect(testState.resolveExecutionHostId).not.toHaveBeenCalled()
|
||||
expect(testState.loadRuntimeTerminalQuickCommands).not.toHaveBeenCalled()
|
||||
|
||||
testState.executionHostId = 'runtime:build'
|
||||
await act(async () => root.render(createElement(Probe)))
|
||||
|
||||
expect(testState.resolveExecutionHostId).toHaveBeenCalledOnce()
|
||||
expect(testState.loadRuntimeTerminalQuickCommands).toHaveBeenCalledWith('build')
|
||||
})
|
||||
|
||||
it.each([
|
||||
{
|
||||
name: 'unsupported',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import type { GlobalSettings, TerminalQuickCommand } from '../../../shared/types'
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
@@ -9,6 +10,10 @@ import { getHostDisplayLabelOverrides } from '../../../shared/host-setting-overr
|
||||
import { buildExecutionHostRegistry } from '../../../shared/execution-host-registry'
|
||||
import type { PublicKnownRuntimeEnvironment } from '../../../shared/runtime-environments'
|
||||
import { useAppStore } from '@/store'
|
||||
import type {
|
||||
RuntimeTerminalQuickCommands,
|
||||
TerminalQuickCommandHostsSlice
|
||||
} from '@/store/slices/terminal-quick-command-hosts'
|
||||
import { getExecutionHostIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
|
||||
export type TerminalQuickCommandHost = {
|
||||
@@ -31,6 +36,30 @@ export type HostedTerminalQuickCommand = {
|
||||
key: string
|
||||
}
|
||||
|
||||
type TerminalQuickCommandHostState = {
|
||||
executionHostId: ExecutionHostId
|
||||
loadRemote: TerminalQuickCommandHostsSlice['loadRuntimeTerminalQuickCommands'] | null
|
||||
remoteConnectionGeneration: number
|
||||
remoteEnvironmentId: string | null
|
||||
remoteHostId: ExecutionHostId | null
|
||||
remoteState: RuntimeTerminalQuickCommands | undefined
|
||||
runtimeEnvironments: PublicKnownRuntimeEnvironment[]
|
||||
settings: GlobalSettings | null
|
||||
}
|
||||
|
||||
const EMPTY_RUNTIME_ENVIRONMENTS: PublicKnownRuntimeEnvironment[] = []
|
||||
const DISABLED_TERMINAL_QUICK_COMMAND_HOSTS: TerminalQuickCommandHost[] = []
|
||||
const DISABLED_TERMINAL_QUICK_COMMAND_HOST_STATE: TerminalQuickCommandHostState = {
|
||||
executionHostId: LOCAL_EXECUTION_HOST_ID,
|
||||
loadRemote: null,
|
||||
remoteConnectionGeneration: 0,
|
||||
remoteEnvironmentId: null,
|
||||
remoteHostId: null,
|
||||
remoteState: undefined,
|
||||
runtimeEnvironments: EMPTY_RUNTIME_ENVIRONMENTS,
|
||||
settings: null
|
||||
}
|
||||
|
||||
export function getHostedTerminalQuickCommandKey(
|
||||
hostId: ExecutionHostId,
|
||||
commandId: string
|
||||
@@ -68,41 +97,59 @@ export function getTerminalQuickCommandHostOptions(
|
||||
}).map((host) => ({ id: host.id, label: host.label }))
|
||||
}
|
||||
|
||||
export function useTerminalQuickCommandHosts(worktreeId: string): {
|
||||
export function useTerminalQuickCommandHosts(
|
||||
worktreeId: string,
|
||||
enabled = true
|
||||
): {
|
||||
executionHostId: ExecutionHostId
|
||||
hosts: TerminalQuickCommandHost[]
|
||||
refreshRemoteHost: () => void
|
||||
remoteHostLoadFailed: boolean
|
||||
remoteHostPending: boolean
|
||||
} {
|
||||
const executionHostId = useAppStore((state) => getExecutionHostIdForWorktree(state, worktreeId))
|
||||
const settings = useAppStore((state) => state.settings)
|
||||
const runtimeEnvironments = useAppStore((state) => state.runtimeEnvironments)
|
||||
const remoteState = useAppStore((state) => {
|
||||
const parsed = parseExecutionHostId(executionHostId)
|
||||
return parsed?.kind === 'runtime'
|
||||
? state.runtimeTerminalQuickCommands.get(parsed.environmentId)
|
||||
: undefined
|
||||
})
|
||||
const loadRemote = useAppStore((state) => state.loadRuntimeTerminalQuickCommands)
|
||||
const parsedExecutionHost = parseExecutionHostId(executionHostId)
|
||||
const remoteHostId = parsedExecutionHost?.kind === 'runtime' ? parsedExecutionHost.id : null
|
||||
const remoteEnvironmentId =
|
||||
parsedExecutionHost?.kind === 'runtime' ? parsedExecutionHost.environmentId : null
|
||||
const remoteConnectionGeneration = useAppStore((state) =>
|
||||
remoteEnvironmentId
|
||||
? (state.runtimeStatusByEnvironmentId.get(remoteEnvironmentId)?.connectionGeneration ?? 0)
|
||||
: 0
|
||||
const {
|
||||
executionHostId,
|
||||
loadRemote,
|
||||
remoteConnectionGeneration,
|
||||
remoteEnvironmentId,
|
||||
remoteHostId,
|
||||
remoteState,
|
||||
runtimeEnvironments,
|
||||
settings
|
||||
} = useAppStore(
|
||||
useShallow((state): TerminalQuickCommandHostState => {
|
||||
if (!enabled) {
|
||||
return DISABLED_TERMINAL_QUICK_COMMAND_HOST_STATE
|
||||
}
|
||||
const executionHostId = getExecutionHostIdForWorktree(state, worktreeId)
|
||||
const parsedExecutionHost = parseExecutionHostId(executionHostId)
|
||||
const remoteEnvironmentId =
|
||||
parsedExecutionHost?.kind === 'runtime' ? parsedExecutionHost.environmentId : null
|
||||
return {
|
||||
executionHostId,
|
||||
loadRemote: state.loadRuntimeTerminalQuickCommands,
|
||||
remoteConnectionGeneration: remoteEnvironmentId
|
||||
? (state.runtimeStatusByEnvironmentId.get(remoteEnvironmentId)?.connectionGeneration ?? 0)
|
||||
: 0,
|
||||
remoteEnvironmentId,
|
||||
remoteHostId: parsedExecutionHost?.kind === 'runtime' ? parsedExecutionHost.id : null,
|
||||
remoteState: remoteEnvironmentId
|
||||
? state.runtimeTerminalQuickCommands.get(remoteEnvironmentId)
|
||||
: undefined,
|
||||
runtimeEnvironments: state.runtimeEnvironments,
|
||||
settings: state.settings
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (remoteEnvironmentId) {
|
||||
if (loadRemote && remoteEnvironmentId) {
|
||||
void loadRemote(remoteEnvironmentId)
|
||||
}
|
||||
}, [loadRemote, remoteConnectionGeneration, remoteEnvironmentId])
|
||||
|
||||
const refreshRemoteHost = useCallback((): void => {
|
||||
if (remoteEnvironmentId) {
|
||||
if (loadRemote && remoteEnvironmentId) {
|
||||
void loadRemote(remoteEnvironmentId, { force: true })
|
||||
}
|
||||
}, [loadRemote, remoteEnvironmentId])
|
||||
@@ -122,6 +169,9 @@ export function useTerminalQuickCommandHosts(worktreeId: string): {
|
||||
)
|
||||
|
||||
const hosts = useMemo(() => {
|
||||
if (!enabled) {
|
||||
return DISABLED_TERMINAL_QUICK_COMMAND_HOSTS
|
||||
}
|
||||
const hostOptions = getTerminalQuickCommandHostOptions(settings, runtimeEnvironments)
|
||||
const result: TerminalQuickCommandHost[] = [
|
||||
{
|
||||
@@ -146,6 +196,7 @@ export function useTerminalQuickCommandHosts(worktreeId: string): {
|
||||
})
|
||||
return result
|
||||
}, [
|
||||
enabled,
|
||||
remoteConnectionGeneration,
|
||||
remoteEnvironmentId,
|
||||
remoteHostId,
|
||||
|
||||
Reference in New Issue
Block a user