|
@@ -1,37 +1,72 @@
|
|
|
-import React, { useEffect, useState } from 'react';
|
|
|
+import React, { useEffect, useRef, useState } from 'react';
|
|
|
import { View, Platform, Text, StatusBar } from 'react-native';
|
|
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
|
-import MapView, { Geojson, UrlTile } from 'react-native-maps';
|
|
|
|
|
|
import kye from '../../../../../assets/geojson/kye.json';
|
|
|
import { Header } from 'src/components';
|
|
|
import { useGetKyeQuery, usePostSetKye } from '@api/travels';
|
|
|
import { StoreType, storage } from 'src/storage';
|
|
|
|
|
|
-import { FeatureCollection } from '@turf/turf';
|
|
|
-import { FASTEST_MAP_HOST } from 'src/constants';
|
|
|
+import { VECTOR_MAP_HOST } from 'src/constants';
|
|
|
import { styles } from './styles';
|
|
|
-import InfoIcon from 'assets/icons/info-solid.svg';
|
|
|
-import { NAVIGATION_PAGES } from 'src/types';
|
|
|
-import { useNavigation } from '@react-navigation/native';
|
|
|
-
|
|
|
-interface PropertiesData {
|
|
|
- id: number;
|
|
|
- tt: string;
|
|
|
- mega: string;
|
|
|
- name: string;
|
|
|
- fill?: string;
|
|
|
-}
|
|
|
+import MapLibreGL, { MapViewRef } from '@maplibre/maplibre-react-native';
|
|
|
+
|
|
|
+MapLibreGL.setAccessToken(null);
|
|
|
+
|
|
|
+let kye_fill = {
|
|
|
+ id: 'kye_fill',
|
|
|
+ style: {
|
|
|
+ fillColor: 'rgba(21, 99, 123, 0.4)'
|
|
|
+ },
|
|
|
+
|
|
|
+ maxzoom: 12
|
|
|
+};
|
|
|
+
|
|
|
+let kye_fill_visited = {
|
|
|
+ id: 'kye_fill_visited',
|
|
|
+ style: {
|
|
|
+ fillColor: 'rgba(132, 138, 68, 0.6)'
|
|
|
+ },
|
|
|
+ maxzoom: 12
|
|
|
+};
|
|
|
+
|
|
|
+let kye_line = {
|
|
|
+ id: 'kye_line',
|
|
|
+ filter: ['all'],
|
|
|
+ style: {
|
|
|
+ lineColor: 'rgba(14, 80, 109, 1)',
|
|
|
+ lineWidth: ['interpolate', ['linear'], ['zoom'], 0, 0.8, 4, 1, 5, 1.5, 12, 3],
|
|
|
+ lineWidthTransition: { duration: 300, delay: 0 }
|
|
|
+ },
|
|
|
+ maxzoom: 16
|
|
|
+};
|
|
|
|
|
|
const EarthScreen = () => {
|
|
|
- const token = storage.get('token', StoreType.STRING) as string || '';
|
|
|
- const [geojson, setGeojson] = useState<FeatureCollection>(kye as FeatureCollection);
|
|
|
- const { data } = useGetKyeQuery(token, true);
|
|
|
+ const token = (storage.get('token', StoreType.STRING) as string) || '';
|
|
|
+ const { data } = useGetKyeQuery(token, !!token);
|
|
|
const { mutateAsync } = usePostSetKye();
|
|
|
const [visited, setVisited] = useState<number[]>([]);
|
|
|
const [score, setScore] = useState({ base: 0, percentage: 0 });
|
|
|
const [quadrantsAll, setQuadrantsAll] = useState<number>(1);
|
|
|
- const navigation = useNavigation();
|
|
|
+
|
|
|
+ const generateFilter = (ids: number[]) => {
|
|
|
+ if (!ids || !ids.length) return ['==', 'id', -1];
|
|
|
+
|
|
|
+ return [
|
|
|
+ 'any',
|
|
|
+ ...ids.map((id) => {
|
|
|
+ if (id > 612) {
|
|
|
+ return ['>=', 'id', 613];
|
|
|
+ } else {
|
|
|
+ return ['==', 'id', id];
|
|
|
+ }
|
|
|
+ })
|
|
|
+ ];
|
|
|
+ };
|
|
|
+
|
|
|
+ const [filter, setFilter] = useState<any[]>(generateFilter([]));
|
|
|
+
|
|
|
+ const mapRef = useRef<MapViewRef>(null);
|
|
|
|
|
|
useEffect(() => {
|
|
|
if (!data || !data.regions) return;
|
|
@@ -40,46 +75,10 @@ const EarthScreen = () => {
|
|
|
}, [data]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
- const updatedGeojson = updateGeojsonStyles(geojson);
|
|
|
- setGeojson(updatedGeojson);
|
|
|
+ setFilter(generateFilter(visited));
|
|
|
showScore();
|
|
|
}, [visited]);
|
|
|
|
|
|
- const getFeatureStyle = (properties: PropertiesData) => {
|
|
|
- const style = {
|
|
|
- fill: 'transparent'
|
|
|
- };
|
|
|
-
|
|
|
- if (properties.tt == '1') {
|
|
|
- if (properties.id > 612) {
|
|
|
- if (Math.max(...visited) > 612) {
|
|
|
- style.fill = 'rgba(132, 138, 68, 0.5)';
|
|
|
- } else {
|
|
|
- style.fill = 'rgba(21, 99, 123, 0.5)';
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (visited.includes(properties.id)) {
|
|
|
- style.fill = 'rgba(132, 138, 68, 0.5)';
|
|
|
- } else {
|
|
|
- style.fill = 'rgba(21, 99, 123, 0.5)';
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- style.fill = 'rgba(230, 230, 230, 0.5)';
|
|
|
- }
|
|
|
-
|
|
|
- return style;
|
|
|
- };
|
|
|
-
|
|
|
- const updateGeojsonStyles = (geojson: FeatureCollection) => {
|
|
|
- const updatedFeatures = geojson.features.map((feature) => {
|
|
|
- const style = getFeatureStyle(feature.properties as PropertiesData);
|
|
|
- return { ...feature, properties: { ...feature.properties, ...style } };
|
|
|
- });
|
|
|
-
|
|
|
- return { ...geojson, features: updatedFeatures };
|
|
|
- };
|
|
|
-
|
|
|
const markQuadrant = async (qid: number) => {
|
|
|
if (!token) return;
|
|
|
|
|
@@ -151,20 +150,34 @@ const EarthScreen = () => {
|
|
|
setScore({ base: score, percentage: calc });
|
|
|
};
|
|
|
|
|
|
+ const onMapPress = async (event: any) => {
|
|
|
+ if (!mapRef.current) return;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const { screenPointX, screenPointY } = event.properties;
|
|
|
+
|
|
|
+ const { features } = await mapRef.current.queryRenderedFeaturesAtPoint(
|
|
|
+ [screenPointX, screenPointY],
|
|
|
+ undefined,
|
|
|
+ ['kye_fill']
|
|
|
+ );
|
|
|
+
|
|
|
+ if (features?.length) {
|
|
|
+ const selectedKye = features[0];
|
|
|
+
|
|
|
+ if (selectedKye.properties && selectedKye.properties.tt == '1') {
|
|
|
+ markQuadrant(selectedKye.properties.id);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to get coordinates on EarthScreen', error);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
- <SafeAreaView style={{ height: '100%' }}>
|
|
|
+ <SafeAreaView style={{ height: '100%' }} edges={['top']}>
|
|
|
<View style={styles.wrapper}>
|
|
|
- <Header
|
|
|
- label={'My Earth'}
|
|
|
- // rightElement={
|
|
|
- // <TouchableOpacity
|
|
|
- // onPress={() => navigation.navigate(NAVIGATION_PAGES.EARTH_INFO as never)}
|
|
|
- // style={{ width: 30 }}
|
|
|
- // >
|
|
|
- // <InfoIcon />
|
|
|
- // </TouchableOpacity>
|
|
|
- // }
|
|
|
- />
|
|
|
+ <Header label={'My Earth'} />
|
|
|
{token && (
|
|
|
<View style={styles.score}>
|
|
|
<Text style={[styles.scoreText, { fontWeight: 'bold' }]}>Your score: {score.base}</Text>
|
|
@@ -173,39 +186,44 @@ const EarthScreen = () => {
|
|
|
)}
|
|
|
</View>
|
|
|
|
|
|
- <View style={[styles.container, { paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }]}>
|
|
|
- <MapView
|
|
|
+ <View
|
|
|
+ style={[
|
|
|
+ styles.container,
|
|
|
+ { paddingTop: Platform.OS === 'android' ? StatusBar.currentHeight : 0 }
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <MapLibreGL.MapView
|
|
|
+ ref={mapRef}
|
|
|
style={styles.map}
|
|
|
- showsMyLocationButton={false}
|
|
|
- showsCompass={false}
|
|
|
- zoomControlEnabled={false}
|
|
|
- mapType={Platform.OS == 'android' ? 'none' : 'standard'}
|
|
|
- maxZoomLevel={15}
|
|
|
- minZoomLevel={0}
|
|
|
- initialRegion={{
|
|
|
- latitude: 0,
|
|
|
- longitude: 0,
|
|
|
- latitudeDelta: 180,
|
|
|
- longitudeDelta: 180
|
|
|
- }}
|
|
|
+ styleJSON={VECTOR_MAP_HOST + '/nomadmania-maps.json'}
|
|
|
+ rotateEnabled={false}
|
|
|
+ attributionEnabled={false}
|
|
|
+ onPress={onMapPress}
|
|
|
>
|
|
|
- <UrlTile
|
|
|
- urlTemplate={`${FASTEST_MAP_HOST}/tiles_osm/{z}/{x}/{y}`}
|
|
|
- maximumZ={15}
|
|
|
- maximumNativeZ={13}
|
|
|
- shouldReplaceMapContent
|
|
|
- minimumZ={0}
|
|
|
- />
|
|
|
- <Geojson
|
|
|
- geojson={geojson as any}
|
|
|
- zIndex={1}
|
|
|
- tappable={true}
|
|
|
- onPress={(event) => {
|
|
|
- markQuadrant(event.feature.properties?.id);
|
|
|
- }}
|
|
|
- tracksViewChanges={false}
|
|
|
- />
|
|
|
- </MapView>
|
|
|
+ <MapLibreGL.ShapeSource id="kye" shape={kye as any}>
|
|
|
+ <MapLibreGL.LineLayer
|
|
|
+ id={kye_line.id}
|
|
|
+ filter={kye_line.filter as any}
|
|
|
+ maxZoomLevel={kye_line.maxzoom}
|
|
|
+ style={kye_line.style as any}
|
|
|
+ belowLayerID="waterway-name"
|
|
|
+ />
|
|
|
+ <MapLibreGL.FillLayer
|
|
|
+ id={kye_fill.id}
|
|
|
+ filter={['==', 'tt', '1']}
|
|
|
+ style={kye_fill.style}
|
|
|
+ maxZoomLevel={kye_fill.maxzoom}
|
|
|
+ belowLayerID={kye_fill_visited.id}
|
|
|
+ />
|
|
|
+ <MapLibreGL.FillLayer
|
|
|
+ id={kye_fill_visited.id}
|
|
|
+ filter={filter as any}
|
|
|
+ style={kye_fill_visited.style}
|
|
|
+ maxZoomLevel={kye_fill_visited.maxzoom}
|
|
|
+ belowLayerID={kye_line.id}
|
|
|
+ />
|
|
|
+ </MapLibreGL.ShapeSource>
|
|
|
+ </MapLibreGL.MapView>
|
|
|
</View>
|
|
|
</SafeAreaView>
|
|
|
);
|