// 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, }, });