123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- import React, { useEffect, useRef, useState } from 'react';
- import { StyleSheet, View } from 'react-native';
- import * as Location from 'expo-location';
- import * as MapLibreRN from '@maplibre/maplibre-react-native';
- import { SheetManager, useSheetRouteParams, useSheetRouter } from 'react-native-actions-sheet';
- import { Colors } from 'src/theme';
- import { VECTOR_MAP_HOST } from 'src/constants';
- import { ButtonVariants } from 'src/types/components';
- import { Button } from 'src/components';
- const RouteB = () => {
- const router = useSheetRouter('chat-attachments');
- const params = useSheetRouteParams('chat-attachments', 'route-b');
- const {
- onSendLocation,
- insetsBottom
- }: {
- onSendLocation: (coords: { latitude: number; longitude: number }) => void;
- insetsBottom: number;
- } = params;
- const [currentLocation, setCurrentLocation] = useState<{
- latitude: number;
- longitude: number;
- } | null>(null);
- const [selectedLocation, setSelectedLocation] = useState<{
- latitude: number;
- longitude: number;
- } | null>(null);
- const [loading, setLoading] = useState(true);
- const cameraRef = useRef<MapLibreRN.CameraRef | null>(null);
- const [mapDimensions, setMapDimensions] = useState({ width: 0, height: 0, x: 0, y: 0 });
- useEffect(() => {
- const getLocation = async () => {
- try {
- const { status } = await Location.requestForegroundPermissionsAsync();
- if (status !== 'granted') {
- return;
- }
- const location = await Location.getCurrentPositionAsync({});
- const coords = {
- latitude: location.coords.latitude,
- longitude: location.coords.longitude
- };
- setCurrentLocation(coords);
- setSelectedLocation(coords);
- } catch (err) {
- console.warn('Error fetching location:', err);
- }
- };
- getLocation();
- }, []);
- useEffect(() => {
- if (currentLocation) {
- const timeoutId = setTimeout(() => {
- if (cameraRef.current) {
- cameraRef.current.setCamera({
- centerCoordinate: [currentLocation.longitude, currentLocation.latitude],
- zoomLevel: 14,
- animationDuration: 500
- });
- setLoading(false);
- } else {
- console.warn('Camera ref is not available.');
- }
- }, 500);
- return () => clearTimeout(timeoutId);
- }
- }, [currentLocation]);
- const confirmLocation = () => {
- if (selectedLocation) {
- onSendLocation(selectedLocation);
- }
- SheetManager.hide('location-picker');
- SheetManager.hide('chat-attachments');
- };
- const sendCurrentLocation = () => {
- if (currentLocation) {
- onSendLocation(currentLocation);
- }
- SheetManager.hide('location-picker');
- SheetManager.hide('chat-attachments');
- };
- const handleRegionChange = (event: any) => {
- const { geometry } = event;
- if (geometry) {
- const [longitude, latitude] = geometry.coordinates;
- setSelectedLocation({ latitude, longitude });
- }
- };
- return (
- <View style={[styles.container, { paddingBottom: 8 + insetsBottom }]}>
- <View
- style={styles.mapContainer}
- onLayout={(event) => {
- const { x, y, width, height } = event.nativeEvent.layout;
- setMapDimensions({ x, y, width, height });
- }}
- >
- <MapLibreRN.MapView
- style={{ flex: 1 }}
- mapStyle={VECTOR_MAP_HOST + '/nomadmania-maps.json'}
- compassEnabled={false}
- rotateEnabled={false}
- attributionEnabled={false}
- onRegionDidChange={handleRegionChange}
- >
- <MapLibreRN.Camera ref={cameraRef} />
- {currentLocation && (
- <MapLibreRN.PointAnnotation
- id="currentLocation"
- coordinate={[currentLocation.longitude, currentLocation.latitude]}
- >
- <View style={styles.currentLocationMarker} />
- </MapLibreRN.PointAnnotation>
- )}
- </MapLibreRN.MapView>
- </View>
- <View
- style={[
- styles.centerMarker,
- { left: mapDimensions.width / 2 - 12, top: mapDimensions.height / 2 - 12 }
- ]}
- >
- <View style={styles.selectedLocationMarker} />
- </View>
- <View style={styles.mapActions}>
- <Button
- children="Send current location"
- onPress={sendCurrentLocation}
- variant={ButtonVariants.FILL}
- disabled={loading}
- />
- <Button
- children="Send selected location"
- onPress={confirmLocation}
- variant={ButtonVariants.OPACITY}
- containerStyles={{ backgroundColor: Colors.DARK_BLUE, borderColor: Colors.DARK_BLUE, }}
- textStyles={{ color: Colors.WHITE }}
- />
- <Button
- children="Close"
- onPress={() => router?.goBack()}
- variant={ButtonVariants.OPACITY}
- containerStyles={{ backgroundColor: Colors.WHITE, borderColor: '#B7C6CB' }}
- textStyles={{ color: Colors.DARK_BLUE }}
- />
- </View>
- </View>
- );
- };
- const styles = StyleSheet.create({
- container: {
- backgroundColor: Colors.FILL_LIGHT,
- minHeight: 600,
- gap: 16
- },
- mapContainer: { flex: 1 },
- mapActions: {
- flexDirection: 'column',
- gap: 8,
- paddingHorizontal: 16
- },
- currentLocationMarker: {
- width: 20,
- height: 20,
- backgroundColor: Colors.ORANGE,
- borderRadius: 10,
- borderWidth: 2,
- borderColor: Colors.WHITE
- },
- selectedLocationMarker: {
- width: 24,
- height: 24,
- backgroundColor: Colors.DARK_BLUE,
- borderRadius: 12,
- borderWidth: 2,
- borderColor: Colors.WHITE
- },
- centerMarker: {
- position: 'absolute',
- zIndex: 1000
- }
- });
- export default RouteB;
|