mirror of
https://github.com/stablyai/orca.git
synced 2026-09-28 08:02:43 +00:00
fix: guard create project state (#3680)
This commit is contained in:
@@ -1,14 +1,9 @@
|
||||
/**
|
||||
* Step for AddRepoDialog (orca#763).
|
||||
*
|
||||
* Split from AddRepoDialog and AddRepoSteps to keep both under the 400-line
|
||||
* oxlint limit, following the same pattern as useRemoteRepo.
|
||||
*/
|
||||
|
||||
// Step for AddRepoDialog (orca#763), split out so create-project state stays scoped.
|
||||
import React, { useCallback, useRef, useState } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { Folder, GitBranch, Home, Pencil } from 'lucide-react'
|
||||
import { useAppStore } from '@/store'
|
||||
import { useMountedRef } from '@/hooks/useMountedRef'
|
||||
import { DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
@@ -33,6 +28,7 @@ export function useCreateRepo(
|
||||
const [createKind, setCreateKind] = useState<RepoKind>('git')
|
||||
const [createError, setCreateError] = useState<string | null>(null)
|
||||
const [isCreating, setIsCreating] = useState(false)
|
||||
const mountedRef = useMountedRef()
|
||||
|
||||
// Why: monotonic ID so stale create callbacks can detect they were superseded
|
||||
// when the user clicks Back or closes the dialog mid-create. Mirrors the
|
||||
@@ -57,11 +53,11 @@ export function useCreateRepo(
|
||||
}
|
||||
const gen = createGenRef.current
|
||||
const dir = await window.api.repos.pickDirectory()
|
||||
if (dir && gen === createGenRef.current) {
|
||||
if (dir && gen === createGenRef.current && mountedRef.current) {
|
||||
setCreateParent(dir)
|
||||
setCreateError(null)
|
||||
}
|
||||
}, [])
|
||||
}, [mountedRef])
|
||||
|
||||
const handleCreate = useCallback(async () => {
|
||||
const name = createName.trim()
|
||||
@@ -73,8 +69,7 @@ export function useCreateRepo(
|
||||
setIsCreating(true)
|
||||
setCreateError(null)
|
||||
try {
|
||||
const settings = useAppStore.getState().settings
|
||||
const target = getActiveRuntimeTarget(settings)
|
||||
const target = getActiveRuntimeTarget(useAppStore.getState().settings)
|
||||
const result =
|
||||
target.kind === 'environment'
|
||||
? await callRuntimeRpc<{ repo: Repo } | { error: string }>(
|
||||
@@ -94,7 +89,7 @@ export function useCreateRepo(
|
||||
})
|
||||
// Why: if the user closed the dialog or clicked Back mid-create,
|
||||
// createGenRef was bumped by resetCreateState. Ignore stale results.
|
||||
if (gen !== createGenRef.current) {
|
||||
if (gen !== createGenRef.current || !mountedRef.current) {
|
||||
return
|
||||
}
|
||||
if ('error' in result) {
|
||||
@@ -133,7 +128,7 @@ export function useCreateRepo(
|
||||
setAddedRepo(repo)
|
||||
setExistingWorkspaceSource?.('create_project')
|
||||
await fetchWorktrees(repo.id)
|
||||
if (gen !== createGenRef.current) {
|
||||
if (gen !== createGenRef.current || !mountedRef.current) {
|
||||
return
|
||||
}
|
||||
setStep('setup')
|
||||
@@ -141,7 +136,7 @@ export function useCreateRepo(
|
||||
// Why: folder repos skip the Git setup step, so activate the synthetic
|
||||
// root workspace before closing. Matches addNonGitFolder's behavior.
|
||||
await fetchWorktrees(repo.id)
|
||||
if (gen !== createGenRef.current) {
|
||||
if (gen !== createGenRef.current || !mountedRef.current) {
|
||||
return
|
||||
}
|
||||
const folderWorktree = useAppStore.getState().worktreesByRepo[repo.id]?.[0]
|
||||
@@ -151,15 +146,14 @@ export function useCreateRepo(
|
||||
closeModal()
|
||||
}
|
||||
} catch (err) {
|
||||
if (gen !== createGenRef.current) {
|
||||
if (gen !== createGenRef.current || !mountedRef.current) {
|
||||
return
|
||||
}
|
||||
const message = err instanceof Error ? err.message : String(err)
|
||||
setCreateError(message)
|
||||
setCreateError(err instanceof Error ? err.message : String(err))
|
||||
} finally {
|
||||
// Why: only clear the loading state if this invocation is still current;
|
||||
// a superseded create must not flip the flag back off for a new flow.
|
||||
if (gen === createGenRef.current) {
|
||||
if (gen === createGenRef.current && mountedRef.current) {
|
||||
setIsCreating(false)
|
||||
}
|
||||
}
|
||||
@@ -168,6 +162,7 @@ export function useCreateRepo(
|
||||
createParent,
|
||||
createKind,
|
||||
fetchWorktrees,
|
||||
mountedRef,
|
||||
setStep,
|
||||
setAddedRepo,
|
||||
closeModal,
|
||||
@@ -327,8 +322,7 @@ export function CreateStep({
|
||||
})
|
||||
}, [cancelRadioFocusFrame, createKind, onKindChange])
|
||||
|
||||
const trimmedName = createName.trim()
|
||||
const canSubmit = trimmedName.length > 0 && createParent.trim().length > 0 && !isCreating
|
||||
const canSubmit = createName.trim().length > 0 && createParent.trim().length > 0 && !isCreating
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user