aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorIvan Chen <ivan@thetaggid.com>2020-12-29 20:21:24 -0500
committerGitHub <noreply@github.com>2020-12-29 20:21:24 -0500
commitbd2f89805d0bb1c2f1d08fe8d91099aa4f109d35 (patch)
treeac7219e034a0c4035096c6df8dbe6b92446b5111 /src/components
parentec478d4981c726856485b49b49ac33b0d9e6a903 (diff)
[TMA-461] Notifications Screen (#151)
* renamed ProfileStack to MainStack, created initial notifications data type * cleaned up code * added notifications to redux * finished sectioned list * updated types to make more sense * finished sectioned notifications by date * updated notification type and tested mock backend integration * finished read or unread logic * minor changes * another minor fix * finished integration * moved stuff * added ability to navigate to user profile Co-authored-by: Husam Salhab <47015061+hsalhab@users.noreply.github.com>
Diffstat (limited to 'src/components')
-rw-r--r--src/components/notifications/Notification.tsx150
-rw-r--r--src/components/notifications/index.ts1
-rw-r--r--src/components/profile/ProfilePreview.tsx35
3 files changed, 159 insertions, 27 deletions
diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx
new file mode 100644
index 00000000..f533e42d
--- /dev/null
+++ b/src/components/notifications/Notification.tsx
@@ -0,0 +1,150 @@
+import {useNavigation} from '@react-navigation/native';
+import React, {useEffect, useState} from 'react';
+import {Image, StyleSheet, Text, View} from 'react-native';
+import {TouchableWithoutFeedback} from 'react-native-gesture-handler';
+import {useDispatch, useStore} from 'react-redux';
+import {loadAvatar} from '../../services';
+import {RootState} from '../../store/rootReducer';
+import {NotificationType, ScreenType} from '../../types';
+import {fetchUserX, SCREEN_HEIGHT, userXInStore} from '../../utils';
+
+interface NotificationProps {
+ item: NotificationType;
+ screenType: ScreenType;
+}
+
+const Notification: React.FC<NotificationProps> = (props) => {
+ const {
+ item: {
+ actor: {id, username, first_name, last_name},
+ verbage,
+ notification_type,
+ notification_object,
+ unread,
+ },
+ screenType,
+ } = props;
+ const navigation = useNavigation();
+ const state: RootState = useStore().getState();
+ const dispatch = useDispatch();
+
+ const [avatarURI, setAvatarURI] = useState<string | undefined>(undefined);
+ const [momentURI, setMomentURI] = useState<string | undefined>(undefined);
+ const backgroundColor = unread ? '#DCF1F1' : 'rgba(0,0,0,0)';
+
+ useEffect(() => {
+ let mounted = true;
+ const loadAvatarImage = async (user_id: string) => {
+ const response = await loadAvatar(user_id, true);
+ if (mounted) {
+ setAvatarURI(response);
+ }
+ };
+ loadAvatarImage(id);
+ return () => {
+ mounted = false;
+ };
+ }, [id]);
+
+ // TODO: this should be moment thumbnail, waiting for that to complete
+ // useEffect(() => {
+ // let mounted = true;
+ // const loadMomentImage = async (user_id: string) => {
+ // const response = await loadAvatar(user_id, true);
+ // if (mounted) {
+ // setMomentURI(response);
+ // }
+ // };
+ // loadMomentImage(id);
+ // return () => {
+ // mounted = false;
+ // };
+ // }, [id, notification_object]);
+
+ const onNotificationTap = async () => {
+ switch (notification_type) {
+ case 'FLO':
+ if (!userXInStore(state, screenType, id)) {
+ await fetchUserX(
+ dispatch,
+ {userId: id, username: username},
+ screenType,
+ );
+ }
+ navigation.push('Profile', {
+ userXId: id,
+ screenType,
+ });
+ break;
+ default:
+ break;
+ }
+ };
+
+ return (
+ <TouchableWithoutFeedback
+ style={[styles.container, {backgroundColor}]}
+ onPress={onNotificationTap}>
+ <View style={styles.avatarContainer}>
+ <Image
+ style={styles.avatar}
+ source={
+ avatarURI
+ ? {uri: avatarURI, cache: 'only-if-cached'}
+ : require('../../assets/images/avatar-placeholder.png')
+ }
+ />
+ </View>
+ <View style={styles.contentContainer}>
+ <Text style={styles.actorName}>
+ {first_name} {last_name}
+ </Text>
+ <Text>{verbage}</Text>
+ </View>
+ {/* TODO: Still WIP */}
+ {/* {notification_type === 'CMT' && notification_object && (
+ <Image
+ style={styles.moment}
+ source={{uri: momentURI, cache: 'only-if-cached'}}
+ />
+ )} */}
+ </TouchableWithoutFeedback>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flexDirection: 'row',
+ height: SCREEN_HEIGHT / 12,
+ flex: 1,
+ alignItems: 'center',
+ },
+ avatarContainer: {
+ marginLeft: '5%',
+ flex: 1,
+ justifyContent: 'center',
+ },
+ avatar: {
+ height: 42,
+ width: 42,
+ borderRadius: 20,
+ },
+ contentContainer: {
+ flex: 5,
+ marginLeft: '5%',
+ height: '80%',
+ flexDirection: 'column',
+ justifyContent: 'space-around',
+ },
+ actorName: {
+ fontWeight: 'bold',
+ },
+ moment: {
+ position: 'absolute',
+ height: 42,
+ width: 42,
+ right: '5%',
+ },
+});
+
+export default Notification;
diff --git a/src/components/notifications/index.ts b/src/components/notifications/index.ts
new file mode 100644
index 00000000..0260ce24
--- /dev/null
+++ b/src/components/notifications/index.ts
@@ -0,0 +1 @@
+export {default as Notification} from './Notification';
diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx
index cc18e457..49c79e2d 100644
--- a/src/components/profile/ProfilePreview.tsx
+++ b/src/components/profile/ProfilePreview.tsx
@@ -14,12 +14,14 @@ import RNFetchBlob from 'rn-fetch-blob';
import AsyncStorage from '@react-native-community/async-storage';
import {PROFILE_PHOTO_THUMBNAIL_ENDPOINT} from '../../constants';
import {UserType, PreviewType} from '../../types';
-import {isUserBlocked} from '../../services';
+import {isUserBlocked, loadAvatar} from '../../services';
import {useSelector, useDispatch, useStore} from 'react-redux';
import {RootState} from '../../store/rootreducer';
import {logout} from '../../store/actions';
import {fetchUserX, userXInStore} from '../../utils';
+import {SearchResultsBackground} from '../search';
import NavigationBar from 'src/routes/tabs';
+
const NO_USER: UserType = {
userId: '',
username: '',
@@ -52,34 +54,13 @@ const ProfilePreview: React.FC<ProfilePreviewProps> = ({
const dispatch = useDispatch();
useEffect(() => {
let mounted = true;
- const loadAvatar = async () => {
- try {
- const token = await AsyncStorage.getItem('token');
- if (!token) {
- setUser(NO_USER);
- return;
- }
- const response = await RNFetchBlob.config({
- fileCache: true,
- appendExt: 'jpg',
- }).fetch('GET', PROFILE_PHOTO_THUMBNAIL_ENDPOINT + `${id}/`, {
- Authorization: 'Token ' + token,
- });
- const status = response.info().status;
- if (status === 200) {
- if (mounted) {
- setAvatarURI(response.path());
- }
- return;
- }
- if (mounted) {
- setAvatarURI('');
- }
- } catch (error) {
- console.log(error);
+ const loadAvatarImage = async () => {
+ const response = await loadAvatar(id, true);
+ if (mounted) {
+ setAvatarURI(response);
}
};
- loadAvatar();
+ loadAvatarImage();
return () => {
mounted = false;
};