aboutsummaryrefslogtreecommitdiff
path: root/src/screens
diff options
context:
space:
mode:
Diffstat (limited to 'src/screens')
-rw-r--r--src/screens/main/Notifications.tsx13
-rw-r--r--src/screens/main/NotificationsScreen.tsx167
-rw-r--r--src/screens/main/index.ts2
-rw-r--r--src/screens/profile/IndividualMoment.tsx2
-rw-r--r--src/screens/profile/MomentCommentsScreen.tsx2
5 files changed, 170 insertions, 16 deletions
diff --git a/src/screens/main/Notifications.tsx b/src/screens/main/Notifications.tsx
deleted file mode 100644
index ca8c41c3..00000000
--- a/src/screens/main/Notifications.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React from 'react';
-import {ComingSoon} from '../../components';
-
-/**
- * Navigation Screen for displaying other users'
- * actions on the logged in user's posts
- */
-
-const Notifications: React.FC = () => {
- return <ComingSoon />;
-};
-
-export default Notifications;
diff --git a/src/screens/main/NotificationsScreen.tsx b/src/screens/main/NotificationsScreen.tsx
new file mode 100644
index 00000000..2343215f
--- /dev/null
+++ b/src/screens/main/NotificationsScreen.tsx
@@ -0,0 +1,167 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import moment from 'moment';
+import React, {useCallback, useEffect, useState} from 'react';
+import {
+ RefreshControl,
+ SectionList,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+import {SafeAreaView} from 'react-native-safe-area-context';
+import {useDispatch, useSelector} from 'react-redux';
+import {Notification} from '../../components/notifications';
+import {loadUserNotifications} from '../../store/actions';
+import {RootState} from '../../store/rootReducer';
+import {NotificationType, ScreenType} from '../../types';
+import {getDateAge, SCREEN_HEIGHT} from '../../utils';
+
+const NotificationsScreen: React.FC = () => {
+ const [refreshing, setRefreshing] = useState(false);
+ // used for figuring out which ones are unread
+ const [lastViewed, setLastViewed] = useState<moment.Moment | undefined>(
+ undefined,
+ );
+ const {notifications} = useSelector(
+ (state: RootState) => state.notifications,
+ );
+ const [sectionedNotifications, setSectionedNotifications] = useState<
+ {title: 'Today' | 'Yesterday' | 'This Week'; data: NotificationType[]}[]
+ >([]);
+
+ const dispatch = useDispatch();
+
+ const onRefresh = useCallback(() => {
+ const refrestState = async () => {
+ dispatch(loadUserNotifications());
+ };
+ setRefreshing(true);
+ refrestState().then(() => {
+ setRefreshing(false);
+ });
+ }, [dispatch]);
+
+ // handles storing and fetching the "previously viewed" information
+ useEffect(() => {
+ const getAndUpdateLastViewed = async () => {
+ const key = 'notificationLastViewed';
+ const previousLastViewed = await AsyncStorage.getItem(key);
+ setLastViewed(
+ previousLastViewed == null
+ ? moment.unix(0)
+ : moment(previousLastViewed),
+ );
+ await AsyncStorage.setItem(key, moment().toString());
+ };
+ getAndUpdateLastViewed();
+ }, [notifications]);
+
+ // handles sectioning notifications to "date age"
+ // mark notifications as read or unread
+ useEffect(() => {
+ const sortedNotifications = (notifications ?? [])
+ .slice()
+ .sort((a, b) => (a.timestamp < b.timestamp ? 1 : -1));
+ let todays = [];
+ let yesterdays = [];
+ let thisWeeks = [];
+ for (const n of sortedNotifications) {
+ const notificationDate = moment(n.timestamp);
+ const dateAge = getDateAge(notificationDate);
+ if (dateAge === 'unknown') {
+ continue;
+ }
+ const unread = lastViewed ? lastViewed.diff(notificationDate) < 0 : false;
+ const newN = {...n, unread};
+ switch (dateAge) {
+ case 'today':
+ todays.push(newN);
+ continue;
+ case 'yesterday':
+ yesterdays.push(newN);
+ continue;
+ case 'thisWeek':
+ thisWeeks.push(newN);
+ continue;
+ default:
+ continue;
+ }
+ }
+ setSectionedNotifications([
+ {
+ title: 'Today',
+ data: todays,
+ },
+ {
+ title: 'Yesterday',
+ data: yesterdays,
+ },
+ {
+ title: 'This Week',
+ data: thisWeeks,
+ },
+ ]);
+ }, [lastViewed, notifications]);
+
+ const renderNotification = ({item}: {item: NotificationType}) => (
+ <Notification item={item} screenType={ScreenType.Notifications} />
+ );
+
+ const renderSectionHeader = ({section: {title}}) => (
+ <View style={styles.sectionHeaderContainer}>
+ <Text style={styles.sectionHeader}>{title}</Text>
+ </View>
+ );
+
+ return (
+ <SafeAreaView>
+ <View style={styles.header}>
+ <Text style={styles.headerText}>Notifications</Text>
+ <View style={styles.underline} />
+ </View>
+ <SectionList
+ contentContainerStyle={styles.container}
+ sections={sectionedNotifications}
+ keyExtractor={(item, index) => index.toString()}
+ renderItem={renderNotification}
+ renderSectionHeader={renderSectionHeader}
+ refreshControl={
+ <RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
+ }
+ />
+ </SafeAreaView>
+ );
+};
+
+const styles = StyleSheet.create({
+ header: {
+ marginLeft: '5%',
+ marginTop: '5%',
+ alignSelf: 'flex-start',
+ flexDirection: 'column',
+ },
+ headerText: {
+ fontWeight: 'bold',
+ fontSize: 16,
+ },
+ underline: {
+ borderWidth: 2,
+ borderColor: '#8F01FF',
+ },
+ container: {
+ paddingBottom: '20%',
+ minHeight: (SCREEN_HEIGHT * 8) / 10,
+ },
+ sectionHeaderContainer: {
+ width: '100%',
+ backgroundColor: '#f3f2f2',
+ },
+ sectionHeader: {
+ marginLeft: '5%',
+ marginTop: '5%',
+ marginBottom: '2%',
+ fontSize: 16,
+ },
+});
+
+export default NotificationsScreen;
diff --git a/src/screens/main/index.ts b/src/screens/main/index.ts
index b15f76da..a5a723d7 100644
--- a/src/screens/main/index.ts
+++ b/src/screens/main/index.ts
@@ -1,3 +1,3 @@
export {default as Home} from './Home';
-export {default as Notifications} from './Notifications';
+export {default as NotificationsScreen} from './NotificationsScreen';
export {default as Upload} from './Upload';
diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx
index 469c648e..91742324 100644
--- a/src/screens/profile/IndividualMoment.tsx
+++ b/src/screens/profile/IndividualMoment.tsx
@@ -4,7 +4,7 @@ import {StackNavigationProp} from '@react-navigation/stack';
import React from 'react';
import {FlatList, StyleSheet, View} from 'react-native';
import {useSelector} from 'react-redux';
-import {ProfileStackParams} from 'src/routes/profile/ProfileStack';
+import {ProfileStackParams} from 'src/routes/main/ProfileStack';
import {
IndividualMomentTitleBar,
MomentPostContent,
diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx
index 2cc809a3..ebe4da28 100644
--- a/src/screens/profile/MomentCommentsScreen.tsx
+++ b/src/screens/profile/MomentCommentsScreen.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import {RouteProp, useNavigation} from '@react-navigation/native';
-import {ProfileStackParams} from '../../routes/profile';
+import {ProfileStackParams} from '../../routes/main';
import {CenteredView, CommentTile} from '../../components';
import {CommentType} from '../../types';
import {ScrollView, StyleSheet, Text, View} from 'react-native';