authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-09-17 20:20:02-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-17 20:20:02-07:00
log18dcc43ace0a7b0d93f2fd61907b2a4e27522936
tree6e509c34ea3e4ba4163f621ad2531b289152d6e4
parent767a5dbd00d0a2050745a2ae2e29050c5282b8c0
signature Signed by PGP key B5690EEEBB952194

refactor(mobile): share connection form fields (#12364)


3 files changed, 63 insertions(+), 56 deletions(-)

apps/mobile/src/features/connection/ConnectionEnvironmentRow.tsx+19-28
......@@ -10,7 +10,7 @@ import { useCallback, useState } from "react";
1010import { Platform, Alert, Pressable, View } from "react-native";
1111import Animated, { FadeIn, FadeOut, LinearTransition } from "react-native-reanimated";
1212
13import { AppText as Text, AppTextInput as TextInput } from "../../components/AppText";
13import { AppText as Text } from "../../components/AppText";
1414import { EnvironmentMachineSymbol } from "../../components/EnvironmentMachineSymbol";
1515import { MaterialButton } from "../../components/MaterialButton";
1616import { MaterialIconButton } from "../../components/MaterialIconButton";
......@@ -18,6 +18,7 @@ import { ThemedSwitch } from "../../components/ThemedSwitch";
1818import { cn } from "../../lib/cn";
1919import type { ConnectedEnvironmentSummary } from "../../state/remote-runtime-types";
2020import { serverEnvironment } from "../../state/server";
21import { ConnectionFormField } from "./ConnectionFormField";
2122import { ConnectionStatusDot } from "./ConnectionStatusDot";
2223
2324function connectionStatusLabel(environment: ConnectedEnvironmentSummary): string | null {
......@@ -152,34 +153,24 @@ export function ConnectionEnvironmentRow(props: {
152153 </Text>
153154 ) : (
154155 <>
155 <View className="gap-1.5">
156 <Text className="text-2xs font-t3-bold tracking-[0.8px] uppercase text-foreground-muted">
157 Label
158 </Text>
159 <TextInput
160 autoCapitalize="words"
161 autoCorrect={false}
162 placeholder="My MacBook"
163 value={label}
164 onChangeText={setLabel}
165 className="rounded-[14px] border border-input-border bg-input px-4 py-3 text-base text-foreground"
166 />
167 </View>
156 <ConnectionFormField
157 label="Label"
158 autoCapitalize="words"
159 autoCorrect={false}
160 placeholder="My MacBook"
161 value={label}
162 onChangeText={setLabel}
163 />
168164
169 <View className="gap-1.5">
170 <Text className="text-2xs font-t3-bold tracking-[0.8px] uppercase text-foreground-muted">
171 URL
172 </Text>
173 <TextInput
174 autoCapitalize="none"
175 autoCorrect={false}
176 keyboardType="url"
177 placeholder="192.168.1.100:8080"
178 value={url}
179 onChangeText={setUrl}
180 className="rounded-[14px] border border-input-border bg-input px-4 py-3 text-base text-foreground"
181 />
182 </View>
165 <ConnectionFormField
166 label="URL"
167 autoCapitalize="none"
168 autoCorrect={false}
169 keyboardType="url"
170 placeholder="192.168.1.100:8080"
171 value={url}
172 onChangeText={setUrl}
173 />
183174 </>
184175 )}
185176
apps/mobile/src/features/connection/ConnectionFormField.tsx created+25
......@@ -0,0 +1,25 @@
1import { View } from "react-native";
2
3import { AppText, AppTextInput, type AppTextInputProps } from "../../components/AppText";
4import { cn } from "../../lib/cn";
5
6type ConnectionFormFieldProps = Omit<AppTextInputProps, "className"> & {
7 readonly label: string;
8 readonly className?: string;
9};
10
11/** Labeled connection input with a native wrapper retained inside form sheets. */
12export function ConnectionFormField({ label, className, ...inputProps }: ConnectionFormFieldProps) {
13 return (
14 <View collapsable={false} className={cn("gap-1.5", className)}>
15 <AppText className="text-2xs font-t3-bold tracking-[0.8px] uppercase text-foreground-muted">
16 {label}
17 </AppText>
18 <AppTextInput
19 accessibilityLabel={label}
20 {...inputProps}
21 className="rounded-[14px] px-4 py-3.5"
22 />
23 </View>
24 );
25}
apps/mobile/src/features/connection/ConnectionsNewRouteScreen.tsx+19-28
......@@ -13,8 +13,9 @@ import { Alert, Linking, Platform, View } from "react-native";
1313import { useSafeAreaInsets } from "react-native-safe-area-context";
1414import { useUniwindTheme } from "../../lib/useUniwindTheme";
1515import { SettingsScreen } from "../settings/components/SettingsScreen";
16import { AppText as Text, AppTextInput as TextInput } from "../../components/AppText";
16import { AppText as Text } from "../../components/AppText";
1717import { ErrorBanner } from "../../components/ErrorBanner";
18import { ConnectionFormField } from "./ConnectionFormField";
1819import { ConnectionSheetButton } from "./ConnectionSheetButton";
1920import { buildPairingUrl, extractPairingUrlFromQrPayload, parsePairingUrl } from "./pairing";
2021import { useRemoteConnections } from "../../state/use-remote-environment-registry";
......@@ -262,34 +263,24 @@ export function ConnectionsNewRouteScreen({
262263 )
263264 ) : (
264265 <View collapsable={false} className="gap-4 rounded-[24px] bg-card p-4">
265 <View collapsable={false} className="gap-1.5">
266 <Text className="text-2xs font-t3-bold tracking-[0.8px] uppercase text-foreground-muted">
267 Host
268 </Text>
269 <TextInput
270 autoCapitalize="none"
271 autoCorrect={false}
272 keyboardType="url"
273 placeholder="192.168.1.100:8080"
274 value={hostInput}
275 onChangeText={handleHostChange}
276 className="rounded-[14px] border border-input-border bg-input px-4 py-3.5 text-base text-foreground"
277 />
278 </View>
266 <ConnectionFormField
267 label="Host"
268 autoCapitalize="none"
269 autoCorrect={false}
270 keyboardType="url"
271 placeholder="192.168.1.100:8080"
272 value={hostInput}
273 onChangeText={handleHostChange}
274 />
279275
280 <View collapsable={false} className="gap-1.5">
281 <Text className="text-2xs font-t3-bold tracking-[0.8px] uppercase text-foreground-muted">
282 Pairing code
283 </Text>
284 <TextInput
285 autoCapitalize="none"
286 autoCorrect={false}
287 placeholder="abc-123-xyz"
288 value={codeInput}
289 onChangeText={handleCodeChange}
290 className="rounded-[14px] border border-input-border bg-input px-4 py-3.5 text-base text-foreground"
291 />
292 </View>
276 <ConnectionFormField
277 label="Pairing code"
278 autoCapitalize="none"
279 autoCorrect={false}
280 placeholder="abc-123-xyz"
281 value={codeInput}
282 onChangeText={handleCodeChange}
283 />
293284
294285 {pairingConnectionError ? <ErrorBanner message={pairingConnectionError} /> : null}
295286