// components/SettingsDrawer.tsx
import React, { useEffect, useRef, useState } from 'react';
import { View, StyleSheet, Animated, Dimensions, ScrollView, Pressable, Platform, TouchableOpacity } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useTheme } from '@react-navigation/native';
import { useRouter } from 'expo-router';
import { useSettingsDrawer } from '@/lib/contexts/SettingsDrawerContext';
import {
Moon, Sun, LogOut, User, ChevronRight, X, Bell, HelpCircle,
Smartphone, Database, Zap, RefreshCw, AlertTriangle, Globe, PackageOpen
} from 'lucide-react-native';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Switch } from '@/components/ui/switch';
import { Separator } from '@/components/ui/separator';
import { Text } from '@/components/ui/text';
import { useColorScheme } from '@/lib/theme/useColorScheme';
import NostrLoginSheet from '@/components/sheets/NostrLoginSheet';
import RelayManagement from '@/components/RelayManagement';
import { useNDKCurrentUser, useNDKAuth } from '@/lib/hooks/useNDK';
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from '@/components/ui/alert-dialog';
const { width: SCREEN_WIDTH } = Dimensions.get('window');
const DRAWER_WIDTH = SCREEN_WIDTH * 0.85;
type MenuItem = {
id: string;
icon: React.ElementType;
label: string;
onPress: () => void;
rightElement?: React.ReactNode;
};
export default function SettingsDrawer() {
const router = useRouter();
const { isDrawerOpen, closeDrawer } = useSettingsDrawer();
const { currentUser, isAuthenticated } = useNDKCurrentUser();
const { logout } = useNDKAuth();
const { toggleColorScheme, isDarkColorScheme } = useColorScheme();
const theme = useTheme();
const [isLoginSheetOpen, setIsLoginSheetOpen] = useState(false);
const [showSignOutAlert, setShowSignOutAlert] = useState(false);
const [showRelayManager, setShowRelayManager] = useState(false);
const slideAnim = useRef(new Animated.Value(-DRAWER_WIDTH)).current;
const fadeAnim = useRef(new Animated.Value(0)).current;
// Handle drawer animation when open state changes
useEffect(() => {
if (isDrawerOpen) {
Animated.parallel([
Animated.spring(slideAnim, {
toValue: 0,
useNativeDriver: true,
speed: 20,
bounciness: 4
}),
Animated.timing(fadeAnim, {
toValue: 1,
duration: 200,
useNativeDriver: true
})
]).start();
} else {
Animated.parallel([
Animated.spring(slideAnim, {
toValue: -DRAWER_WIDTH,
useNativeDriver: true,
speed: 20,
bounciness: 4
}),
Animated.timing(fadeAnim, {
toValue: 0,
duration: 200,
useNativeDriver: true
})
]).start();
}
}, [isDrawerOpen]);
// Navigate to relevant screen for login
const navigateToLogin = () => {
// Go to the profile tab which should have login functionality
closeDrawer();
setTimeout(() => {
router.push("/(tabs)/profile");
}, 300);
};
// Handle profile click - different behavior on iOS vs Android
const handleProfileClick = () => {
if (!isAuthenticated) {
if (Platform.OS === 'ios') {
// On iOS, use the sheet directly
setIsLoginSheetOpen(true);
} else {
// On Android, navigate to profile tab
navigateToLogin();
}
} else {
// Navigate to profile edit screen in the future
console.log('Navigate to profile edit');
}
};
// Handle sign out button click
const handleSignOut = () => {
setShowSignOutAlert(true);
};
// Function to handle confirmed sign out
const confirmSignOut = async () => {
await logout();
closeDrawer();
};
// Open relay management
const handleRelayManagement = () => {
setShowRelayManager(true);
};
// Nostr integration handler
const handleNostrIntegration = () => {
if (!isAuthenticated) {
if (Platform.OS === 'ios') {
// On iOS, use the sheet directly
setIsLoginSheetOpen(true);
} else {
// On Android, navigate to profile tab
navigateToLogin();
}
} else {
// Show Nostr settings in the future
console.log('Show Nostr settings');
}
};
// Define menu items
const menuItems: MenuItem[] = [
{
id: 'appearance',
icon: isDarkColorScheme ? Moon : Sun,
label: 'Dark Mode',
onPress: () => {},
rightElement: (
),
},
{
id: 'notifications',
icon: Bell,
label: 'Notifications',
onPress: () => closeDrawer(),
},
{
id: 'data-sync',
icon: RefreshCw,
label: 'Data Sync',
onPress: () => closeDrawer(),
},
{
id: 'backup-restore',
icon: Database,
label: 'Backup & Restore',
onPress: () => closeDrawer(),
},
{
id: 'relays',
icon: Globe,
label: 'Manage Relays',
onPress: handleRelayManagement,
},
{
id: 'powr-packs',
icon: PackageOpen,
label: 'POWR Packs',
onPress: () => {
closeDrawer();
router.push("/(packs)/manage");
},
},
{
id: 'device',
icon: Smartphone,
label: 'Device Settings',
onPress: () => closeDrawer(),
},
{
id: 'nostr',
icon: Zap,
label: 'Nostr Integration',
onPress: handleNostrIntegration,
},
{
id: 'about',
icon: HelpCircle,
label: 'About',
onPress: () => closeDrawer(),
},
];
if (!isDrawerOpen) return null;
return (
<>
{/* Backdrop overlay */}
{/* Drawer */}
{/* Header with close button */}
Settings
{/* Profile section - make it touchable */}
{isAuthenticated && currentUser?.profile?.image ? (
) : null}
{isAuthenticated && currentUser?.profile?.name ? (
{currentUser.profile.name.charAt(0).toUpperCase()}
) : (
)}
{isAuthenticated ? currentUser?.profile?.name || 'Nostr User' : 'Not Logged In'}
{isAuthenticated ? 'Edit Profile' : 'Login with Nostr'}
{/* Menu items */}
{menuItems.map((item, index) => (
{item.label}
{item.rightElement ? (
item.rightElement
) : (
)}
{index < menuItems.length - 1 && (
)}
))}
{/* Sign out button at the bottom - only show when authenticated */}
{isAuthenticated && (
)}
{/* Only render the NostrLoginSheet on iOS */}
{Platform.OS === 'ios' && (
setIsLoginSheetOpen(false)}
/>
)}
{/* Relay Management Sheet */}
setShowRelayManager(false)}
/>
{/* Sign Out Alert Dialog */}
For Real?
Are you sure you want to sign out? Make sure you've backed up your private key.
Lost keys cannot be recovered and all your data will be inaccessible.
setShowSignOutAlert(false)}>
Cancel
Sign Out
>
);
}
const styles = StyleSheet.create({
drawer: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
width: DRAWER_WIDTH,
borderRightWidth: 1,
...Platform.select({
ios: {
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.25,
shadowRadius: 3.84,
},
android: {
elevation: 5,
},
}),
},
header: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
paddingHorizontal: 16,
height: 60,
},
profileSection: {
flexDirection: 'row',
alignItems: 'center',
padding: 16,
borderBottomWidth: 1,
},
profileInfo: {
flex: 1,
marginLeft: 12,
},
menuList: {
flex: 1,
},
menuContent: {
padding: 16,
},
menuItem: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingVertical: 12,
},
menuItemLeft: {
flexDirection: 'row',
alignItems: 'center',
},
footer: {
padding: 16,
paddingBottom: Platform.OS === 'ios' ? 16 : 16,
},
});