123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- import {
- View,
- Platform,
- TouchableOpacity,
- Text
- } from 'react-native';
- import React, { useEffect, useState, useRef, useMemo } from 'react';
- import MapView, { UrlTile, Geojson } from 'react-native-maps';
- import * as turf from '@turf/turf';
- import * as FileSystem from 'expo-file-system';
- import MenuIcon from '../../../../assets/icons/menu.svg';
- import SearchIcon from '../../../../assets/icons/search.svg';
- import RadarIcon from '../../../../assets/icons/radar.svg';
- import LocationIcon from '../../../../assets/icons/location.svg';
- import CloseSvg from '../../../../assets/icons/close.svg';
- import regions from '../../../../assets/geojson/nm2022.json';
- import dareRegions from '../../../../assets/geojson/mqp.json';
- import NetInfo from "@react-native-community/netinfo";
- import { getFirstDatabase, getSecondDatabase } from '../../../db';
- import RegionPopup from '../../../components/RegionPopup';
- import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
- import { styles } from './style';
- import { findRegionInDataset, calculateMapRegion } from '../../../utils/mapHelpers';
- import { getData } from '../../../modules/map/regionData';
- const tilesBaseURL = 'https://maps.nomadmania.com/tiles_osm';
- const localTileDir = `${FileSystem.cacheDirectory}tiles`;
- const gridUrl = 'https://maps.nomadmania.com/tiles_nm/grid';
- const localGridDir = `${FileSystem.cacheDirectory}tiles/grid`;
- const visitedTiles = 'https://maps.nomadmania.com/tiles_nm/user_visited/51363';
- const localVisitedDir = `${FileSystem.cacheDirectory}tiles/user_visited`;
- const dareTiles = 'https://maps.nomadmania.com/tiles_nm/regions_mqp';
- const localDareDir = `${FileSystem.cacheDirectory}tiles/regions_mqp`;
- interface Region {
- id: number;
- name: string;
- region_photos: string;
- visitors_count: number;
- }
- interface MapScreenProps {
- navigation: BottomTabNavigationProp<any>;
- }
- const MapScreen: React.FC<MapScreenProps> = ({ navigation }) => {
- const mapRef = useRef<MapView>(null);
- const [isConnected, setIsConnected] = useState<boolean | null>(true);
- const [selectedRegion, setSelectedRegion] = useState(null);
- const [popupVisible, setPopupVisible] = useState<boolean | null>(false);
- const [regionData, setRegionData] = useState<Region | null>(null);
- const [userAvatars, setUserAvatars] = useState<string[]>([]);
- useEffect(() => {
- navigation.setOptions({
- tabBarStyle: {
- display: popupVisible ? 'none' : 'flex',
- position: 'absolute',
- ...Platform.select({
- android: {
- height: 58,
- },
- }),
- }
- });
- }, [popupVisible, navigation]);
- const handleRegionData = (regionData: Region, avatars: string[]) => {
- setRegionData(regionData);
- setUserAvatars(avatars);
- };
- const handleMapPress = async (event: { nativeEvent: { coordinate: { latitude: any; longitude: any; }; }; }) => {
- const { latitude, longitude } = event.nativeEvent.coordinate;
- const point = turf.point([longitude, latitude]);
- setUserAvatars([]);
- let db = getSecondDatabase();
- let tableName = 'places';
- let foundRegion = findRegionInDataset(dareRegions, point);
- if (!foundRegion) {
- foundRegion = findRegionInDataset(regions, point);
- db = getFirstDatabase();
- tableName = 'regions';
- }
- if (foundRegion) {
- const id = foundRegion.properties?.id;
- setSelectedRegion({
- type: 'FeatureCollection',
- features: [{
- geometry: foundRegion.geometry,
- properties: {
- ...foundRegion.properties,
- fill: "rgba(57, 115, 172, 0.2)",
- stroke: "#3973AC",
- },
- type: 'Feature',
- }]
- });
- await getData(db, id, tableName, handleRegionData)
- .then(() => {
- setPopupVisible(true);
- })
- .catch(error => {
- console.error("Error fetching data", error);
- });
- const bounds = turf.bbox(foundRegion);
- const region = calculateMapRegion(bounds);
- mapRef.current?.animateToRegion(region, 1000);
- } else {
- handleClosePopup();
- }
- };
- useEffect(() => {
- const unsubscribe = NetInfo.addEventListener(state => {
- setIsConnected(state.isConnected);
- });
-
- return () => unsubscribe();
- }, []);
- const renderMapTiles = (
- url: string,
- cacheDir: string,
- zIndex: number,
- opacity = 1
- ) => (
- <UrlTile
- urlTemplate={`${url}/{z}/{x}/{y}`}
- maximumZ={15}
- maximumNativeZ={13}
- tileCachePath={`${cacheDir}`}
- shouldReplaceMapContent
- minimumZ={0}
- offlineMode={!isConnected}
- opacity={opacity}
- zIndex={zIndex}
- />
- );
- function renderGeoJSON() {
- if (!selectedRegion) return null;
- return (
- <Geojson
- geojson={selectedRegion}
- fillColor="rgba(57, 115, 172, 0.2)"
- strokeColor="#3973ac"
- strokeWidth={Platform.OS == 'android' ? 3 : 2}
- zIndex={3}
- />
- );
- };
- const handleClosePopup = () => {
- setPopupVisible(false);
- setSelectedRegion(null);
- }
- const renderedGeoJSON = useMemo(() => renderGeoJSON(), [selectedRegion]);
- return (
- <View style={styles.container}>
- <MapView
- ref={mapRef}
- showsMyLocationButton={false}
- showsCompass={false}
- zoomControlEnabled={false}
- onPress={handleMapPress}
- style={styles.map}
- mapType={Platform.OS == 'android' ? 'none' : 'standard'}
- offlineMode={!isConnected}
- maxZoomLevel={15}
- minZoomLevel={0}
- >
- {renderedGeoJSON}
- {renderMapTiles(tilesBaseURL, localTileDir, 1)}
- {renderMapTiles(gridUrl, localGridDir, 2)}
- {renderMapTiles(visitedTiles, localVisitedDir, 2, 0.5)}
- {renderMapTiles(dareTiles, localDareDir, 2, 0.5)}
- </MapView>
- {popupVisible && regionData ? (
- <>
- <TouchableOpacity
- style={[ styles.cornerButton, styles.topLeftButton, styles.closeLeftButton ]}
- onPress={handleClosePopup}
- >
- <CloseSvg
- fill="white"
- width={13}
- height={13}
- />
- <Text style={styles.textClose}>Close</Text>
- </TouchableOpacity>
- <TouchableOpacity style={[ styles.cornerButton, styles.topRightButton, styles.bottomButton ]}>
- <LocationIcon />
- </TouchableOpacity>
- <RegionPopup
- region={regionData}
- userAvatars={userAvatars}
- onMarkVisited={() => console.log('Mark as visited')}
- />
- </>
- ) : (
- <>
- <TouchableOpacity style={[styles.cornerButton, styles.topLeftButton]}>
- <MenuIcon />
- </TouchableOpacity>
- <TouchableOpacity style={[styles.cornerButton, styles.topRightButton]}>
- <SearchIcon />
- </TouchableOpacity>
- <TouchableOpacity style={[styles.cornerButton, styles.bottomButton, styles.bottomLeftButton]}>
- <RadarIcon />
- </TouchableOpacity>
- <TouchableOpacity style={[styles.cornerButton, styles.bottomButton, styles.bottomRightButton]}>
- <LocationIcon />
- </TouchableOpacity>
- </>
- )}
- </View>
- );
- }
- export default MapScreen;
|