aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/assets/images/hide-caret.pngbin0 -> 285 bytes
-rw-r--r--src/assets/images/hide-caret@2x.pngbin0 -> 441 bytes
-rw-r--r--src/assets/images/hide-caret@3x.pngbin0 -> 603 bytes
-rw-r--r--src/components/comments/AddComment.tsx1
-rw-r--r--src/components/common/GradientBorderButton.tsx5
-rw-r--r--src/components/notifications/Notification.tsx3
-rw-r--r--src/routes/main/MainStackScreen.tsx21
-rw-r--r--src/screens/main/NotificationsScreen.tsx150
-rw-r--r--src/screens/suggestedPeople/SuggestedPeopleScreen.tsx15
-rw-r--r--src/services/SuggestedPeopleService.ts8
10 files changed, 168 insertions, 35 deletions
diff --git a/src/assets/images/hide-caret.png b/src/assets/images/hide-caret.png
new file mode 100644
index 00000000..bb05b53a
--- /dev/null
+++ b/src/assets/images/hide-caret.png
Binary files differ
diff --git a/src/assets/images/hide-caret@2x.png b/src/assets/images/hide-caret@2x.png
new file mode 100644
index 00000000..3f4689d3
--- /dev/null
+++ b/src/assets/images/hide-caret@2x.png
Binary files differ
diff --git a/src/assets/images/hide-caret@3x.png b/src/assets/images/hide-caret@3x.png
new file mode 100644
index 00000000..a44c36fe
--- /dev/null
+++ b/src/assets/images/hide-caret@3x.png
Binary files differ
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: {