import React, { useEffect, useRef } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Dimensions, BackHandler, Animated, } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons'; import { useTheme } from '../contexts/ThemeContext'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; const { width } = Dimensions.get('window'); interface AndroidUpdatePopupProps { visible: boolean; updateInfo: { isAvailable: boolean; manifest?: { id?: string; version?: string; description?: string; }; }; onUpdateNow: () => void; onUpdateLater: () => void; onDismiss: () => void; isInstalling?: boolean; } const AndroidUpdatePopup: React.FC = ({ visible, updateInfo, onUpdateNow, onUpdateLater, onDismiss, isInstalling = false, }) => { const { currentTheme } = useTheme(); const insets = useSafeAreaInsets(); const backHandlerRef = useRef(null); const timeoutRef = useRef(null); const fadeAnim = useRef(new Animated.Value(0)).current; const scaleAnim = useRef(new Animated.Value(0.8)).current; const getReleaseNotes = () => { const manifest: any = updateInfo?.manifest || {}; return ( manifest.description || manifest.releaseNotes || manifest.extra?.releaseNotes || manifest.metadata?.releaseNotes || '' ); }; // Handle Android back button useEffect(() => { if (visible) { backHandlerRef.current = BackHandler.addEventListener('hardwareBackPress', () => { if (!isInstalling) { onDismiss(); return true; } return false; }); } return () => { if (backHandlerRef.current) { backHandlerRef.current.remove(); backHandlerRef.current = null; } }; }, [visible, isInstalling, onDismiss]); // Animation effects useEffect(() => { if (visible) { // Animate in Animated.parallel([ Animated.timing(fadeAnim, { toValue: 1, duration: 200, useNativeDriver: true, }), Animated.spring(scaleAnim, { toValue: 1, tension: 100, friction: 8, useNativeDriver: true, }), ]).start(); // Safety timeout timeoutRef.current = setTimeout(() => { console.warn('AndroidUpdatePopup: Timeout reached, auto-dismissing'); onDismiss(); }, 30000); } else { // Animate out Animated.parallel([ Animated.timing(fadeAnim, { toValue: 0, duration: 150, useNativeDriver: true, }), Animated.timing(scaleAnim, { toValue: 0.8, duration: 150, useNativeDriver: true, }), ]).start(); } return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; } }; }, [visible, fadeAnim, scaleAnim, onDismiss]); if (!visible || !updateInfo.isAvailable) { return null; } return ( {/* Header */} Update Available A new version of Nuvio is ready to install {/* Update Info */} Version: {updateInfo.manifest?.id || 'Latest'} {!!getReleaseNotes() && ( {getReleaseNotes()} )} {/* Actions */} {isInstalling ? ( <> Installing... ) : ( <> Update Now )} Later Dismiss ); }; const styles = StyleSheet.create({ overlay: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 9999, backgroundColor: 'rgba(0, 0, 0, 0.8)', justifyContent: 'center', alignItems: 'center', paddingHorizontal: 20, }, overlayContent: { width: '100%', height: '100%', justifyContent: 'center', alignItems: 'center', }, backdrop: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'transparent', }, popup: { width: Math.min(width - 40, 400), borderRadius: 20, borderWidth: 1, backgroundColor: '#1a1a1a', elevation: 15, overflow: 'hidden', }, header: { alignItems: 'center', paddingHorizontal: 24, paddingTop: 32, paddingBottom: 20, }, iconContainer: { width: 64, height: 64, borderRadius: 32, alignItems: 'center', justifyContent: 'center', marginBottom: 16, }, title: { fontSize: 24, fontWeight: '700', letterSpacing: 0.3, marginBottom: 8, textAlign: 'center', }, subtitle: { fontSize: 16, textAlign: 'center', lineHeight: 22, }, updateInfo: { paddingHorizontal: 24, paddingBottom: 20, }, infoRow: { flexDirection: 'row', alignItems: 'flex-start', marginBottom: 12, }, infoLabel: { fontSize: 14, fontWeight: '500', marginLeft: 8, marginRight: 8, marginTop: 2, minWidth: 60, }, infoValue: { fontSize: 14, fontWeight: '600', flex: 1, lineHeight: 20, }, descriptionContainer: { marginTop: 8, padding: 12, borderRadius: 8, backgroundColor: 'rgba(255, 255, 255, 0.15)', }, description: { fontSize: 14, lineHeight: 20, }, actions: { paddingHorizontal: 24, paddingBottom: 20, }, button: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 14, paddingHorizontal: 20, borderRadius: 12, gap: 8, marginBottom: 12, }, primaryButton: { elevation: 4, }, secondaryButton: { borderWidth: 1, flex: 1, marginHorizontal: 4, }, disabledButton: { opacity: 0.6, }, buttonText: { color: 'white', fontSize: 16, fontWeight: '600', letterSpacing: 0.3, }, secondaryActions: { flexDirection: 'row', gap: 8, }, secondaryButtonText: { fontSize: 15, fontWeight: '500', }, }); export default AndroidUpdatePopup;