|
@@ -74,6 +74,13 @@ const localDareDir = `${FileSystem.cacheDirectory}tiles/regions_mqp`;
|
|
|
|
|
|
const AnimatedMarker = Animation.createAnimatedComponent(Marker);
|
|
|
|
|
|
+const INITIAL_REGION = {
|
|
|
+ latitude: 0,
|
|
|
+ longitude: 0,
|
|
|
+ latitudeDelta: 180,
|
|
|
+ longitudeDelta: 180
|
|
|
+};
|
|
|
+
|
|
|
const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
const [dareData, setDareData] = useState(jsonData);
|
|
|
const tilesBaseURL = `${FASTEST_MAP_HOST}/tiles_osm`;
|
|
@@ -141,6 +148,8 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
const savedVisitedTilesUrl = storage.get('visitedTilesUrl', StoreType.STRING) as string;
|
|
|
const [userInfoData, setUserInfoData] = useState<any>(null);
|
|
|
|
|
|
+ const [initialRegion, setInitialRegion] = useState(INITIAL_REGION);
|
|
|
+
|
|
|
useFocusEffect(
|
|
|
useCallback(() => {
|
|
|
const updateMarkers = async () => {
|
|
@@ -164,6 +173,27 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
}, [userData])
|
|
|
);
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
+ const loadInitialRegion = () => {
|
|
|
+ try {
|
|
|
+ const savedInitialRegion = storage.get('initialRegion', StoreType.STRING) as string;
|
|
|
+ if (savedInitialRegion) {
|
|
|
+ const region = JSON.parse(savedInitialRegion);
|
|
|
+ setInitialRegion(region);
|
|
|
+
|
|
|
+ const currentZoom = Math.log2(360 / region.latitudeDelta);
|
|
|
+ if (currentZoom >= 7) {
|
|
|
+ findFeaturesInVisibleMapArea(region);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('Failed to load saved initial region:', e);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ loadInitialRegion();
|
|
|
+ }, [dareData]);
|
|
|
+
|
|
|
useEffect(() => {
|
|
|
if (route.params?.id && route.params?.type && dareData) {
|
|
|
handleFindRegion(route.params?.id, route.params?.type);
|
|
@@ -283,17 +313,21 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- let currentLocation = await Location.getCurrentPositionAsync({});
|
|
|
+ let currentLocation = await Location.getCurrentPositionAsync({
|
|
|
+ accuracy: Location.Accuracy.Low
|
|
|
+ });
|
|
|
setLocation(currentLocation.coords);
|
|
|
})();
|
|
|
}, []);
|
|
|
|
|
|
const findFeaturesInVisibleMapArea = async (visibleMapArea: {
|
|
|
- latitude?: any;
|
|
|
- longitude?: any;
|
|
|
+ latitude: any;
|
|
|
+ longitude: any;
|
|
|
latitudeDelta: any;
|
|
|
- longitudeDelta?: any;
|
|
|
+ longitudeDelta: any;
|
|
|
}) => {
|
|
|
+ storage.set('initialRegion', JSON.stringify(visibleMapArea));
|
|
|
+
|
|
|
if (!isConnected) return;
|
|
|
const currentZoom = Math.log2(360 / visibleMapArea.latitudeDelta);
|
|
|
setZoomLevel(currentZoom);
|
|
@@ -362,15 +396,17 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
});
|
|
|
setLocation(currentLocation.coords);
|
|
|
|
|
|
- mapRef.current?.animateToRegion(
|
|
|
- {
|
|
|
- latitude: currentLocation.coords.latitude,
|
|
|
- longitude: currentLocation.coords.longitude,
|
|
|
- latitudeDelta: 5,
|
|
|
- longitudeDelta: 5
|
|
|
- },
|
|
|
- 800
|
|
|
- );
|
|
|
+ currentLocation.coords?.latitude &&
|
|
|
+ currentLocation.coords?.longitude &&
|
|
|
+ mapRef.current?.animateToRegion(
|
|
|
+ {
|
|
|
+ latitude: currentLocation.coords.latitude,
|
|
|
+ longitude: currentLocation.coords.longitude,
|
|
|
+ latitudeDelta: 5,
|
|
|
+ longitudeDelta: 5
|
|
|
+ },
|
|
|
+ 800
|
|
|
+ );
|
|
|
|
|
|
handleClosePopup();
|
|
|
};
|
|
@@ -394,7 +430,11 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
const handleMapPress = async (event: {
|
|
|
nativeEvent: { coordinate: { latitude: any; longitude: any }; action?: string };
|
|
|
}) => {
|
|
|
- if (event.nativeEvent?.action === 'marker-press') return;
|
|
|
+ if (
|
|
|
+ event.nativeEvent?.action === 'marker-press' ||
|
|
|
+ event.nativeEvent?.action === 'callout-inside-press'
|
|
|
+ )
|
|
|
+ return;
|
|
|
|
|
|
cancelTokenRef.current = true;
|
|
|
const { latitude, longitude } = event.nativeEvent.coordinate;
|
|
@@ -404,10 +444,10 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
let tableName = 'places';
|
|
|
let foundRegion: any;
|
|
|
|
|
|
- type !== 1 && (foundRegion = findRegionInDataset(dareData, point));
|
|
|
+ type !== 1 && (foundRegion = dareData ? findRegionInDataset(dareData, point) : null);
|
|
|
|
|
|
if (type === 1) {
|
|
|
- foundRegion = findRegionInDataset(regions, point);
|
|
|
+ foundRegion = regions ? findRegionInDataset(regions, point) : null;
|
|
|
db = getFirstDatabase();
|
|
|
tableName = 'regions';
|
|
|
|
|
@@ -433,19 +473,20 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
refreshDatabases();
|
|
|
});
|
|
|
|
|
|
- await mutateCountriesData(
|
|
|
- { id: +countryId, token },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'countries', ...data.data });
|
|
|
- const bounds = turf.bbox(data.data.bbox);
|
|
|
- const center = data.data.center;
|
|
|
- const region = calculateMapCountry(bounds, center);
|
|
|
-
|
|
|
- mapRef.current?.animateToRegion(region, 1000);
|
|
|
+ token &&
|
|
|
+ (await mutateCountriesData(
|
|
|
+ { id: +countryId, token },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'countries', id: +countryId, ...data.data });
|
|
|
+ const bounds = turf.bbox(data.data.bbox);
|
|
|
+ const center = data.data.center;
|
|
|
+ const region = calculateMapCountry(bounds, center);
|
|
|
+
|
|
|
+ mapRef.current?.animateToRegion(region, 1000);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- );
|
|
|
+ ));
|
|
|
|
|
|
return;
|
|
|
}
|
|
@@ -453,7 +494,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
}
|
|
|
|
|
|
if (!foundRegion) {
|
|
|
- foundRegion = findRegionInDataset(regions, point);
|
|
|
+ foundRegion = regions ? findRegionInDataset(regions, point) : null;
|
|
|
db = getFirstDatabase();
|
|
|
tableName = 'regions';
|
|
|
}
|
|
@@ -492,34 +533,37 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
zoomLevel < 7 && mapRef.current?.animateToRegion(region, 1000);
|
|
|
|
|
|
if (tableName === 'regions') {
|
|
|
- await mutateUserData(
|
|
|
- { region_id: +id, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'nm', ...data });
|
|
|
+ token &&
|
|
|
+ (await mutateUserData(
|
|
|
+ { region_id: +id, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'nm', id: +id, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- );
|
|
|
- await mutateAsync(
|
|
|
- { regions: JSON.stringify([id]), token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setSeries(data.series);
|
|
|
+ ));
|
|
|
+ token &&
|
|
|
+ (await mutateAsync(
|
|
|
+ { regions: JSON.stringify([id]), token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setSeries(data.series);
|
|
|
|
|
|
- const allMarkers = data.items.map(processMarkerData);
|
|
|
- setProcessedMarkers(allMarkers);
|
|
|
+ const allMarkers = data.items.map(processMarkerData);
|
|
|
+ setProcessedMarkers(allMarkers);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- );
|
|
|
+ ));
|
|
|
} else {
|
|
|
- await mutateUserDataDare(
|
|
|
- { dare_id: +id, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'dare', ...data });
|
|
|
+ token &&
|
|
|
+ (await mutateUserDataDare(
|
|
|
+ { dare_id: +id, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'dare', id: +id, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- );
|
|
|
+ ));
|
|
|
setProcessedMarkers([]);
|
|
|
}
|
|
|
} else {
|
|
@@ -529,10 +573,49 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
|
|
|
const handleFindRegion = async (id: number, type: string) => {
|
|
|
cancelTokenRef.current = true;
|
|
|
- const db = type === 'regions' ? getFirstDatabase() : getSecondDatabase();
|
|
|
- const dataset = type === 'regions' ? regions : dareData;
|
|
|
+ const db =
|
|
|
+ type === 'regions'
|
|
|
+ ? getFirstDatabase()
|
|
|
+ : type === 'countries'
|
|
|
+ ? getCountriesDatabase()
|
|
|
+ : getSecondDatabase();
|
|
|
+
|
|
|
+ if (type === 'countries') {
|
|
|
+ setSelectedRegion(null);
|
|
|
+ setMarkers([]);
|
|
|
+ setProcessedMarkers([]);
|
|
|
|
|
|
- const foundRegion = dataset.features.find((region: any) => region.properties.id === id);
|
|
|
+ await getData(db, id, type, handleRegionData)
|
|
|
+ .then(() => {
|
|
|
+ setRegionPopupVisible(true);
|
|
|
+ })
|
|
|
+ .catch((error) => {
|
|
|
+ console.error('Error fetching data', error);
|
|
|
+ refreshDatabases();
|
|
|
+ });
|
|
|
+
|
|
|
+ token &&
|
|
|
+ (await mutateCountriesData(
|
|
|
+ { id: +id, token },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'countries', id: +id, ...data.data });
|
|
|
+ const bounds = turf.bbox(data.data.bbox);
|
|
|
+ const center = data.data.center;
|
|
|
+ const region = calculateMapCountry(bounds, center);
|
|
|
+
|
|
|
+ mapRef.current?.animateToRegion(region, 1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ));
|
|
|
+
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const dataset = type === 'regions' ? regions : dareData;
|
|
|
+ const foundRegion = dataset
|
|
|
+ ? dataset.features.find((region: any) => region.properties.id === id)
|
|
|
+ : null;
|
|
|
|
|
|
if (foundRegion) {
|
|
|
setSelectedRegion({
|
|
@@ -565,35 +648,38 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
mapRef.current?.animateToRegion(region, 1000);
|
|
|
|
|
|
if (type === 'regions') {
|
|
|
- await mutateUserData(
|
|
|
- { region_id: +id, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'nm', ...data });
|
|
|
+ token &&
|
|
|
+ (await mutateUserData(
|
|
|
+ { region_id: +id, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'nm', id: +id, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- );
|
|
|
- await mutateAsync(
|
|
|
- { regions: JSON.stringify([id]), token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setSeries(data.series);
|
|
|
+ ));
|
|
|
+ token &&
|
|
|
+ (await mutateAsync(
|
|
|
+ { regions: JSON.stringify([id]), token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setSeries(data.series);
|
|
|
|
|
|
- const allMarkers = data.items.map(processMarkerData);
|
|
|
- setProcessedMarkers(allMarkers);
|
|
|
- setMarkers(allMarkers);
|
|
|
+ const allMarkers = data.items.map(processMarkerData);
|
|
|
+ setProcessedMarkers(allMarkers);
|
|
|
+ setMarkers(allMarkers);
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- );
|
|
|
+ ));
|
|
|
} else {
|
|
|
- await mutateUserDataDare(
|
|
|
- { dare_id: +id, token: String(token) },
|
|
|
- {
|
|
|
- onSuccess: (data) => {
|
|
|
- setUserData({ type: 'dare', ...data });
|
|
|
+ token &&
|
|
|
+ (await mutateUserDataDare(
|
|
|
+ { dare_id: +id, token: String(token) },
|
|
|
+ {
|
|
|
+ onSuccess: (data) => {
|
|
|
+ setUserData({ type: 'dare', id: +id, ...data });
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- );
|
|
|
+ ));
|
|
|
setProcessedMarkers([]);
|
|
|
setMarkers([]);
|
|
|
}
|
|
@@ -614,6 +700,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
offlineMode={!isConnected}
|
|
|
opacity={opacity}
|
|
|
zIndex={zIndex}
|
|
|
+ tileSize={256}
|
|
|
/>
|
|
|
);
|
|
|
|
|
@@ -756,12 +843,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
return (
|
|
|
<View style={styles.container}>
|
|
|
<ClusteredMapView
|
|
|
- initialRegion={{
|
|
|
- latitude: 0,
|
|
|
- longitude: 0,
|
|
|
- latitudeDelta: 180,
|
|
|
- longitudeDelta: 180
|
|
|
- }}
|
|
|
+ region={initialRegion}
|
|
|
ref={mapRef}
|
|
|
showsMyLocationButton={false}
|
|
|
showsCompass={false}
|
|
@@ -841,7 +923,13 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
handleUpdateDare(id, visits);
|
|
|
}}
|
|
|
disabled={!token || !isConnected}
|
|
|
- updateSlow={handleUpdateSlow}
|
|
|
+ updateSlow={(id, v, s11, s31, s101) => {
|
|
|
+ if (!token) {
|
|
|
+ setIsWarningModalVisible(true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ handleUpdateSlow(id, v, s11, s31, s101);
|
|
|
+ }}
|
|
|
openEditSlowModal={handleOpenEditSlowModal}
|
|
|
/>
|
|
|
</>
|
|
@@ -955,7 +1043,7 @@ const MapScreen: React.FC<MapScreenProps> = ({ navigation, route }) => {
|
|
|
setVisitedTiles={setVisitedTiles}
|
|
|
setSeriesFilter={setSeriesFilter}
|
|
|
isPublicView={false}
|
|
|
- isLogged={!!token}
|
|
|
+ isLogged={token ? true : false}
|
|
|
/>
|
|
|
<EditModal
|
|
|
isVisible={isEditSlowModalVisible}
|