|
@@ -64,7 +64,12 @@ import FilterModal from './FilterModal';
|
|
|
import { useGetListDareQuery } from '@api/myDARE';
|
|
|
import { useGetIconsQuery, usePostSetToggleItem } from '@api/series';
|
|
|
import MarkerItem from './MarkerItem';
|
|
|
-import { usePostGetUsersLocationQuery, usePostUpdateLocationMutation } from '@api/location';
|
|
|
+import {
|
|
|
+ usePostGetSettingsQuery,
|
|
|
+ usePostGetUsersLocationQuery,
|
|
|
+ usePostUpdateLocationMutation
|
|
|
+} from '@api/location';
|
|
|
+import UserItem from './UserItem';
|
|
|
|
|
|
MapLibreGL.setAccessToken(null);
|
|
|
MapLibreGL.Logger.setLogLevel('error');
|
|
@@ -82,7 +87,7 @@ let regions_visited = {
|
|
|
style: {
|
|
|
fillColor: 'rgba(255, 126, 0, 1)',
|
|
|
fillOpacity: 0.6,
|
|
|
- fillOutlineColor: 'rgba(14, 80, 109, 1)'
|
|
|
+ fillOutlineColor: 'rgba(14, 80, 109, 0)'
|
|
|
},
|
|
|
filter: generateFilter([]),
|
|
|
maxzoom: 10
|
|
@@ -96,7 +101,7 @@ let countries_visited = {
|
|
|
style: {
|
|
|
fillColor: 'rgba(255, 126, 0, 1)',
|
|
|
fillOpacity: 0.6,
|
|
|
- fillOutlineColor: 'rgba(14, 80, 109, 1)'
|
|
|
+ fillOutlineColor: 'rgba(14, 80, 109, 0)'
|
|
|
},
|
|
|
filter: generateFilter([]),
|
|
|
maxzoom: 10
|
|
@@ -122,18 +127,7 @@ let regions = {
|
|
|
'source-layer': 'regions',
|
|
|
style: {
|
|
|
fillColor: 'rgba(15, 63, 79, 0)',
|
|
|
- fillOutlineColor: 'rgba(14, 80, 109, 1)'
|
|
|
- },
|
|
|
- paint: {
|
|
|
- 'line-width': {
|
|
|
- base: 0.2,
|
|
|
- stops: [
|
|
|
- [0, 0.2],
|
|
|
- [4, 1],
|
|
|
- [5, 1.5],
|
|
|
- [12, 3]
|
|
|
- ]
|
|
|
- },
|
|
|
+ fillOutlineColor: 'rgba(14, 80, 109, 0)'
|
|
|
},
|
|
|
filter: ['all'],
|
|
|
maxzoom: 16
|
|
@@ -146,18 +140,7 @@ let countries = {
|
|
|
'source-layer': 'countries',
|
|
|
style: {
|
|
|
fillColor: 'rgba(15, 63, 79, 0)',
|
|
|
- fillOutlineColor: 'rgba(14, 80, 109, 1)'
|
|
|
- },
|
|
|
- paint: {
|
|
|
- 'line-width': {
|
|
|
- base: 0.2,
|
|
|
- stops: [
|
|
|
- [0, 0.2],
|
|
|
- [4, 1],
|
|
|
- [5, 1.5],
|
|
|
- [12, 3]
|
|
|
- ]
|
|
|
- }
|
|
|
+ fillOutlineColor: 'rgba(14, 80, 109, 0)'
|
|
|
},
|
|
|
filter: ['all'],
|
|
|
maxzoom: 16
|
|
@@ -208,7 +191,7 @@ let series_layer = {
|
|
|
'text-offset': [0, 0.6],
|
|
|
'text-padding': 2,
|
|
|
'text-size': 12,
|
|
|
- 'visibility': 'visible',
|
|
|
+ visibility: 'visible',
|
|
|
'text-optional': true,
|
|
|
'text-ignore-placement': false,
|
|
|
'text-allow-overlap': false
|
|
@@ -242,7 +225,7 @@ let series_visited = {
|
|
|
'text-offset': [0, 0.6],
|
|
|
'text-padding': 2,
|
|
|
'text-size': 12,
|
|
|
- 'visibility': 'visible',
|
|
|
+ visibility: 'visible',
|
|
|
'text-optional': true,
|
|
|
'text-ignore-placement': false,
|
|
|
'text-allow-overlap': false
|
|
@@ -291,6 +274,7 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
const [showNomads, setShowNomads] = useState(
|
|
|
(storage.get('showNomads', StoreType.BOOLEAN) as boolean) ?? false
|
|
|
);
|
|
|
+ const { data: locationSettings, refetch } = usePostGetSettingsQuery(token, !!token);
|
|
|
const { mutateAsync: updateLocation } = usePostUpdateLocationMutation();
|
|
|
const { data: visitedRegionIds, refetch: refetchVisitedRegions } =
|
|
|
usePostGetVisitedRegionsIdsQuery(
|
|
@@ -373,60 +357,62 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
const [images, setImages] = useState<any>({});
|
|
|
const { mutateAsync: updateSeriesItem } = usePostSetToggleItem();
|
|
|
const [nomads, setNomads] = useState<GeoJSON.FeatureCollection | null>(null);
|
|
|
- const { data: usersLocation } = usePostGetUsersLocationQuery(
|
|
|
+ const { data: usersLocation, refetch: refetchUsersLocation } = usePostGetUsersLocationQuery(
|
|
|
token,
|
|
|
!!token && showNomads && Boolean(location)
|
|
|
);
|
|
|
+ const [selectedUser, setSelectedUser] = useState<any>(null);
|
|
|
|
|
|
useEffect(() => {
|
|
|
if (!showNomads) {
|
|
|
setNomads(null);
|
|
|
+ } else {
|
|
|
+ refetchUsersLocation();
|
|
|
}
|
|
|
}, [showNomads]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
if (usersLocation) {
|
|
|
- console.log('usersLocation', usersLocation);
|
|
|
setNomads(usersLocation.geojson);
|
|
|
}
|
|
|
}, [usersLocation]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
- let loadedImages: any = {};
|
|
|
-
|
|
|
if (seriesIcons) {
|
|
|
- seriesIcons.data.forEach(async (icon) => {
|
|
|
+ let loadedSeriesImages: any = {};
|
|
|
+
|
|
|
+ seriesIcons.data.forEach((icon) => {
|
|
|
const id = icon.id;
|
|
|
const img = API_HOST + '/static/img/series_new2/' + icon.new_icon_png;
|
|
|
const imgVisited = API_HOST + '/static/img/series_new2/' + icon.new_icon_visited_png;
|
|
|
- if (!img || !imgVisited) return;
|
|
|
- try {
|
|
|
- const iconImage = { uri: img };
|
|
|
- const visitedIconImage = { uri: imgVisited };
|
|
|
-
|
|
|
- loadedImages[id] = iconImage;
|
|
|
- loadedImages[`${id}v`] = visitedIconImage;
|
|
|
- } catch (error) {
|
|
|
- console.error(`Error loading icon for series_id ${id}:`, error);
|
|
|
+ if (img && imgVisited) {
|
|
|
+ loadedSeriesImages[id] = { uri: img };
|
|
|
+ loadedSeriesImages[`${id}v`] = { uri: imgVisited };
|
|
|
}
|
|
|
});
|
|
|
+
|
|
|
+ setImages((prevImages: any) => ({ ...prevImages, ...loadedSeriesImages }));
|
|
|
}
|
|
|
+ }, [seriesIcons]);
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
if (nomads && nomads.features) {
|
|
|
+ let loadedNomadsImages: any = {};
|
|
|
+
|
|
|
nomads.features.forEach((feature) => {
|
|
|
const user_id = `user_${feature.properties?.id}`;
|
|
|
const avatarUrl = `${API_HOST}${feature.properties?.avatar}`;
|
|
|
if (avatarUrl) {
|
|
|
- loadedImages[user_id] = { uri: avatarUrl };
|
|
|
+ loadedNomadsImages[user_id] = { uri: avatarUrl };
|
|
|
if (feature.properties) {
|
|
|
feature.properties.icon_key = user_id;
|
|
|
}
|
|
|
}
|
|
|
});
|
|
|
- }
|
|
|
|
|
|
- setImages(loadedImages);
|
|
|
- }, [nomads, seriesIcons]);
|
|
|
+ setImages((prevImages: any) => ({ ...prevImages, ...loadedNomadsImages }));
|
|
|
+ }
|
|
|
+ }, [nomads]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
const loadDatabases = async () => {
|
|
@@ -554,12 +540,21 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
}
|
|
|
}, [selectedRegion]);
|
|
|
|
|
|
+ useFocusEffect(
|
|
|
+ useCallback(() => {
|
|
|
+ if (token) {
|
|
|
+ refetch();
|
|
|
+ }
|
|
|
+ }, [])
|
|
|
+ );
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
(async () => {
|
|
|
let { status } = await Location.getForegroundPermissionsAsync();
|
|
|
- if (status !== 'granted') {
|
|
|
+ if (status !== 'granted' || !token || !locationSettings || locationSettings.sharing === 0) {
|
|
|
setShowNomads(false);
|
|
|
storage.set('showNomads', false);
|
|
|
+ setNomads(null);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -572,8 +567,11 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
lat: currentLocation.coords.latitude,
|
|
|
lng: currentLocation.coords.longitude
|
|
|
});
|
|
|
+ if (showNomads && token) {
|
|
|
+ refetchUsersLocation();
|
|
|
+ }
|
|
|
})();
|
|
|
- }, []);
|
|
|
+ }, [locationSettings]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
const currentYear = moment().year();
|
|
@@ -657,7 +655,7 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
|
|
|
const onMapPress = async (event: any) => {
|
|
|
if (!mapRef.current) return;
|
|
|
- if (selectedMarker) {
|
|
|
+ if (selectedMarker || selectedUser) {
|
|
|
closeCallout();
|
|
|
return;
|
|
|
}
|
|
@@ -692,13 +690,13 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
if (tableName === 'regions') {
|
|
|
token
|
|
|
? await mutateUserData(
|
|
|
- { region_id: +foundRegion, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'nm', id: +foundRegion, ...data });
|
|
|
+ { region_id: +foundRegion, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'nm', id: +foundRegion, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- )
|
|
|
+ )
|
|
|
: setUserData({ type: 'nm', id: +foundRegion });
|
|
|
if (regionsList) {
|
|
|
const region = regionsList.data.find((region) => region.id === +foundRegion);
|
|
@@ -715,13 +713,13 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
} else if (tableName === 'countries') {
|
|
|
token
|
|
|
? await mutateCountriesData(
|
|
|
- { id: +foundRegion, token },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'countries', id: +foundRegion, ...data.data });
|
|
|
+ { id: +foundRegion, token },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'countries', id: +foundRegion, ...data.data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- )
|
|
|
+ )
|
|
|
: setUserData({ type: 'countries', id: +foundRegion });
|
|
|
if (countriesList) {
|
|
|
const region = countriesList.data.find((region) => region.id === +foundRegion);
|
|
@@ -738,13 +736,13 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
} else {
|
|
|
token
|
|
|
? await mutateUserDataDare(
|
|
|
- { dare_id: +foundRegion, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'dare', id: +foundRegion, ...data });
|
|
|
+ { dare_id: +foundRegion, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'dare', id: +foundRegion, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- )
|
|
|
+ )
|
|
|
: setUserData({ type: 'dare', id: +foundRegion });
|
|
|
if (dareList) {
|
|
|
const region = dareList.data.find((region) => region.id === +foundRegion);
|
|
@@ -814,6 +812,9 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
lat: currentLocation.coords.latitude,
|
|
|
lng: currentLocation.coords.longitude
|
|
|
});
|
|
|
+ if (showNomads && token) {
|
|
|
+ refetchUsersLocation();
|
|
|
+ }
|
|
|
if (currentLocation.coords) {
|
|
|
cameraRef.current?.flyTo(
|
|
|
[currentLocation.coords.longitude, currentLocation.coords.latitude],
|
|
@@ -890,13 +891,13 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
if (type === 'regions') {
|
|
|
token
|
|
|
? await mutateUserData(
|
|
|
- { region_id: id, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'nm', id, ...data });
|
|
|
+ { region_id: id, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'nm', id, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- )
|
|
|
+ )
|
|
|
: setUserData({ type: 'nm', id });
|
|
|
|
|
|
if (regionsList) {
|
|
@@ -914,13 +915,13 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
} else if (type === 'countries') {
|
|
|
token
|
|
|
? await mutateCountriesData(
|
|
|
- { id, token },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'countries', id, ...data.data });
|
|
|
+ { id, token },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'countries', id, ...data.data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- )
|
|
|
+ )
|
|
|
: setUserData({ type: 'countries', id });
|
|
|
|
|
|
if (countriesList) {
|
|
@@ -938,13 +939,13 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
} else {
|
|
|
token
|
|
|
? await mutateUserDataDare(
|
|
|
- { dare_id: +id, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'dare', id: +id, ...data });
|
|
|
+ { dare_id: +id, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'dare', id: +id, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- )
|
|
|
+ )
|
|
|
: setUserData({ type: 'dare', id: +id });
|
|
|
|
|
|
if (dareList) {
|
|
@@ -985,11 +986,13 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
series_id,
|
|
|
id
|
|
|
});
|
|
|
+ setSelectedUser(null);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
const closeCallout = () => {
|
|
|
setSelectedMarker(null);
|
|
|
+ setSelectedUser(null);
|
|
|
};
|
|
|
|
|
|
const toggleSeries = useCallback(
|
|
@@ -1027,6 +1030,24 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
setModalState((prevState) => ({ ...prevState, ...updates }));
|
|
|
};
|
|
|
|
|
|
+ const handleUserPress = (event: any) => {
|
|
|
+ const selectedFeature = event.features[0];
|
|
|
+ const { coordinates } = selectedFeature.geometry;
|
|
|
+ const { avatar, first_name, last_name, flag, id, last_seen } = selectedFeature.properties;
|
|
|
+ if (selectedFeature) {
|
|
|
+ setSelectedUser({
|
|
|
+ coordinates,
|
|
|
+ avatar: { uri: API_HOST + avatar },
|
|
|
+ first_name,
|
|
|
+ last_name,
|
|
|
+ flag: { uri: API_HOST + flag },
|
|
|
+ id,
|
|
|
+ last_seen
|
|
|
+ });
|
|
|
+ setSelectedMarker(null);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
return (
|
|
|
<SafeAreaView style={{ height: '100%' }}>
|
|
|
<StatusBar translucent backgroundColor="transparent" />
|
|
@@ -1046,6 +1067,19 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
|
|
|
{type === 'regions' && (
|
|
|
<>
|
|
|
+ <MapLibreGL.LineLayer
|
|
|
+ id="nm-regions-line-layer"
|
|
|
+ sourceID={regions.source}
|
|
|
+ sourceLayerID={regions['source-layer']}
|
|
|
+ filter={regions.filter as any}
|
|
|
+ maxZoomLevel={regions.maxzoom}
|
|
|
+ style={{
|
|
|
+ lineColor: 'rgba(14, 80, 109, 1)',
|
|
|
+ lineWidth: ['interpolate', ['linear'], ['zoom'], 0, 0.2, 4, 1, 5, 1.5, 12, 3],
|
|
|
+ lineWidthTransition: { duration: 300, delay: 0 }
|
|
|
+ }}
|
|
|
+ belowLayerID="waterway-name"
|
|
|
+ />
|
|
|
<MapLibreGL.FillLayer
|
|
|
id={regions.id}
|
|
|
sourceID={regions.source}
|
|
@@ -1068,6 +1102,19 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
)}
|
|
|
{type === 'countries' && (
|
|
|
<>
|
|
|
+ <MapLibreGL.LineLayer
|
|
|
+ id="countries-line-layer"
|
|
|
+ sourceID={countries.source}
|
|
|
+ sourceLayerID={countries['source-layer']}
|
|
|
+ filter={countries.filter as any}
|
|
|
+ maxZoomLevel={countries.maxzoom}
|
|
|
+ style={{
|
|
|
+ lineColor: 'rgba(14, 80, 109, 1)',
|
|
|
+ lineWidth: ['interpolate', ['linear'], ['zoom'], 0, 0.2, 4, 1, 5, 1.5, 12, 3],
|
|
|
+ lineWidthTransition: { duration: 300, delay: 0 }
|
|
|
+ }}
|
|
|
+ belowLayerID="waterway-name"
|
|
|
+ />
|
|
|
<MapLibreGL.FillLayer
|
|
|
id={countries.id}
|
|
|
sourceID={countries.source}
|
|
@@ -1182,23 +1229,30 @@ const MapScreen: any = ({ navigation, route }: { navigation: any; route: any })
|
|
|
)}
|
|
|
</MapLibreGL.VectorSource>
|
|
|
|
|
|
- {nomads && (
|
|
|
- <MapLibreGL.ShapeSource
|
|
|
- id="nomads"
|
|
|
- shape={nomads}
|
|
|
- onPress={(event) => console.log(event.features)}
|
|
|
- >
|
|
|
+ {nomads && showNomads && (
|
|
|
+ <MapLibreGL.ShapeSource id="nomads" shape={nomads} onPress={handleUserPress}>
|
|
|
<MapLibreGL.SymbolLayer
|
|
|
id="nomads_symbol"
|
|
|
style={{
|
|
|
iconImage: ['get', 'icon_key'],
|
|
|
- iconSize: 0.15,
|
|
|
+ iconSize: [
|
|
|
+ 'interpolate',
|
|
|
+ ['linear'],
|
|
|
+ ['zoom'],
|
|
|
+ 0, 0.07,
|
|
|
+ 10, 0.12,
|
|
|
+ 15, 0.18,
|
|
|
+ 20, 0.2
|
|
|
+ ],
|
|
|
iconAllowOverlap: true
|
|
|
}}
|
|
|
+ filter={['!=', 'id', +userId]}
|
|
|
></MapLibreGL.SymbolLayer>
|
|
|
</MapLibreGL.ShapeSource>
|
|
|
)}
|
|
|
|
|
|
+ {selectedUser && <UserItem marker={selectedUser} />}
|
|
|
+
|
|
|
{selectedMarker && (
|
|
|
<MarkerItem marker={selectedMarker} toggleSeries={toggleSeries} token={token} />
|
|
|
)}
|