A React Native app for the ultimate thinking partner.
at bf2a37bf805fa5ccc8b5badeeb098f842186e615 70 lines 2.0 kB view raw
1import React, { useEffect, useRef } from 'react'; 2import { View, Text, Animated, StyleSheet } from 'react-native'; 3import { darkTheme, lightTheme } from '../theme'; 4 5interface LiveStatusIndicatorProps { 6 status: string; // e.g., "thinking", "searching the web", "saying", "thought" 7 isDark?: boolean; 8} 9 10const LiveStatusIndicator: React.FC<LiveStatusIndicatorProps> = ({ status, isDark = true }) => { 11 const theme = isDark ? darkTheme : lightTheme; 12 const rainbowAnimValue = useRef(new Animated.Value(0)).current; 13 14 // Animate rainbow gradient 15 useEffect(() => { 16 rainbowAnimValue.setValue(0); 17 const animation = Animated.loop( 18 Animated.timing(rainbowAnimValue, { 19 toValue: 1, 20 duration: 3000, 21 useNativeDriver: false, 22 }) 23 ); 24 animation.start(); 25 return () => animation.stop(); 26 }, []); 27 28 // Special cases for past tense verbs (don't use "is") 29 const isPastTense = status === 'thought'; 30 const displayText = isPastTense ? status : `is ${status}`; 31 32 return ( 33 <View style={styles.container}> 34 <Text style={[styles.text, { color: theme.colors.text.primary }]}>(</Text> 35 <Animated.Text 36 style={[ 37 styles.coText, 38 { 39 color: rainbowAnimValue.interpolate({ 40 inputRange: [0, 0.2, 0.4, 0.6, 0.8, 1], 41 outputRange: ['#FF6B6B', '#FFD93D', '#6BCF7F', '#4D96FF', '#9D4EDD', '#FF6B6B'] 42 }) 43 } 44 ]} 45 > 46 co 47 </Animated.Text> 48 <Text style={[styles.text, { color: theme.colors.text.primary }]}> {displayText})</Text> 49 </View> 50 ); 51}; 52 53const styles = StyleSheet.create({ 54 container: { 55 flexDirection: 'row', 56 alignItems: 'baseline', 57 paddingVertical: 4, 58 marginBottom: 12, 59 }, 60 text: { 61 fontSize: 24, 62 fontFamily: 'Lexend_400Regular', 63 }, 64 coText: { 65 fontSize: 24, 66 fontFamily: 'Lexend_700Bold', 67 }, 68}); 69 70export default React.memo(LiveStatusIndicator);