/** * Loader Utilities * Beautiful custom loading component with chat icon and animations */ import React, { useEffect, useRef } from 'react'; import { View, Text, ActivityIndicator, Animated, StyleSheet, Dimensions } from 'react-native'; //@ts-ignore import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; // Get screen dimensions const { width, height } = Dimensions.get('window'); /** * Interface for loader props */ export interface LoaderProps { isLoading: boolean; loadingText?: string; showChatIcon?: boolean; iconName?: string; iconSize?: number; backgroundColor?: string; primaryColor?: string; textColor?: string; } /** * Beautiful Custom Loader Component */ export const CustomLoader: React.FC = ({ isLoading, loadingText = 'Loading...', showChatIcon = true, iconName = 'chat-processing', iconSize = 40, backgroundColor = 'rgba(255, 255, 255, 1)', // Pure white primaryColor = '#007AFF', textColor = '#333333' }) => { // Animation values const fadeAnim = useRef(new Animated.Value(0)).current; const scaleAnim = useRef(new Animated.Value(0.8)).current; const pulseAnim = useRef(new Animated.Value(1)).current; useEffect(() => { if (isLoading) { // Instant animations for better UX during navigation Animated.parallel([ Animated.timing(fadeAnim, { toValue: 1, duration: 0, useNativeDriver: true, }), Animated.timing(scaleAnim, { toValue: 1, duration: 0, useNativeDriver: true, }), ]).start(); // Pulse animation with reduced intensity const pulseAnimation = Animated.loop( Animated.sequence([ Animated.timing(pulseAnim, { toValue: 1.05, duration: 800, useNativeDriver: true, }), Animated.timing(pulseAnim, { toValue: 1, duration: 800, useNativeDriver: true, }), ]) ); pulseAnimation.start(); return () => { pulseAnimation.stop(); }; } else { // Instant hide animations for better UX during navigation Animated.parallel([ Animated.timing(fadeAnim, { toValue: 0, duration: 0, useNativeDriver: true, }), Animated.timing(scaleAnim, { toValue: 0.8, duration: 0, useNativeDriver: true, }), ]).start(); } }, [isLoading]); if (!isLoading) return null; return ( {/* Chat Icon */} {showChatIcon && ( )} {/* Loading Spinner */} {/* Loading Text */} {loadingText} {/* Loading Dots Animation */} {[0, 1, 2].map((index) => ( ))} ); }; /** * Enhanced Loader with Progress */ export const ProgressLoader: React.FC = ({ isLoading, loadingText = 'Loading...', progress = 0, ...props }) => { const progressAnim = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.timing(progressAnim, { toValue: progress, duration: 300, useNativeDriver: false, }).start(); }, [progress]); return ( ); }; /** * Create loader styles */ const styles = StyleSheet.create({ loaderContainer: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, zIndex: 9999, justifyContent: 'center', alignItems: 'center', backgroundColor: 'rgba(255, 255, 255, 1)', // Pure white background }, loaderContent: { alignItems: 'center', justifyContent: 'center', paddingHorizontal: 40, paddingVertical: 30, borderRadius: 20, shadowColor: '#000', shadowOffset: { width: 0, height: 4, }, shadowOpacity: 0.15, shadowRadius: 4.65, elevation: 8, backgroundColor: 'rgba(255, 255, 255, 1)', borderWidth: 1, borderColor: 'rgba(0, 0, 0, 0.05)', }, chatIconContainer: { width: 80, height: 80, borderRadius: 40, justifyContent: 'center', alignItems: 'center', marginBottom: 20, shadowColor: '#007AFF', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5, }, spinnerContainer: { marginBottom: 20, }, spinner: { transform: [{ scale: 1.2 }], }, loadingText: { fontSize: 18, fontWeight: '600', textAlign: 'center', marginBottom: 15, letterSpacing: 0.5, }, dotsContainer: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }, dot: { width: 8, height: 8, borderRadius: 4, marginHorizontal: 4, }, }); /** * Predefined loader configurations with vector icons */ export const LOADER_CONFIGS = { CHAT: { loadingText: 'Connecting to chat...', showChatIcon: true, iconName: 'chat-processing' as const, iconSize: 40, primaryColor: '#007AFF', }, ODOO: { loadingText: 'Loading T4B...', showChatIcon: true, iconName: 'chat-processing' as const, iconSize: 40, primaryColor: '#875A7B', }, NAVIGATION: { loadingText: 'Navigating...', showChatIcon: true, iconName: 'navigation' as const, iconSize: 40, primaryColor: '#28A745', }, MESSAGE: { loadingText: 'Sending message...', showChatIcon: true, iconName: 'message-text' as const, iconSize: 40, primaryColor: '#FF6B35', }, SYNC: { loadingText: 'Synchronizing...', showChatIcon: true, iconName: 'sync' as const, iconSize: 40, primaryColor: '#9C27B0', }, DEFAULT: { loadingText: 'Loading...', showChatIcon: true, iconName: 'loading' as const, iconSize: 40, primaryColor: '#007AFF', }, } as const; /** * Quick loader functions with vector icons */ export const createChatLoader = (isLoading: boolean, text?: string) => ( ); export const createOdooLoader = (isLoading: boolean, text?: string) => ( ); export const createNavigationLoader = (isLoading: boolean, text?: string) => ( ); export const createMessageLoader = (isLoading: boolean, text?: string) => ( ); export const createSyncLoader = (isLoading: boolean, text?: string) => ( ); export const createDefaultLoader = (isLoading: boolean, text?: string) => ( );