浏览代码

merged indoor map changes

cdmoss 2 年之前
父节点
当前提交
6c081d6b75

+ 2 - 1
App.tsx

@@ -12,6 +12,7 @@ import { createNavigationContainerRef, NavigationContainer } from '@react-naviga
 import { colors } from './src/utils/GlobalUtils';
 import { AuthContextProvider } from './src/data/Auth/AuthContext';
 import { QueryClient, QueryClientProvider, useQueryClient } from 'react-query';
+import { navigationRef } from './src/navigation/RootNavigator';
 
 const App: React.FC = () => {
   const updateDismissed = useRef<boolean>(false)
@@ -81,7 +82,7 @@ const App: React.FC = () => {
         <MenuProvider>
           <SafeAreaView style={{height: '100%', backgroundColor: colors.red}}>
             <StatusBar barStyle='light-content' backgroundColor={colors.red}/>
-            <NavigationContainer>
+            <NavigationContainer ref={navigationRef}>
               <AuthContextProvider>
                 <Atlas/>
               </AuthContextProvider>

+ 1 - 0
android/app/src/main/java/com/clicknpush/mobile/MainApplication.java

@@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
 
 import com.facebook.react.PackageList;
 import com.facebook.react.ReactApplication;
+import fr.greweb.reactnativeviewshot.RNViewShotPackage;
 import com.lugg.ReactNativeConfig.ReactNativeConfigPackage;
 import com.facebook.react.ReactInstanceManager;
 import com.facebook.react.ReactNativeHost;

+ 2 - 0
android/settings.gradle

@@ -1,4 +1,6 @@
 rootProject.name = 'cnp-mobile'
+include ':react-native-view-shot'
+project(':react-native-view-shot').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-view-shot/android')
 include ':react-native-config'
 project(':react-native-config').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-config/android')
 

二进制
assets/desk.png


二进制
assets/elevator.png


二进制
assets/kiosk.png


二进制
assets/monitor.png


二进制
assets/ramp.png


二进制
assets/water.png


+ 2 - 0
ios/Podfile

@@ -15,6 +15,8 @@ target 'cnpmobile' do
   # Convert all permission pods into static libraries
 pod 'react-native-config', :path => '../node_modules/react-native-config'
 
+pod 'react-native-view-shot', :path => '../node_modules/react-native-view-shot'
+
 pre_install do |installer|
   Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
 

+ 16 - 0
package-lock.json

@@ -65,6 +65,7 @@
         "react-native-gesture-handler": "~1.10.2",
         "react-native-get-random-values": "~1.7.0",
         "react-native-maps": "0.29.3",
+        "react-native-material-menu": "^2.0.0",
         "react-native-modal": "^12.0.3",
         "react-native-multi-selectbox": "^1.5.0",
         "react-native-multiple-select": "^0.5.7",
@@ -25063,6 +25064,15 @@
         "react-native-web": "^0.13"
       }
     },
+    "node_modules/react-native-material-menu": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/react-native-material-menu/-/react-native-material-menu-2.0.0.tgz",
+      "integrity": "sha512-SmO9PLE3E469EPbVWZqvdu6JGPPZIm7YjqDcWs2PPoY0k7w2V9tFo3BmmLXNzNZDCVCAi+PPSsL7h/5WkfHcSg==",
+      "peerDependencies": {
+        "react": "*",
+        "react-native": "*"
+      }
+    },
     "node_modules/react-native-modal": {
       "version": "12.1.0",
       "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-12.1.0.tgz",
@@ -51241,6 +51251,12 @@
         "@types/geojson": "^7946.0.7"
       }
     },
+    "react-native-material-menu": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/react-native-material-menu/-/react-native-material-menu-2.0.0.tgz",
+      "integrity": "sha512-SmO9PLE3E469EPbVWZqvdu6JGPPZIm7YjqDcWs2PPoY0k7w2V9tFo3BmmLXNzNZDCVCAi+PPSsL7h/5WkfHcSg==",
+      "requires": {}
+    },
     "react-native-modal": {
       "version": "12.1.0",
       "resolved": "https://registry.npmjs.org/react-native-modal/-/react-native-modal-12.1.0.tgz",

+ 1 - 0
package.json

@@ -83,6 +83,7 @@
     "react-native-gesture-handler": "~1.10.2",
     "react-native-get-random-values": "~1.7.0",
     "react-native-maps": "0.29.3",
+    "react-native-material-menu": "^2.0.0",
     "react-native-modal": "^12.0.3",
     "react-native-multi-selectbox": "^1.5.0",
     "react-native-multiple-select": "^0.5.7",

+ 2 - 0
src/components/Atlas.tsx

@@ -13,6 +13,8 @@ import { useAuth } from '../data/Auth/AuthContext';
 import BaseStackNavigator from '../navigation/BaseStackNavigator';
 import { Error } from './Error';
 
+import { navigationRef } from '../navigation/RootNavigator';
+
 export enum TokenState {
   CheckingToken,
   ValidToken,

+ 1 - 4
src/components/Map/MainMapComponent/ArrowButton.tsx

@@ -7,15 +7,12 @@ import { colors, lmTypes } from "../../../utils/GlobalUtils";
 function ArrowButton(props) {
     if (props.num != 0) {
         return (
-          <View style={{ flex: 1.2, marginHorizontal: 7, backgroundColor: "#d4d4d4", height: 53.5, maxWidth: 60, borderRadius: 8 }}>
-            {/* <TouchableOpacity style={styles.arrowButton} onPress={() => { setFloor(prevState => prevState + props.num) }}></TouchableOpacity> */}
             <TouchableOpacity style={styles.arrowButton} onPress={props.propEvent} >
               <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
                 {/* <FontAwesomeIcon icon="fa-solid fa-left" /> */}
-                <FontAwesome style={{ marginLeft: (props.num == 1 ? 5 : -5) }} color={"white"} size={35} name={props.fontAweIcon} />
+                <FontAwesome style={{ marginLeft: (props.num == 1 ? 5 : -5) }} color={"white"} size={20} name={props.fontAweIcon} />
               </View>
             </TouchableOpacity>
-          </View>
         )
       }
       else {

+ 10 - 9
src/components/Map/MainMapComponent/BottomButtons.tsx

@@ -1,17 +1,18 @@
-import { View, Text, TouchableOpacity, StyleSheet, Linking} from 'react-native'
+import { View, Text, TouchableOpacity, StyleSheet, Linking } from 'react-native'
 import React from 'react'
 import { colors, lmTypes } from "../../../utils/GlobalUtils";
 
 function BottomButtons(props) {
   return (
-<View style={{ flexDirection: "row", justifyContent: "space-around", alignItems: "flex-end", borderColor: "green", borderWidth: 0 }}>
-        <TouchableOpacity style={{ backgroundColor: colors.red, height: 30, paddingHorizontal: 7, paddingTop: 3, borderRadius: 5 }} onPress={() => props.navigation.goBack()}>
-          <Text style={{ fontSize: 16, color: "white", textAlign: "right", textAlignVertical: "bottom" }}>{"Go back to map"}</Text>
-        </TouchableOpacity>
-        <TouchableOpacity style={{ backgroundColor: colors.red, height: 30, paddingHorizontal: 7, paddingTop: 3, borderRadius: 5 }} onPress={() => Linking.openURL('https://www.library.ualberta.ca/')}>
-          <Text style={{ fontSize: 16, color: "white", textAlign: "center", }}>{"Resources"}</Text>
-        </TouchableOpacity>
-      </View>  )
+    <View style={{ flexDirection: "row", justifyContent: "space-around", alignItems: "flex-end", borderColor: "green", borderWidth: 0 }}>
+      <TouchableOpacity style={{ backgroundColor: colors.red, height: 30, paddingHorizontal: 7, paddingTop: 3, borderRadius: 5 }} onPress={() => props.navigation.goBack()}>
+        <Text style={{ fontSize: 16, color: "white", textAlign: "right", textAlignVertical: "bottom" }}>{"Go back outdoors"}</Text>
+      </TouchableOpacity>
+      <TouchableOpacity style={{ backgroundColor: colors.red, height: 30, paddingHorizontal: 7, paddingTop: 3, borderRadius: 5 }} onPress={() => Linking.openURL('https://www.ualberta.ca/facilities-operations/portfolio/emergency-management-office/emergency-procedures/alarms-evacuation.html')}>
+        <Text style={{ fontSize: 16, color: "white", textAlign: "center", }}>{"Resources"}</Text>
+      </TouchableOpacity>
+    </View>
+  )
 }
 
 

+ 8 - 21
src/components/Map/MainMapComponent/IndoorMap.tsx

@@ -40,10 +40,6 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
 
   const [localLandmarks, setLocalLandmarks] = useState<Landmark[]>([])
 
-
-  const [sport, setSport] = useState("football");
-
-
   const imageDim = 0.05 * Dimensions.get("window").width;
 
   const loadCircles = applyFilter(landmarks)?.map((item) => {
@@ -74,8 +70,7 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
               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, })
+              Toast.show("An error has occured. Please ensure finger 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
@@ -119,23 +114,13 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
     )
   }
 
-  function serialize() {
-    const element = renderSvg();
-    const webJsx = Platform.OS === 'web' ? element : toWeb(element);
-    const svgString = ReactDOMServer.renderToStaticMarkup(webJsx);
-    console.log(svgString)
-    // setText(svgString)
-    return svgString
-  }
-
   function changer(num) {
     setFloor(prevState => prevState + num)
   }
 
   // TODO: wire up promptaddlandmark, applyfilters, and focuslandmark methods passed from MapNavigator
   return (
-    <View style={{ height: '100%', width: '100%', padding: 5 }}>
-      {/* {console.log("THE STATE IS NOW " + floor)} */}
+    <View style={{ height: '100%', width: Dimensions.get("screen").width, backgroundColor:colors.red }}>
 
       <StatusBar backgroundColor={colors.red} />
       <CustomModal />
@@ -245,7 +230,7 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
       {/* <TouchableOpacity style={styles.arrowButton} onPress={() => setFloor(prevState => prevState+1)} ><Text>Increase floor by 1</Text></TouchableOpacity> */}
 
 
-      <BottomButtons navigation={navigation}/>
+      {/* <BottomButtons navigation={navigation}/> */}
       {/* <Text>{floor}</Text> */}
 
     </View >
@@ -258,8 +243,8 @@ const styles = StyleSheet.create({
     // backgroundColor: "#fff",
     justifyContent: "center",
     borderColor: "black",
-    borderWidth: 2,
-    marginVertical: 7,
+    borderWidth: 0,
+    marginVertical: 0,
     aspectRatio: 8 / 10,  // (caters to portrait mode) (width is 80% the value of height dimension)
     // flex: 1,
     // // backgroundColor: "#fff",
@@ -270,7 +255,9 @@ const styles = StyleSheet.create({
     width: '100%',
     height: '100%',
     maxWidth: "100%",
-    maxHeight: "100%"
+    maxHeight: "100%",
+    backgroundColor:"white",
+    
   },
   image: {
     alignItems: 'center',

+ 1 - 5
src/components/Map/MainMapComponent/OutdoorMap.tsx

@@ -83,15 +83,11 @@ const OutdoorMap: React.FC<OutdoorMapProps> = (props) => {
     }, [props.route])
 
     useEffect(() => {
-        console.log("mapindex: " +mapNavIndex.index)
-        console.log("auth: " +props.authNavIndex)
         const toMap = mapNavIndex.index == 0 && props.authNavIndex == 0
-        console.log(toMap)
 
         if (toMap) mapState.setLoading(true)
 
         setTimeout(() => {
-            console.log("stop loading")
             mapState.setLoading(false)
         }, 500);
 
@@ -150,7 +146,7 @@ const OutdoorMap: React.FC<OutdoorMapProps> = (props) => {
          useEffect(() => {
             const checkForegroundLocationPermissions = async () =>  {
                 if (AppState.currentState == 'active') {
-                    console.log('Checking location permissions...')
+                    console.log('[Permissions]: Checking location permissions...')
                     if (Platform.OS == 'android') {        
                         const permitted = await checkVoicePermissions([PERMISSIONS.ANDROID.ACCESS_COARSE_LOCATION, PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION])
                         mapState.toggleFgroundLocationPermission(permitted)

+ 44 - 23
src/components/Map/Panels/AddLandmarkPanel.tsx

@@ -8,7 +8,7 @@
 import { FontAwesome } from "@expo/vector-icons";
 import { ImageInfo } from "expo-image-picker/build/ImagePicker.types";
 import React, { memo, useEffect, useState, useRef } from "react";
-import { ActivityIndicator, Dimensions, Image, Platform, SafeAreaView, Text, TextInput, TouchableOpacity, View, ImageSourcePropType, Share, KeyboardEventName, Keyboard, } from 'react-native';
+import { ActivityIndicator, Dimensions, Image, Platform, SafeAreaView, Text, TextInput, TouchableOpacity, View, ImageSourcePropType, Share, KeyboardEventName, Keyboard, StyleSheet } from 'react-native';
 import { ScrollView } from "react-native-gesture-handler";
 import Modal from 'react-native-modal';
 import Picker from 'react-native-picker-select';
@@ -21,7 +21,7 @@ import { Svg, Rect, Image as ImageSVG, Circle } from 'react-native-svg'
 import ReactDOMServer from 'react-dom/server'; //npm i --save-dev @types/react-dom
 
 import IndoorFloor from "../IndoorFloor";
-import ViewShot from "react-native-view-shot";
+import ViewShot, { captureRef, captureScreen } from "react-native-view-shot";
 
 /**
  * Props for the {@link AddLandmarkPanel} component.
@@ -66,7 +66,6 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
             const keyboardDidShowListener = Keyboard.addListener(
                 validEventString,
                 () => {
-                    console.log("Keyboard shown");
                   setKeyboardOpened(true); // or some other action
                 }
               );
@@ -89,7 +88,6 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
      */
      const determineModalHeight = () => {
         if (keyboardOpened) {
-            console.log('changing height')
             return Dimensions.get("window").height * .45
         }
         else if (photos?.length > 0) 
@@ -100,8 +98,8 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
     const capture: any = useRef();
 
     const imgWidth = 346
-    const imgHeight = 443
-    const imageDim = 27
+    const imgHeight = 448
+    const imageDim = 25
 
     useEffect(() => {
         /**
@@ -187,10 +185,20 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
      */
     const submit = async () => {
         if (typeof newLandmark.floor === 'number') {
-            // let imageURI = await capture.current.capture()
-            let imageURI = "string"
-            console.log("*AddLandmarkPanel* imageURI is " + imageURI)
-            await addLandmarkMutation.mutateAsync({ landmarkValue: newLandmark, photos: photos, indoorLmLocImg: imageURI })
+            try {
+                const uri = await captureRef(capture, {
+                    format: "jpg",
+                    quality: 1,
+                    result: 'base64'
+                })    
+
+                console.log("Image is", uri.substring(0, 100))
+                await addLandmarkMutation.mutateAsync({ landmarkValue: newLandmark, photos: photos, indoorLmLocImg: uri }); // pass it in here
+
+
+            } catch (error) {
+                console.error("Oops, snapshot failed", error)
+            }
         }
         else {
             await addLandmarkMutation.mutateAsync({ landmarkValue: newLandmark, photos: photos })
@@ -337,22 +345,35 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
             </SafeAreaView>
             <PhotoPicker multiple={true} menuType='alert' photoSourceMenuOpened={photoSourceMenuOpened} onReceivedPhotoResult={result => addPhoto(result)} cancel={() => togglePhotoSourceMenu(false)} />
 
-            {/* <View style={{position:'absolute', zIndex:-1}}>
-            <ViewShot ref={capture} options={{format:'jpg'}}>
-                <Svg>
-                    {renderIndoorLandmarkPin(newLandmark)}
-                    <IndoorFloor floorNum={newLandmark.floor} />
-                    Issue rn is that upon initial rendering, RN doesnt know what "newLandmark" is
 
-                    <ImageSVG x={100} y={100} width={imageDim} height={imageDim} href={lmTypes[2]['image'] as ImageSourcePropType} />
-                    <IndoorFloor floorNum={2} />
-                </Svg> 
+            <ViewShot style={{ width: imgWidth+20, height: imgHeight+20, position: 'absolute', right: -2000 }} ref={capture} >
+                {/* {console.log("newLandmark is " + newLandmark)} */}
+                {newLandmark == null || newLandmark.floor == null || newLandmark.landmark_type == null ? <></> :
+                    <View style={styles.container}>
+                        <Svg>
+                            {console.log("x coord is " + newLandmark.longitude + " and y coord is " + newLandmark.latitude)}
+                            <ImageSVG x={newLandmark.longitude*imgWidth-3} y={newLandmark.latitude*imgHeight-3} width={imageDim} height={imageDim} href={lmTypes[newLandmark.landmark_type]['image'] as ImageSourcePropType} />
+                            <IndoorFloor floorNum={newLandmark.floor} />
+                        </Svg>
+                    </View>
+                }
             </ViewShot>
-            </View> */}
-
-
         </Modal>
     )
 }
 
-export default memo(AddLandmarkPanel);
+const styles = StyleSheet.create({
+    container: {
+        aspectRatio: 8 / 10,  // (caters to portrait mode) (width is 80% the value of height dimension)
+        width: '100%',
+        height: '100%',
+        maxWidth: "100%",
+        maxHeight: "100%",
+        backgroundColor: "white",
+        padding:10
+    }
+})
+
+
+
+export default memo(AddLandmarkPanel);

+ 1 - 1
src/components/Profile/LoginView.tsx

@@ -14,12 +14,12 @@ import { useAuth } from "../../data/Auth/AuthContext";
 import { BaseStackNavigationProp } from "../../navigation/BaseStackNavigator";
 import { API_URL } from "../../utils/RequestUtils";
 import { GenericButton, PrimaryButton } from "../Buttons";
-import UnauthorizedLayout from "./AuthLayout";
 import { ProfileSectionHeader } from "./ProfileSections/ProfileSectionHeader";
 import * as Linking from 'expo-linking';
 import { BrowserLink, ProfileLegal } from "./ProfileSections/ProfileLegal";
 import { Separator } from "../Separator";
 import Collapsible from "react-native-collapsible";
+import UnauthorizedLayout from "./AuthLayout";
 
 /**
  * Props used by the {@link Intro} screen.

+ 63 - 12
src/navigation/MapNavigator.tsx

@@ -4,7 +4,7 @@ import { createNativeStackNavigator } from "@react-navigation/native-stack"
 import { StackNavigationProp } from "@react-navigation/stack"
 import { observer } from "mobx-react"
 import React, { useEffect, useState } from "react"
-import { Dimensions, Image, ScrollView, View } from "react-native"
+import { Alert, Dimensions, Image, ScrollView, View, Linking, Text } from "react-native"
 import { Chip } from "react-native-paper"
 import { IconButton } from "../components/Buttons"
 import IndoorMap from "../components/Map/MainMapComponent/IndoorMap"
@@ -19,6 +19,12 @@ import { Landmark, useLandmarks } from '../data/landmarks'
 import { colors, lmTypes, } from "../utils/GlobalUtils"
 import { MainTabsNavigationProp } from "./MainTabsNavigator"
 
+import { Menu, MenuItem, MenuDivider } from 'react-native-material-menu';
+import { navigate } from "./RootNavigator"
+import { Separator } from "../components/Separator"
+
+
+
 const MapStackNavigator = createNativeStackNavigator()
 
 export type MapStackParamList = {
@@ -39,10 +45,11 @@ const MapNavigator: React.FC = ({ }) => {
 
     // const currentRouteIndex = useNavigation().getState().routes[0].state.index
     // const currentRouteName = useNavigation().getState().routes[0].state.routeNames[currentRouteIndex]
-
     const navigationState = useNavigationState(state => state)
     const [currentRoute, setCurrentRoute] = useState<string>()
 
+    const [visible, setVisible] = useState(false);
+
     useEffect(() => {
         const currentRouteIndex = navigationState?.routes[0]?.state?.index
         const currentRouteName = navigationState?.routes[0]?.state?.routeNames[currentRouteIndex]
@@ -134,9 +141,7 @@ const MapNavigator: React.FC = ({ }) => {
                             setSelectedLandmarkId={mapState.setSelectedLandmarkId} />}
                 </MapStackNavigator.Screen>
 
-                <MapStackNavigator.Screen name="Indoor" listeners={{
-                    
-                }} >
+                <MapStackNavigator.Screen name="Indoor" >
                     {({ navigation }) =>
                         <IndoorMap
                             navigation={navigation}
@@ -147,15 +152,13 @@ const MapNavigator: React.FC = ({ }) => {
                         />}
                 </MapStackNavigator.Screen>
 
-
-
             </MapStackNavigator.Navigator>
 
 
 
             {/* Filter chips and button*/}
             {!mapState.filterVisible && currentRoute == 'Indoor' ?
-                <View style={{width:Dimensions.get("window").width*0.8 ,marginLeft:Dimensions.get("window").width*0.1, borderColor:"red" , borderWidth:0, bottom: 55, position: 'absolute', flexDirection: "row-reverse", justifyContent: 'flex-end' }}>
+                <View style={{ top: 60, right: 7.5 , position: 'absolute', flexDirection: "row-reverse", justifyContent: 'flex-end' }}>
                     <IconButton size={16} color={colors.red} style={[mapStyles.filterButtonIndoor]} icon="filter" onPress={() => mapState.toggleFilter(true)} />
                     <ScrollView horizontal={true} contentContainerStyle={{ alignItems: 'center' }} style={{ marginHorizontal: 10, flexDirection: 'row' }}>
                         {mapState.onlyOwned ? <Chip avatar={(<FontAwesome name="user" size={20} color='gray' style={{ textAlign: 'center', textAlignVertical: 'center' }} />)} style={{ borderWidth: 1, borderColor: 'lightgray', marginRight: 5, marginLeft: 10 }} onClose={() => mapState.toggleOnlyOwned(false)}>My landmarks</Chip> : null}
@@ -167,7 +170,7 @@ const MapNavigator: React.FC = ({ }) => {
                         {mapState.minLmRating > 0 ? <Chip avatar={(<FontAwesome name="star" size={20} color='gray' style={{ textAlign: 'center', textAlignVertical: 'center' }} />)} style={{ borderWidth: 1, borderColor: 'lightgray', marginLeft: 5, marginRight: 10 }} onClose={() => mapState.setMinLmRating(0)}>Minimum rating: {mapState.minLmRating}</Chip> : null}
                     </ScrollView>
                 </View>
-                 :
+                :
                 <View style={{ top: 10, marginLeft: 40, marginRight: 20, position: 'absolute', flexDirection: "row-reverse", justifyContent: 'flex-end' }}>
                     <IconButton size={20} color={colors.red} style={[mapStyles.filterButtonOutdoor]} icon="filter" onPress={() => mapState.toggleFilter(true)} />
                     <ScrollView horizontal={true} contentContainerStyle={{ alignItems: 'center' }} style={{ marginHorizontal: 10, flexDirection: 'row' }}>
@@ -180,10 +183,58 @@ const MapNavigator: React.FC = ({ }) => {
                         {mapState.minLmRating > 0 ? <Chip avatar={(<FontAwesome name="star" size={20} color='gray' style={{ textAlign: 'center', textAlignVertical: 'center' }} />)} style={{ borderWidth: 1, borderColor: 'lightgray', marginLeft: 5, marginRight: 10 }} onClose={() => mapState.setMinLmRating(0)}>Minimum rating: {mapState.minLmRating}</Chip> : null}
                     </ScrollView>
                 </View>
-                }
-  
+            }
+
+            {/* Create Hamburger icon */}
+            {currentRoute == 'Indoor' ?
+                <View style={{ top: 100, right: 7.5 , position: 'absolute', }}>
+                    <Menu
+                        visible={visible}
+                        anchor={<IconButton size={16} color={colors.red} style={[mapStyles.filterButtonIndoor]} icon="bars" onPress={() => setVisible(true)} />}
+                        onRequestClose={() => setVisible(false)}
+                    >
+                        <MenuItem onPress={() => {
+                            setVisible(false)
+                            navigate("Outdoor")
+                            // Alert.alert("Cameron Library")
+                        }}>Go back outdoors</MenuItem>
+
+                        <MenuItem onPress={() => {
+                            setVisible(false)
+                            Linking.openURL('https://www.ualberta.ca/facilities-operations/portfolio/emergency-management-office/emergency-procedures/alarms-evacuation.html')
+                            // Alert.alert("Cameron Library")
+                        }}>Resources</MenuItem>
+
+                    </Menu>
+                </View>
+                :
+                <View style={{ top: 60, right: 20, position: 'absolute', }}>
+                    <Menu
+                        visible={visible}
+                        anchor={<IconButton size={20} color={colors.red} style={[mapStyles.filterButtonOutdoor]} icon="bars" onPress={() => setVisible(true)} />}
+                        onRequestClose={() => setVisible(false)}
+                    >
+                        <MenuItem disabled={true} disabledTextColor='black' style={{alignItems: 'center', borderColor: 'black', borderBottomWidth: 1, marginHorizontal: 10, opacity: .7}}>
+                            <Text>Indoor buildings</Text>
+                        </MenuItem>
+                        <MenuItem onPress={() => {
+                            setVisible(false)
+                            navigate("Indoor")
+                            // Alert.alert("Cameron Library")
+                        }}>Cameron</MenuItem>
+
+                        <MenuDivider />
+                        <MenuItem disabled>More indoor maps on the way!</MenuItem>
+
+                    </Menu>
+
+                    {/* either "bars" or "list"  */}
+                </View>
+            }
+
+
 
-  {/* {!mapState.filterVisible ?
+            {/* {!mapState.filterVisible ?
                 <View style={{ top: 10, marginLeft: 40, marginRight: 20, position: 'absolute', flexDirection: "row-reverse", justifyContent: 'flex-end' }}>
                     <IconButton size={20} color={colors.red} style={[mapStyles.filterButton]} icon="filter" onPress={() => mapState.toggleFilter(true)} />
                     <ScrollView horizontal={true} contentContainerStyle={{ alignItems: 'center' }} style={{ marginHorizontal: 10, flexDirection: 'row' }}>

+ 1 - 1
src/navigation/RootNavigator.ts → src/navigation/RootNavigator.tsx

@@ -7,4 +7,4 @@ export function navigate(name, params?) {
   if (navigationRef.isReady()) {
     navigationRef.navigate(name as never, params as never);
   }
-}
+}

+ 6 - 1
src/utils/GlobalUtils.ts

@@ -28,7 +28,12 @@ export const lmTypes: {[key: number]: {image: ImageURISource, label: string}} =
     7: {image: require('../../assets/power.png'), label: "power issue"},
     8: {image: require('../../assets/crosswalk.png'), label: "crosswalk issue"},
     9: {image: require('../../assets/ice.png'), label: "ice"},
-    
+    10: {image: require('../../assets/desk.png'), label: "desk"},
+    11: {image: require('../../assets/elevator.png'), label: "elevator"},
+    12: {image: require('../../assets/kiosk.png'), label: "kiosk"},
+    13: {image: require('../../assets/monitor.png'), label: "monitor"},
+    14: {image: require('../../assets/ramp.png'), label: "ramp"},
+    15: {image: require('../../assets/water.png'), label: "water"},
 } 
 
 export const GlobalStyles = StyleSheet.create({

+ 2 - 2
src/utils/RequestUtils.ts

@@ -27,7 +27,7 @@ import Config from 'react-native-config'
 //export const API_URL = 'http://192.168.3.81:8000'
 // export const API_URL = 'https://staging.clicknpush.ca'
 
-// export const API_URL = 'http://192.168.3.162:8000'
-export const API_URL = 'http://192.168.3.102:8000'
+// export const API_URL = 'http://192.168.3.162:8000'   // Chase
+export const API_URL = 'http://192.168.3.102:8000'       // Eric
 
 // export const API_URL = Config.API_URL

+ 6 - 21
yarn.lock

@@ -4882,13 +4882,6 @@
   "resolved" "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz"
   "version" "2.2.0"
 
-"bindings@^1.5.0":
-  "integrity" "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="
-  "resolved" "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz"
-  "version" "1.5.0"
-  dependencies:
-    "file-uri-to-path" "1.0.0"
-
 "bl@^4.0.3", "bl@^4.1.0":
   "integrity" "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="
   "resolved" "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz"
@@ -8344,19 +8337,6 @@
   "resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
   "version" "1.0.0"
 
-"fsevents@^1.2.7":
-  "integrity" "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw=="
-  "resolved" "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz"
-  "version" "1.2.13"
-  dependencies:
-    "bindings" "^1.5.0"
-    "nan" "^2.12.1"
-
-"fsevents@^2.1.2", "fsevents@~2.3.2":
-  "integrity" "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="
-  "resolved" "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
-  "version" "2.3.2"
-
 "function-bind@^1.1.1":
   "integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
   "resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
@@ -11548,7 +11528,7 @@
     "object-assign" "^4.0.1"
     "thenify-all" "^1.0.0"
 
-"nan@^2.12.1", "nan@^2.14.2":
+"nan@^2.14.2":
   "integrity" "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ=="
   "resolved" "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz"
   "version" "2.15.0"
@@ -13976,6 +13956,11 @@
   dependencies:
     "@types/geojson" "^7946.0.7"
 
+"react-native-material-menu@^2.0.0":
+  "integrity" "sha512-SmO9PLE3E469EPbVWZqvdu6JGPPZIm7YjqDcWs2PPoY0k7w2V9tFo3BmmLXNzNZDCVCAi+PPSsL7h/5WkfHcSg=="
+  "resolved" "https://registry.npmjs.org/react-native-material-menu/-/react-native-material-menu-2.0.0.tgz"
+  "version" "2.0.0"
+
 "react-native-modal@^12.0.3":
   "integrity" "sha512-9myTNZ75gz6MPg1Cngm01x59JbaVkTeWoZvmChmW//PbSAdfbP/dFPnzbidL9IDrRh6Ftuuq8WSuM0aoS5m2lg=="
   "resolved" "https://registry.npmjs.org/react-native-modal/-/react-native-modal-12.1.0.tgz"