1import { Button } from "../../components/ui/Button";
2import {
3 projectCloneDisplayName,
4 projectCloneProgressSummary,
5 type ProjectCloneSnapshot,
6} from "@t3tools/contracts";
7import { View } from "react-native";
8
9import { AppActivityIndicator } from "../../components/ui/AppActivityIndicator";
10import { cn } from "../../lib/cn";
11import { AppText as Text } from "../../components/ui/AppText";
12
13export function ProjectCloneBanner(props: {
14 readonly clone: ProjectCloneSnapshot;
15 readonly onCancel: () => void;
16 readonly onRetry: () => void;
17 readonly onRemove: () => void;
18}) {
19 const { clone } = props;
20 const name = projectCloneDisplayName(clone);
21 if (clone.phase === "running") {
22 return (
23 <View className="flex-row items-center gap-3 rounded-2xl border border-border bg-card px-3.5 py-3">
24 <AppActivityIndicator size="small" />
25 <View className="min-w-0 flex-1">
26 <Text className="font-t3-medium text-sm" numberOfLines={1}>
27 Cloning {name}
28 </Text>
29 <Text className="text-xs text-foreground-muted" numberOfLines={1}>
30 {projectCloneProgressSummary(clone)}
31 </Text>
32 </View>
33 <BannerAction label="Cancel" onPress={props.onCancel} />
34 </View>
35 );
36 }
37 const cancelled = clone.phase === "cancelled";
38 return (
39 <View
40 className={cn(
41 "rounded-2xl border px-3.5 py-3",
42 cancelled ? "border-warning-border bg-warning" : "border-danger-border bg-danger",
43 )}
44 >
45 <Text
46 className={cn(
47 "font-t3-medium text-sm",
48 cancelled ? "text-warning-foreground" : "text-danger-foreground",
49 )}
50 numberOfLines={1}
51 >
52 {cancelled ? `Cancelled cloning ${name}` : `Failed to clone ${name}`}
53 </Text>
54 {clone.error ? (
55 <Text className="mt-0.5 text-xs text-danger-foreground" numberOfLines={3}>
56 {clone.error}
57 </Text>
58 ) : null}
59 <View className="mt-2 flex-row justify-end gap-2">
60 <BannerAction label="Remove project" onPress={props.onRemove} />
61 <BannerAction label="Retry" onPress={props.onRetry} />
62 </View>
63 </View>
64 );
65}
66
67function BannerAction(props: { readonly label: string; readonly onPress: () => void }) {
68 return (
69 <Button
70 label={props.label}
71 tone="secondary"
72 accessibilityLabel={props.label}
73 onPress={props.onPress}
74 />
75 );
76}