import { useState, useEffect } from 'react';
import { View, Text, ScrollView, TextInput, Switch, Pressable, Alert, ActivityIndicator } from 'react-native';
import { router } from 'expo-router';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useSettings } from '@/hooks/use-settings';
export default function SettingsScreen() {
const { settings, isLoading, updateSettings, resetSettings } = useSettings();
const insets = useSafeAreaInsets();
const [serverUrl, setServerUrl] = useState(settings.serverUrl);
const [useSpeaker, setUseSpeaker] = useState(settings.useSpeaker);
const [keepScreenOn, setKeepScreenOn] = useState(settings.keepScreenOn);
const [theme, setTheme] = useState<'dark' | 'light' | 'auto'>(settings.theme);
const [hasChanges, setHasChanges] = useState(false);
const [isTesting, setIsTesting] = useState(false);
const [testResult, setTestResult] = useState<{ success: boolean; message: string } | null>(null);
// Update local state when settings load
useEffect(() => {
setServerUrl(settings.serverUrl);
setUseSpeaker(settings.useSpeaker);
setKeepScreenOn(settings.keepScreenOn);
setTheme(settings.theme);
}, [settings]);
// Track changes
useEffect(() => {
const changed =
serverUrl !== settings.serverUrl ||
useSpeaker !== settings.useSpeaker ||
keepScreenOn !== settings.keepScreenOn ||
theme !== settings.theme;
setHasChanges(changed);
}, [serverUrl, useSpeaker, keepScreenOn, theme, settings]);
function validateServerUrl(url: string): boolean {
try {
const urlObj = new URL(url);
return urlObj.protocol === 'ws:' || urlObj.protocol === 'wss:';
} catch {
return false;
}
}
async function handleSave() {
// Validate server URL
if (!validateServerUrl(serverUrl)) {
Alert.alert(
'Invalid URL',
'Server URL must be a valid WebSocket URL (ws:// or wss://)',
[{ text: 'OK' }]
);
return;
}
try {
await updateSettings({
serverUrl,
useSpeaker,
keepScreenOn,
theme,
});
Alert.alert(
'Settings Saved',
'Your settings have been saved successfully.',
[
{
text: 'OK',
onPress: () => router.back(),
},
]
);
} catch (error) {
Alert.alert(
'Error',
'Failed to save settings. Please try again.',
[{ text: 'OK' }]
);
}
}
async function handleReset() {
Alert.alert(
'Reset Settings',
'Are you sure you want to reset all settings to defaults?',
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Reset',
style: 'destructive',
onPress: async () => {
try {
await resetSettings();
Alert.alert('Settings Reset', 'All settings have been reset to defaults.');
} catch (error) {
Alert.alert('Error', 'Failed to reset settings. Please try again.');
}
},
},
]
);
}
function handleCancel() {
if (hasChanges) {
Alert.alert(
'Discard Changes',
'You have unsaved changes. Are you sure you want to go back?',
[
{ text: 'Stay', style: 'cancel' },
{
text: 'Discard',
style: 'destructive',
onPress: () => router.back(),
},
]
);
} else {
router.back();
}
}
async function handleTestConnection() {
if (!validateServerUrl(serverUrl)) {
Alert.alert(
'Invalid URL',
'Server URL must be a valid WebSocket URL (ws:// or wss://)',
[{ text: 'OK' }]
);
return;
}
setIsTesting(true);
setTestResult(null);
try {
const ws = new WebSocket(serverUrl);
const timeout = setTimeout(() => {
ws.close();
setTestResult({
success: false,
message: 'Connection timeout - server did not respond',
});
setIsTesting(false);
}, 5000);
ws.onopen = () => {
clearTimeout(timeout);
ws.close();
setTestResult({
success: true,
message: 'Connection successful',
});
setIsTesting(false);
};
ws.onerror = () => {
clearTimeout(timeout);
setTestResult({
success: false,
message: 'Connection failed - check URL and network',
});
setIsTesting(false);
};
} catch (error) {
setTestResult({
success: false,
message: 'Failed to create connection',
});
setIsTesting(false);
}
}
if (isLoading) {
return (
Loading settings...
);
}
return (
{/* Header */}
Settings
Cancel
{/* Server Configuration */}
Server Configuration
WebSocket URL
{
setServerUrl(text);
setTestResult(null);
}}
autoCapitalize="none"
autoCorrect={false}
keyboardType="url"
/>
Must be a valid WebSocket URL (ws:// or wss://)
{/* Test Connection Button */}
{isTesting ? (
<>
Testing...
>
) : (
Test Connection
)}
{/* Test Result */}
{testResult && (
{testResult.message}
)}
{/* Audio Settings */}
Audio
Use Speaker
Play audio through speaker instead of earpiece
Keep Screen On
Prevent screen from sleeping during voice sessions
{/* Theme Settings */}
Theme
Theme selection (coming soon)
{(['dark', 'light', 'auto'] as const).map((themeOption) => (
{theme === themeOption && (
)}
{themeOption}
))}
{/* Action Buttons */}
Save Settings
Reset to Defaults
{/* App Info */}
Voice Assistant Mobile
Version 1.0.0
);
}