diff --git a/client/app.json b/client/app.json index 065ff59..d26a3d5 100644 --- a/client/app.json +++ b/client/app.json @@ -1,7 +1,7 @@ { "expo": { - "name": "traintrape-moi-client", - "slug": "traintrape-moi-client", + "name": "Traintrape-moi", + "slug": "traintrape-moi", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/images/icon.png", @@ -33,6 +33,17 @@ "resizeMode": "contain", "backgroundColor": "#ffffff" } + ], + [ + "@maplibre/maplibre-react-native" + ], + [ + "expo-location", + { + "isAndroidBackgroundLocationEnabled": true, + "isIosBackgroundLocationEnabled": true, + "locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location." + } ] ], "experiments": { diff --git a/client/app/(tabs)/index.jsx b/client/app/(tabs)/index.jsx deleted file mode 100644 index 2462a76..0000000 --- a/client/app/(tabs)/index.jsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Platform, StyleSheet } from 'react-native' -import { ThemedView } from '@/components/ThemedView' - -export default function MapScreen() { - if (Platform.OS === "web") { - const maplibre = require('react-map-gl/maplibre') - const Map = maplibre.Map - return - - - } - else { - const MapLibreGL = require('@maplibre/maplibre-react-native') - MapLibreGL.setAccessToken(null) - return ( - - - - ) - } -} - -const styles = StyleSheet.create({ - page: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: '#F5FCFF', - }, - map: { - flex: 1, - alignSelf: 'stretch', - }, -}); diff --git a/client/app/(tabs)/index.tsx b/client/app/(tabs)/index.tsx new file mode 100644 index 0000000..3da84e8 --- /dev/null +++ b/client/app/(tabs)/index.tsx @@ -0,0 +1,45 @@ +import { StyleSheet } from 'react-native' +import { ThemedView } from '@/components/ThemedView' +import { useEffect, useState } from 'react' +import "maplibre-gl/dist/maplibre-gl.css" + +import * as Location from 'expo-location' +import Map from '@/components/map' +import { ThemedText } from '@/components/ThemedText' + +export default function MapScreen() { + const [location, setLocation] = useState(null) + const [locationAccessGranted, setLocationAccessGranted] = useState(false) + + useEffect(() => { + async function watchPosition() { + let { status } = await Location.requestForegroundPermissionsAsync() + if (status !== 'granted') { + setLocationAccessGranted(false) + alert("Vous devez activer votre géolocalisation pour utiliser l'application.") + return + } + setLocationAccessGranted(true) + await Location.watchPositionAsync({accuracy: Location.Accuracy.BestForNavigation}, location => setLocation(location)) + } + watchPosition() + }, []) + + return ( + + {locationAccessGranted ? : La géolocalisation est requise pour utiliser la carte.} + + ) +} + +const styles = StyleSheet.create({ + page: { + flex: 1, + justifyContent: 'center', + alignItems: 'center' + }, + map: { + flex: 1, + alignSelf: 'stretch', + }, +}); diff --git a/client/components/map.tsx b/client/components/map.tsx new file mode 100644 index 0000000..4a29830 --- /dev/null +++ b/client/components/map.tsx @@ -0,0 +1,38 @@ +import { StyleSheet, Text } from 'react-native' +import MapLibreGL, { Camera, FillLayer, LineLayer, MapView, PointAnnotation, RasterLayer, RasterSource, ShapeSource, UserLocation } from '@maplibre/maplibre-react-native' +import { LocationObject } from 'expo-location' +import { FontAwesome5 } from '@expo/vector-icons' +import { circle } from '@turf/circle' + +export default function Map({ location }: { location: LocationObject | null }) { + MapLibreGL.setAccessToken(null) + const accuracyCircle = circle([location?.coords.longitude ?? 0, location?.coords.latitude ?? 0], location?.coords.accuracy ?? 0, {steps: 64, units: 'meters'}) + return ( + + {/* FIXME Il faudra pouvoir avoir un bouton de suivi pour activer le suivi de la caméro */} + {location && } + + + + {/* FIXME Il faudra avoir uniquement les positions des autres personnes, puisque sa propre position peut être obtenue nativement */} + + + + + + + {/* */} + + ) +} + +const styles = StyleSheet.create({ + map: { + flex: 1, + alignSelf: 'stretch', + } +}) diff --git a/client/components/map.web.tsx b/client/components/map.web.tsx new file mode 100644 index 0000000..fb088cf --- /dev/null +++ b/client/components/map.web.tsx @@ -0,0 +1,26 @@ +import { circle } from "@turf/circle" +import { LocationObject } from "expo-location" +import { RLayer, RMap, RMarker, RNavigationControl, RSource } from "maplibre-react-components" + +export default function Map({ location }: { location: LocationObject }) { + if (!location) + // FIXME On devrait avoir la position qui se centre sur la position une fois qu'elle est établie + return <> + const accuracyCircle = circle([location?.coords.longitude ?? 0, location?.coords.latitude ?? 0], location?.coords.accuracy ?? 0, {steps: 64, units: 'meters'}) + return ( + + + + + + + + + + {location && } + + ) +} \ No newline at end of file diff --git a/client/package-lock.json b/client/package-lock.json index c1ac43d..dc72e9e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12,6 +12,7 @@ "@maplibre/maplibre-react-native": "^10.0.0-alpha.28", "@react-navigation/bottom-tabs": "^7.0.0", "@react-navigation/native": "^7.0.0", + "@turf/circle": "^7.1.0", "expo": "~52.0.11", "expo-blur": "~14.0.1", "expo-constants": "~17.0.3", @@ -19,6 +20,7 @@ "expo-font": "~13.0.1", "expo-haptics": "~14.0.0", "expo-linking": "~7.0.3", + "expo-location": "^18.0.2", "expo-router": "~4.0.9", "expo-splash-screen": "~0.29.13", "expo-status-bar": "~2.0.0", @@ -26,6 +28,7 @@ "expo-system-ui": "~4.0.4", "expo-web-browser": "~14.0.1", "maplibre-gl": "^4.7.1", + "maplibre-react-components": "^0.1.9", "react": "18.3.1", "react-dom": "18.3.1", "react-map-gl": "^7.1.7", @@ -4422,6 +4425,21 @@ "url": "https://opencollective.com/turf" } }, + "node_modules/@turf/circle": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-7.1.0.tgz", + "integrity": "sha512-6qhF1drjwH0Dg3ZB9om1JkWTJfAqBcbtIrAj5UPlrAeHP87hGoCO2ZEsFEAL9Q18vntpivT89Uho/nqQUjJhYw==", + "license": "MIT", + "dependencies": { + "@turf/destination": "^7.1.0", + "@turf/helpers": "^7.1.0", + "@types/geojson": "^7946.0.10", + "tslib": "^2.6.2" + }, + "funding": { + "url": "https://opencollective.com/turf" + } + }, "node_modules/@turf/destination": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-7.1.0.tgz", @@ -6281,6 +6299,15 @@ "node": ">=6" } }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -7618,6 +7645,15 @@ "react-native": "*" } }, + "node_modules/expo-location": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/expo-location/-/expo-location-18.0.2.tgz", + "integrity": "sha512-45wPrQCv5UQM/RZcOJIei8za0lSyEm5wlb3izLa9P45bqlu3ChRZhYfZz+gMQhVb/oorVqzIVUQhKRTTz7GOXQ==", + "license": "MIT", + "peerDependencies": { + "expo": "*" + } + }, "node_modules/expo-manifests": { "version": "0.15.4", "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-0.15.4.tgz", @@ -10960,6 +10996,25 @@ "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1" } }, + "node_modules/maplibre-react-components": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/maplibre-react-components/-/maplibre-react-components-0.1.9.tgz", + "integrity": "sha512-UjKZBi/qdKKQ1UejWoSVMedaU3T8D/FHxIj/WSjKbxrqhe1wWk4Mo79xT9yM6N/l1HXyPlf0RXeHbwLv5edh3g==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "maplibre-gl": "^3.0.0 || ^4.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "maplibre-gl": { + "optional": false + } + } + }, "node_modules/marky": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", diff --git a/client/package.json b/client/package.json index 70bc736..86dab20 100644 --- a/client/package.json +++ b/client/package.json @@ -18,6 +18,7 @@ "@maplibre/maplibre-react-native": "^10.0.0-alpha.28", "@react-navigation/bottom-tabs": "^7.0.0", "@react-navigation/native": "^7.0.0", + "@turf/circle": "^7.1.0", "expo": "~52.0.11", "expo-blur": "~14.0.1", "expo-constants": "~17.0.3", @@ -25,6 +26,7 @@ "expo-font": "~13.0.1", "expo-haptics": "~14.0.0", "expo-linking": "~7.0.3", + "expo-location": "^18.0.2", "expo-router": "~4.0.9", "expo-splash-screen": "~0.29.13", "expo-status-bar": "~2.0.0", @@ -32,6 +34,7 @@ "expo-system-ui": "~4.0.4", "expo-web-browser": "~14.0.1", "maplibre-gl": "^4.7.1", + "maplibre-react-components": "^0.1.9", "react": "18.3.1", "react-dom": "18.3.1", "react-map-gl": "^7.1.7", diff --git a/client/tsconfig.json b/client/tsconfig.json index 92f3d7d..ae0a8b9 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -13,6 +13,6 @@ "**/*.tsx", ".expo/types/**/*.ts", "expo-env.d.ts", - "app/(tabs)/index.jsx" + "app/(tabs)/index.tsx" ] }