aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorAshm Walia <40498934+ashmgarv@users.noreply.github.com>2020-10-24 16:12:39 -0700
committerGitHub <noreply@github.com>2020-10-24 19:12:39 -0400
commit84d283b44f2b6cecb757edcd94e717a36c3ba3c3 (patch)
tree532a6c415c57b90bb90243b2d99845bb3e93d058 /src/components
parent8b680e97ad4689493d2c398281cc0da8e333aa04 (diff)
[TMA 301] Add follow/unfollow button to profile (#70)
* Follow Unfollow User * Fixed an issue and moved api call to Content.tsx * last * Small changes
Diffstat (limited to 'src/components')
-rw-r--r--src/components/profile/Content.tsx83
-rw-r--r--src/components/profile/FollowUnfollow.tsx40
-rw-r--r--src/components/profile/ProfileBody.tsx22
3 files changed, 142 insertions, 3 deletions
diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx
index 8f20cd8d..8a3c36ff 100644
--- a/src/components/profile/Content.tsx
+++ b/src/components/profile/Content.tsx
@@ -3,7 +3,7 @@ import React, {useCallback, useEffect, useState} from 'react';
import {Alert, LayoutChangeEvent, StyleSheet, View} from 'react-native';
import Animated from 'react-native-reanimated';
import {AuthContext, ProfileContext} from '../../routes/';
-import {MomentType} from 'src/types';
+import {MomentType, ProfilePreviewType} from 'src/types';
import {defaultMoments, MOMENTS_ENDPOINT} from '../../constants';
import {SCREEN_HEIGHT} from '../../utils';
import TaggsBar from '../taggs/TaggsBar';
@@ -11,6 +11,7 @@ import {Moment} from '../moments';
import ProfileBody from './ProfileBody';
import ProfileCutout from './ProfileCutout';
import ProfileHeader from './ProfileHeader';
+import {loadFollowers, followOrUnfollowUser} from '../../services';
interface ContentProps {
y: Animated.Value<number>;
@@ -22,10 +23,23 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => {
const {newMomentsAvailable, updateMoments, user} = isProfileView
? React.useContext(ProfileContext)
: React.useContext(AuthContext);
+ const {logout} = React.useContext(AuthContext);
const [imagesList, setImagesList] = useState<MomentType[]>([]);
const [imagesMap, setImagesMap] = useState<Map<string, MomentType[]>>(
new Map(),
);
+
+ const [followed, setFollowed] = React.useState<boolean>(false);
+ const [followers, setFollowers] = React.useState<Array<ProfilePreviewType>>(
+ [],
+ );
+ const {user: loggedInUser} = React.useContext(AuthContext);
+
+ /**
+ * If own profile is being viewed then do not show the follow button.
+ */
+ const isOwnProfile = loggedInUser.username === user.username;
+
const onLayout = (e: LayoutChangeEvent) => {
const {height} = e.nativeEvent.layout;
setProfileBodyHeight(height);
@@ -80,6 +94,63 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => {
}
}, [userId, createImagesMap, updateMoments, newMomentsAvailable]);
+ /**
+ * This hook is called just on the load of profile.
+ */
+ useEffect(() => {
+ const updateFollowedValue = async () => {
+ const token = await AsyncStorage.getItem('token');
+ if (!token) {
+ logout();
+ return;
+ }
+
+ const listFollowers: ProfilePreviewType[] = await loadFollowers(
+ userId,
+ token,
+ );
+
+ /**
+ * Check if the logged in user actually follows the user being viewed.
+ */
+ const isActuallyFollowed = listFollowers.some(
+ (follower) => follower.username === loggedInUser.username,
+ );
+
+ if (followed != isActuallyFollowed) {
+ setFollowed(isActuallyFollowed);
+ }
+ setFollowers(listFollowers);
+ };
+
+ /**
+ * Update the followed value if and only if a profile is being viewed and you are loading a profile afresh that is not your own profile.
+ */
+ if (isProfileView && !isOwnProfile) {
+ updateFollowedValue();
+ }
+ }, []);
+
+ /**
+ * Handles a click on the follow / unfollow button.
+ */
+ const handleFollowUnfollow = async () => {
+ const token = await AsyncStorage.getItem('token');
+ if (!token) {
+ logout();
+ return;
+ }
+ const isUpdatedSuccessful = await followOrUnfollowUser(
+ loggedInUser.userId,
+ userId,
+ token,
+ followed,
+ );
+ if (isUpdatedSuccessful) {
+ setFollowed(!followed);
+ }
+ };
+
return (
<Animated.ScrollView
style={styles.container}
@@ -90,7 +161,15 @@ const Content: React.FC<ContentProps> = ({y, isProfileView}) => {
<ProfileCutout>
<ProfileHeader {...{isProfileView}} />
</ProfileCutout>
- <ProfileBody {...{onLayout, isProfileView}} />
+ <ProfileBody
+ {...{
+ onLayout,
+ isProfileView,
+ isOwnProfile,
+ followed,
+ handleFollowUnfollow,
+ }}
+ />
<TaggsBar {...{y, profileBodyHeight, isProfileView}} />
<View style={styles.momentsContainer}>
{defaultMoments.map((title, index) => (
diff --git a/src/components/profile/FollowUnfollow.tsx b/src/components/profile/FollowUnfollow.tsx
new file mode 100644
index 00000000..bb1e9ef7
--- /dev/null
+++ b/src/components/profile/FollowUnfollow.tsx
@@ -0,0 +1,40 @@
+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 53b86708..7091a077 100644
--- a/src/components/profile/ProfileBody.tsx
+++ b/src/components/profile/ProfileBody.tsx
@@ -1,24 +1,44 @@
import React from 'react';
import {StyleSheet, View, Text, LayoutChangeEvent} from 'react-native';
import {AuthContext, ProfileContext} from '../../routes/';
+import FollowUnfollow from './FollowUnfollow';
interface ProfileBodyProps {
onLayout: (event: LayoutChangeEvent) => void;
isProfileView: boolean;
+ followed: boolean;
+ isOwnProfile: boolean;
+ handleFollowUnfollow: Function;
}
-const ProfileBody: React.FC<ProfileBodyProps> = ({onLayout, isProfileView}) => {
+const ProfileBody: React.FC<ProfileBodyProps> = ({
+ onLayout,
+ isProfileView,
+ followed,
+ isOwnProfile,
+ handleFollowUnfollow,
+}) => {
const {
profile,
user: {username},
} = isProfileView
? React.useContext(ProfileContext)
: React.useContext(AuthContext);
+
const {biography, website} = profile;
+
return (
<View onLayout={onLayout} style={styles.container}>
<Text style={styles.username}>{`@${username}`}</Text>
<Text style={styles.biography}>{`${biography}`}</Text>
<Text style={styles.website}>{`${website}`}</Text>
+ {isProfileView && !isOwnProfile ? (
+ <FollowUnfollow
+ followed={followed}
+ handleFollowUnfollow={handleFollowUnfollow}
+ />
+ ) : (
+ <></>
+ )}
</View>
);
};