Jelajahi Sumber

non account landmark photos, other polish items

chase 2 tahun lalu
induk
melakukan
6a41bdec98

+ 11 - 1
src/components/Buttons.tsx

@@ -7,7 +7,7 @@
 
 import { FontAwesome } from "@expo/vector-icons";
 import React from "react";
-import { StyleProp, StyleSheet, Text, TouchableOpacity, ViewStyle } from "react-native";
+import { Pressable, StyleProp, StyleSheet, Text, TouchableOpacity, ViewStyle } from "react-native";
 import { colors } from "../utils/GlobalUtils";
 
 interface ButtonProps {
@@ -55,6 +55,16 @@ export const IconButton: React.FC<IconButtonProps> = ({onPress, style, size, col
     )
 }
 
+export const GenericButton: React.FC<TextButtonProps> = ({onPress, style, text}) => {
+    const [isPressed, setIsPressed] = React.useState(false);
+
+    return (
+        <Pressable style={[style, { backgroundColor: isPressed ? '#D3D3D3' : 'white'}]} onPress={onPress} onPressIn={() => setIsPressed(true)} onPressOut={() => setIsPressed(false)}>
+            <Text style={{color: 'black', }}>{text}</Text>
+        </Pressable>
+    )
+}
+
 const styles = StyleSheet.create({
     btn: {
         borderRadius: 50,

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

@@ -89,9 +89,6 @@ const OutdoorMap: React.FC<OutdoorMapProps> = (props) => {
         console.log(toMap)
 
         if (toMap) mapState.setLoading(true)
-        else {
-            flyToUser()
-        }
 
         setTimeout(() => {
             console.log("stop loading")

+ 2 - 1
src/components/Map/Panels/LandmarkDetailsPanel/CommentsContainer.tsx

@@ -32,6 +32,7 @@ interface CommentsContainerProps {
     setKeyboardOpened: (state: boolean) => void
     keyboardOpened: boolean
     authNavigation: MainTabsNavigationProp
+    toggleLmDetails: (state: boolean) => void
 }
 
 /**
@@ -104,7 +105,7 @@ export const CommentsContainer: React.FC<CommentsContainerProps> = (props) => {
         </View>
         </> : 
         <View>
-            <SecondaryButton text="Login to add comments" onPress={() => {console.log(props.authNavigation); props.authNavigation.navigate("Account")}} style={{marginBottom: 20}}/>
+            <SecondaryButton text="Login to add comments" onPress={() => {props.toggleLmDetails(false); props.authNavigation.navigate("Account")}} style={{marginBottom: 20}}/>
         </View>}
     </View>)
 }

+ 2 - 1
src/components/Map/Panels/LandmarkDetailsPanel/DetailsBody.tsx

@@ -136,6 +136,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
             </>: <EditingDisabledUpperView />}
             {!props.editingEnabled ?
             <CommentsContainer
+                toggleLmDetails={props.toggleLmDetails}
                 authNavigation={props.authNavigation}
                 setKeyboardOpened={props.setKeyboardOpened}
                 keyboardOpened={props.keyboardOpened}
@@ -152,7 +153,7 @@ export const DetailsBody: React.FC<DetailsBodyProps> = (props) => {
                 editComment={props.editComment}
                 startEditingComment={props.startEditingComment}
                 deleteComment={props.deleteComment} /> : null}
-            {!props.editingEnabled ?
+            {!props.editingEnabled && !props.keyboardOpened ?
             <LandmarkPhotos 
                 profileId={props.profileId}
                 deletePhotoStatus={props.deletePhotoStatus}

+ 6 - 3
src/components/Map/Panels/LandmarkDetailsPanel/DetailsHeader.tsx

@@ -7,7 +7,7 @@
 
 import { FontAwesome } from "@expo/vector-icons";
 import React from "react";
-import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
+import { Alert, StyleSheet, Text, TouchableOpacity, View } from "react-native";
 import { QueryStatus } from "react-query";
 import { useAuth } from "../../../../data/Auth/AuthContext";
 import { Landmark } from "../../../../data/landmarks";
@@ -35,7 +35,7 @@ interface DetailsHeaderProps {
  * @param 
  */
 export const DetailsHeader: React.FC<DetailsHeaderProps> = (props) => {
-    const {landmarkOwnedByUser} = useAuth()
+    const {landmarkOwnedByUser, anonUserId} = useAuth()
 
     const photosAreBusy = () => {
         return props.processingPhoto ||
@@ -126,7 +126,10 @@ export const DetailsHeader: React.FC<DetailsHeaderProps> = (props) => {
                             </TouchableOpacity>
                         </View> : // landmark has not been liked by user
                         <TouchableOpacity onPress={async () => { //this touchable will add a like to this landmark
-                            if (props.profile?.id !== props.landmark?.id) {
+                            if (anonUserId) {
+                                Alert.alert("You must be logged in to rate landmarks.");
+                            }
+                            if (landmarkOwnedByUser(props.landmark)) {
                                 await props.rateLandmark(1);
                             }
                         }}>

+ 6 - 5
src/components/Map/Panels/LandmarkDetailsPanel/LandmarkDetails.tsx

@@ -116,13 +116,13 @@ const LandmarkDetails: React.FC<LandmarkDetailsProps> = ({authNavigation, landma
 
     useEffect(() => {
     const keyboardDidShowListener = Keyboard.addListener(
-      'keyboardDidShow',
+      'keyboardWillShow',
       () => {
         setKeyboardOpened(true); // or some other action
       }
     );
     const keyboardDidHideListener = Keyboard.addListener(
-      'keyboardDidHide',
+      'keyboardWillHide',
       () => {
         setKeyboardOpened(false); // or some other action
       }
@@ -328,8 +328,8 @@ const LandmarkDetails: React.FC<LandmarkDetailsProps> = ({authNavigation, landma
     const determineModalHeight = () => {
         if (selectedImage > -1) 
             return Dimensions.get("window").height 
-        else if ((keyboardOpened && Platform.OS == 'android') || editingEnabled || (!landmarkOwnedByUser(landmarkQuery?.data?.landmark) && landmarkQuery?.data?.landmark?.photos?.length == 0)) {
-            return Dimensions.get("window").height * .5
+        else if ((keyboardOpened) || editingEnabled || (!landmarkOwnedByUser(landmarkQuery?.data?.landmark) && landmarkQuery?.data?.landmark?.photos?.length == 0)) {
+            return Dimensions.get("window").height * .4
         }
         else if (landmarkQuery?.data?.landmark?.photos?.length > 0) 
             return Dimensions.get("window").height * .9 
@@ -341,7 +341,7 @@ const LandmarkDetails: React.FC<LandmarkDetailsProps> = ({authNavigation, landma
         <Modal 
             useNativeDriver={true}
             useNativeDriverForBackdrop={true}
-            avoidKeyboard={false}
+            avoidKeyboard={true}
             onBackdropPress={() => {
                 if (editingEnabled) {
                     Keyboard.dismiss();
@@ -353,6 +353,7 @@ const LandmarkDetails: React.FC<LandmarkDetailsProps> = ({authNavigation, landma
             isVisible={visible}>
             <SafeAreaView 
                 style={[styles.container, {height: determineModalHeight()}]}>
+
                 {selectedImage > -1 ?
                 <View style={{ padding: 14}}>
                     <View style={{justifyContent: 'space-between', flexDirection: 'row'}}>

+ 26 - 2
src/components/Profile/LoginView.tsx

@@ -9,12 +9,17 @@ import { makeRedirectUri } from "expo-auth-session";
 import * as WebBrowser from 'expo-web-browser';
 import { maybeCompleteAuthSession } from "expo-web-browser";
 import React, { useState } from "react";
-import { ActivityIndicator, Image, StyleSheet, Text, TouchableOpacity, View } from "react-native";
+import { ActivityIndicator, Image, Pressable, StyleSheet, Text, TouchableHighlight, TouchableOpacity, View } from "react-native";
 import { useAuth } from "../../data/Auth/AuthContext";
 import { BaseStackNavigationProp } from "../../navigation/BaseStackNavigator";
 import { API_URL } from "../../utils/RequestUtils";
-import { PrimaryButton } from "../Buttons";
+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";
 
 /**
  * Props used by the {@link Intro} screen.
@@ -43,6 +48,7 @@ const LoginView : React.FC<{navigation: BaseStackNavigationProp}> = ({navigation
      * */
     const loginMessageState = "";
     const [loginMessage, setLoginMessage] = useState<string>(loginMessageState);
+    const [legalCollapsed, toggleLegal] = useState<boolean>(true)
     /**
      * @type {boolean} 
      * React state holding the error state of the component.
@@ -70,6 +76,14 @@ const LoginView : React.FC<{navigation: BaseStackNavigationProp}> = ({navigation
         await WebBrowser.openBrowserAsync(API_URL + "/privacy")
     }
 
+    const openFeedback = () => {
+        Linking.openURL('mailto:dev@clicknpush.ca')
+    }
+
+    const openLegal = () => {
+        toggleLegal(!legalCollapsed)
+    }
+
     return (
         <UnauthorizedLayout>
             {!loginMessage ?
@@ -80,6 +94,16 @@ const LoginView : React.FC<{navigation: BaseStackNavigationProp}> = ({navigation
                 <View style={styles.btnContainer}>
                     <PrimaryButton text="Login" onPress={login}/>
                     <PrimaryButton text="Create account" onPress={goToRegistration} />
+                    <View style={{width: '100%'}}>
+                        <GenericButton text="Legal" style={{justifyContent: 'center', alignItems: 'center', padding: 20, width: '100%', }} onPress={openLegal}/>
+                        <Separator color="#E0E0E0" />
+                        <Collapsible collapsed={legalCollapsed} style={{borderColor: '#E0E0E0', borderBottomWidth: 1, borderRightWidth: 1, borderLeftWidth: 1, justifyContent: 'center', alignItems: 'center', padding: 20}} >
+                            <BrowserLink style={{marginBottom: 20}} text="Mobile app third-party licenses" route="mobile-tpl"/>
+                            <BrowserLink text="API third-party licenses" route="api-tpl"/>
+                        </Collapsible>
+                    </View>
+                    <Separator color="#D3D3D3" />
+                    <GenericButton text="Provide feedback" style={{justifyContent: 'center', alignItems: 'center', padding: 20, width: '100%', }} onPress={openFeedback}/>
                 </View>
             </View> :
             <View style={{height: '100%', justifyContent: "center", alignItems: "center"}}>

+ 6 - 0
src/components/Profile/ProfileSections.tsx

@@ -79,6 +79,10 @@ export const ProfileSections: React.FC<ProfileSectionsProps> = ({
         if (!legalCollapsed) toggleLegal(true)
     }
 
+    const openFeedback = () => {
+        Linking.openURL('mailto:dev@clicknpush.ca')
+    }
+
     const openLegal = () => {
         toggleLegal(!legalCollapsed)
         if (!infoCollapsed) toggleInfo(true)
@@ -105,6 +109,8 @@ export const ProfileSections: React.FC<ProfileSectionsProps> = ({
             {/* <ProfileSkills openSkills={openSkills} skillsCollapsed={skillsCollapsed} /> */}
             <ProfilePrefs openPrefs={openPrefs} showTips={profile?.show_tips} prefsCollapsed={prefsCollapsed} toggleTipsAsync={toggleTipsAsync} />
             <ProfileSubscription openSubscription={openSubscription} subscriptionCollapsed={subscriptionCollapsed} />
+            <ProfileLegal openLegal={openLegal} legalCollapsed={legalCollapsed} />
+            <ProfileSectionHeader isCollapsed={true} collapseToggleMethod={openFeedback} title="Provide feedback"/>
         </View>
     )
 }

+ 10 - 10
src/components/Profile/ProfileSections/ProfileLegal.tsx

@@ -16,19 +16,19 @@ interface ProfileLegalProps {
     legalCollapsed: boolean
 }
 
-export const ProfileLegal: React.FC<ProfileLegalProps> = ({openLegal, legalCollapsed}) => {    
-    const BrowserLink: React.FC<{text:string, route:string, style?: ViewStyle}> = ({style, text, route}) => {
-        return (
-            <TouchableOpacity style={[{alignItems: 'center'}, style]} onPress={async () => await WebBrowser.openBrowserAsync(API_URL + "/" + route)}>
-                <Text style={{fontWeight: 'bold', textDecorationLine:'underline'}}>{text}</Text>
-            </TouchableOpacity>
-        )
-    }
+export const BrowserLink: React.FC<{text:string, route:string, style?: ViewStyle}> = ({style, text, route}) => {
+    return (
+        <TouchableOpacity style={[{alignItems: 'center'}, style]} onPress={async () => await WebBrowser.openBrowserAsync(API_URL + "/" + route)}>
+            <Text style={{fontWeight: 'bold', }}>{text}</Text>
+        </TouchableOpacity>
+    )
+}
 
+export const ProfileLegal: React.FC<ProfileLegalProps> = ({openLegal, legalCollapsed}) => {    
     return (
         <ProfileSection isCollapsed={legalCollapsed} collapseToggleMethod={openLegal} title="Terms">
-            <BrowserLink style={{marginBottom: 10}} text="MOBILE APP THIRD-PARTY LICENSES" route="mobile-tpl"/>
-            <BrowserLink text="API THIRD-PARTY LICENSES" route="api-tpl"/>
+            <BrowserLink style={{marginBottom: 10}} text="Mobile app third-party licenses" route="mobile-tpl"/>
+            <BrowserLink text="API third-party licenses" route="api-tpl"/>
         </ProfileSection>
     )
 }

+ 1 - 2
src/components/Profile/ProfileTemplate.tsx

@@ -7,7 +7,7 @@
 
 import { observer } from "mobx-react"
 import React from "react"
-import { ImageBackground } from "react-native"
+import { ImageBackground, Text } from "react-native"
 import { useAuth } from "../../data/Auth/AuthContext"
 import { BaseStackNavigationProp } from "../../navigation/BaseStackNavigator"
 import LoginView from "./LoginView"
@@ -30,7 +30,6 @@ const ProfileTemplate: React.FC<{navigation: BaseStackNavigationProp}> = ({navig
     return (
         <ImageBackground source={require('../../../assets/cover.jpg')} style={ProfileMainStyles.profileMainContainer}>
             {accessToken ? <Profile /> : <LoginView navigation={navigation} />}
-            <ProfileSectionHeader isCollapsed={true} collapseToggleMethod={openFeedback} title="Provide feedback"/>
         </ImageBackground>
     )
 }

+ 23 - 12
src/data/landmarks.ts

@@ -230,7 +230,7 @@ export const useDeleteLandmark = () => {
                 url: `/api/landmark/${id}`,
             }
 
-            if (!accessToken) config.data = {anonymous: anonUserId}
+            if (!accessToken) config.data = {...config.data, anonymous: anonUserId}
             
 
             const response = await sendApiRequestAsync({
@@ -249,17 +249,22 @@ export const useDeleteLandmark = () => {
 }
 
 export const useAddLandmarkPhoto = () => {
-    const {sendApiRequestAsync} = useAuth()
+    const {sendApiRequestAsync, accessToken, anonUserId} = useAuth()
     const queryClient = useQueryClient();
 
     const addLandmarkPhoto = async (photo: LMPhoto) => {
         if (photo) {
+            console.log(photo.landmark)
+            const config: AxiosRequestConfig = {
+                method: 'POST',
+                url: `/api/landmark/photos/`,
+                data: photo
+            }
+        
+            if (!accessToken) config.data = {...config.data, anonymous: anonUserId}
+
             const response = await sendApiRequestAsync({
-                axiosConfig: {
-                    method: 'POST',
-                    url: `/api/landmark/photos/`,
-                    data: photo,
-                }, 
+                axiosConfig: config, 
                 authorized: true,
                 errorMessage: 'Something went wrong when adding landmark photo'
             });   
@@ -279,16 +284,22 @@ export const useAddLandmarkPhoto = () => {
 } 
 
 export const useDeleteLandmarkPhoto = () => {
-    const {sendApiRequestAsync} = useAuth()
+    const {sendApiRequestAsync, accessToken, anonUserId} = useAuth()
     const queryClient = useQueryClient();
 
     const deleteLandmarkPhoto = async (photoId: string) => {
         if (photoId) {
+            const config: AxiosRequestConfig = {
+                method: 'DELETE',
+                url: `/api/landmark/photos/${photoId}`
+            }
+
+            if (!accessToken) {
+                config.data = {...config.data, anonymous: anonUserId}
+            }
+
             const response = await sendApiRequestAsync({
-                axiosConfig: {
-                    method: 'DELETE',
-                    url: `/api/landmark/photos/${photoId}`
-                },
+                axiosConfig: config,
                 authorized: true,
                 errorMessage: 'Something went wrong when deleting landmark photos'
             });   

+ 0 - 1
src/navigation/MainTabsNavigator.tsx

@@ -33,7 +33,6 @@ const MainTabs = createBottomTabNavigator();
 const tabBarOptions: BottomTabNavigationOptions = {
     //keyboardHidesTabBar: true,
     tabBarActiveTintColor: 'white',
-    tabBarActiveBackgroundColor: '#e35555',
     tabBarInactiveTintColor: "lightgray",
     headerShown: false,
     tabBarStyle: {backgroundColor: colors.red, justifyContent: 'center'},