import React, { createContext, useContext, useState, useCallback, useRef } from 'react'; import { View, Text, StyleSheet, Animated, Platform, Dimensions } from 'react-native'; import { MaterialCommunityIcons } from '@expo/vector-icons'; import { useAppTheme } from './ThemeContext'; interface ToastContextType { showToast: (message: string, type?: 'success' | 'error' | 'info') => void; } const { width } = Dimensions.get('window'); const LIME = '#C6F135'; const ToastContext = createContext(undefined); export function ToastProvider({ children }: { children: React.ReactNode }) { const { colors, isDark } = useAppTheme(); const [toast, setToast] = useState<{ message: string, type: string } | null>(null); const translateY = useRef(new Animated.Value(-120)).current; const opacity = useRef(new Animated.Value(0)).current; const showToast = useCallback((message: string, type: 'success' | 'error' | 'info' = 'info') => { setToast({ message, type }); translateY.setValue(-120); opacity.setValue(0); Animated.sequence([ Animated.parallel([ Animated.spring(translateY, { toValue: Platform.OS === 'ios' ? 60 : 40, useNativeDriver: true, friction: 9, tension: 50 }), Animated.timing(opacity, { toValue: 1, duration: 400, useNativeDriver: true }) ]), Animated.delay(2800), Animated.parallel([ Animated.timing(translateY, { toValue: -120, duration: 300, useNativeDriver: true }), Animated.timing(opacity, { toValue: 0, duration: 300, useNativeDriver: true }) ]) ]).start(() => setToast(null)); }, []); // Theme configuration for the toast const getMeta = () => { if (!toast) return { icon: 'information', color: LIME }; switch(toast.type) { case 'success': return { icon: 'check-circle', color: LIME }; case 'error': return { icon: 'alert-circle', color: '#EF4444' }; default: return { icon: 'information', color: '#3B82F6' }; } }; const meta = getMeta(); const toastBg = isDark ? '#1A1A1A' : '#1A1A1A'; // Solid dark toast for both modes is more premium const border = isDark ? '#2A2A2A' : '#333'; return ( {children} {toast && ( {toast.message} )} ); } export function useToast() { const context = useContext(ToastContext); if (context === undefined) { return { showToast: (msg: string) => console.log('Toast (Fallback):', msg) }; } return context; } const styles = StyleSheet.create({ container: { position: 'absolute', top: 0, left: 20, right: 20, alignItems: 'center', }, toast: { flexDirection: 'row', alignItems: 'center', paddingVertical: 14, paddingHorizontal: 16, borderRadius: 20, borderWidth: 1, shadowColor: '#000', shadowOffset: { width: 0, height: 15 }, shadowOpacity: 0.25, shadowRadius: 20, elevation: 12, width: '100%', maxWidth: 450, }, iconBox: { width: 42, height: 42, borderRadius: 12, alignItems: 'center', justifyContent: 'center', }, text: { marginLeft: 14, fontSize: 14, fontFamily: 'Outfit_700Bold', color: '#FFFFFF', flexShrink: 1, }, });