learning_ai_invt_trdg/mobile/components/FloatingChatButton.tsx

102 lines
2.4 KiB
TypeScript

import React, { useEffect } from 'react';
import { View, StyleSheet } from 'react-native';
import { useRouter } from 'expo-router';
import { LinearGradient } from 'expo-linear-gradient';
import { Ionicons } from '@expo/vector-icons';
import Animated, {
useAnimatedStyle,
useSharedValue,
withRepeat,
withSequence,
withTiming,
withSpring,
} from 'react-native-reanimated';
import { Colors, Shadows } from '@/constants/theme';
import PressableScale from '@/components/PressableScale';
export default function FloatingChatButton() {
const router = useRouter();
const floatY = useSharedValue(0);
const dotScale = useSharedValue(1);
useEffect(() => {
floatY.value = withRepeat(
withSequence(
withTiming(-4, { duration: 1500 }),
withTiming(0, { duration: 1500 })
),
-1
);
dotScale.value = withRepeat(
withSequence(
withTiming(1.3, { duration: 1000 }),
withTiming(1, { duration: 1000 })
),
-1
);
}, []);
const iconFloat = useAnimatedStyle(() => ({
transform: [{ translateY: floatY.value }],
}));
const dotPulse = useAnimatedStyle(() => ({
transform: [{ scale: dotScale.value }],
}));
return (
<PressableScale
style={styles.container}
haptic="medium"
onPress={() => router.push('/chat')}
>
<LinearGradient
colors={['#1a1b2e', '#0f1017']}
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
style={styles.gradient}
>
<Animated.View style={iconFloat}>
<Ionicons name="hardware-chip-outline" size={26} color={Colors.accent.green} />
</Animated.View>
</LinearGradient>
<Animated.View style={[styles.pulseDot, dotPulse]} />
</PressableScale>
);
}
const styles = StyleSheet.create({
container: {
position: 'absolute',
bottom: 100,
right: 20,
width: 56,
height: 56,
borderRadius: 16,
zIndex: 100,
...Shadows.card,
shadowColor: '#000',
shadowOpacity: 0.5,
},
gradient: {
width: 56,
height: 56,
borderRadius: 16,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1.5,
borderColor: 'rgba(0,255,136,0.25)',
},
pulseDot: {
position: 'absolute',
top: -3,
right: -3,
width: 14,
height: 14,
borderRadius: 7,
backgroundColor: Colors.accent.green,
borderWidth: 2,
borderColor: '#0a0b10',
},
});