Update files
This commit is contained in:
@@ -416,7 +416,6 @@ export default function SettingsScreen() {
|
||||
const [pendingRemoveHost, setPendingRemoveHost] = useState<HostProfile | null>(null);
|
||||
const [isRemovingHost, setIsRemovingHost] = useState(false);
|
||||
const [editingDaemon, setEditingDaemon] = useState<HostProfile | null>(null);
|
||||
const [editLabel, setEditLabel] = useState("");
|
||||
const [isSavingEdit, setIsSavingEdit] = useState(false);
|
||||
const isLoading = settingsLoading || daemonLoading;
|
||||
const isMountedRef = useRef(true);
|
||||
@@ -460,13 +459,11 @@ export default function SettingsScreen() {
|
||||
|
||||
const handleEditDaemon = useCallback((profile: HostProfile) => {
|
||||
setEditingDaemon(profile);
|
||||
setEditLabel(profile.label ?? "");
|
||||
}, []);
|
||||
|
||||
const handleCloseEditDaemon = useCallback(() => {
|
||||
if (isSavingEdit) return;
|
||||
setEditingDaemon(null);
|
||||
setEditLabel("");
|
||||
}, [isSavingEdit]);
|
||||
|
||||
const closeAddConnectionFlow = useCallback(() => {
|
||||
@@ -510,17 +507,11 @@ export default function SettingsScreen() {
|
||||
pendingEditReopenServerId,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!editingDaemon) return;
|
||||
if (editingDaemonLive) return;
|
||||
handleCloseEditDaemon();
|
||||
}, [editingDaemon, editingDaemonLive, handleCloseEditDaemon]);
|
||||
|
||||
const handleSaveEditDaemon = useCallback(async () => {
|
||||
const handleSaveEditDaemon = useCallback(async (nextLabelRaw: string) => {
|
||||
if (!editingDaemon) return;
|
||||
if (isSavingEdit) return;
|
||||
|
||||
const nextLabel = editLabel.trim();
|
||||
const nextLabel = nextLabelRaw.trim();
|
||||
if (!nextLabel) {
|
||||
Alert.alert("Label required", "Enter a label for this host.");
|
||||
return;
|
||||
@@ -536,7 +527,7 @@ export default function SettingsScreen() {
|
||||
} finally {
|
||||
setIsSavingEdit(false);
|
||||
}
|
||||
}, [editLabel, editingDaemon, handleCloseEditDaemon, isSavingEdit, updateHost]);
|
||||
}, [editingDaemon, handleCloseEditDaemon, isSavingEdit, updateHost]);
|
||||
|
||||
const handleRemoveConnection = useCallback(
|
||||
async (serverId: string, connectionId: string) => {
|
||||
@@ -757,84 +748,14 @@ export default function SettingsScreen() {
|
||||
</AdaptiveModalSheet>
|
||||
) : null}
|
||||
|
||||
<AdaptiveModalSheet
|
||||
title="Edit host"
|
||||
<EditHostModal
|
||||
visible={Boolean(editingDaemon)}
|
||||
host={editingDaemonLive ?? editingDaemon}
|
||||
isSaving={isSavingEdit}
|
||||
onClose={handleCloseEditDaemon}
|
||||
testID="edit-host-modal"
|
||||
>
|
||||
<View style={styles.formField}>
|
||||
<Text style={styles.label}>Label</Text>
|
||||
<AdaptiveTextInput
|
||||
style={styles.input}
|
||||
value={editLabel}
|
||||
onChangeText={setEditLabel}
|
||||
placeholder="My Host"
|
||||
placeholderTextColor={defaultTheme.colors.mutedForeground}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{editingDaemonLive ? (
|
||||
<View style={styles.formField}>
|
||||
<Text style={styles.label}>Connections</Text>
|
||||
<View style={{ gap: 8 }}>
|
||||
{editingDaemonLive.connections.map((conn) => {
|
||||
const title =
|
||||
conn.type === "relay"
|
||||
? `Relay (${conn.relayEndpoint})`
|
||||
: `Direct (${conn.endpoint})`;
|
||||
return (
|
||||
<View
|
||||
key={conn.id}
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: 12,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 12,
|
||||
borderRadius: 12,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.border,
|
||||
backgroundColor: theme.colors.surface2,
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: theme.colors.foreground, fontSize: 12, flex: 1 }}>
|
||||
{title}
|
||||
</Text>
|
||||
<Pressable
|
||||
onPress={() => void handleRemoveConnection(editingDaemonLive.serverId, conn.id)}
|
||||
>
|
||||
<Text style={{ color: theme.colors.destructive, fontSize: 12, fontWeight: "500" }}>
|
||||
Remove
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
<View style={styles.formActionsRow}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onPress={handleCloseEditDaemon}
|
||||
disabled={isSavingEdit}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
onPress={() => void handleSaveEditDaemon()}
|
||||
disabled={isSavingEdit}
|
||||
>
|
||||
{isSavingEdit ? "Saving..." : "Save"}
|
||||
</Button>
|
||||
</View>
|
||||
</AdaptiveModalSheet>
|
||||
onSave={(label) => void handleSaveEditDaemon(label)}
|
||||
onRemoveConnection={handleRemoveConnection}
|
||||
/>
|
||||
|
||||
{/* Appearance */}
|
||||
<View style={styles.section}>
|
||||
@@ -895,6 +816,126 @@ export default function SettingsScreen() {
|
||||
);
|
||||
}
|
||||
|
||||
interface EditHostModalProps {
|
||||
visible: boolean;
|
||||
host: HostProfile | null;
|
||||
isSaving: boolean;
|
||||
onClose: () => void;
|
||||
onSave: (label: string) => void;
|
||||
onRemoveConnection: (serverId: string, connectionId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
function EditHostModal({
|
||||
visible,
|
||||
host,
|
||||
isSaving,
|
||||
onClose,
|
||||
onSave,
|
||||
onRemoveConnection,
|
||||
}: EditHostModalProps) {
|
||||
const [draftLabel, setDraftLabel] = useState("");
|
||||
const activeServerIdRef = useRef<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!visible || !host) return;
|
||||
if (activeServerIdRef.current !== host.serverId) {
|
||||
setDraftLabel(host.label ?? "");
|
||||
activeServerIdRef.current = host.serverId;
|
||||
return;
|
||||
}
|
||||
if (!draftLabel.trim()) {
|
||||
setDraftLabel(host.label ?? "");
|
||||
}
|
||||
}, [visible, host, draftLabel]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!visible) {
|
||||
activeServerIdRef.current = null;
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
return (
|
||||
<AdaptiveModalSheet
|
||||
title="Edit host"
|
||||
visible={visible}
|
||||
onClose={onClose}
|
||||
testID="edit-host-modal"
|
||||
>
|
||||
<View style={styles.formField}>
|
||||
<Text style={styles.label}>Label</Text>
|
||||
<AdaptiveTextInput
|
||||
style={styles.input}
|
||||
value={draftLabel}
|
||||
onChangeText={setDraftLabel}
|
||||
placeholder="My Host"
|
||||
placeholderTextColor={defaultTheme.colors.mutedForeground}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{host ? (
|
||||
<View style={styles.formField}>
|
||||
<Text style={styles.label}>Connections</Text>
|
||||
<View style={{ gap: 8 }}>
|
||||
{host.connections.map((conn) => {
|
||||
const title =
|
||||
conn.type === "relay"
|
||||
? `Relay (${conn.relayEndpoint})`
|
||||
: `Direct (${conn.endpoint})`;
|
||||
return (
|
||||
<View
|
||||
key={conn.id}
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: 12,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 12,
|
||||
borderRadius: 12,
|
||||
borderWidth: 1,
|
||||
borderColor: defaultTheme.colors.border,
|
||||
backgroundColor: defaultTheme.colors.surface2,
|
||||
}}
|
||||
>
|
||||
<Text style={{ color: defaultTheme.colors.foreground, fontSize: 12, flex: 1 }}>
|
||||
{title}
|
||||
</Text>
|
||||
<Pressable
|
||||
onPress={() => void onRemoveConnection(host.serverId, conn.id)}
|
||||
>
|
||||
<Text style={{ color: defaultTheme.colors.destructive, fontSize: 12, fontWeight: "500" }}>
|
||||
Remove
|
||||
</Text>
|
||||
</Pressable>
|
||||
</View>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
<View style={styles.formActionsRow}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onPress={onClose}
|
||||
disabled={isSaving}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
onPress={() => onSave(draftLabel)}
|
||||
disabled={isSaving}
|
||||
>
|
||||
{isSaving ? "Saving..." : "Save"}
|
||||
</Button>
|
||||
</View>
|
||||
</AdaptiveModalSheet>
|
||||
);
|
||||
}
|
||||
|
||||
interface DaemonCardProps {
|
||||
daemon: HostProfile;
|
||||
connectionStatus: ConnectionStatus;
|
||||
|
||||
@@ -163,6 +163,15 @@ export function SelectField({
|
||||
[getWebKey, onPress, preventWebDefault]
|
||||
);
|
||||
|
||||
const normalizedValue = (value ?? "").trim();
|
||||
const normalizedPlaceholder = (placeholder ?? "").trim();
|
||||
const hasConcreteValue =
|
||||
normalizedValue.length > 0 &&
|
||||
(normalizedPlaceholder.length === 0 || normalizedValue !== normalizedPlaceholder);
|
||||
const displayText = hasConcreteValue
|
||||
? normalizedValue
|
||||
: (normalizedPlaceholder || "Select...");
|
||||
|
||||
return (
|
||||
<View style={styles.selectFieldContainer}>
|
||||
<Pressable
|
||||
@@ -423,6 +432,14 @@ export function FormSelectTrigger({
|
||||
},
|
||||
[getWebKey, onPress, preventWebDefault]
|
||||
);
|
||||
const normalizedValue = (value ?? "").trim();
|
||||
const normalizedPlaceholder = (placeholder ?? "").trim();
|
||||
const hasConcreteValue =
|
||||
normalizedValue.length > 0 &&
|
||||
(normalizedPlaceholder.length === 0 || normalizedValue !== normalizedPlaceholder);
|
||||
const displayText = hasConcreteValue
|
||||
? normalizedValue
|
||||
: (normalizedPlaceholder || "Select...");
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
@@ -451,11 +468,11 @@ export function FormSelectTrigger({
|
||||
<ActivityIndicator size="small" color={defaultTheme.colors.foregroundMuted} />
|
||||
) : (
|
||||
<Text
|
||||
style={value ? styles.compactSelectValue : styles.compactSelectPlaceholder}
|
||||
style={hasConcreteValue ? styles.compactSelectValue : styles.compactSelectPlaceholder}
|
||||
numberOfLines={1}
|
||||
ellipsizeMode={valueEllipsizeMode}
|
||||
>
|
||||
{value || placeholder || "Select..."}
|
||||
{displayText}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
@@ -1426,7 +1443,10 @@ const styles = StyleSheet.create((theme) => ({
|
||||
paddingVertical: theme.spacing[1],
|
||||
},
|
||||
agentConfigRow: {
|
||||
flexDirection: "row",
|
||||
flexDirection: {
|
||||
xs: "column",
|
||||
md: "row",
|
||||
},
|
||||
gap: theme.spacing[2],
|
||||
},
|
||||
agentConfigColumn: {
|
||||
|
||||
@@ -1206,7 +1206,10 @@ const stylesheet = StyleSheet.create((theme) => ({
|
||||
},
|
||||
list: {
|
||||
flex: 1,
|
||||
paddingHorizontal: theme.spacing[2],
|
||||
paddingHorizontal: {
|
||||
xs: theme.spacing[2],
|
||||
md: theme.spacing[4],
|
||||
},
|
||||
},
|
||||
streamItemWrapper: {
|
||||
width: "100%",
|
||||
|
||||
@@ -1050,24 +1050,18 @@ export function GitDiffPane({ serverId, agentId, cwd }: GitDiffPaneProps) {
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={gitActions.primary.label}
|
||||
>
|
||||
<View style={styles.splitButtonPrimaryInner}>
|
||||
<View
|
||||
style={[
|
||||
styles.splitButtonContent,
|
||||
gitActions.primary.status === "pending" && styles.splitButtonContentHidden,
|
||||
]}
|
||||
>
|
||||
{gitActions.primary.status === "pending" ? (
|
||||
<ActivityIndicator
|
||||
size="small"
|
||||
color={theme.colors.foreground}
|
||||
style={styles.splitButtonSpinnerOnly}
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.splitButtonContent}>
|
||||
{gitActions.primary.icon}
|
||||
<Text style={styles.splitButtonText}>{getActionDisplayLabel(gitActions.primary)}</Text>
|
||||
</View>
|
||||
{gitActions.primary.status === "pending" ? (
|
||||
<ActivityIndicator
|
||||
size="small"
|
||||
color={theme.colors.foreground}
|
||||
style={styles.splitButtonSpinnerOverlay}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
)}
|
||||
</Pressable>
|
||||
{gitActions.secondary.length > 0 ? (
|
||||
<DropdownMenu>
|
||||
@@ -1306,11 +1300,6 @@ const styles = StyleSheet.create((theme) => ({
|
||||
justifyContent: "center",
|
||||
position: "relative",
|
||||
},
|
||||
splitButtonPrimaryInner: {
|
||||
position: "relative",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
},
|
||||
splitButtonPrimaryDisabled: {
|
||||
opacity: 0.6,
|
||||
},
|
||||
@@ -1326,11 +1315,7 @@ const styles = StyleSheet.create((theme) => ({
|
||||
justifyContent: "center",
|
||||
gap: theme.spacing[2],
|
||||
},
|
||||
splitButtonContentHidden: {
|
||||
opacity: 0,
|
||||
},
|
||||
splitButtonSpinnerOverlay: {
|
||||
position: "absolute",
|
||||
splitButtonSpinnerOnly: {
|
||||
transform: [{ scale: 0.8 }],
|
||||
},
|
||||
splitButtonCaret: {
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
import { useDaemonConnections } from "@/contexts/daemon-connections-context";
|
||||
import { useDaemonRegistry } from "@/contexts/daemon-registry-context";
|
||||
import { formatConnectionStatus } from "@/utils/daemons";
|
||||
import { shortenPath } from "@/utils/shorten-path";
|
||||
import { usePanelStore } from "@/stores/panel-store";
|
||||
import { useSessionStore } from "@/stores/session-store";
|
||||
import { useCreateFlowStore } from "@/stores/create-flow-store";
|
||||
@@ -199,11 +200,25 @@ export function DraftAgentScreen({
|
||||
isCreateFlow: true,
|
||||
onlineServerIds,
|
||||
});
|
||||
const daemonLabelByServerId = useMemo(() => {
|
||||
const map = new Map<string, string>();
|
||||
for (const daemon of daemons) {
|
||||
const label = daemon.label?.trim();
|
||||
map.set(daemon.serverId, label && label.length > 0 ? label : daemon.serverId);
|
||||
}
|
||||
return map;
|
||||
}, [daemons]);
|
||||
const hostEntry = selectedServerId
|
||||
? connectionStates.get(selectedServerId)
|
||||
: undefined;
|
||||
const selectedDaemonLabel = selectedServerId
|
||||
? daemonLabelByServerId.get(selectedServerId)
|
||||
: null;
|
||||
const hostLabel =
|
||||
hostEntry?.daemon.label ?? selectedServerId ?? "Select host";
|
||||
selectedDaemonLabel ??
|
||||
hostEntry?.daemon.label ??
|
||||
selectedServerId ??
|
||||
"Select host";
|
||||
const isMobile =
|
||||
UnistylesRuntime.breakpoint === "xs" || UnistylesRuntime.breakpoint === "sm";
|
||||
const isSidebarOpen = isMobile ? mobileView === "agent-list" : desktopAgentListOpen;
|
||||
@@ -561,9 +576,8 @@ export function DraftAgentScreen({
|
||||
const handleSelectWorktreePath = useCallback(
|
||||
(path: string) => {
|
||||
setSelectedWorktreePath(path);
|
||||
setWorkingDirFromUser(path);
|
||||
},
|
||||
[setWorkingDirFromUser]
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -591,35 +605,36 @@ export function DraftAgentScreen({
|
||||
|
||||
const selectedWorktreeLabel =
|
||||
worktreeOptions.find((option) => option.path === selectedWorktreePath)?.label ?? "";
|
||||
const displayWorkingDir = shortenPath(workingDir);
|
||||
const worktreeTriggerValue =
|
||||
worktreeMode === "create"
|
||||
? "Create new worktree"
|
||||
: selectedWorktreeLabel || "Select worktree";
|
||||
const hostOptions = useMemo(
|
||||
() =>
|
||||
Array.from(connectionStates.values()).map(({ daemon, status }) => ({
|
||||
daemons.map((daemon) => ({
|
||||
id: daemon.serverId,
|
||||
label: daemon.label?.trim() ? daemon.label : daemon.serverId,
|
||||
description: formatConnectionStatus(status),
|
||||
label: daemonLabelByServerId.get(daemon.serverId) ?? daemon.serverId,
|
||||
description: formatConnectionStatus(
|
||||
connectionStates.get(daemon.serverId)?.status ?? "idle"
|
||||
),
|
||||
})),
|
||||
[connectionStates]
|
||||
[connectionStates, daemonLabelByServerId, daemons]
|
||||
);
|
||||
const worktreeComboOptions = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: "__create_new__",
|
||||
label: "Create new worktree",
|
||||
description: "Create a new isolated worktree",
|
||||
},
|
||||
{
|
||||
id: "__none__",
|
||||
label: "None",
|
||||
description: "Do not use a worktree",
|
||||
},
|
||||
{
|
||||
id: "__create_new__",
|
||||
label: "Create new worktree",
|
||||
},
|
||||
...worktreeOptions.map((option) => ({
|
||||
id: option.path,
|
||||
label: option.label,
|
||||
description: option.path,
|
||||
description: shortenPath(option.path),
|
||||
})),
|
||||
],
|
||||
[worktreeOptions]
|
||||
@@ -922,12 +937,12 @@ export function DraftAgentScreen({
|
||||
) : (
|
||||
<ScrollView style={styles.scrollView} contentContainerStyle={styles.configScrollContent}>
|
||||
<View style={styles.configSection}>
|
||||
<View style={styles.topSelectorRow}>
|
||||
<View style={isMobile ? styles.stackedSelectorGroup : styles.topSelectorRow}>
|
||||
<FormSelectTrigger
|
||||
controlRef={workingDirAnchorRef}
|
||||
containerStyle={styles.topSelectorPrimary}
|
||||
containerStyle={isMobile ? styles.fullSelector : styles.topSelectorPrimary}
|
||||
label="Working directory"
|
||||
value={workingDir}
|
||||
value={displayWorkingDir}
|
||||
placeholder="/path/to/project"
|
||||
onPress={() => setIsWorkingDirOpen(true)}
|
||||
icon={<Folder size={16} color={theme.colors.foregroundMuted} />}
|
||||
@@ -936,7 +951,7 @@ export function DraftAgentScreen({
|
||||
/>
|
||||
<FormSelectTrigger
|
||||
controlRef={hostAnchorRef}
|
||||
containerStyle={styles.topSelectorSecondary}
|
||||
containerStyle={isMobile ? styles.fullSelector : styles.topSelectorSecondary}
|
||||
label="Host"
|
||||
value={hostLabel}
|
||||
placeholder="Select host"
|
||||
@@ -952,36 +967,7 @@ export function DraftAgentScreen({
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
{trimmedWorkingDir.length > 0 && !isNonGitDirectory ? (
|
||||
<View style={styles.topSelectorRow}>
|
||||
<FormSelectTrigger
|
||||
controlRef={worktreeAnchorRef}
|
||||
containerStyle={
|
||||
worktreeMode === "create" ? styles.halfSelector : styles.topSelectorPrimary
|
||||
}
|
||||
label="Worktree"
|
||||
value={worktreeTriggerValue}
|
||||
placeholder="Select worktree"
|
||||
onPress={() => setIsWorktreePickerOpen(true)}
|
||||
icon={<GitBranch size={16} color={theme.colors.foregroundMuted} />}
|
||||
showLabel={false}
|
||||
valueEllipsizeMode="middle"
|
||||
/>
|
||||
{worktreeMode === "create" ? (
|
||||
<FormSelectTrigger
|
||||
controlRef={branchAnchorRef}
|
||||
containerStyle={styles.halfSelector}
|
||||
label="Base branch"
|
||||
value={baseBranch}
|
||||
placeholder="From branch"
|
||||
onPress={() => setIsBranchOpen(true)}
|
||||
disabled={repoInfoStatus === "loading"}
|
||||
icon={<GitBranch size={16} color={theme.colors.foregroundMuted} />}
|
||||
showLabel={false}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
) : null}
|
||||
{isMobile ? <View style={styles.formSeparator} /> : null}
|
||||
<AgentConfigRow
|
||||
providerDefinitions={providerDefinitions}
|
||||
selectedProvider={selectedProvider}
|
||||
@@ -994,6 +980,43 @@ export function DraftAgentScreen({
|
||||
isModelLoading={isModelLoading}
|
||||
onSelectModel={setModelFromUser}
|
||||
/>
|
||||
{isMobile && trimmedWorkingDir.length > 0 && !isNonGitDirectory ? (
|
||||
<View style={styles.formSeparator} />
|
||||
) : null}
|
||||
{trimmedWorkingDir.length > 0 && !isNonGitDirectory ? (
|
||||
<View style={isMobile ? styles.stackedSelectorGroup : styles.topSelectorRow}>
|
||||
<FormSelectTrigger
|
||||
controlRef={worktreeAnchorRef}
|
||||
containerStyle={
|
||||
isMobile
|
||||
? styles.fullSelector
|
||||
: worktreeMode === "create"
|
||||
? styles.halfSelector
|
||||
: styles.topSelectorPrimary
|
||||
}
|
||||
label="Worktree"
|
||||
value={worktreeTriggerValue}
|
||||
placeholder="Select worktree"
|
||||
onPress={() => setIsWorktreePickerOpen(true)}
|
||||
icon={<GitBranch size={16} color={theme.colors.foregroundMuted} />}
|
||||
showLabel={false}
|
||||
valueEllipsizeMode="middle"
|
||||
/>
|
||||
{worktreeMode === "create" ? (
|
||||
<FormSelectTrigger
|
||||
controlRef={branchAnchorRef}
|
||||
containerStyle={isMobile ? styles.fullSelector : styles.halfSelector}
|
||||
label="Base branch"
|
||||
value={baseBranch}
|
||||
placeholder="From branch"
|
||||
onPress={() => setIsBranchOpen(true)}
|
||||
disabled={repoInfoStatus === "loading"}
|
||||
icon={<GitBranch size={16} color={theme.colors.foregroundMuted} />}
|
||||
showLabel={false}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
) : null}
|
||||
{baseBranchError ? <Text style={styles.errorInlineText}>{baseBranchError}</Text> : null}
|
||||
{repoInfoError ? <Text style={styles.errorInlineText}>{repoInfoError}</Text> : null}
|
||||
{gitBlockingError ? <Text style={styles.errorInlineText}>{gitBlockingError}</Text> : null}
|
||||
@@ -1046,7 +1069,10 @@ export function DraftAgentScreen({
|
||||
/>
|
||||
|
||||
<Combobox
|
||||
options={agentWorkingDirSuggestions.map((path) => ({ id: path, label: path }))}
|
||||
options={agentWorkingDirSuggestions.map((path) => ({
|
||||
id: path,
|
||||
label: shortenPath(path),
|
||||
}))}
|
||||
value={workingDir}
|
||||
onSelect={setWorkingDirFromUser}
|
||||
searchPlaceholder="/path/to/project"
|
||||
@@ -1136,7 +1162,10 @@ const styles = StyleSheet.create((theme) => ({
|
||||
justifyContent: "flex-end",
|
||||
},
|
||||
configSection: {
|
||||
paddingHorizontal: theme.spacing[0],
|
||||
paddingHorizontal: {
|
||||
xs: theme.spacing[4],
|
||||
md: theme.spacing[0],
|
||||
},
|
||||
paddingTop: theme.spacing[3],
|
||||
paddingBottom: theme.spacing[4],
|
||||
gap: theme.spacing[2],
|
||||
@@ -1149,6 +1178,22 @@ const styles = StyleSheet.create((theme) => ({
|
||||
alignItems: "center",
|
||||
gap: theme.spacing[2],
|
||||
},
|
||||
stackedSelectorGroup: {
|
||||
gap: theme.spacing[2],
|
||||
},
|
||||
fullSelector: {
|
||||
width: "100%",
|
||||
},
|
||||
formSeparator: {
|
||||
height: theme.borderWidth[1],
|
||||
backgroundColor: {
|
||||
xs: theme.colors.surface1,
|
||||
sm: theme.colors.surface1,
|
||||
md: theme.colors.border,
|
||||
},
|
||||
marginHorizontal: theme.spacing[1],
|
||||
marginVertical: theme.spacing[2],
|
||||
},
|
||||
topSelectorPrimary: {
|
||||
flex: 7,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user