// React import { useState, useEffect, useMemo, useRef } from 'react'; import { View, Image, Alert, StyleSheet, TouchableOpacity } from 'react-native'; import MapView, { Marker, Circle, Polygon } from 'react-native-maps'; import LinearGradient from 'react-native-linear-gradient'; // Components import { DashedCircle, InvertedCircle, InvertedPolygon } from './layer'; // Contexts import { useTeamContext } from '../context/teamContext'; // Hook import { useLocation } from '../hook/useLocation'; // Util import { ZONE_TYPES, INITIAL_REGIONS, GAME_STATE } from '../constants'; export const CustomMap = () => { const { location } = useLocation(); const {teamInfos, zoneType, zoneExtremities, gameState} = useTeamContext(); const {enemyLocation, startingArea, lastSentLocation, hasHandicap} = teamInfos; const [centerMap, setCenterMap] = useState(true); const mapRef = useRef(null); // Center the map on user position useEffect(() => { if (centerMap && location && mapRef.current) { mapRef.current.animateToRegion({...location, latitudeDelta: 0, longitudeDelta: 0.02}, 1000); } }, [centerMap, location]); // Map layers const latToLatitude = (pos) => ({latitude: pos.lat, longitude: pos.lng}); const startZone = useMemo(() => { if (gameState != GAME_STATE.PLACEMENT || !startingArea) return null; return ( ); }, [gameState, startingArea]); const gameZone = useMemo(() => { if (gameState !== GAME_STATE.PLAYING || !zoneExtremities) return null; const items = []; const nextZoneStrokeColor = "rgb(90, 90, 90)"; const zoneColor = "rgba(25, 83, 169, 0.4)"; const strokeWidth = 3; const lineDashPattern = [30, 10]; if (zoneType === ZONE_TYPES.CIRCLE) { if (zoneExtremities.begin) items.push( ); if (zoneExtremities.end) items.push( ); } else if (zoneType === ZONE_TYPES.POLYGON) { if (zoneExtremities.begin) items.push( latToLatitude(pos))} fillColor={zoneColor} /> ); if (zoneExtremities.end) items.push( latToLatitude(pos))} strokeColor={nextZoneStrokeColor} strokeWidth={strokeWidth} lineDashPattern={lineDashPattern} /> ); } return items.length ? items : null; }, [gameState, zoneType, zoneExtremities]); const currentPositionMarker = useMemo(() => { if (!location) return null; return ( Alert.alert("Position actuelle", "Ceci est votre position")}> ); }, [location]); const lastPositionMarker = useMemo(() => { if (gameState != GAME_STATE.PLAYING || !lastSentLocation || hasHandicap) return null; return ( Alert.alert("Position envoyée", "Ceci est votre dernière position connue par le serveur")}> ); }, [gameState, hasHandicap, lastSentLocation]); const enemyPositionMarker = useMemo(() => { if (gameState != GAME_STATE.PLAYING || !enemyLocation || hasHandicap) return null; return ( Alert.alert("Position ennemie", "Ceci est la dernière position de vos ennemis connue")}> ); }, [gameState, hasHandicap, enemyLocation]); return ( setCenterMap(false)} toolbarEnabled={false}> {startZone} {gameZone} {currentPositionMarker} {lastPositionMarker} {enemyPositionMarker} { !centerMap && setCenterMap(true)}> } ); }; const styles = StyleSheet.create({ container: { flex: 1, width: '100%', borderTopLeftRadius: 30, borderTopRightRadius: 30, overflow: 'hidden', }, centerMap: { position: 'absolute', right: 20, top: 20, width: 40, height: 40, borderRadius: 20, backgroundColor: 'white', borderWidth: 2, borderColor: 'black', alignItems: 'center', justifyContent: 'center', }, markerImage: { width: 24, height: 24 } });