// React import { useState, useEffect, useMemo, Fragment } from 'react'; import { View, Text, Image, Alert, StyleSheet, TouchableOpacity } from 'react-native'; // Expo import { useRouter } from 'expo-router'; // Components import { CustomMap } from '../components/map'; import { Drawer } from '../components/drawer'; import { TimerMMSS } from '../components/timer'; // Contexts import { useTeamConnexion } from '../context/teamConnexionContext'; import { useTeamContext } from '../context/teamContext'; // Hooks import { useGame } from '../hook/useGame'; import { useTimeDifference } from '../hook/useTimeDifference'; // Services import { startLocationTracking } from '../services/backgroundLocationTask'; // Util import { secondsToMMSS } from '../util/functions'; // Constants import { GAME_STATE, COLORS } from '../constants'; const Interface = () => { const router = useRouter(); const {teamInfos, messages, nextZoneDate, isShrinking, gameState} = useTeamContext(); const {name, ready, captured, locationSendDeadline, outOfZone, outOfZoneDeadline, hasHandicap, enemyHasHandicap} = teamInfos; const {loggedIn, logout} = useTeamConnexion(); const {sendCurrentPosition} = useGame(); const [timeLeftSendLocation] = useTimeDifference(locationSendDeadline, 1000); const [timeLeftNextZone] = useTimeDifference(nextZoneDate, 1000); const [timeLeftOutOfZone] = useTimeDifference(outOfZoneDeadline, 1000); const [bottomContainerHeight, setBottomContainerHeight] = useState(0); const statusMessage = useMemo(() => { switch (gameState) { case GAME_STATE.SETUP: return messages?.waiting || "Préparation de la partie"; case GAME_STATE.PLACEMENT: return "Phase de placement"; case GAME_STATE.PLAYING: if (captured) return messages?.captured || "Vous avez été éliminé..."; if (!outOfZone) return "La partie est en cours"; if (!hasHandicap) return `Veuillez retourner dans la zone\nHandicap dans ${secondsToMMSS(-timeLeftOutOfZone)}`; else return `Veuillez retourner dans la zone\nVotre position est révélée en continue`; case GAME_STATE.FINISHED: return `Vous avez ${captured ? (messages?.loser || "perdu...") : (messages?.winner || "gagné !")}`; default: return "Inconnue"; } }, [gameState, messages, outOfZone, hasHandicap, timeLeftOutOfZone, captured]); // Router useEffect(() => { if (!loggedIn) { router.replace("/"); } }, [router, loggedIn]); // Activating geolocation tracking useEffect(() => { startLocationTracking(); }, []); return ( Alert.alert("Settings")}> {(name ?? "Indisponible")} {statusMessage} { gameState == GAME_STATE.PLACEMENT && {ready ? "Placé" : "Non placé"} } { gameState == GAME_STATE.PLAYING && !captured && } { enemyHasHandicap && Position ennemie révélée en continue ! } setBottomContainerHeight(event.nativeEvent.layout.height)}> { gameState == GAME_STATE.PLAYING && !captured && !hasHandicap && } { gameState == GAME_STATE.PLAYING && !captured && } ); }; export default Interface; const styles = StyleSheet.create({ globalContainer: { backgroundColor: COLORS.background, flex: 1, }, topContainer: { width: '100%', alignItems: 'center', padding: 15, }, topheadContainer: { width: "100%", flexDirection: "row", justifyContent: 'space-between' }, teamNameContainer: { width: '100%', alignItems: 'center', justifyContent: 'center' }, logContainer: { width: '100%', alignItems: 'center', justifyContent: 'center', marginTop: 15 }, gameState: { borderWidth: 2, borderRadius: 10, width: "100%", backgroundColor: 'white', padding: 10, }, infoContainer: { width: '100%', alignItems: 'center', justifyContent: 'center', flexDirection: 'row', marginTop: 15 }, readyIndicator: { width: "100%", maxWidth: 240, height: 61, alignItems: 'center', justifyContent: 'center', padding: 3, borderRadius: 10 }, bottomContainer: { flex: 1, }, updatePosition: { position: 'absolute', right: 30, bottom: 80, width: 60, height: 60, borderRadius: 30, backgroundColor: 'white', borderWidth: 4, borderColor: 'black', alignItems: 'center', justifyContent: 'center', }, });