diff options
author | Ivan Chen <ivan@thetaggid.com> | 2021-02-05 13:29:46 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-05 13:29:46 -0500 |
commit | 07a2e3841d49b3fb278f17676c1007b003f58b9e (patch) | |
tree | 0e8c9ebdb03ac2e64172f9a593288f08e2a8108b /src/components/notifications/Notification.tsx | |
parent | 454f5dec8cbf2065ba615fa83183cbde44ffee21 (diff) | |
parent | c3cd8f95c6534fb5eb78af299ef424c50aefd85a (diff) |
Merge branch 'master' into tma590-friendslist-buttons
Diffstat (limited to 'src/components/notifications/Notification.tsx')
-rw-r--r-- | src/components/notifications/Notification.tsx | 188 |
1 files changed, 144 insertions, 44 deletions
diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index e648b554..951a5bf6 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -1,18 +1,31 @@ import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; -import {Image, StyleSheet, Text, View} from 'react-native'; +import {Alert, Image, StyleSheet, Text, View} from 'react-native'; import {TouchableWithoutFeedback} from 'react-native-gesture-handler'; +import LinearGradient from 'react-native-linear-gradient'; import {useDispatch, useStore} from 'react-redux'; -import {loadImageFromURL, loadMomentThumbnail} from '../../services'; +import {BACKGROUND_GRADIENT_MAP} from '../../constants'; +import {ERROR_DELETED_OBJECT} from '../../constants/strings'; +import { + loadImageFromURL, + loadMoments, + loadMomentThumbnail, +} from '../../services'; import { acceptFriendRequest, declineFriendRequest, loadUserNotifications, + updateReplyPosted, updateUserXFriends, } from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {MomentType, NotificationType, ScreenType} from '../../types'; -import {fetchUserX, SCREEN_HEIGHT, userXInStore} from '../../utils'; +import { + fetchUserX, + getTokenOrLogout, + SCREEN_HEIGHT, + userXInStore, +} from '../../utils'; import AcceptDeclineButtons from '../common/AcceptDeclineButtons'; interface NotificationProps { @@ -40,27 +53,51 @@ const Notification: React.FC<NotificationProps> = (props) => { const [avatar, setAvatar] = useState<string | undefined>(undefined); const [momentURI, setMomentURI] = useState<string | undefined>(undefined); - const backgroundColor = unread ? '#DCF1F1' : 'rgba(0,0,0,0)'; + const [onTapLoadProfile, setOnTapLoadProfile] = useState<boolean>(false); useEffect(() => { (async () => { const response = await loadImageFromURL(thumbnail_url); if (response) { setAvatar(response); + } else { + setAvatar(undefined); } })(); }, []); useEffect(() => { + if (onTapLoadProfile) { + fetchUserX(dispatch, {userId: id, username: username}, screenType); + } + return () => { + setOnTapLoadProfile(false); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [onTapLoadProfile]); + + useEffect(() => { let mounted = true; const loadMomentImage = async (moment_id: string) => { const response = await loadMomentThumbnail(moment_id); if (mounted && response) { setMomentURI(response); + } else { + // if not set to empty, it will re-use the previous notification's state + setMomentURI(undefined); } }; - if (notification_type === 'CMT' && notification_object) { - loadMomentImage(notification_object.moment_id); + if ( + (notification_type === 'CMT' || + notification_type === 'MOM_3+' || + notification_type === 'MOM_FRIEND') && + notification_object + ) { + loadMomentImage( + notification_object.moment_id + ? notification_object.moment_id + : notification_object.parent_comment.moment_id, + ); return () => { mounted = false; }; @@ -84,31 +121,85 @@ const Notification: React.FC<NotificationProps> = (props) => { }); break; case 'CMT': - // find the moment we need to display - const moment = loggedInUserMoments?.find( - (m) => m.moment_id === notification_object?.moment_id, + //Notification object is set to null if the comment / comment_thread / moment gets deleted + if (!notification_object) { + Alert.alert(ERROR_DELETED_OBJECT); + break; + } + let {moment_id} = notification_object; + let {comment_id} = notification_object; + + //If this is a thread, get comment_id and moment_id from parent_comment + if (!notification_object?.moment_id) { + moment_id = notification_object?.parent_comment?.moment_id; + comment_id = notification_object?.parent_comment?.comment_id; + } + + // Now find the moment we need to display + let moment: MomentType | undefined = loggedInUserMoments?.find( + (m) => m.moment_id === moment_id, ); + let userXId; + + // If moment does not belong to the logged in user, then the comment was probably a reply to logged in user's comment + // on userX's moment + // Load moments for userX + if (!moment) { + let moments: MomentType[] = []; + try { + //Populate local state in the mean time + setOnTapLoadProfile(true); + const token = await getTokenOrLogout(dispatch); + moments = await loadMoments(id, token); + } catch (err) { + console.log(err); + } + moment = moments?.find((m) => m.moment_id === moment_id); + userXId = id; + } + + //Now if moment was found, navigate to the respective moment if (moment) { + if (notification_object?.parent_comment) { + dispatch(updateReplyPosted(notification_object)); + } navigation.push('IndividualMoment', { moment, - userXId: undefined, // we're only viewing our own moment here + userXId: userXId, // we're only viewing our own moment here screenType, }); setTimeout(() => { navigation.push('MomentCommentsScreen', { - moment_id: moment.moment_id, + moment_id: moment_id, screenType, + comment_id: comment_id, }); }, 500); } break; + case 'MOM_3+': + case 'MOM_FRIEND': + const object = notification_object as MomentType; + await fetchUserX( + dispatch, + {userId: id, username: username}, + screenType, + ); + navigation.push('IndividualMoment', { + moment: object, + userXId: id, + screenType, + }); + break; default: break; } }; const handleAcceptRequest = async () => { - await dispatch(acceptFriendRequest({id, username, first_name, last_name})); + await dispatch( + acceptFriendRequest({id, username, first_name, last_name, thumbnail_url}), + ); await dispatch(updateUserXFriends(id, state)); dispatch(loadUserNotifications()); }; @@ -118,48 +209,57 @@ const Notification: React.FC<NotificationProps> = (props) => { dispatch(loadUserNotifications()); }; - return ( - <> - <TouchableWithoutFeedback - style={[styles.container, {backgroundColor}]} - onPress={onNotificationTap}> - <View style={styles.avatarContainer}> - <Image - style={styles.avatar} - source={ - avatar - ? {uri: avatar, cache: 'only-if-cached'} - : require('../../assets/images/avatar-placeholder.png') - } + const renderContent = () => ( + <TouchableWithoutFeedback + style={styles.container} + onPress={onNotificationTap}> + <View style={styles.avatarContainer}> + <Image + style={styles.avatar} + source={ + avatar + ? {uri: avatar} + : require('../../assets/images/avatar-placeholder.png') + } + /> + </View> + <View style={styles.contentContainer}> + <Text style={styles.actorName}> + {first_name} {last_name} + </Text> + <Text>{verbage}</Text> + </View> + {notification_type === 'FRD_REQ' && ( + <View style={styles.buttonsContainer}> + <AcceptDeclineButtons + requester={{id, username, first_name, last_name}} + onAccept={handleAcceptRequest} + onReject={handleDeclineFriendRequest} /> </View> - <View style={styles.contentContainer}> - <Text style={styles.actorName}> - {first_name} {last_name} - </Text> - <Text>{verbage}</Text> - </View> - {notification_type === 'FRD_REQ' && ( - <View style={styles.buttonsContainer}> - <AcceptDeclineButtons - requester={{id, username, first_name, last_name}} - onAccept={handleAcceptRequest} - onReject={handleDeclineFriendRequest} - /> - </View> - )} - {notification_type === 'CMT' && notification_object && ( + )} + {(notification_type === 'CMT' || + notification_type === 'MOM_3+' || + notification_type === 'MOM_FRIEND') && + notification_object && ( <Image style={styles.moment} source={{uri: momentURI}} /> )} - </TouchableWithoutFeedback> - </> + </TouchableWithoutFeedback> + ); + + return unread ? ( + <LinearGradient colors={BACKGROUND_GRADIENT_MAP[2]} useAngle angle={90}> + {renderContent()} + </LinearGradient> + ) : ( + renderContent() ); }; const styles = StyleSheet.create({ container: { flexDirection: 'row', - height: SCREEN_HEIGHT / 10, + height: Math.round(SCREEN_HEIGHT / 10), flex: 1, alignItems: 'center', }, |