import React, { useEffect, useState, useRef } from "react"; import useWebSocket from "react-use-websocket"; import axios from "axios"; import {Animated, Easing, ImageBackground, useColorScheme, View} from "react-native"; import { Avatar, List, Button, useTheme, } from "react-native-paper"; import themes from "@/app/themes"; import styles from "@/app/styles"; import log from "@/util/log" export const API_URL = process.env.EXPO_PUBLIC_API_URL; export const WS_URL = process.env.EXPO_PUBLIC_WS_URL; interface Message { Id: string; Name: string; Image: string; Status: string; Theme: string; Timestamp: string; } interface StatusProps { id: string; name: string; image: string; currentStatus: string; setStatus: (currentStatus: string) => void; currentTheme: string; isProfileActive: boolean; } const StatusPage: React.FC = ({ id, name, image, currentStatus, setStatus, currentTheme, isProfileActive }) => { log.debug("WebSocket URL: ", WS_URL); log.debug("API URL: ", API_URL); const theme = useTheme(); const colorScheme = useColorScheme(); log.debug(themes[currentTheme as keyof typeof themes][colorScheme === 'dark' ? 'dark' : 'light'].colors.primary); const [messages, setMessages] = useState([]); const { lastMessage } = useWebSocket(WS_URL + "/ws", { shouldReconnect: () => true, }); // Animated values for background color pulsing const pulseAnimOnTheWay = useRef(new Animated.Value(0)).current; const pulseAnimArrived = useRef(new Animated.Value(0)).current; // Function to trigger the color pulsing animation const startPulsing = (animationRef: Animated.Value) => { Animated.loop( Animated.sequence([ Animated.timing(animationRef, { toValue: 1, duration: 800, easing: Easing.inOut(Easing.ease), useNativeDriver: false, }), Animated.timing(animationRef, { toValue: 0, duration: 800, easing: Easing.inOut(Easing.ease), useNativeDriver: false, }), ]) ).start(); }; const stopPulsing = (animationRef: Animated.Value) => { animationRef.setValue(0); animationRef.stopAnimation(); }; useEffect(() => { log.debug("Updated status: ", currentStatus); if (currentStatus === "On the Way") { startPulsing(pulseAnimOnTheWay); } else { stopPulsing(pulseAnimOnTheWay); } if (currentStatus === "Arrived") { startPulsing(pulseAnimArrived); } else { stopPulsing(pulseAnimArrived); } }, [currentStatus]); // Interpolated colors for pulsing effect const getPulseColor = (animValue: Animated.Value) => animValue.interpolate({ inputRange: [0, 1], outputRange: [theme.colors.inversePrimary, theme.colors.primaryContainer], }); const pulseColorOnTheWay = getPulseColor(pulseAnimOnTheWay); const pulseColorArrived = getPulseColor(pulseAnimArrived); // Function to handle status change const handleStatusPress = async (status: string) => { try { if (currentStatus === status) { // If pressed again, send "none" status and clear currentStatus log.debug(`Removing status: ${status}`); const message: Message = { Id: id, Name: name, Image: image, Status: "none", Theme: currentTheme, Timestamp: new Date().toISOString() }; await axios.post(API_URL + "/set", message); setTimeout(() => { setStatus("none"); // Reset status }, 0) } else { // Otherwise, send the new status log.debug(`Setting status: ${status}`); const message: Message = { Id: id, Name: name, Image: image, Status: status, Theme: currentTheme, Timestamp: new Date().toISOString() }; await axios.post(API_URL + "/set", message); setTimeout(() => { setStatus(status); }, 0) } } catch (error) { log.error(`Error sending status '${status}':`, error); } }; // Determine the button label based on whether it's animating const getButtonLabel = (status: string) => { if (status === "On the Way") return currentStatus === "On the Way" ? "Traveling" : "On the way"; if (status === "Arrived") return currentStatus === "Arrived" ? "At the dog park" : "Arrived"; return status; }; useEffect(() => { if (lastMessage?.data) { try { const newMessage: Message = JSON.parse(lastMessage.data); log.debug("Current Status", currentStatus); setMessages((prev) => { if (newMessage.Id === id && newMessage.Status !== currentStatus) { log.debug("Status different, change to: ", newMessage.Status); setTimeout(() => { setStatus(newMessage.Status); }, 0); //return prev.filter((msg) => msg.Id !== newMessage.Id); }else{ log.debug("Status equal, no change"); } return prev.filter((msg) => msg.Id !== newMessage.Id).concat(newMessage); }); } catch (error) { log.error("Error parsing WebSocket message:", error); } } }, [lastMessage, setStatus, id]); return ( On the Way {messages.filter(msg => msg.Status === "On the Way") .sort((a, b) => new Date(a.Timestamp).getTime() - new Date(b.Timestamp).getTime()) .map(item => ( } /> ))} Arrived {messages.filter(msg => msg.Status === "Arrived") .sort((a, b) => new Date(a.Timestamp).getTime() - new Date(b.Timestamp).getTime()) .map(item => ( } /> ))} ); }; export default StatusPage;