Browse Source

Merge branch 'global-alerts' of ericCNP:apps/atlas-mobile-ts into global-alerts

Eric Li 2 năm trước cách đây
mục cha
commit
02c1d89070

+ 48 - 1
ios/Podfile.lock

@@ -55,6 +55,15 @@ PODS:
     - ReactCommon/turbomodule/core (= 0.64.3)
   - filter_audio (0.5.0)
   - glog (0.3.5)
+  - libwebp (1.2.1):
+    - libwebp/demux (= 1.2.1)
+    - libwebp/mux (= 1.2.1)
+    - libwebp/webp (= 1.2.1)
+  - libwebp/demux (1.2.1):
+    - libwebp/webp
+  - libwebp/mux (1.2.1):
+    - libwebp/demux
+  - libwebp/webp (1.2.1)
   - Permission-Camera (3.1.0):
     - RNPermissions
   - Permission-LocationAccuracy (3.1.0):
@@ -351,6 +360,14 @@ PODS:
     - React-Core
   - RNCPicker (2.3.0):
     - React-Core
+  - RNDeviceInfo (8.6.0):
+    - React-Core
+  - RNFastImage (8.5.11):
+    - React-Core
+    - SDWebImage (~> 5.11.1)
+    - SDWebImageWebPCoder (~> 0.8.4)
+  - RNFS (2.19.0):
+    - React-Core
   - RNGestureHandler (1.10.3):
     - React-Core
   - RNPermissions (3.1.0):
@@ -387,8 +404,16 @@ PODS:
   - RNScreens (3.8.0):
     - React-Core
     - React-RCTImage
+  - RNSha256 (1.4.7):
+    - React
   - RNSVG (12.1.1):
     - React
+  - SDWebImage (5.11.1):
+    - SDWebImage/Core (= 5.11.1)
+  - SDWebImage/Core (5.11.1)
+  - SDWebImageWebPCoder (0.8.4):
+    - libwebp (~> 1.0)
+    - SDWebImage/Core (~> 5.10)
   - Spokestack-iOS (14.1.0):
     - filter_audio (~> 0.5.0)
     - TensorFlowLiteSwift (~> 2.3.0)
@@ -472,10 +497,14 @@ DEPENDENCIES:
   - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
   - "RNCCheckbox (from `../node_modules/@react-native-community/checkbox`)"
   - "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
+  - RNDeviceInfo (from `../node_modules/react-native-device-info`)
+  - RNFastImage (from `../node_modules/react-native-fast-image`)
+  - RNFS (from `../node_modules/react-native-fs`)
   - RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
   - RNPermissions (from `../node_modules/react-native-permissions`)
   - RNReanimated (from `../node_modules/react-native-reanimated`)
   - RNScreens (from `../node_modules/react-native-screens`)
+  - RNSha256 (from `../node_modules/react-native-sha256`)
   - RNSVG (from `../node_modules/react-native-svg`)
   - UMTaskManagerInterface (from `../node_modules/unimodules-task-manager-interface/ios`)
   - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -484,6 +513,9 @@ SPEC REPOS:
   trunk:
     - boost-for-react-native
     - filter_audio
+    - libwebp
+    - SDWebImage
+    - SDWebImageWebPCoder
     - Spokestack-iOS
     - TensorFlowLiteC
     - TensorFlowLiteSwift
@@ -621,6 +653,12 @@ EXTERNAL SOURCES:
     :path: "../node_modules/@react-native-community/checkbox"
   RNCPicker:
     :path: "../node_modules/@react-native-picker/picker"
+  RNDeviceInfo:
+    :path: "../node_modules/react-native-device-info"
+  RNFastImage:
+    :path: "../node_modules/react-native-fast-image"
+  RNFS:
+    :path: "../node_modules/react-native-fs"
   RNGestureHandler:
     :path: "../node_modules/react-native-gesture-handler"
   RNPermissions:
@@ -629,6 +667,8 @@ EXTERNAL SOURCES:
     :path: "../node_modules/react-native-reanimated"
   RNScreens:
     :path: "../node_modules/react-native-screens"
+  RNSha256:
+    :path: "../node_modules/react-native-sha256"
   RNSVG:
     :path: "../node_modules/react-native-svg"
   UMTaskManagerInterface:
@@ -664,6 +704,7 @@ SPEC CHECKSUMS:
   FBReactNativeSpec: 1a1323e59b9777f66cbec06bb2f568ce5f72abf6
   filter_audio: 1f071989c5a9ad0e0c9c45d08084513deb30d065
   glog: 73c2498ac6884b13ede40eda8228cb1eee9d9d62
+  libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
   Permission-Camera: 0db4fd6e1c556c1cf47f38b989a8084cea3ec3dd
   Permission-LocationAccuracy: f2fa6140c0362473a061b771dd1b702db581138c
   Permission-LocationAlways: f1e021c3b348946cd7c5760172925b749e5d07a6
@@ -705,11 +746,17 @@ SPEC CHECKSUMS:
   ReactCommon: 8fea6422328e2fc093e25c9fac67adbcf0f04fb4
   RNCCheckbox: 6bd119c26c6eb8264a29d59ff66cb70a14de3349
   RNCPicker: c796ddf16cd93e980a5a5642eebcee9eb9da1e76
+  RNDeviceInfo: 7257d02f4ec94882c309c987cf42f3588d85103e
+  RNFastImage: 1f2cab428712a4baaf78d6169eaec7f622556dd7
+  RNFS: fc610f78fdf8bfc89a9e5cc2f898519f4dba1002
   RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
   RNPermissions: 4b54095940aea8c03fa3e6c92d4ac3647b31ed4e
   RNReanimated: 241c586663f44f19a53883c63375fdd041253960
   RNScreens: 6e1ea5787989f92b0671049b808aef64fa1ef98c
+  RNSha256: bf2c90a9e0cec6dcbcc4100e4e19715ae7feaa34
   RNSVG: 551acb6562324b1d52a4e0758f7ca0ec234e278f
+  SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
+  SDWebImageWebPCoder: f93010f3f6c031e2f8fb3081ca4ee6966c539815
   Spokestack-iOS: 090ed0e757276f2407beec82fa851ec3e408b5b9
   TensorFlowLiteC: 51f50caf5777f740a70e2c1a5dbdc149e7aeb50b
   TensorFlowLiteSwift: fb152cc1eec36b25b03a23c07f5d58113170af58
@@ -718,4 +765,4 @@ SPEC CHECKSUMS:
 
 PODFILE CHECKSUM: 36a2eb9184cd7de694ef4e992701e848c207fffb
 
-COCOAPODS: 1.11.2
+COCOAPODS: 1.11.3

+ 14 - 0
ios/cnpmobile.xcodeproj/project.pbxproj

@@ -299,10 +299,14 @@
 				"${BUILT_PRODUCTS_DIR}/RCTTypeSafety/RCTTypeSafety.framework",
 				"${BUILT_PRODUCTS_DIR}/RNCCheckbox/RNCCheckbox.framework",
 				"${BUILT_PRODUCTS_DIR}/RNCPicker/RNCPicker.framework",
+				"${BUILT_PRODUCTS_DIR}/RNDeviceInfo/RNDeviceInfo.framework",
+				"${BUILT_PRODUCTS_DIR}/RNFS/RNFS.framework",
+				"${BUILT_PRODUCTS_DIR}/RNFastImage/RNFastImage.framework",
 				"${BUILT_PRODUCTS_DIR}/RNGestureHandler/RNGestureHandler.framework",
 				"${BUILT_PRODUCTS_DIR}/RNReanimated/RNReanimated.framework",
 				"${BUILT_PRODUCTS_DIR}/RNSVG/RNSVG.framework",
 				"${BUILT_PRODUCTS_DIR}/RNScreens/RNScreens.framework",
+				"${BUILT_PRODUCTS_DIR}/RNSha256/RNSha256.framework",
 				"${BUILT_PRODUCTS_DIR}/React-Core/React.framework",
 				"${BUILT_PRODUCTS_DIR}/React-CoreModules/CoreModules.framework",
 				"${BUILT_PRODUCTS_DIR}/React-RCTAnimation/RCTAnimation.framework",
@@ -319,8 +323,11 @@
 				"${BUILT_PRODUCTS_DIR}/React-jsinspector/jsinspector.framework",
 				"${BUILT_PRODUCTS_DIR}/React-perflogger/reactperflogger.framework",
 				"${BUILT_PRODUCTS_DIR}/ReactCommon/ReactCommon.framework",
+				"${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
+				"${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder/SDWebImageWebPCoder.framework",
 				"${BUILT_PRODUCTS_DIR}/Yoga/yoga.framework",
 				"${BUILT_PRODUCTS_DIR}/glog/glog.framework",
+				"${BUILT_PRODUCTS_DIR}/libwebp/libwebp.framework",
 				"${BUILT_PRODUCTS_DIR}/react-native-config/react_native_config.framework",
 				"${BUILT_PRODUCTS_DIR}/react-native-get-random-values/react_native_get_random_values.framework",
 				"${BUILT_PRODUCTS_DIR}/react-native-maps/react_native_maps.framework",
@@ -337,10 +344,14 @@
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTTypeSafety.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNCCheckbox.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNCPicker.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNDeviceInfo.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNFS.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNFastImage.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNGestureHandler.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNReanimated.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNSVG.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNScreens.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNSha256.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CoreModules.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTAnimation.framework",
@@ -357,8 +368,11 @@
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsinspector.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/reactperflogger.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactCommon.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageWebPCoder.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libwebp.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_config.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_get_random_values.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/react_native_maps.framework",

+ 40 - 0
package-lock.json

@@ -61,10 +61,12 @@
         "react-native-device-info": "^8.6.0",
         "react-native-dialog": "^9.2.0",
         "react-native-dotenv": "^3.3.0",
+        "react-native-fast-image": "^8.5.11",
         "react-native-fs": "^2.19.0",
         "react-native-gesture-handler": "~1.10.2",
         "react-native-get-random-values": "~1.7.0",
         "react-native-maps": "0.29.3",
+        "react-native-maps-directions": "^1.8.0",
         "react-native-material-menu": "^2.0.0",
         "react-native-modal": "^12.0.3",
         "react-native-multi-selectbox": "^1.5.0",
@@ -24988,6 +24990,15 @@
         "node": ">=10"
       }
     },
+    "node_modules/react-native-fast-image": {
+      "version": "8.5.11",
+      "resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-8.5.11.tgz",
+      "integrity": "sha512-cNW4bIJg3nvKaheG8vGMfqCt5LMWX9MS5+wMudgKIHbGO51spRr4sgnlhVgwHLcZ5aeNOVJ8CPRxDIWKRq/0QA==",
+      "peerDependencies": {
+        "react": "^16.8.6 || ^17.0.0",
+        "react-native": ">=0.60.0"
+      }
+    },
     "node_modules/react-native-fs": {
       "version": "2.19.0",
       "resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.19.0.tgz",
@@ -25064,6 +25075,20 @@
         "react-native-web": "^0.13"
       }
     },
+    "node_modules/react-native-maps-directions": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/react-native-maps-directions/-/react-native-maps-directions-1.8.0.tgz",
+      "integrity": "sha512-7KWfPrvPLU8VP2nEqsnrWlOuylidlRWWDdk3lqT5Nb1q87FeyzNgA7Ib7n6cZlQwH4usTRlJSnzNo/yQ3u4AZw==",
+      "dependencies": {
+        "lodash.isequal": "^4.5.0",
+        "prop-types": "^15.6.0"
+      },
+      "peerDependencies": {
+        "react": "*",
+        "react-native": "*",
+        "react-native-maps": ">=0.12.1"
+      }
+    },
     "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",
@@ -51192,6 +51217,12 @@
         }
       }
     },
+    "react-native-fast-image": {
+      "version": "8.5.11",
+      "resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-8.5.11.tgz",
+      "integrity": "sha512-cNW4bIJg3nvKaheG8vGMfqCt5LMWX9MS5+wMudgKIHbGO51spRr4sgnlhVgwHLcZ5aeNOVJ8CPRxDIWKRq/0QA==",
+      "requires": {}
+    },
     "react-native-fs": {
       "version": "2.19.0",
       "resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.19.0.tgz",
@@ -51251,6 +51282,15 @@
         "@types/geojson": "^7946.0.7"
       }
     },
+    "react-native-maps-directions": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/react-native-maps-directions/-/react-native-maps-directions-1.8.0.tgz",
+      "integrity": "sha512-7KWfPrvPLU8VP2nEqsnrWlOuylidlRWWDdk3lqT5Nb1q87FeyzNgA7Ib7n6cZlQwH4usTRlJSnzNo/yQ3u4AZw==",
+      "requires": {
+        "lodash.isequal": "^4.5.0",
+        "prop-types": "^15.6.0"
+      }
+    },
     "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",

+ 1 - 0
package.json

@@ -79,6 +79,7 @@
     "react-native-device-info": "^8.6.0",
     "react-native-dialog": "^9.2.0",
     "react-native-dotenv": "^3.3.0",
+    "react-native-fast-image": "^8.5.11",
     "react-native-fs": "^2.19.0",
     "react-native-gesture-handler": "~1.10.2",
     "react-native-get-random-values": "~1.7.0",

+ 32 - 0
src/components/LandmarkTypePicker.tsx

@@ -0,0 +1,32 @@
+import React from 'react'
+import Picker, { Item } from 'react-native-picker-select'
+import { FontAwesome } from "@expo/vector-icons";
+
+interface LandmarkTypePickerProps {
+    onValueChange: (value: any, index: number) => void,
+    value?: any,
+    items: Item[],
+    placeholder?: {} | Item 
+}
+
+const LandmarkTypePicker: React.FC<LandmarkTypePickerProps> = ({items, value, onValueChange, placeholder}) => {
+    return (
+    <Picker
+        style={{
+            inputIOS: { color: 'white' },
+            inputAndroid: { color: 'white', alignItems: 'center', justifyContent: 'center' },
+            viewContainer: { marginVertical: 5, flex: 1}, 
+            iconContainer: { height: '100%', justifyContent: 'center' },
+            placeholder: { color: 'white' }
+        }}
+        textInputProps={{ placeholderTextColor: 'white', selectionColor: 'white' }}
+        Icon={() => <FontAwesome name="chevron-down" color='white' style={{alignSelf: 'center'}} size={20} />}
+        placeholder={placeholder}
+        value={value}
+        onValueChange={onValueChange}
+        useNativeAndroidPickerStyle={true}
+        items={items}
+    />)
+}
+
+export default React.memo(LandmarkTypePicker)

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

@@ -44,6 +44,9 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
   const imageDim = 0.05 * Dimensions.get("window").width;
 
   const loadLandmarks = applyFilter(landmarks)?.map((item) => {
+    if (!lmTypesIndoor[item.landmark_type]) {
+      return null
+    }
     if (item.floor == floor && SVGdim[0] != 1 && SVGdim[1] != 1) {
       return (
         <Image
@@ -53,7 +56,7 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
           y={item.latitude * SVGdim[1]}
           width={imageDim}
           height={imageDim}
-          href={lmTypesIndoor[item.landmark_type]['image'] as ImageSourcePropType} />
+          href={lmTypesIndoor[item.landmark_type].image as ImageSourcePropType} />
       )
     }
   }

+ 0 - 3
src/components/Map/MainMapComponent/OutdoorMap.tsx

@@ -27,9 +27,6 @@ import { VoicePanel } from "../Panels/VoicePanel";
 import mapStyles from "./Map.styles";
 import { useOutdoorMapState } from "./useMapState";
 
-import MapViewDirections from 'react-native-maps-directions';
-
-
 /**
  * An interface representing the user location retrieved from [expo-location]{@link https://docs.expo.dev/versions/latest/sdk/location/}.
  * @category Map

+ 5 - 14
src/components/Map/Panels/AddLandmarkPanel.tsx

@@ -13,7 +13,7 @@ import { ScrollView } from "react-native-gesture-handler";
 import Modal from 'react-native-modal';
 import Picker from 'react-native-picker-select';
 import { Landmark, LMPhoto, useAddLandmark } from "../../../data/landmarks";
-import { colors, lmTypes, lmTypes as lmTypess, lmTypesIndoor } from "../../../utils/GlobalUtils";
+import { colors, lmTypes as allLmTypes, lmTypesIndoor } from "../../../utils/GlobalUtils";
 import { IconButton, SecondaryButton } from "../../Buttons";
 import { PhotoPicker } from "../../PhotoPicker";
 import TouchOpaq from "./LandmarkDetailsPanel/TouchOpaq";
@@ -25,6 +25,7 @@ import IndoorFloor from "../IndoorFloor";
 import ViewShot, { captureRef, captureScreen } from "react-native-view-shot";
 
 import { useNavigationState } from "@react-navigation/native"
+import LandmarkTypePicker from "../../LandmarkTypePicker";
 
 
 /**
@@ -114,7 +115,7 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
     const imgHeight = 448
     const imageDim = 25
     
-    let lmTypes = lmTypess
+    let lmTypes = allLmTypes
     if(currentRoute=="Indoor") {
         lmTypes = lmTypesIndoor
     }
@@ -248,14 +249,7 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
                                         {newLandmark?.description}
                                     </TextInput>
                                     <View style={{ flexDirection: 'row' }}>
-                                        <Picker
-                                            style={{
-                                                inputIOS: { color: 'white' },
-                                                inputAndroid: { color: 'white' },
-                                                viewContainer: { marginVertical: 5, flex: 1 }, placeholder: { color: 'white' }
-                                            }}
-                                            textInputProps={{ placeholderTextColor: 'white', selectionColor: 'white' }}
-                                            Icon={() => <FontAwesome name="chevron-down" color='white' size={20} />}
+                                        <LandmarkTypePicker 
                                             placeholder={{ label: "Select a landmark type...", value: 0 }}
                                             value={newLandmark?.landmark_type}
                                             onValueChange={(value) => {
@@ -266,17 +260,14 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({ newLandmark, setNewLandm
                                                     setNewLandmark({ ...newLandmark, landmark_type: undefined, title: 'no title' })
                                                 }
                                             }}
-                                            useNativeAndroidPickerStyle={true}
                                             items={Object.keys(lmTypes)?.map(icon => {
                                                 return (
                                                     { label: lmTypes[parseInt(icon)]?.label.toUpperCase(), value: icon, key: icon }
                                                 )
-                                            })}
-                                        />
+                                            })}/>
 
                                         {newLandmark?.landmark_type ? <Image style={{ marginLeft: 20 }} source={lmTypes[newLandmark.landmark_type].image} />
                                             : null}
-                                            <Text>{currentRoute=="Indoor" ? "INDOOR" : "OUTDOOR"}</Text>
                                     </View>
                                 </View>
                                 {newLandmark?.landmark_type ?

+ 2 - 2
src/components/Map/Panels/FilterPanel/FilterPanel.tsx

@@ -120,9 +120,9 @@ export const FilterPanel: React.FC<FilterPanelProps> = (props) => {
 
     const OwnedFilter: React.FC = () => {
         return (
-            <View style={{flexDirection: 'row', alignItems: 'center', marginBottom: 10}} >
+            <View style={{flexDirection: 'row', paddingTop: 10, paddingBottom: 15}} >
                 <Text>Only show my landmarks:</Text>
-                <Checkbox value={localOwned} onValueChange={() => toggleLocalOwned(!localOwned)} boxType="square" style={{marginLeft: 20, width: 25, height: 25, marginBottom:10}} />
+                <Checkbox value={localOwned} onValueChange={() => toggleLocalOwned(!localOwned)} boxType="square" style={{marginLeft: 10, width: 20, height: 20}} />
             </View>
         )
     }

+ 12 - 21
src/components/Map/Panels/LandmarkDetailsPanel/DetailsBody.tsx

@@ -6,22 +6,20 @@
  */
 
 import { FontAwesome } from "@expo/vector-icons";
-import { ImageInfo } from "expo-image-picker/build/ImagePicker.types";
+import { useNavigationState } from "@react-navigation/native";
 import React, { MutableRefObject, useEffect, useState } from "react";
-import { ActivityIndicator, FlatList, Image, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View } from "react-native";
+import { FlatList, Image, ScrollView, StyleSheet, Text, TextInput, View } from "react-native";
 import Picker from "react-native-picker-select";
 import { QueryStatus } from "react-query";
 import { LMComment } from "../../../../data/comments";
 import { Landmark, LMPhoto } from "../../../../data/landmarks";
 import { MainTabsNavigationProp } from "../../../../navigation/MainTabsNavigator";
-import { lmTypes as lmTypess , lmTypesIndoor } from "../../../../utils/GlobalUtils";
-import { IconButton, PrimaryButton } from "../../../Buttons";
-import { PhotoPicker } from "../../../PhotoPicker";
+import { lmTypes as allLmTypes, lmTypesIndoor } from "../../../../utils/GlobalUtils";
+import LandmarkTypePicker from "../../../LandmarkTypePicker";
 import { Separator } from "../../../Separator";
 import { CommentsContainer } from "./CommentsContainer";
 import { LandmarkPhotos } from "./LandmarkPhotos";
 
-import { useNavigationState } from "@react-navigation/native"
 
 
 interface DetailsBodyProps {
@@ -70,7 +68,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
     }, [navigationState])
 
 
-    let lmTypes = lmTypess
+    let lmTypes = allLmTypes
     if(currentRoute=="Indoor") {
         lmTypes = lmTypesIndoor
     }
@@ -90,28 +88,21 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
      * Sub-component that renders picker for landmark types
      * @param 
      */
-    const LandmarkTypePicker: React.FC = () => {
+    const LandmarkTypePickerContainer: React.FC = () => {
         return (
         <View style={{flexDirection: 'row', marginBottom: 20, justifyContent: "space-between"}}>
             {props.updatedLandmark?.landmark_type ? 
             <>
-                <Picker
-                    style={{
-                        inputIOS: {color: 'white', textAlignVertical: 'center'}, 
-                        inputAndroid: {color: 'white', textAlignVertical: 'center'},
-                        iconContainer: {flex: 1, justifyContent: 'center', height: '100%'},
-                        viewContainer: {padding: 5, elevation: 1, flex: 1, justifyContent: 'center'}, placeholder: {color: 'white'}}}
+                <LandmarkTypePicker 
                     placeholder={{}}
-                    Icon={() => <FontAwesome name="chevron-down" color='white' size={20} />}
-                    value={props.updatedLandmark?.landmark_type}
+                    value={props.updatedLandmark?.landmark_type} 
                     onValueChange={(value) => {
                         props.setUpdatedLandmark({...props.updatedLandmark, landmark_type: value, title: lmTypes[value].label})
-                    }}
-                    useNativeAndroidPickerStyle={true}
+                    }}  
                     items={Object.keys(lmTypes)?.filter(icon => parseInt(icon) != props.landmark?.landmark_type).map(icon => {
                         return (
                             {label: lmTypes[parseInt(icon)].label.toUpperCase(), value: icon, key: icon}
-                        )})} />
+                        )})}/>
                 {props.updatedLandmark ? <Image style={{marginLeft: 20}} source={lmTypes[props.updatedLandmark?.landmark_type].image}/> : null}
             </>
             : null}
@@ -132,7 +123,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
                         <Text style={{color: 'white', fontSize: 13}}>{props.landmark?.description}</Text>
                     </ScrollView>
                 </View>
-                {props.landmark?.landmark_type ? <Image source={lmTypes[props.landmark?.landmark_type].image} /> : null}
+                {props.landmark?.landmark_type ? <Image source={lmTypes[props.landmark?.landmark_type]?.image} /> : null}
             </View>
         )
     }
@@ -141,7 +132,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
         <ScrollView nestedScrollEnabled={true} contentContainerStyle={{justifyContent: 'space-between'}} style={{flex: 1, marginHorizontal: 20}}>
             {props.editingEnabled ?
             <>
-                <LandmarkTypePicker />
+                <LandmarkTypePickerContainer />
                 <Separator style={{marginBottom: 20, opacity: .5}} color="lightgray" />
                 <Text style={{color: 'white', marginBottom: 10}}>Description</Text>
                 {/* {console.log("*DETAILS BODY: currentRotue is " + currentRoute)} */}

+ 14 - 17
src/components/Map/Panels/VoicePanel.tsx

@@ -7,8 +7,9 @@
 
 import { FontAwesome } from '@expo/vector-icons';
 import * as Linking from "expo-linking";
-import React, { useEffect, useState } from 'react';
-import { ActivityIndicator, AppState, FlatList, Image, ImageURISource, KeyboardAvoidingView, Text, TouchableOpacity, View, ViewStyle } from 'react-native';
+import FastImage, {} from 'react-native-fast-image'
+import React, { useEffect, useMemo, useRef, useState } from 'react';
+import { ActivityIndicator, AppState, FlatList, Image, ImageRequireSource, ImageURISource, KeyboardAvoidingView, Text, TouchableOpacity, View, ViewStyle } from 'react-native';
 import { Pulse, Wave } from 'react-native-animated-spinkit';
 import Config from 'react-native-config';
 import Modal from "react-native-modal";
@@ -202,8 +203,8 @@ export const VoicePanel: React.FC<VoicePanelProps> = ({
                     }
                     else {
                         // otherwise give the user another chance to speak
-                        setListening(true)
-                        await Spokestack.activate()
+                        // setListening(true)
+                        // await Spokestack.activate()
                     }
                 }
             }
@@ -230,7 +231,7 @@ export const VoicePanel: React.FC<VoicePanelProps> = ({
         }
         // handle unrecognized result
         else {
-            await Spokestack.activate();
+            //await Spokestack.activate();
         }
     }
 
@@ -416,17 +417,13 @@ export const VoicePanel: React.FC<VoicePanelProps> = ({
         await Spokestack.activate()
     }
 
-    const back = async () => {
-        setAction({...action, actionStep: action.actionStep - 1})
-    }
-
-    const LmTypeDisplay: React.FC<{lmType: {image: ImageURISource, label:string}, style?: ViewStyle}> = ({lmType, style}) => {
-        return (
+    const LmTypeDisplay: React.FC<{lmType: {image: ImageRequireSource, label:string}, style?: ViewStyle}> = ({lmType, style}) => {
+        return useMemo(() => (
             <View style={[{marginVertical: 5, flexDirection: 'row'}, style]}>  
-                <Image style={{height: 25, width: 18}} source={lmType.image} />
+                <FastImage style={{height: 25, width: 18}} source={lmType.image} />
                 <Text style={{fontSize: 15, marginLeft: 10, textAlign: 'center', color: 'white'}}>{lmType.label}</Text>
             </View>
-        )
+        ), [lmType])
     }
 
     const ActionOptions: React.FC<{currentAction?: VoiceAction}> = ({currentAction}) => {
@@ -444,12 +441,12 @@ export const VoicePanel: React.FC<VoicePanelProps> = ({
                                     <Text style={{fontSize: 17, margin: 20, color: 'white'}}>Choose from the available types: </Text> 
                                     <FlatList 
                                         style={{marginBottom: 20, marginHorizontal:20}}
-                                        data={Object.keys(lmTypes).map(typeId => typeId)}
+                                        data={Object.values(lmTypes).map(value => {return {label: value.label, image: value.image}})}
                                         numColumns={2}
-                                        keyExtractor={item => item}
-                                        renderItem={(item => {
+                                        keyExtractor={(item) => item.label}
+                                        renderItem={((item) => {
                                             return (
-                                                <LmTypeDisplay key={item.item} lmType={lmTypes[item.item]} style={{flexBasis: '50%'}} />
+                                                <LmTypeDisplay key={item.item.label} lmType={item.item} style={{flexBasis: '50%'}} />
                                             )})} />
                                 </View>
                             )

+ 2 - 1
src/data/Auth/AuthContext.tsx

@@ -197,7 +197,7 @@ export const AuthContextProvider: React.FC = ({children}) => {
         if (authorized && !axiosConfig?.headers?.Authorization) {
             axiosConfig.headers = {
                 ...axiosConfig.headers,
-                Authorization: `Bearer ${accessToken}`
+                Authorization: `Bearer ${accessToken}`,
             }   
         }
 
@@ -206,6 +206,7 @@ export const AuthContextProvider: React.FC = ({children}) => {
         try {
             return await axios(axiosConfig)
         } catch (error) {
+            console.log(error.response.request._headers)
             reportAxiosError(errorMessage, error)
         }
     }

+ 10 - 5
src/data/landmarks.ts

@@ -120,6 +120,7 @@ export const useAddLandmark = () => {
 
     const createLandmark = async (data: {landmarkValue: Landmark | undefined, photos?: LMPhoto[], indoorLmLocImg?: string}): Promise<Landmark | undefined> => {
         if (data.landmarkValue) {
+            console.log("user id is: " + userId)
             if (userId) {
                 data.landmarkValue.user = userId
             } else if (anonUserId) {
@@ -140,7 +141,7 @@ export const useAddLandmark = () => {
                         indoorLmLocImg: data.indoorLmLocImg
                     },
                 },
-                authorized: false,
+                authorized: true,
                 errorMessage: "Something went wrong when creating a landmark"
             });   
             return response?.data;
@@ -177,7 +178,7 @@ export const useEditLandmark = () => {
 
             const response = await sendApiRequestAsync({
                 axiosConfig: config, 
-                authorized: false,
+                authorized: true,
                 errorMessage: 'Something went wrong when updating a landmark'
             });   
             return response?.data;
@@ -228,7 +229,7 @@ export const useDeleteLandmark = () => {
         if (id) {
             const config: AxiosRequestConfig = {
                 method: 'DELETE',
-                url: `/api/landmark/${id}`,
+                url: `/api/landmark/${id}/`,
             }
 
             if (!accessToken) config.data = {...config.data, anonymous: anonUserId}
@@ -237,7 +238,7 @@ export const useDeleteLandmark = () => {
 
             const response = await sendApiRequestAsync({
                 axiosConfig: config,
-                authorized: !!accessToken,
+                authorized: true,
                 errorMessage: 'Something went wrong when deleting a landmark'
             });   
             return response?.data;
@@ -264,6 +265,8 @@ export const useAddLandmarkPhoto = () => {
         
             if (!accessToken) config.data = {...config.data, anonymous: anonUserId}
 
+            console.log(accessToken)
+
             const response = await sendApiRequestAsync({
                 axiosConfig: config, 
                 authorized: true,
@@ -292,13 +295,15 @@ export const useDeleteLandmarkPhoto = () => {
         if (photoId) {
             const config: AxiosRequestConfig = {
                 method: 'DELETE',
-                url: `/api/landmark/photos/${photoId}`
+                url: `/api/landmark/photos/${photoId}/`
             }
 
             if (!accessToken) {
                 config.data = {...config.data, anonymous: anonUserId}
             }
 
+            console.log(accessToken)
+
             const response = await sendApiRequestAsync({
                 axiosConfig: config,
                 authorized: true,

+ 2 - 4
src/navigation/MapNavigator.tsx

@@ -35,7 +35,7 @@ export type MapStackParamList = {
 export type MapStackNavigationProp = StackNavigationProp<MapStackParamList>
 
 const MapNavigator: React.FC = ({ }) => {
-    const { userId, anonUserId } = useAuth()
+    const { landmarkOwnedByUser } = useAuth()
     const mapState = useMapState()
     const authNavigation = useNavigation() as MainTabsNavigationProp
     const authRoute = useRoute() as AuthTabsMapRouteProp
@@ -68,7 +68,6 @@ const MapNavigator: React.FC = ({ }) => {
     useEffect(() => {
         const refetchLandmarksOnFilterOptionsChange = async () => {
             applyFilters(landmarksQuery?.data)
-            console.log('[Map]: Filters changed')
         }
         refetchLandmarksOnFilterOptionsChange()
     }, [mapState.lmFilteredTypes, mapState.onlyOwned, mapState.minLmRating])
@@ -84,7 +83,7 @@ const MapNavigator: React.FC = ({ }) => {
             }
 
             if (mapState.onlyOwned) {
-                landmarks = landmarks?.filter(lm => lm.user == userId || lm.anonymous == anonUserId);
+                landmarks = landmarks?.filter(lm => landmarkOwnedByUser(lm));
             }
         }
 
@@ -121,7 +120,6 @@ const MapNavigator: React.FC = ({ }) => {
     return (
         <View style={{ flex: 1 }}>
             <MapStackNavigator.Navigator screenOptions={{ headerShown: false }} initialRouteName="Outdoor">
-
                 <MapStackNavigator.Screen name="Outdoor" >
                     {({ navigation }) =>
                         <OutdoorMap

+ 3 - 3
src/utils/GlobalUtils.ts

@@ -5,7 +5,7 @@
  * <dev@clicknpush.ca>, January 2022
  */
 
-import { Alert, ImageURISource, Permission, Platform, StyleSheet, View } from "react-native";
+import { Alert, ImageRequireSource, ImageURISource, Permission, Platform, StyleSheet, View } from "react-native";
 import { checkMultiple, PERMISSIONS, requestMultiple, RESULTS, } from "react-native-permissions";
 
 // global constants
@@ -18,7 +18,7 @@ export const SECURESTORE_REFRESHTOKEN = "refresh"
 export const SECURESTORE_NOTIFTOKEN = 'notif'
 export const SECURESTORE_IDTOKEN = 'id'
 
-export const lmTypes: {[key: number]: {image: ImageURISource, label: string}} = {
+export const lmTypes: {[key: number]: {image: ImageRequireSource, label: string}} = {
     // 1: {image: require('../../assets/uneven.png'), label: "rough terrain"}, not currently in use
     2: {image: require('../../assets/stairs.png'), label: "stairs"},
     3: {image: require('../../assets/barrier.png'), label: "barrier"},
@@ -32,7 +32,7 @@ export const lmTypes: {[key: number]: {image: ImageURISource, label: string}} =
     16: {image: require('../../assets/childfriendly.png'), label: "child friendly area"},
 }
 
-export const lmTypesIndoor: {[key: number]: {image: ImageURISource, label: string}} = {
+export const lmTypesIndoor: {[key: number]: {image: ImageRequireSource, label: string}} = {
     2: {image: require('../../assets/stairs.png'), label: "stairs"},
     5: {image: require('../../assets/information.png'), label: "information"},
     6: {image: require('../../assets/washroom.png'), label: "accessible washroom"},

+ 2 - 2
src/utils/RequestUtils.ts

@@ -25,8 +25,8 @@ 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.102:8001'   // Chase
-export const API_URL = 'http://192.168.0.22:8000'       // Eric
+export const API_URL = 'http://192.168.3.102:8000'   // Chase
+//export const API_URL = 'http://192.168.0.22:8000'       // Eric
 //export const API_URL = 'https://app.clicknpush.ca'
 
 // export const API_URL = Config.API_URL

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 345 - 338
yarn.lock


Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác