/**
* Settings tab - notifications, app info
* Server selection is handled via the global header selector
*/
import { View, ScrollView, Pressable, Switch, Alert, ActivityIndicator } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useRouter } from 'expo-router';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { ChevronRight, LogOut } from 'lucide-react-native';
import { useAuthStore } from '@/lib/authStore';
import { Text } from '@/components/ui/text';
import { Card } from '@/components/ui/card';
import { cn } from '@/lib/utils';
import { api } from '@/lib/api';
import { colors } from '@/lib/theme';
import Constants from 'expo-constants';
function SettingsRow({
label,
value,
onPress,
showChevron,
leftIcon,
rightIcon,
destructive,
}: {
label: string;
value?: string;
onPress?: () => void;
showChevron?: boolean;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
destructive?: boolean;
}) {
const content = (
{leftIcon && {leftIcon}}
{label}
{value && {value}}
{rightIcon}
{showChevron && (
)}
);
if (onPress) {
return (
{content}
);
}
return content;
}
function SettingsToggle({
label,
description,
value,
onValueChange,
disabled,
isLoading,
}: {
label: string;
description?: string;
value: boolean;
onValueChange: (value: boolean) => void;
disabled?: boolean;
isLoading?: boolean;
}) {
return (
{label}
{description && (
{description}
)}
{isLoading ? (
) : (
)}
);
}
function SettingsSection({
title,
children,
}: {
title: string;
children: React.ReactNode;
}) {
return (
{title}
{children}
);
}
function Divider() {
return ;
}
export default function SettingsScreen() {
const router = useRouter();
const queryClient = useQueryClient();
const {
activeServerId,
activeServer,
isLoading: isAuthLoading,
logout,
} = useAuthStore();
const appVersion = Constants.expoConfig?.version || '1.0.0';
// Fetch notification preferences
const {
data: preferences,
isLoading: isLoadingPrefs,
error: prefsError,
} = useQuery({
queryKey: ['notifications', 'preferences'],
queryFn: api.notifications.getPreferences,
staleTime: 1000 * 60, // 1 minute
enabled: !!activeServerId,
});
// Update mutation for quick toggle
const updateMutation = useMutation({
mutationFn: api.notifications.updatePreferences,
onMutate: async (newData) => {
await queryClient.cancelQueries({
queryKey: ['notifications', 'preferences'],
});
const previousData = queryClient.getQueryData([
'notifications',
'preferences',
]);
queryClient.setQueryData(
['notifications', 'preferences'],
(old: typeof preferences) => (old ? { ...old, ...newData } : old)
);
return { previousData };
},
onError: (_err, _newData, context) => {
if (context?.previousData) {
queryClient.setQueryData(
['notifications', 'preferences'],
context.previousData
);
}
},
onSettled: () => {
void queryClient.invalidateQueries({
queryKey: ['notifications', 'preferences'],
});
},
});
const handleDisconnect = () => {
Alert.alert(
'Disconnect from Server',
'Are you sure you want to disconnect? You will need to scan a QR code to reconnect.',
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Disconnect',
style: 'destructive',
onPress: () => {
void (async () => {
await queryClient.cancelQueries();
await logout();
queryClient.clear();
})();
},
},
]
);
};
const handleTogglePush = (value: boolean) => {
updateMutation.mutate({ pushEnabled: value });
};
const navigateToNotificationSettings = () => {
router.push('/settings/notifications');
};
// Count enabled notification events for summary
const enabledEventCount = preferences
? [
preferences.onViolationDetected,
preferences.onStreamStarted,
preferences.onStreamStopped,
preferences.onConcurrentStreams,
preferences.onNewDevice,
preferences.onTrustScoreChanged,
preferences.onServerDown,
preferences.onServerUp,
].filter(Boolean).length
: 0;
return (
{/* Connected Server Info */}
{activeServer && (
}
destructive
/>
)}
{/* Notification Settings */}
{activeServerId && (
{prefsError ? (
Failed to load notification settings
) : (
<>
Configure which events trigger notifications, quiet hours, and filters.
>
)}
)}
{/* App Info */}
{/* Loading indicator */}
{isAuthLoading && (
)}
);
}