App.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import { StyleSheet, View, Platform, Button } from 'react-native';
  2. import * as FileSystem from 'expo-file-system';
  3. import { useEffect, useState } from 'react';
  4. import MapView, { UrlTile, Geojson, Marker } from 'react-native-maps';
  5. import initDB from './app/database/db';
  6. import {fetchRegion, getForRegion} from './app/api/api';
  7. import {loadGeoJSONData, loadMarkersData, downloadTile} from './app/functions';
  8. import NetInfo from "@react-native-community/netinfo";
  9. const tilesBaseURL = 'https://maps.nomadmania.com/tiles_osm';
  10. const localTileDir = `${FileSystem.cacheDirectory}tiles`;
  11. export default function App() {
  12. const [isConnected, setIsConnected] = useState(null);
  13. const [geoJSON, setGeoJSON] = useState(null);
  14. const [markers, setMarkers] = useState(null);
  15. const region = 226;
  16. useEffect(() => {
  17. const unsubscribe = NetInfo.addEventListener(state => {
  18. setIsConnected(state.isConnected);
  19. });
  20. return () => unsubscribe();
  21. }, []);
  22. const downloadTiles = async () => {
  23. for (let z = 0; z <= 6; z++) {
  24. const numTiles = Math.pow(2, z);
  25. for (let x = 0; x < numTiles; x++) {
  26. for (let y = 0; y < numTiles; y++) {
  27. await downloadTile(`${tilesBaseURL}/${z}/${x}/${y}`, z, x, y);
  28. }
  29. }
  30. }
  31. };
  32. useEffect(() => {
  33. async function prepare() {
  34. if (isConnected !== null) {
  35. console.log("Connected: ", isConnected);
  36. if (isConnected) {
  37. await fetchRegion(region);
  38. await getForRegion(region);
  39. }
  40. await loadMarkersData().then(data => {
  41. setMarkers(data);
  42. }).catch(error => {
  43. console.error("Error loading markers data: ", error);
  44. })
  45. await loadGeoJSONData(region).then(data => {
  46. setGeoJSON({
  47. type: 'FeatureCollection',
  48. features: [
  49. {
  50. type: 'Feature',
  51. properties: {
  52. },
  53. geometry: {
  54. type: data?.type,
  55. coordinates: data?.coordinates,
  56. }
  57. }
  58. ]
  59. });
  60. }).catch(error => {
  61. console.error("Error loading GeoJSON data: ", error);
  62. });
  63. }
  64. }
  65. initDB();
  66. prepare();
  67. }, [isConnected]);
  68. const renderLocalTiles = () => {
  69. return (
  70. <UrlTile
  71. urlTemplate={`${tilesBaseURL}/{z}/{x}/{y}`}
  72. maximumZ={15}
  73. maximumNativeZ={13}
  74. tileCachePath={`${localTileDir}`}
  75. shouldReplaceMapContent
  76. minimumZ={0}
  77. offlineMode={!isConnected}
  78. opacity={1}
  79. zIndex={1}
  80. />
  81. );
  82. };
  83. function renderGeoJSON() {
  84. if (!geoJSON) return null;
  85. return (
  86. <Geojson
  87. geojson={geoJSON}
  88. strokeColor="#3973ac"
  89. fillColor="rgba(57, 115, 172, 0.2)"
  90. strokeWidth={3}
  91. zIndex={2}
  92. fiilRule="evenodd"
  93. />
  94. );
  95. };
  96. const renderMarkers = () => {
  97. if (!markers) return null;
  98. return markers?.map((marker, idx) => (
  99. <Marker
  100. key={(idx)}
  101. coordinate={{ latitude: parseFloat(marker.l), longitude: parseFloat(marker.g) }}
  102. title={marker.n}
  103. description={marker.d}
  104. image={{uri: `https://nomadmania.com/static/img/series/${marker.i}`}}
  105. />
  106. ));
  107. };
  108. return (
  109. <View style={styles.container}>
  110. <MapView
  111. style={styles.map}
  112. mapType={Platform.OS == 'android' ? 'none' : 'standard'}
  113. zoomControlEnabled
  114. offlineMode={!isConnected}
  115. maxZoomLevel={15}
  116. minZoomLevel={0}
  117. >
  118. {renderLocalTiles()}
  119. {renderGeoJSON()}
  120. {renderMarkers()}
  121. </MapView>
  122. {isConnected && (
  123. <View style={styles.btn}>
  124. <Button title={`Cache all tiles for zoom levels 0 - 6`} onPress={downloadTiles}></Button>
  125. </View>
  126. )}
  127. <View>
  128. <Button title={isConnected ? "Enable offline mode" : "Disable offline mode"} onPress={() => setIsConnected(!isConnected)} />
  129. </View>
  130. </View>
  131. );
  132. }
  133. const styles = StyleSheet.create({
  134. container: {
  135. flex: 1,
  136. },
  137. map: {
  138. flex: 1,
  139. },
  140. btn: {
  141. marginBottom: 5,
  142. }
  143. });