Skip to content

Commit 84f960c

Browse files
committed
block ui when clonign
1 parent 8ca2693 commit 84f960c

File tree

3 files changed

+80
-16
lines changed

3 files changed

+80
-16
lines changed

src/renderer/features/repository-picker/components/RepositoryPicker.tsx

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ChevronDownIcon } from "@radix-ui/react-icons";
44
import { Box, Button, Flex, Popover, Text, TextField } from "@radix-ui/themes";
55
import { useRepositoryIntegration } from "@renderer/hooks/useIntegrations";
66
import type { RepositoryConfig } from "@shared/types";
7+
import { cloneStore } from "@stores/cloneStore";
78
import { useMemo, useRef, useState } from "react";
89
import { useHotkeys } from "react-hotkeys-hook";
910

@@ -34,6 +35,7 @@ export function RepositoryPicker({
3435
const searchInputRef = useRef<HTMLInputElement>(null);
3536

3637
const { repositories, githubIntegration } = useRepositoryIntegration();
38+
const { isCloning } = cloneStore();
3739

3840
const displayValue = value ? `${value.repository}` : placeholder;
3941

@@ -103,19 +105,32 @@ export function RepositoryPicker({
103105
}
104106
};
105107

106-
const renderItem = (repo: RepositoryConfig) => (
107-
<Command.Item
108-
key={`${repo.organization}/${repo.repository}`}
109-
onSelect={() => handleSelect(repo)}
110-
>
111-
<Flex direction="row" gap="4">
112-
<Text size="1">{repo.repository}</Text>
113-
<Text size="1" color="gray" className="text-gray-9">
114-
{repo.organization}
115-
</Text>
116-
</Flex>
117-
</Command.Item>
118-
);
108+
const renderItem = (repo: RepositoryConfig) => {
109+
const repoKey = `${repo.organization}/${repo.repository}`;
110+
const cloning = isCloning(repoKey);
111+
112+
return (
113+
<Command.Item
114+
key={repoKey}
115+
onSelect={() => handleSelect(repo)}
116+
disabled={cloning}
117+
>
118+
<Flex direction="row" gap="4" align="center">
119+
<Text size="1" color={cloning ? "gray" : undefined}>
120+
{repo.repository}
121+
</Text>
122+
<Text size="1" color="gray" className="text-gray-9">
123+
{repo.organization}
124+
</Text>
125+
{cloning && (
126+
<Text size="1" color="amber">
127+
Cloning...
128+
</Text>
129+
)}
130+
</Flex>
131+
</Command.Item>
132+
);
133+
};
119134

120135
const hasIntegration = githubIntegration !== null;
121136

src/renderer/features/tasks/components/CliTaskPanel.tsx

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { useTaskExecutionStore } from "@features/tasks/stores/taskExecutionStore
1111
import { ShellTerminal } from "@features/terminal/components/ShellTerminal";
1212
import { Box, Flex, Text } from "@radix-ui/themes";
1313
import type { RepositoryConfig } from "@shared/types";
14+
import { cloneStore } from "@stores/cloneStore";
1415
import { useLayoutStore } from "@stores/layoutStore";
1516
import { repositoryWorkspaceStore } from "@stores/repositoryWorkspaceStore";
1617
import { useTabStore } from "@stores/tabStore";
@@ -51,10 +52,20 @@ export function CliTaskPanel() {
5152
selectedRepository,
5253
derivedPath,
5354
pathExists,
55+
isInitiatingClone,
5456
selectRepository,
5557
validateAndUpdatePath,
5658
} = repositoryWorkspaceStore();
5759

60+
const { isCloning } = cloneStore();
61+
const repoIsCloning =
62+
isInitiatingClone ||
63+
(selectedRepository
64+
? isCloning(
65+
`${selectedRepository.organization}/${selectedRepository.repository}`,
66+
)
67+
: false);
68+
5869
const [isFocused, setIsFocused] = useState(false);
5970
const [isShellFocused, setIsShellFocused] = useState(false);
6071
const caretRef = useRef<HTMLDivElement>(null);
@@ -196,6 +207,13 @@ export function CliTaskPanel() {
196207
}
197208
}, [cliMode, editor]);
198209

210+
// Update editor editable state based on clone status
211+
useEffect(() => {
212+
if (editor) {
213+
editor.setEditable(!repoIsCloning);
214+
}
215+
}, [editor, repoIsCloning]);
216+
199217
// Validate path on mount if repository is selected
200218
useEffect(() => {
201219
if (selectedRepository) {
@@ -204,7 +222,13 @@ export function CliTaskPanel() {
204222
}, [selectedRepository, validateAndUpdatePath]);
205223

206224
const handleSubmit = useCallback(() => {
207-
if (!editor || !isAuthenticated || !client || !selectedRepository) {
225+
if (
226+
!editor ||
227+
!isAuthenticated ||
228+
!client ||
229+
!selectedRepository ||
230+
repoIsCloning
231+
) {
208232
return;
209233
}
210234

@@ -268,6 +292,7 @@ export function CliTaskPanel() {
268292
lastUsedRunMode,
269293
setRunMode,
270294
runTask,
295+
repoIsCloning,
271296
]);
272297

273298
return (
@@ -360,6 +385,8 @@ export function CliTaskPanel() {
360385
>
361386
{!selectedRepository ? (
362387
<EmptyStateMessage message="Select a repository to start" />
388+
) : repoIsCloning ? (
389+
<EmptyStateMessage message="Repository is being cloned..." />
363390
) : (
364391
<>
365392
<Text

src/renderer/stores/repositoryWorkspaceStore.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ interface RepositoryWorkspaceState {
1010
derivedPath: string;
1111
pathExists: boolean;
1212
isValidating: boolean;
13+
isInitiatingClone: boolean;
1314

1415
selectRepository: (repo: RepositoryConfig) => Promise<void>;
1516
clearRepository: () => void;
@@ -151,6 +152,7 @@ export const repositoryWorkspaceStore = create<RepositoryWorkspaceState>()(
151152
derivedPath: "",
152153
pathExists: false,
153154
isValidating: false,
155+
isInitiatingClone: false,
154156

155157
clearRepository: () => {
156158
stopPolling();
@@ -186,6 +188,21 @@ export const repositoryWorkspaceStore = create<RepositoryWorkspaceState>()(
186188
},
187189

188190
selectRepository: async (repo: RepositoryConfig) => {
191+
const repoKey = `${repo.organization}/${repo.repository}`;
192+
const { isCloning } = cloneStore.getState();
193+
194+
if (isCloning(repoKey)) {
195+
await window.electronAPI.showMessageBox({
196+
type: "warning",
197+
title: "Repository cloning",
198+
message: `${repoKey} is currently being cloned`,
199+
detail:
200+
"Please wait for the clone to complete before selecting this repository.",
201+
buttons: ["OK"],
202+
});
203+
return;
204+
}
205+
189206
const targetPath = getDerivedPath(repo);
190207

191208
if (!targetPath) {
@@ -216,10 +233,15 @@ export const repositoryWorkspaceStore = create<RepositoryWorkspaceState>()(
216233
selectedRepository: repo,
217234
derivedPath: targetPath,
218235
pathExists: false,
236+
isInitiatingClone: true,
219237
});
220238

221-
await initiateClone(repo, targetPath);
222-
startPolling();
239+
try {
240+
await initiateClone(repo, targetPath);
241+
startPolling();
242+
} finally {
243+
set({ isInitiatingClone: false });
244+
}
223245
},
224246
};
225247
},

0 commit comments

Comments
 (0)