diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/assets/images/hide-caret.png | bin | 0 -> 285 bytes | |||
-rw-r--r-- | src/assets/images/hide-caret@2x.png | bin | 0 -> 441 bytes | |||
-rw-r--r-- | src/assets/images/hide-caret@3x.png | bin | 0 -> 603 bytes | |||
-rw-r--r-- | src/components/comments/AddComment.tsx | 1 | ||||
-rw-r--r-- | src/components/common/GradientBorderButton.tsx | 5 | ||||
-rw-r--r-- | src/components/notifications/Notification.tsx | 3 | ||||
-rw-r--r-- | src/routes/main/MainStackScreen.tsx | 21 | ||||
-rw-r--r-- | src/screens/main/NotificationsScreen.tsx | 150 | ||||
-rw-r--r-- | src/screens/suggestedPeople/SuggestedPeopleScreen.tsx | 15 | ||||
-rw-r--r-- | src/services/SuggestedPeopleService.ts | 8 |
10 files changed, 168 insertions, 35 deletions
diff --git a/src/assets/images/hide-caret.png b/src/assets/images/hide-caret.png Binary files differnew file mode 100644 index 00000000..bb05b53a --- /dev/null +++ b/src/assets/images/hide-caret.png diff --git a/src/assets/images/hide-caret@2x.png b/src/assets/images/hide-caret@2x.png Binary files differnew file mode 100644 index 00000000..3f4689d3 --- /dev/null +++ b/src/assets/images/hide-caret@2x.png diff --git a/src/assets/images/hide-caret@3x.png b/src/assets/images/hide-caret@3x.png Binary files differnew file mode 100644 index 00000000..a44c36fe --- /dev/null +++ b/src/assets/images/hide-caret@3x.png diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 56011f05..3b195a2b 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -115,7 +115,6 @@ const AddComment: React.FC<AddCommentProps> = ({ placeholderTextColor="grey" onChangeText={setComment} value={comment} - autoCorrect={false} multiline={true} ref={ref} /> diff --git a/src/components/common/GradientBorderButton.tsx b/src/components/common/GradientBorderButton.tsx index 00f46a96..32ac5c52 100644 --- a/src/components/common/GradientBorderButton.tsx +++ b/src/components/common/GradientBorderButton.tsx @@ -46,11 +46,12 @@ const styles = StyleSheet.create({ }, gradientContainer: { width: SCREEN_WIDTH / 2 - 40, - height: 40, + height: 43, }, label: { fontWeight: '500', fontSize: normalize(14), + textAlign: 'center', }, maskBorder: { borderRadius: 20, @@ -58,7 +59,7 @@ const styles = StyleSheet.create({ textContainer: { position: 'absolute', width: SCREEN_WIDTH / 2 - 40, - height: 40, + height: 43, justifyContent: 'center', alignItems: 'center', }, diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index f83abcbc..c8a8aa06 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -256,10 +256,11 @@ const styles = StyleSheet.create({ container: { flexDirection: 'row', height: Math.round(SCREEN_HEIGHT / 10), - width: SCREEN_WIDTH * 0.9, + width: SCREEN_WIDTH, flex: 1, alignSelf: 'center', alignItems: 'center', + paddingHorizontal: '8%', }, avatarContainer: { height: 42, diff --git a/src/routes/main/MainStackScreen.tsx b/src/routes/main/MainStackScreen.tsx index 4f655a64..d2f0d460 100644 --- a/src/routes/main/MainStackScreen.tsx +++ b/src/routes/main/MainStackScreen.tsx @@ -278,11 +278,21 @@ export const headerBarOptions: ( height={normalize(18)} width={normalize(18)} color={color} - style={styles.backButton} + style={[ + styles.backButton, + color === 'white' ? styles.backButtonShadow : {}, + ]} /> ), headerTitle: () => ( - <Text style={[styles.headerTitle, {color: color}]}>{title}</Text> + <Text + style={[ + styles.headerTitle, + {color: color}, + {fontSize: title.length > 18 ? normalize(14) : normalize(16)}, + ]}> + {title} + </Text> ), }); @@ -304,8 +314,13 @@ const styles = StyleSheet.create({ backButton: { marginLeft: 30, }, + backButtonShadow: { + shadowColor: 'black', + shadowRadius: 3, + shadowOpacity: 0.7, + shadowOffset: {width: 0, height: 0}, + }, headerTitle: { - fontSize: normalize(16), letterSpacing: normalize(1.3), fontWeight: '700', }, diff --git a/src/screens/main/NotificationsScreen.tsx b/src/screens/main/NotificationsScreen.tsx index 74bcf906..501c44fc 100644 --- a/src/screens/main/NotificationsScreen.tsx +++ b/src/screens/main/NotificationsScreen.tsx @@ -17,6 +17,7 @@ import { Text, View, } from 'react-native'; +import {TouchableOpacity} from 'react-native-gesture-handler'; import {SafeAreaView} from 'react-native-safe-area-context'; import {useDispatch, useSelector} from 'react-redux'; import {TabsGradient, TaggPrompt} from '../../components'; @@ -48,8 +49,20 @@ const NotificationsScreen: React.FC = () => { const [showSPNotifyPopUp, setShowSPNotifyPopUp] = useState(false); const {user: loggedInUser} = useSelector((state: RootState) => state.user); const [sectionedNotifications, setSectionedNotifications] = useState< - {title: 'Today' | 'Yesterday' | 'This Week'; data: NotificationType[]}[] + { + 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<NotificationType[]>( + [], + ); + const dispatch = useDispatch(); const refreshNotifications = () => { @@ -112,6 +125,7 @@ const NotificationsScreen: React.FC = () => { let todays = []; let yesterdays = []; let thisWeeks = []; + let friendRequests = []; for (const n of sortedNotifications) { const notificationDate = moment(n.timestamp); const dateAge = getDateAge(notificationDate); @@ -120,34 +134,47 @@ const NotificationsScreen: React.FC = () => { } 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; + + 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 + 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]); - - useEffect(() => { - console.log(sectionedNotifications); - }, [sectionedNotifications]); + }, [lastViewed, notifications, showSPNotifyPopUp, requestLimit]); const renderNotification = ({item}: {item: NotificationType}) => ( <Notification @@ -157,13 +184,74 @@ const NotificationsScreen: React.FC = () => { /> ); - const renderSectionHeader = ({section: {title, data}}) => + const renderSectionHeader = ({ + section: {title, data}, + }: { + section: {title: string; data: NotificationType[]}; + }) => data.length !== 0 && ( <View style={styles.sectionHeaderContainer}> - <Text style={styles.sectionHeader}>{title}</Text> + <Text + style={[ + styles.sectionFont, + styles.sectionHeader, + styles.sectionLocation, + ]}> + {title} + </Text> </View> ); + const renderSectionFooter = ({ + section: {title}, + }: { + section: {title: string}; + }) => { + if (title === 'Friend Requests') { + if (footerEnabled) { + return ( + <TouchableOpacity + style={styles.sectionHeaderContainer} + onPress={() => { + setRequestLimit(DEFAULT_NOTIFICATIONS_SIZE); + }}> + <View + style={[styles.sectionLocation, styles.hiddenSectionContainer]}> + <Image + style={styles.hideImageStyles} + source={require('../../assets/images/hide-caret.png')} + /> + <Text style={[styles.sectionFont, styles.sectionFooter]}> + {'Hide'} + </Text> + </View> + </TouchableOpacity> + ); + } + + if (allFriendRequests.length > DEFAULT_NOTIFICATIONS_SIZE) { + return ( + <TouchableOpacity + style={styles.sectionHeaderContainer} + onPress={() => { + setRequestLimit(allFriendRequests.length); + }}> + <Text + style={[ + styles.sectionFont, + styles.sectionFooter, + styles.sectionLocation, + ]}> + {`+ ${allFriendRequests.length - requestLimit} More`} + </Text> + </TouchableOpacity> + ); + } + } + + return null; + }; + const SPPromptNotification: ReactElement = showSPNotifyPopUp ? ( <TaggPrompt messageHeader={'New Suggested People Page!'} @@ -198,13 +286,15 @@ const NotificationsScreen: React.FC = () => { <SectionList contentContainerStyle={styles.container} sections={sectionedNotifications} - keyExtractor={(item, index) => index.toString()} + keyExtractor={(_item, index) => index.toString()} renderItem={renderNotification} renderSectionHeader={renderSectionHeader} + renderSectionFooter={renderSectionFooter} ListHeaderComponent={SPPromptNotification} refreshControl={ <RefreshControl refreshing={refreshing} onRefresh={onRefresh} /> } + extraData={requestLimit} ListEmptyComponent={ <View style={styles.emptyViewContainer}> <EmptyNotificationView /> @@ -240,16 +330,30 @@ const styles = StyleSheet.create({ }, sectionHeaderContainer: { width: '100%', + backgroundColor: 'white', }, - sectionHeader: { + + 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', diff --git a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx index 61adc171..4094b0a3 100644 --- a/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx +++ b/src/screens/suggestedPeople/SuggestedPeopleScreen.tsx @@ -8,7 +8,6 @@ import { ViewToken, } from 'react-native'; -import Animated from 'react-native-reanimated'; import {useDispatch, useSelector, useStore} from 'react-redux'; import {TabsGradient, TaggLoadingIndicator, Background} from '../../components'; import {SP_PAGE_SIZE} from '../../constants'; @@ -39,7 +38,6 @@ import SPBody from './SPBody'; */ const SuggestedPeopleScreen: React.FC = () => { - const y = Animated.useValue(0); const navigation = useNavigation(); const state: RootState = useStore().getState(); const dispatch = useDispatch(); @@ -65,6 +63,13 @@ const SuggestedPeopleScreen: React.FC = () => { people.length ? setLoading(false) : setLoading(true); }, [people]); + /* + * The randomly-generated seed used by the API to order the suggested people. + */ + const [randomizationSeed, setRandomizationSeed] = useState<number>( + Math.random(), + ); + const stausBarRef = useRef(hideStatusBar); // loads data and append it to users based on current page @@ -106,6 +111,7 @@ const SuggestedPeopleScreen: React.FC = () => { await getSuggestedPeople( SP_PAGE_SIZE, shouldResetData ? 0 : page * SP_PAGE_SIZE, + randomizationSeed, ); loadNextPage().then((newUsers) => { @@ -131,15 +137,18 @@ const SuggestedPeopleScreen: React.FC = () => { await Promise.all(users.map((user) => loadUserData(user))); }; + // TODO: only reload data, don't reset screen type, which causes the entire + // screen to re-render and makes for bad UX const onRefresh = () => { const reset = async () => { - await dispatch(resetScreenType(screenType)); + dispatch(resetScreenType(screenType)); setShouldResetData(true); }; setRefreshing(true); reset().then(() => { setRefreshing(false); }); + setRandomizationSeed(Math.random()); }; useFocusEffect( diff --git a/src/services/SuggestedPeopleService.ts b/src/services/SuggestedPeopleService.ts index e51914b0..4f56feb9 100644 --- a/src/services/SuggestedPeopleService.ts +++ b/src/services/SuggestedPeopleService.ts @@ -63,10 +63,14 @@ export const sendSuggestedPeoplePhoto = async (photoUri: string) => { } }; -export const getSuggestedPeople = async (limit: number, offset: number) => { +export const getSuggestedPeople = async ( + limit: number, + offset: number, + seed: number, +) => { try { const token = await AsyncStorage.getItem('token'); - const url = `${SP_USERS_ENDPOINT}?limit=${limit}&offset=${offset}`; + const url = `${SP_USERS_ENDPOINT}?limit=${limit}&offset=${offset}&seed=${seed}`; const response = await fetch(url, { method: 'GET', headers: { |