54 lines
2.2 KiB
TypeScript
54 lines
2.2 KiB
TypeScript
// Kleine Indikator-Komponenten für den SOS-Header / Chat:
|
|
// - ThinkingDots: 3 hüpfende Punkte ("Lyra denkt nach")
|
|
// - VoiceBars: animierte Balken für Sprach-Aktivität
|
|
import { useEffect, useRef } from 'react';
|
|
import { View, Animated, StyleSheet } from 'react-native';
|
|
|
|
export function ThinkingDots() {
|
|
const anim = useRef([new Animated.Value(0), new Animated.Value(0), new Animated.Value(0)]).current;
|
|
useEffect(() => {
|
|
const animations = anim.map((a, i) =>
|
|
Animated.loop(Animated.sequence([
|
|
Animated.delay(i * 160),
|
|
Animated.timing(a, { toValue: 1, duration: 300, useNativeDriver: true }),
|
|
Animated.timing(a, { toValue: 0, duration: 300, useNativeDriver: true }),
|
|
])),
|
|
);
|
|
animations.forEach((a) => a.start());
|
|
return () => animations.forEach((a) => a.stop());
|
|
}, []);
|
|
return (
|
|
<View style={st.thinkingRow}>
|
|
{anim.map((a, i) => (
|
|
<Animated.View key={i} style={[st.thinkingDot, { transform: [{ translateY: a.interpolate({ inputRange: [0, 1], outputRange: [0, -5] }) }] }]} />
|
|
))}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
export function VoiceBars({ count, baseColor }: { count: number; baseColor: string }) {
|
|
const anims = useRef(Array.from({ length: count }, () => new Animated.Value(4))).current;
|
|
useEffect(() => {
|
|
const animations = anims.map((a, i) =>
|
|
Animated.loop(Animated.sequence([
|
|
Animated.timing(a, { toValue: 4 + Math.random() * 14, duration: 450 + (i % 5) * 80, useNativeDriver: false }),
|
|
Animated.timing(a, { toValue: 4, duration: 450 + (i % 5) * 80, useNativeDriver: false }),
|
|
])),
|
|
);
|
|
animations.forEach((a) => a.start());
|
|
return () => animations.forEach((a) => a.stop());
|
|
}, []);
|
|
return (
|
|
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 2, height: 20 }}>
|
|
{anims.map((a, i) => (
|
|
<Animated.View key={i} style={{ width: 2.5, height: a, borderRadius: 2, backgroundColor: baseColor, opacity: 0.75 }} />
|
|
))}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const st = StyleSheet.create({
|
|
thinkingRow: { flexDirection: 'row', gap: 4, paddingHorizontal: 4, paddingVertical: 2, alignItems: 'center' },
|
|
thinkingDot: { width: 7, height: 7, borderRadius: 3.5, backgroundColor: '#9ca3af' },
|
|
});
|