|
@@ -1,8 +1,8 @@
|
|
import React, { useState, useEffect, Children } from 'react';
|
|
import React, { useState, useEffect, Children } from 'react';
|
|
-import { View, Text, StatusBar, StyleSheet, Dimensions, Button, ActivityIndicator, Alert, Modal, PanResponderCallbacks, PanResponderGestureState, GestureResponderEvent, ImageSourcePropType, TouchableOpacity, Platform } from 'react-native';
|
|
|
|
|
|
+import { View, Text, StatusBar, StyleSheet, Dimensions, Button, ActivityIndicator, Alert, Modal, PanResponderCallbacks, PanResponderGestureState, GestureResponderEvent, ImageSourcePropType, TouchableOpacity, Platform, Linking, } from 'react-native';
|
|
import { Svg, Defs, Rect, Mask, Circle, Marker, Path, Polyline, Image } from 'react-native-svg';
|
|
import { Svg, Defs, Rect, Mask, Circle, Marker, Path, Polyline, Image } from 'react-native-svg';
|
|
import { RadioButton } from 'react-native-paper';
|
|
import { RadioButton } from 'react-native-paper';
|
|
-import { Picker } from '@react-native-picker/picker';
|
|
|
|
|
|
+import { Picker as EricPicker } from '@react-native-picker/picker';
|
|
import ReactNativeZoomableView from '@openspacelabs/react-native-zoomable-view/src/ReactNativeZoomableView';
|
|
import ReactNativeZoomableView from '@openspacelabs/react-native-zoomable-view/src/ReactNativeZoomableView';
|
|
import Spinner from 'react-native-spinkit'
|
|
import Spinner from 'react-native-spinkit'
|
|
import { colors, lmTypes } from "../../../utils/GlobalUtils";
|
|
import { colors, lmTypes } from "../../../utils/GlobalUtils";
|
|
@@ -10,15 +10,13 @@ import { MapStackNavigationProp } from "../../../navigation/MapNavigator"
|
|
import CustomModal from './modal';
|
|
import CustomModal from './modal';
|
|
import { FontAwesome } from "@expo/vector-icons";
|
|
import { FontAwesome } from "@expo/vector-icons";
|
|
import ReactDOMServer from 'react-dom/server'; //npm i --save-dev @types/react-dom
|
|
import ReactDOMServer from 'react-dom/server'; //npm i --save-dev @types/react-dom
|
|
-
|
|
|
|
-
|
|
|
|
-import BasementC from './images/BasementC.svg';
|
|
|
|
-import FirstFloorC from './images/FirstFloorC.svg'
|
|
|
|
-import SecondFloorC from './images/SecondFloorC.svg'
|
|
|
|
-import ThirdFloorC from './images/ThirdFloorC.svg'
|
|
|
|
-import FourthFloorC from './images/FourthFloorC.svg'
|
|
|
|
-import FifthFloorC from './images/FifthFloorC.svg'
|
|
|
|
import { ZoomableViewEvent } from '@openspacelabs/react-native-zoomable-view/src/typings';
|
|
import { ZoomableViewEvent } from '@openspacelabs/react-native-zoomable-view/src/typings';
|
|
|
|
+import IndoorFloor from '../IndoorFloor'
|
|
|
|
+// import Toast from 'react-native-toast-message';
|
|
|
|
+import Toast from 'react-native-root-toast';
|
|
|
|
+import ArrowButton from './ArrowButton'
|
|
|
|
+import BottomButtons from './BottomButtons'
|
|
|
|
+import Picker from 'react-native-picker-select';
|
|
import { Landmark } from '../../../data/landmarks';
|
|
import { Landmark } from '../../../data/landmarks';
|
|
|
|
|
|
|
|
|
|
@@ -34,7 +32,7 @@ interface IndoorMapProps {
|
|
|
|
|
|
|
|
|
|
const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddLandmark, focusLandmark, applyFilter }) => {
|
|
const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddLandmark, focusLandmark, applyFilter }) => {
|
|
- const [floor, setFloor] = useState(0);
|
|
|
|
|
|
+ const [floor, setFloor] = useState(1);
|
|
const [showME, setShowME] = useState(false);
|
|
const [showME, setShowME] = useState(false);
|
|
const [showDots, setShowDots] = useState(false);
|
|
const [showDots, setShowDots] = useState(false);
|
|
const [showAddedDot, setShowAddedDot] = useState(false)
|
|
const [showAddedDot, setShowAddedDot] = useState(false)
|
|
@@ -42,29 +40,11 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
|
|
|
|
const [localLandmarks, setLocalLandmarks] = useState<Landmark[]>([])
|
|
const [localLandmarks, setLocalLandmarks] = useState<Landmark[]>([])
|
|
|
|
|
|
- const imageDim = 0.05 * Dimensions.get("window").width;
|
|
|
|
|
|
|
|
- function arrowBut(num, fontAweIcon) {
|
|
|
|
- if (num != 0) {
|
|
|
|
- return (
|
|
|
|
- <View style={{ flex: 1.2, marginHorizontal: 7, backgroundColor: "#d4d4d4", height: 53.5, maxWidth: 60 }}>
|
|
|
|
- <TouchableOpacity style={styles.arrowButton} onPress={() => { setFloor(prevState => prevState + num) }}>
|
|
|
|
- <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
|
|
|
|
- {/* <FontAwesomeIcon icon="fa-solid fa-left" /> */}
|
|
|
|
- <FontAwesome style={{ marginLeft: (num == 1 ? 5 : -5) }} color={"white"} size={35} name={fontAweIcon} />
|
|
|
|
- </View>
|
|
|
|
- </TouchableOpacity>
|
|
|
|
- </View>
|
|
|
|
- )
|
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- return (
|
|
|
|
- <View style={{ flex: 1.2, marginHorizontal: 7, height: 53.5, maxWidth: 60, borderRadius: 10 }}>
|
|
|
|
- </View>
|
|
|
|
- )
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ const [sport, setSport] = useState("football");
|
|
|
|
+
|
|
|
|
|
|
|
|
+ const imageDim = 0.05 * Dimensions.get("window").width;
|
|
|
|
|
|
const loadCircles = applyFilter(landmarks)?.map((item) => {
|
|
const loadCircles = applyFilter(landmarks)?.map((item) => {
|
|
if (item.floor == floor && SVGdim[0] != 1 && SVGdim[1] != 1) {
|
|
if (item.floor == floor && SVGdim[0] != 1 && SVGdim[1] != 1) {
|
|
@@ -84,20 +64,28 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
|
|
|
|
|
|
|
|
function addLandmark(evt: GestureResponderEvent) {
|
|
function addLandmark(evt: GestureResponderEvent) {
|
|
- if (evt) {
|
|
|
|
|
|
+ if (evt != null) {
|
|
Alert.alert("Are you sure you want to add a landmark here?", undefined,
|
|
Alert.alert("Are you sure you want to add a landmark here?", undefined,
|
|
[{ text: "Cancel" }
|
|
[{ text: "Cancel" }
|
|
,
|
|
,
|
|
{
|
|
{
|
|
text: "Confirm", onPress: async () => {
|
|
text: "Confirm", onPress: async () => {
|
|
- await promptAddLandmark((evt.nativeEvent.locationX - imageDim / 2) / SVGdim[0], (evt.nativeEvent.locationY - imageDim / 2) / SVGdim[1], floor)
|
|
|
|
|
|
+ try {
|
|
|
|
+ await promptAddLandmark((evt.nativeEvent.locationX - imageDim / 2) / SVGdim[0], (evt.nativeEvent.locationY - imageDim / 2) / SVGdim[1], floor)
|
|
|
|
+ }
|
|
|
|
+ catch (err) {
|
|
|
|
+ console.log("error has been caught!")
|
|
|
|
+ Toast.show("An error has occured. Please ensure thumb is not moving when holding down on screen.", { duration: Toast.durations.LONG, })
|
|
|
|
+
|
|
|
|
+ // Alert.alert("An error has occured." , "Please ensure thumb is not moving when holding down on screen.")
|
|
|
|
+ // consider toast
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- }])
|
|
|
|
|
|
+ }]
|
|
|
|
+ )
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
// Alert.alert("useEffect has been triggered")
|
|
// Alert.alert("useEffect has been triggered")
|
|
setShowAddedDot(false)
|
|
setShowAddedDot(false)
|
|
@@ -105,18 +93,6 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
setTimeout(() => setShowME(true), 100);
|
|
setTimeout(() => setShowME(true), 100);
|
|
})
|
|
})
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- const compArray = [
|
|
|
|
- <BasementC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
|
|
|
|
- <FirstFloorC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
|
|
|
|
- <SecondFloorC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
|
|
|
|
- <ThirdFloorC viewBox='250 136 310 310' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
|
|
|
|
- <FourthFloorC viewBox='260 151 270 260' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
|
|
|
|
- <FifthFloorC viewBox='257 153 270 290' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
|
|
|
|
- ]
|
|
|
|
-
|
|
|
|
-
|
|
|
|
const childToWeb = (child: any) => {
|
|
const childToWeb = (child: any) => {
|
|
const { type, props } = child;
|
|
const { type, props } = child;
|
|
const name = type && type.displayName;
|
|
const name = type && type.displayName;
|
|
@@ -130,16 +106,16 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
function renderSvg() {
|
|
function renderSvg() {
|
|
return (
|
|
return (
|
|
<Svg height="100%" width="100%" style={{ backgroundColor: '#33AAFF' }}>
|
|
<Svg height="100%" width="100%" style={{ backgroundColor: '#33AAFF' }}>
|
|
- <Rect
|
|
|
|
- x="50"
|
|
|
|
- y="50"
|
|
|
|
- width="50"
|
|
|
|
- height="50"
|
|
|
|
- fill="#3399ff"
|
|
|
|
- strokeWidth="3"
|
|
|
|
- stroke="rgb(0,0,0)"
|
|
|
|
- />
|
|
|
|
- </Svg>
|
|
|
|
|
|
+ <Rect
|
|
|
|
+ x="50"
|
|
|
|
+ y="50"
|
|
|
|
+ width="50"
|
|
|
|
+ height="50"
|
|
|
|
+ fill="#3399ff"
|
|
|
|
+ strokeWidth="3"
|
|
|
|
+ stroke="rgb(0,0,0)"
|
|
|
|
+ />
|
|
|
|
+ </Svg>
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
@@ -147,13 +123,14 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
const element = renderSvg();
|
|
const element = renderSvg();
|
|
const webJsx = Platform.OS === 'web' ? element : toWeb(element);
|
|
const webJsx = Platform.OS === 'web' ? element : toWeb(element);
|
|
const svgString = ReactDOMServer.renderToStaticMarkup(webJsx);
|
|
const svgString = ReactDOMServer.renderToStaticMarkup(webJsx);
|
|
- //console.log(svgString)
|
|
|
|
|
|
+ console.log(svgString)
|
|
// setText(svgString)
|
|
// setText(svgString)
|
|
return svgString
|
|
return svgString
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ function changer(num) {
|
|
|
|
+ setFloor(prevState => prevState + num)
|
|
|
|
+ }
|
|
|
|
|
|
// TODO: wire up promptaddlandmark, applyfilters, and focuslandmark methods passed from MapNavigator
|
|
// TODO: wire up promptaddlandmark, applyfilters, and focuslandmark methods passed from MapNavigator
|
|
return (
|
|
return (
|
|
@@ -166,33 +143,54 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
|
|
|
|
<View style={{ borderColor: "blue", borderWidth: 0, maxHeight: 50, flex: 1, flexDirection: "row", justifyContent: "center", }}>
|
|
<View style={{ borderColor: "blue", borderWidth: 0, maxHeight: 50, flex: 1, flexDirection: "row", justifyContent: "center", }}>
|
|
|
|
|
|
- {/* arrow-circle-o-right */}
|
|
|
|
- {floor == 0 ? arrowBut(0, "") : arrowBut(-1, "chevron-left")}
|
|
|
|
|
|
+ {floor == 0 ? <ArrowButton num={0} fontAweIcon={""} /> : <ArrowButton num={-1} fontAweIcon={"chevron-left"} propEvent={() => changer(-1)} />}
|
|
|
|
+
|
|
|
|
+ <View style={{ backgroundColor: colors.red, flex: 5, height: 53.5, width: 200 }}>
|
|
|
|
+ <Picker
|
|
|
|
+ placeholder={{}}
|
|
|
|
+ value={floor}
|
|
|
|
+ style={{ inputAndroid: {color:"white"} , inputIOS: {color:"white"} }}
|
|
|
|
+ onValueChange={(value) => {
|
|
|
|
+ setFloor(value)
|
|
|
|
+ setShowME(false)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ items={[
|
|
|
|
+ { label: 'Basement', value: 0 },
|
|
|
|
+ { label: 'First Floor', value: 1 },
|
|
|
|
+ { label: 'Second Floor', value: 2 },
|
|
|
|
+ { label: 'Third Floor', value: 3 },
|
|
|
|
+ { label: 'Fourth Floor', value: 4 },
|
|
|
|
+ { label: 'Fifth Floor', value: 5 },
|
|
|
|
+ ]}
|
|
|
|
+ />
|
|
|
|
+ </View>
|
|
|
|
|
|
|
|
|
|
- <Picker
|
|
|
|
|
|
+ {/* <EricPicker
|
|
style={{ backgroundColor: colors.red, width: 200, height: 50, flex: 5, color: 'white' }}
|
|
style={{ backgroundColor: colors.red, width: 200, height: 50, flex: 5, color: 'white' }}
|
|
selectedValue={floor} // the text of what gets displayed on the dropdown header
|
|
selectedValue={floor} // the text of what gets displayed on the dropdown header
|
|
onValueChange={(itemValue, itemIndex: number) => {
|
|
onValueChange={(itemValue, itemIndex: number) => {
|
|
setFloor(itemIndex)
|
|
setFloor(itemIndex)
|
|
setShowME(false)
|
|
setShowME(false)
|
|
}}>
|
|
}}>
|
|
- {/* The value in Picker.Item refers to selectedValue in Picker, which refers to the state "floor" */}
|
|
|
|
- <Picker.Item label="Basement" value={0} />
|
|
|
|
- <Picker.Item label="First Floor" value={1} />
|
|
|
|
- <Picker.Item label="Second Floor" value={2} />
|
|
|
|
- <Picker.Item label="Third Floor" value={3} />
|
|
|
|
- <Picker.Item label="Fourth Floor" value={4} />
|
|
|
|
- <Picker.Item label="Fifth Floor" value={5} />
|
|
|
|
- </Picker>
|
|
|
|
|
|
+ The value in EricPicker.Item refers to selectedValue in EricPicker, which refers to the state "floor"
|
|
|
|
+ <EricPicker.Item label="Basement" value={0} />
|
|
|
|
+ <EricPicker.Item label="First Floor" value={1} />
|
|
|
|
+ <EricPicker.Item label="Second Floor" value={2} />
|
|
|
|
+ <EricPicker.Item label="Third Floor" value={3} />
|
|
|
|
+ <EricPicker.Item label="Fourth Floor" value={4} />
|
|
|
|
+ <EricPicker.Item label="Fifth Floor" value={5} />
|
|
|
|
+ </EricPicker> */}
|
|
|
|
|
|
- {floor == 5 ? arrowBut(0, "") : arrowBut(1, "chevron-right")}
|
|
|
|
|
|
|
|
- </View>
|
|
|
|
|
|
+ {/* {floor == 5 ? arrowBut(0, "") : arrowBut(1, "chevron-right")} */}
|
|
|
|
+ {floor == 5 ? <ArrowButton num={0} fontAweIcon={""} /> : <ArrowButton num={1} fontAweIcon={"chevron-right"} propEvent={() => changer(1)} />}
|
|
|
|
|
|
|
|
|
|
|
|
+ </View>
|
|
|
|
|
|
- <View style={{ flex: 1, alignItems: "center", height: '100%', width: '100%' }}>
|
|
|
|
|
|
+ <View style={{ flex: 1, alignItems: "center", height: '100%', width: '100%', borderColor: 'purple', borderWidth: 0 }}>
|
|
<View style={styles.container}>
|
|
<View style={styles.container}>
|
|
{showME === false ?
|
|
{showME === false ?
|
|
<View style={{ display: 'flex', flexDirection: 'row', justifyContent: "center", }}>
|
|
<View style={{ display: 'flex', flexDirection: 'row', justifyContent: "center", }}>
|
|
@@ -204,24 +202,20 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
// bindToBorders={false}
|
|
// bindToBorders={false}
|
|
bindToBorders={true}
|
|
bindToBorders={true}
|
|
|
|
|
|
-
|
|
|
|
zoomStep={2.8}
|
|
zoomStep={2.8}
|
|
// initialZoom={2.2}
|
|
// initialZoom={2.2}
|
|
maxZoom={2.8}
|
|
maxZoom={2.8}
|
|
minZoom={1}
|
|
minZoom={1}
|
|
initialOffsetY={5}
|
|
initialOffsetY={5}
|
|
onLongPress={(event) => {
|
|
onLongPress={(event) => {
|
|
- //console.log(event.nativeEvent)
|
|
|
|
- serialize()
|
|
|
|
|
|
+ console.log("native event is " + event.nativeEvent)
|
|
|
|
+ // serialize()
|
|
addLandmark(event)
|
|
addLandmark(event)
|
|
}}>
|
|
}}>
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
<Svg onLayout={event => {
|
|
<Svg onLayout={event => {
|
|
- // console.log("OFFICIAL: " + event.nativeEvent.layout.width + " , " + event.nativeEvent.layout.height)
|
|
|
|
|
|
+ console.log("OFFICIAL: " + event.nativeEvent.layout.width + " , " + event.nativeEvent.layout.height)
|
|
setSVGdim([event.nativeEvent.layout.width, event.nativeEvent.layout.height])
|
|
setSVGdim([event.nativeEvent.layout.width, event.nativeEvent.layout.height])
|
|
-
|
|
|
|
const transformedLandmarks = localLandmarks.map(item => {
|
|
const transformedLandmarks = localLandmarks.map(item => {
|
|
return { ...item, coordx: item.longitude * event.nativeEvent.layout.width, coordy: item.latitude * event.nativeEvent.layout.height }
|
|
return { ...item, coordx: item.longitude * event.nativeEvent.layout.width, coordy: item.latitude * event.nativeEvent.layout.height }
|
|
})
|
|
})
|
|
@@ -231,15 +225,9 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
>
|
|
>
|
|
{/* {firstTime == true ? undefined : loadCircles} */}
|
|
{/* {firstTime == true ? undefined : loadCircles} */}
|
|
{loadCircles}
|
|
{loadCircles}
|
|
- {compArray[floor]}
|
|
|
|
|
|
+ <IndoorFloor floorNum={floor} />
|
|
</Svg>
|
|
</Svg>
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
</ReactNativeZoomableView>
|
|
</ReactNativeZoomableView>
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
</View>
|
|
</View>
|
|
@@ -249,11 +237,18 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
|
|
setLocalLandmarks(landmarks)
|
|
setLocalLandmarks(landmarks)
|
|
}} /> */}
|
|
}} /> */}
|
|
|
|
|
|
- <Button title='Press me to svgString' color={colors.red} onPress={serialize}></Button>
|
|
|
|
- {/* <Button title="Go back to map" color={colors.red} onPress={() => navigation.goBack()} /> */}
|
|
|
|
|
|
+ {/* <Button title='Press me to svgString' color={colors.red} onPress={serialize}></Button> */}
|
|
|
|
+ {/* <View style={{ flex: 0.1, flexDirection: 'row', alignItems:'flex-end', justifyContent: 'space-around' , borderColor:'green' , borderWidth:0 ,}}>
|
|
|
|
+ <Button title="Go back to map" color={colors.red} onPress={() => navigation.goBack()} />
|
|
|
|
+ <Button title="Resources" color={colors.red} onPress={() => Linking.openURL('https://www.library.ualberta.ca/')} />
|
|
|
|
+ </View> */}
|
|
{/* <TouchableOpacity style={styles.arrowButton} onPress={() => setFloor(prevState => prevState+1)} ><Text>Increase floor by 1</Text></TouchableOpacity> */}
|
|
{/* <TouchableOpacity style={styles.arrowButton} onPress={() => setFloor(prevState => prevState+1)} ><Text>Increase floor by 1</Text></TouchableOpacity> */}
|
|
|
|
|
|
- </View>
|
|
|
|
|
|
+
|
|
|
|
+ <BottomButtons navigation={navigation}/>
|
|
|
|
+ {/* <Text>{floor}</Text> */}
|
|
|
|
+
|
|
|
|
+ </View >
|
|
);
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -265,7 +260,7 @@ const styles = StyleSheet.create({
|
|
borderColor: "black",
|
|
borderColor: "black",
|
|
borderWidth: 2,
|
|
borderWidth: 2,
|
|
marginVertical: 7,
|
|
marginVertical: 7,
|
|
- aspectRatio: 8 / 10, // (caters to portrait mode) (width is 66% the value of height dimension)
|
|
|
|
|
|
+ aspectRatio: 8 / 10, // (caters to portrait mode) (width is 80% the value of height dimension)
|
|
// flex: 1,
|
|
// flex: 1,
|
|
// // backgroundColor: "#fff",
|
|
// // backgroundColor: "#fff",
|
|
// justifyContent: "center",
|
|
// justifyContent: "center",
|
|
@@ -291,8 +286,7 @@ const styles = StyleSheet.create({
|
|
// backgroundColor: "blue",
|
|
// backgroundColor: "blue",
|
|
height: 53.5,
|
|
height: 53.5,
|
|
// borderRadius: 10,
|
|
// borderRadius: 10,
|
|
-
|
|
|
|
- }
|
|
|
|
|
|
+ },
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|