diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/profile/Content.tsx | 57 | ||||
| -rw-r--r-- | src/components/profile/FollowUnfollow.tsx | 40 | ||||
| -rw-r--r-- | src/components/profile/ProfileBody.tsx | 33 | ||||
| -rw-r--r-- | src/components/profile/ProfilePreview.tsx | 21 | ||||
| -rw-r--r-- | src/components/profile/ToggleButton.tsx | 44 |
5 files changed, 140 insertions, 55 deletions
diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index 7afc3fbc..13db60a5 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -11,7 +11,7 @@ import {Moment} from '../moments'; import ProfileBody from './ProfileBody'; import ProfileCutout from './ProfileCutout'; import ProfileHeader from './ProfileHeader'; -import {followOrUnfollowUser} from '../../services'; +import {followOrUnfollowUser, blockOrUnblockUser} from '../../services'; interface ContentProps { y: Animated.Value<number>; @@ -24,10 +24,12 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => { ? React.useContext(ProfileContext) : React.useContext(AuthContext); - const {logout} = React.useContext(AuthContext); const { + logout, user: loggedInUser, updateFollowers: updateLoggedInUserFollowers, + blockedUsers, + updateBlockedUsers, } = React.useContext(AuthContext); /** @@ -36,7 +38,8 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => { const [imagesMap, setImagesMap] = useState<Map<string, MomentType[]>>( new Map(), ); - const [followed, setFollowed] = React.useState<boolean>(false); + const [isFollowed, setIsFollowed] = React.useState<boolean>(false); + const [isBlocked, setIsBlocked] = React.useState<boolean>(false); /** * If own profile is being viewed then do not show the follow button. @@ -81,11 +84,24 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => { const isActuallyFollowed = followers.some( (follower) => follower.username === loggedInUser.username, ); - if (followed != isActuallyFollowed) { - setFollowed(isActuallyFollowed); + if (isFollowed != isActuallyFollowed) { + setIsFollowed(isActuallyFollowed); } }, [followers]); + useEffect(() => { + if (!userId) { + return; + } + + const isActuallyBlocked = blockedUsers.some( + (cur_user) => user.username === cur_user.username, + ); + if (isBlocked != isActuallyBlocked) { + setIsBlocked(isActuallyBlocked); + } + }, [blockedUsers]); + /** * Handles a click on the follow / unfollow button. * updateFollowers and updateLoggedInUerFollowers to make sure that we update followers list / count for both the users in context. @@ -100,10 +116,33 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => { loggedInUser.userId, userId, token, - followed, + isFollowed, + ); + if (isUpdatedSuccessful) { + setIsFollowed(!isFollowed); + updateFollowers(true); + updateLoggedInUserFollowers(true); + } + }; + + /** + * Handles a click on the block / unblock button. + */ + const handleBlockUnblock = async () => { + const token = await AsyncStorage.getItem('token'); + if (!token) { + logout(); + return; + } + const isUpdatedSuccessful = await blockOrUnblockUser( + loggedInUser.userId, + userId, + token, + isBlocked, ); if (isUpdatedSuccessful) { - setFollowed(!followed); + setIsBlocked(!isBlocked); + updateBlockedUsers(true); updateFollowers(true); updateLoggedInUserFollowers(true); } @@ -126,8 +165,10 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => { onLayout, isProfileView, isOwnProfile, - followed, + isFollowed, handleFollowUnfollow, + isBlocked, + handleBlockUnblock, }} /> <TaggsBar {...{y, profileBodyHeight, isProfileView}} /> diff --git a/src/components/profile/FollowUnfollow.tsx b/src/components/profile/FollowUnfollow.tsx deleted file mode 100644 index fa224be3..00000000 --- a/src/components/profile/FollowUnfollow.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import * as React from 'react'; -import {StyleSheet, Text} from 'react-native'; -import {TouchableOpacity} from 'react-native-gesture-handler'; - -type FollowUnfollowProps = { - followed: boolean; - handleFollowUnfollow: Function; -}; - -const FollowUnfollow: React.FC<FollowUnfollowProps> = ({ - followed, - handleFollowUnfollow, -}) => { - return ( - <TouchableOpacity - style={styles.button} - onPress={() => handleFollowUnfollow()}> - <Text style={styles.text}>{!followed ? 'Follow' : 'Unfollow'}</Text> - </TouchableOpacity> - ); -}; - -const styles = StyleSheet.create({ - button: { - justifyContent: 'center', - alignItems: 'center', - width: 110, - height: 40, - borderRadius: 8, - marginTop: '5%', - borderColor: '#698dd3', - backgroundColor: 'white', - borderWidth: 3, - }, - text: { - fontWeight: 'bold', - color: '#698dd3', - }, -}); -export default FollowUnfollow; diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 7091a077..db8c6e0b 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -1,21 +1,26 @@ import React from 'react'; import {StyleSheet, View, Text, LayoutChangeEvent} from 'react-native'; +import {TOGGLE_BUTTON_TYPE} from '../../constants'; import {AuthContext, ProfileContext} from '../../routes/'; -import FollowUnfollow from './FollowUnfollow'; +import ToggleButton from './ToggleButton'; interface ProfileBodyProps { onLayout: (event: LayoutChangeEvent) => void; isProfileView: boolean; - followed: boolean; + isFollowed: boolean; + isBlocked: boolean; isOwnProfile: boolean; handleFollowUnfollow: Function; + handleBlockUnblock: Function; } const ProfileBody: React.FC<ProfileBodyProps> = ({ onLayout, isProfileView, - followed, + isFollowed, + isBlocked, isOwnProfile, handleFollowUnfollow, + handleBlockUnblock, }) => { const { profile, @@ -32,10 +37,20 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ <Text style={styles.biography}>{`${biography}`}</Text> <Text style={styles.website}>{`${website}`}</Text> {isProfileView && !isOwnProfile ? ( - <FollowUnfollow - followed={followed} - handleFollowUnfollow={handleFollowUnfollow} - /> + <View style={styles.toggleButtonContainer}> + {!isBlocked && ( + <ToggleButton + toggleState={isFollowed} + handleToggle={handleFollowUnfollow} + buttonType={TOGGLE_BUTTON_TYPE.FOLLOW_UNFOLLOW} + /> + )} + <ToggleButton + toggleState={isBlocked} + handleToggle={handleBlockUnblock} + buttonType={TOGGLE_BUTTON_TYPE.BLOCK_UNBLOCK} + /> + </View> ) : ( <></> )} @@ -44,6 +59,10 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ }; const styles = StyleSheet.create({ + toggleButtonContainer: { + flexDirection: 'row', + flex: 1, + }, container: { paddingVertical: 5, paddingHorizontal: 20, diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index 9c953e7d..abc29422 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -7,12 +7,15 @@ import { StyleSheet, ViewProps, TouchableOpacity, + Alert, } from 'react-native'; import {useNavigation} from '@react-navigation/native'; import RNFetchBlob from 'rn-fetch-blob'; import AsyncStorage from '@react-native-community/async-storage'; import {AVATAR_PHOTO_ENDPOINT} from '../../constants'; import {UserType} from '../../types'; +import {AuthContext} from '../../routes/'; +import {isUserBlocked} from '../../services'; const NO_USER: UserType = { userId: '', username: '', @@ -38,6 +41,7 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ style, }) => { const navigation = useNavigation(); + const {user: loggedInUser, logout} = React.useContext(AuthContext); const [avatarURI, setAvatarURI] = useState<string | null>(null); const [user, setUser] = useState<UserType>(NO_USER); useEffect(() => { @@ -80,6 +84,16 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ * Cache maintains 10 recently searched users, popping off the oldest one if * needed to make space. */ + + const checkIfUserIsBlocked = async (userId: string) => { + const token = await AsyncStorage.getItem('token'); + if (!token) { + logout(); + return false; + } + return await isUserBlocked(userId, loggedInUser.userId, token); + }; + const addToRecentlyStoredAndNavigateToProfile = async () => { let user: ProfilePreviewType = { id, @@ -87,7 +101,14 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({ first_name, last_name, }; + try { + //If the logged in user is blocked by the user being viewed, do not proceed. + const isUserBlocked = await checkIfUserIsBlocked(user.id); + if (isUserBlocked) { + Alert.alert('You cannot view this profile'); + return; + } if (!isComment) { const jsonValue = await AsyncStorage.getItem( '@recently_searched_users', diff --git a/src/components/profile/ToggleButton.tsx b/src/components/profile/ToggleButton.tsx new file mode 100644 index 00000000..ff14cdde --- /dev/null +++ b/src/components/profile/ToggleButton.tsx @@ -0,0 +1,44 @@ +import * as React from 'react'; +import {StyleSheet, Text} from 'react-native'; +import {TouchableOpacity} from 'react-native-gesture-handler'; +import {getToggleButtonText, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; + +type ToggleButtonProps = { + toggleState: boolean; + handleToggle: Function; + buttonType: string; +}; + +const ToggleButton: React.FC<ToggleButtonProps> = ({ + toggleState, + handleToggle, + buttonType, +}) => { + return ( + <TouchableOpacity style={styles.button} onPress={() => handleToggle()}> + <Text style={styles.text}> + {getToggleButtonText(buttonType, toggleState)} + </Text> + </TouchableOpacity> + ); +}; + +const styles = StyleSheet.create({ + button: { + justifyContent: 'center', + alignItems: 'center', + width: SCREEN_WIDTH * 0.25, + height: SCREEN_WIDTH * 0.1, + borderRadius: 8, + marginTop: '3%', + borderColor: '#698dd3', + backgroundColor: 'white', + borderWidth: 3, + marginHorizontal: '1%', + }, + text: { + fontWeight: 'bold', + color: '#698dd3', + }, +}); +export default ToggleButton; |
