Files
RuView/ui/mobile/src/screens/SettingsScreen/ServerUrlInput.tsx
ruv fdc7142dfa feat: Implement RSSI service for iOS and Web platforms
- Added IosRssiService to handle synthetic RSSI data for iOS.
- Created WebRssiService to simulate RSSI scanning on the web.
- Defined shared types for WifiNetwork and RssiService in rssi.service.ts.
- Introduced simulation service to generate synthetic sensing data.
- Implemented WebSocket service for real-time data handling with reconnection logic.
- Established Zustand stores for managing application state related to MAT and pose data.
- Developed theme context and utility functions for consistent styling and formatting.
- Added type definitions for various application entities including API responses and sensing data.
- Created utility functions for color mapping and URL validation.
- Configured TypeScript settings for the mobile application.
2026-03-02 10:30:33 -05:00

103 lines
3.0 KiB
TypeScript

import { useState } from 'react';
import { Pressable, TextInput, View } from 'react-native';
import { validateServerUrl } from '@/utils/urlValidator';
import { apiService } from '@/services/api.service';
import { ThemedText } from '@/components/ThemedText';
import { colors } from '@/theme/colors';
import { spacing } from '@/theme/spacing';
type ServerUrlInputProps = {
value: string;
onChange: (value: string) => void;
onSave: () => void;
};
export const ServerUrlInput = ({ value, onChange, onSave }: ServerUrlInputProps) => {
const [testResult, setTestResult] = useState('');
const validation = validateServerUrl(value);
const handleTest = async () => {
if (!validation.valid) {
setTestResult('✗ Invalid URL');
return;
}
const start = Date.now();
try {
await apiService.getStatus();
setTestResult(`${Date.now() - start}ms`);
} catch {
setTestResult('✗ Failed');
}
};
return (
<View>
<ThemedText preset="labelMd" style={{ marginBottom: spacing.sm }}>
Server URL
</ThemedText>
<TextInput
value={value}
onChangeText={onChange}
autoCapitalize="none"
autoCorrect={false}
placeholder="http://192.168.1.100:8080"
keyboardType="url"
placeholderTextColor={colors.textSecondary}
style={{
borderWidth: 1,
borderColor: validation.valid ? colors.border : colors.danger,
borderRadius: 10,
backgroundColor: colors.surface,
color: colors.textPrimary,
padding: spacing.sm,
marginBottom: spacing.sm,
}}
/>
{!validation.valid && (
<ThemedText preset="bodySm" style={{ color: colors.danger, marginBottom: spacing.sm }}>
{validation.error}
</ThemedText>
)}
<ThemedText preset="bodySm" style={{ color: colors.textSecondary, marginBottom: spacing.sm }}>
{testResult || 'Ready to test connection'}
</ThemedText>
<View style={{ flexDirection: 'row', gap: spacing.sm }}>
<Pressable
onPress={handleTest}
disabled={!validation.valid}
style={{
flex: 1,
paddingVertical: 10,
borderRadius: 8,
backgroundColor: validation.valid ? colors.accentDim : colors.surfaceAlt,
alignItems: 'center',
}}
>
<ThemedText preset="labelMd" style={{ color: colors.textPrimary }}>
Test Connection
</ThemedText>
</Pressable>
<Pressable
onPress={onSave}
disabled={!validation.valid}
style={{
flex: 1,
paddingVertical: 10,
borderRadius: 8,
backgroundColor: validation.valid ? colors.success : colors.surfaceAlt,
alignItems: 'center',
}}
>
<ThemedText preset="labelMd" style={{ color: colors.textPrimary }}>
Save
</ThemedText>
</Pressable>
</View>
</View>
);
};