102 lines
2.4 KiB
TypeScript
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',
|
|
},
|
|
});
|