Browse Source

Organizing communication responsibility layers between React and the leaflet webview

master
GabrielTrettel 4 years ago
parent
commit
efa024e131
  1. 55
      src/app/components/map/LeafLetMap.js
  2. 2
      src/app/components/map/Map.html
  3. 84
      src/app/components/map/OpenStreetMap.js
  4. 9
      src/app/screens/MapFeedScreen.js

55
src/app/components/map/LeafLetMap.js

@ -0,0 +1,55 @@
import { Asset } from "expo-asset";
import * as FileSystem from "expo-file-system";
const HTML_FILE_PATH = require(`./Map.html`);
const loadHTMLFile = async () => {
try {
const [{ localUri }] = await Asset.loadAsync(HTML_FILE_PATH);
const fileString = await FileSystem.readAsStringAsync(localUri);
return fileString;
} catch (error) {
console.warn(error);
console.warn("Unable to resolve index file");
}
};
function goToPosition(mapRef, lat, long) {
mapRef.injectJavaScript(`map.setView([${lat}, ${long}], 13);`);
}
const code_to_function = {
"1": clickCallback,
"2": markerCallback,
};
function clickCallback(payload) {
return {
object: "click",
cords: payload.content,
};
}
function markerCallback(payload) {
return {
object: "marker",
id: payload.content,
};
}
function parseInput(event) {
const payload = JSON.parse(event.nativeEvent.data);
return code_to_function[payload.code](payload);
}
function insertMarker(mapRef, props) {
mapRef.injectJavaScript(`
if (!(${props.ID} in markers)) {
markers[${props.ID}] = L.marker([${props.cords.lat}, ${props.cords.long}],
{ID: ${props.ID}});
markers[${props.ID}].addTo(map).on('click', onPopupClick);
}
`);
}
export { loadHTMLFile, parseInput, insertMarker, goToPosition };

2
src/app/components/map/Map.html

@ -96,7 +96,7 @@
function onPopupClick(e) { function onPopupClick(e) {
var payload = { var payload = {
code: 2, code: 2,
content: "marker selecionado " + this.options.ID,
content: this.options.ID,
}; };
window.ReactNativeWebView.postMessage(JSON.stringify(payload)); window.ReactNativeWebView.postMessage(JSON.stringify(payload));
} }

84
src/app/components/map/OpenStreetMap.js

@ -1,62 +1,41 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { View } from "react-native"; import { View } from "react-native";
import WebView from "react-native-webview"; import WebView from "react-native-webview";
import { Asset } from "expo-asset";
import * as FileSystem from "expo-file-system";
const HTML_FILE_PATH = require(`./Map.html`);
const loadHTMLFile = async () => {
try {
const [{ localUri }] = await Asset.loadAsync(HTML_FILE_PATH);
const fileString = await FileSystem.readAsStringAsync(localUri);
return fileString;
} catch (error) {
console.warn(error);
console.warn("Unable to resolve index file");
import {
loadHTMLFile,
parseInput,
insertMarker,
goToPosition,
} from "./LeafLetMap";
function bindEventsToListeners(event, clickListener, markerListener) {
switch (event.object) {
case "click":
clickListener(event.cords);
break;
case "marker":
markerListener(event.id);
break;
default:
break;
} }
};
const code_to_function = {
"1": clickCallback,
"2": clickCallback,
};
function clickCallback(payload, props) {
console.log(payload.content);
props.clickListener(JSON.stringify(payload.content));
}
function parseInput(event, props) {
const payload = JSON.parse(event);
code_to_function[payload.code](payload, props);
} }
function insertMarker(mapRef, props) {
mapRef.injectJavaScript(`
markers[${props.ID}] = L.marker([${props.cords.lat}, ${props.cords.long}],
{ID: ${props.ID}});
markers[${props.ID}].addTo(map).on('click', onPopupClick);
`);
}
function goToPosition(mapRef, lat, long) {
mapRef.injectJavaScript(`map.setView([${lat}, ${long}], 13);`);
}
export default function OpenStreetMap(props) {
export default function OpenStreetMap({
markersList,
animateToPosition,
clickListener,
markerListener,
}) {
const [mapRef, setMapRef] = useState(null); const [mapRef, setMapRef] = useState(null);
const [finishedLoad, setFinishedLoad] = useState(false);
const [webviewContent, setWebviewContent] = useState(null); const [webviewContent, setWebviewContent] = useState(null);
if (mapRef != null) { if (mapRef != null) {
props.animateToPosition != null &&
goToPosition(mapRef, ...props.animateToPosition);
animateToPosition != null && goToPosition(mapRef, ...animateToPosition);
props.markersList != null &&
props.markersList.length > 0 &&
props.markersList.map((m) => insertMarker(mapRef, m));
markersList != null &&
markersList.length > 0 &&
markersList.map((m) => insertMarker(mapRef, m));
} }
loadHTMLFile() loadHTMLFile()
@ -70,13 +49,14 @@ export default function OpenStreetMap(props) {
setMapRef(webViewRef); setMapRef(webViewRef);
}} }}
onMessage={(event) => { onMessage={(event) => {
parseInput(event.nativeEvent.data, props);
bindEventsToListeners(
parseInput(event),
clickListener,
markerListener
);
}} }}
javaScriptEnabled={true} javaScriptEnabled={true}
source={{ html: webviewContent }} source={{ html: webviewContent }}
onLoad={() => {
setFinishedLoad(true);
}}
/> />
</View> </View>
); );

9
src/app/screens/MapFeedScreen.js

@ -5,6 +5,9 @@ import OpenStreetMap from "../components/map/OpenStreetMap";
export default function MapFeedScreen() { export default function MapFeedScreen() {
const [position, setPosition] = useState(null); const [position, setPosition] = useState(null);
const [clickListener, setClickListener] = useState(""); const [clickListener, setClickListener] = useState("");
const [markerListener, setMarkerListener] = useState("");
console.log(clickListener);
const markers = [ const markers = [
{ {
@ -28,8 +31,9 @@ export default function MapFeedScreen() {
<View style={styles.container}> <View style={styles.container}>
<OpenStreetMap <OpenStreetMap
animateToPosition={position} animateToPosition={position}
clickListener={setClickListener}
markersList={markers} markersList={markers}
clickListener={setClickListener}
markerListener={setMarkerListener}
/> />
<View style={styles.btn}> <View style={styles.btn}>
@ -53,7 +57,8 @@ export default function MapFeedScreen() {
</View> </View>
<View style={styles.callback}> <View style={styles.callback}>
<Text style={styles.txt}>{clickListener}</Text>
<Text style={styles.txt}>{JSON.stringify(clickListener)}</Text>
<Text style={styles.txt}>{JSON.stringify(markerListener)}</Text>
</View> </View>
</View> </View>
); );

Loading…
Cancel
Save