mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 00:03:15 +00:00
* refactor(mobile): split home modal and rpc client * fix(mobile): restore render-phase remount key in NewWorktreeModal The split moved the form-reset epoch from render-phase refs into useState + useLayoutEffect, which changed when the remount key is computed. On the render where visible flips false->true the key was still the old epoch, so the previous session's NewWorktreeModalContent rendered with visible === true carrying stale form state. Child layout effects run before the parent's, so visible-gated hooks (useNewWorkspaceRepositories, useNewWorktreeDrawerNavigation, useNewWorkspaceRuntimeContext) fired for that stale instance before the parent bumped the epoch and remounted. Restore the ref-based computation so the key is correct on the first render where visible flips true, keeping the composite open/client epoch semantics and the file split intact.
94 lines
3.0 KiB
TypeScript
94 lines
3.0 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import type { RpcClient } from '../transport/rpc-client'
|
|
import type { RpcSuccess } from '../transport/types'
|
|
import { normalizeSetupHookTrust } from '../tasks/setup-hook-trust'
|
|
import type { WorkspaceCreateSetupDecision } from '../tasks/workspace-create-params'
|
|
import type {
|
|
MobileWorkspaceRepo,
|
|
RepoHooksResponse,
|
|
SetupHookDetails
|
|
} from './new-worktree-modal-types'
|
|
|
|
export function useNewWorkspaceSetupScript(args: {
|
|
client: RpcClient | null
|
|
selectedRepo: MobileWorkspaceRepo | null
|
|
}): {
|
|
setupCommand: string | null
|
|
setupSource: string | null
|
|
setupTrust: SetupHookDetails['trust']
|
|
setupRunPolicy: SetupHookDetails['runPolicy']
|
|
setupDecisionChoice: Exclude<WorkspaceCreateSetupDecision, 'inherit'> | null
|
|
setSetupDecisionChoice: (decision: Exclude<WorkspaceCreateSetupDecision, 'inherit'>) => void
|
|
runSetup: boolean
|
|
setRunSetup: (run: boolean) => void
|
|
showAdvanced: boolean
|
|
setShowAdvanced: (show: boolean) => void
|
|
} {
|
|
const { client, selectedRepo } = args
|
|
const [details, setDetails] = useState<SetupHookDetails | null>(null)
|
|
const [setupDecisionChoice, setSetupDecisionChoice] = useState<Exclude<
|
|
WorkspaceCreateSetupDecision,
|
|
'inherit'
|
|
> | null>(null)
|
|
const [runSetup, setRunSetup] = useState(true)
|
|
const [showAdvanced, setShowAdvanced] = useState(false)
|
|
const activeDetails = selectedRepo && details?.repoId === selectedRepo.id ? details : null
|
|
|
|
useEffect(() => {
|
|
if (!client || !selectedRepo) {
|
|
return
|
|
}
|
|
let stale = false
|
|
void client
|
|
.sendRequest('repo.hooks', { repo: `id:${selectedRepo.id}` })
|
|
.then((response) => {
|
|
if (stale || !response.ok) {
|
|
return
|
|
}
|
|
const result = (response as RpcSuccess).result as RepoHooksResponse
|
|
const command = result.hooks?.scripts?.setup?.trim() || null
|
|
const runPolicy = result.setupRunPolicy ?? 'run-by-default'
|
|
setDetails({
|
|
repoId: selectedRepo.id,
|
|
command,
|
|
source: result.source,
|
|
trust: normalizeSetupHookTrust(result.setupTrust),
|
|
runPolicy
|
|
})
|
|
setSetupDecisionChoice(null)
|
|
setRunSetup(runPolicy !== 'skip-by-default')
|
|
if (command && runPolicy === 'ask') {
|
|
setShowAdvanced(true)
|
|
}
|
|
})
|
|
.catch(() => {
|
|
if (!stale) {
|
|
setDetails({
|
|
repoId: selectedRepo.id,
|
|
command: null,
|
|
source: null,
|
|
trust: null,
|
|
runPolicy: 'run-by-default'
|
|
})
|
|
setSetupDecisionChoice(null)
|
|
}
|
|
})
|
|
return () => {
|
|
stale = true
|
|
}
|
|
}, [client, selectedRepo])
|
|
|
|
return {
|
|
setupCommand: activeDetails?.command ?? null,
|
|
setupSource: activeDetails?.source ?? null,
|
|
setupTrust: activeDetails?.trust ?? null,
|
|
setupRunPolicy: activeDetails?.runPolicy ?? 'run-by-default',
|
|
setupDecisionChoice,
|
|
setSetupDecisionChoice,
|
|
runSetup,
|
|
setRunSetup,
|
|
showAdvanced,
|
|
setShowAdvanced
|
|
}
|
|
}
|