import AsyncStorage from '@react-native-community/async-storage'; import PushNotificationIOS from '@react-native-community/push-notification-ios'; import {useFocusEffect, useNavigation} from '@react-navigation/native'; import moment from 'moment'; import React, {useCallback, useEffect, useState} from 'react'; import { Alert, Image, Linking, RefreshControl, SectionList, StatusBar, StyleSheet, Text, View, } from 'react-native'; import {checkPermission} from 'react-native-contacts'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {SafeAreaView} from 'react-native-safe-area-context'; import {useDispatch, useSelector} from 'react-redux'; import FindFriendsBlueIcon from '../../assets/icons/findFriends/find-friends-blue-icon.svg'; import {TabsGradient} from '../../components'; import EmptyContentView from '../../components/common/EmptyContentView'; import {Notification} from '../../components/notifications'; import { loadUserNotifications, updateNewNotificationReceived, } from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {NotificationType, ScreenType} from '../../types'; import {getDateAge, normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; const NotificationsScreen: React.FC = () => { const {newNotificationReceived} = useSelector( (state: RootState) => state.user, ); const [refreshing, setRefreshing] = useState(false); // used for figuring out which ones are unread const [lastViewed, setLastViewed] = useState( undefined, ); const {notifications} = useSelector( (state: RootState) => state.notifications, ); const {suggested_people_linked} = useSelector( (state: RootState) => state.user.profile, ); const [showSPNotifyPopUp, setShowSPNotifyPopUp] = useState(false); const {user: loggedInUser} = useSelector((state: RootState) => state.user); const [sectionedNotifications, setSectionedNotifications] = useState< { title: 'Friend Requests' | 'Today' | 'Yesterday' | 'This Week'; data: NotificationType[]; }[] >([]); const DEFAULT_NOTIFICATIONS_SIZE = 2; const [footerEnabled, setFooterEnabled] = useState(false); const [requestLimit, setRequestLimit] = useState(DEFAULT_NOTIFICATIONS_SIZE); const [allFriendRequests, setFriendRequests] = useState( [], ); const dispatch = useDispatch(); const refreshNotifications = () => { const refrestState = async () => { dispatch(loadUserNotifications()); }; setRefreshing(true); refrestState().then(() => { setRefreshing(false); }); }; const onRefresh = useCallback(() => { refreshNotifications(); }, [refreshNotifications]); useEffect(() => { setShowSPNotifyPopUp(suggested_people_linked !== 2); }, [suggested_people_linked]); useFocusEffect( useCallback(() => { const resetNewNotificationFlag = () => { if (newNotificationReceived) { dispatch(updateNewNotificationReceived(false)); } }; //Called everytime screen is focused if (newNotificationReceived) { refreshNotifications(); } //Called when user leaves the screen return () => resetNewNotificationFlag(); }, [newNotificationReceived, dispatch, refreshNotifications]), ); // 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()); PushNotificationIOS.setApplicationIconBadgeNumber(0); }; 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 = []; let friendRequests = []; 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}; if (n.notification_type === 'FRD_REQ') { friendRequests.push(newN); } else { switch (dateAge) { case 'today': todays.push(newN); continue; case 'yesterday': yesterdays.push(newN); continue; case 'thisWeek': thisWeeks.push(newN); continue; default: continue; } } } setFriendRequests(friendRequests); setFooterEnabled( requestLimit === friendRequests.length && friendRequests.length > DEFAULT_NOTIFICATIONS_SIZE, ); setSectionedNotifications( todays.length === 0 && yesterdays.length === 0 && thisWeeks.length === 0 && friendRequests.length === 0 ? [] : [ { title: 'Friend Requests', data: friendRequests.slice(0, requestLimit), }, {title: 'Today', data: todays}, {title: 'Yesterday', data: yesterdays}, {title: 'This Week', data: thisWeeks}, ], ); }, [lastViewed, notifications, showSPNotifyPopUp, requestLimit]); const renderNotification = ({item}: {item: NotificationType}) => ( ); const renderSectionHeader = ({ section: {title, data}, }: { section: {title: string; data: NotificationType[]}; }) => data.length !== 0 && ( {title} ); const renderSectionFooter = ({ section: {title}, }: { section: {title: string}; }) => { if (title === 'Friend Requests') { if (footerEnabled) { return ( { setRequestLimit(DEFAULT_NOTIFICATIONS_SIZE); }}> {'Hide'} ); } if (allFriendRequests.length > DEFAULT_NOTIFICATIONS_SIZE) { return ( { setRequestLimit(allFriendRequests.length); }}> {`+ ${allFriendRequests.length - requestLimit} More`} ); } } return null; }; const navigation = useNavigation(); const InviteFriends = () => ( { const permission = await checkPermission(); if (permission === 'authorized') { navigation.navigate('InviteFriendsScreen'); } else { Alert.alert( '"Tagg" Would Like to Access Your Contacts', 'This helps you quickly get in touch with friends on the app and more', [ { text: "Don't Allow", style: 'cancel', }, {text: 'Allow', onPress: () => Linking.openSettings()}, ], ); } }}> Invite Friends ); return ( Notifications item.timestamp.toString() + index.toString() } renderItem={renderNotification} renderSectionHeader={renderSectionHeader} renderSectionFooter={renderSectionFooter} refreshControl={ } extraData={requestLimit} ListEmptyComponent={ } /> ); }; const styles = StyleSheet.create({ background: { width: SCREEN_WIDTH, height: SCREEN_HEIGHT, backgroundColor: 'white', }, header: { marginLeft: '8%', marginTop: '5%', alignSelf: 'flex-start', flexDirection: 'row', alignItems: 'stretch', justifyContent: 'space-between', width: SCREEN_WIDTH * 0.9, }, headerText: { fontWeight: '700', fontSize: normalize(18), lineHeight: normalize(21), }, container: { paddingBottom: '20%', minHeight: (SCREEN_HEIGHT * 8) / 10, }, sectionHeaderContainer: { width: '100%', backgroundColor: 'white', }, sectionLocation: { marginLeft: '8%', marginTop: '5%', marginBottom: '2%', }, sectionFont: { fontWeight: '600', fontSize: normalize(12), lineHeight: normalize(14), }, hiddenSectionContainer: { flexDirection: 'row', }, hideImageStyles: {alignSelf: 'center', marginRight: 8}, sectionHeader: { color: '#828282', }, sectionFooter: { color: '#698DD3', }, emptyViewContainer: { flex: 1, justifyContent: 'center', }, findFriendsButton: { flexDirection: 'row', height: 14, marginTop: '5%', }, findFriendsSubheaderText: { marginLeft: '5%', color: '#08E2E2', fontSize: normalize(12), fontWeight: '600', lineHeight: normalize(14.32), }, }); export default NotificationsScreen;