From 013dfb29a603fcd51105e0fa28e8b6adc0f49b86 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Thu, 27 May 2021 15:06:14 -0400 Subject: Bug fix duplicate variables --- src/components/moments/MomentPostContent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index f485396f..c00433e7 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -38,12 +38,12 @@ const MomentPostContent: React.FC = ({ const [elapsedTime, setElapsedTime] = useState(''); const [comments_count, setCommentsCount] = useState(''); const [tags, setTags] = useState(momentTags); - const [visible, setVisible] = useState(false); + // const [visible, setVisible] = useState(false); const state: RootState = useStore().getState(); const navigation = useNavigation(); const dispatch = useDispatch(); const imageRef = useRef(null); - const [fadeValue, setFadeValue] = useState(new Animated.Value(0)); + // const [fadeValue, setFadeValue] = useState(new Animated.Value(0)); const [visible, setVisible] = useState(false); const [fadeValue, setFadeValue] = useState>( -- cgit v1.2.3-70-g09d2 From 68fcf7c533ba7612c94760b1171c506f64bfc0ae Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 1 Jun 2021 14:43:30 -0700 Subject: Filled out basic front-end, need to integrate with back-end --- ios/Podfile.lock | 4 +- src/assets/images/Profile Icon.png | Bin 0 -> 1504 bytes src/assets/images/pill-icon-1.png | Bin 0 -> 868 bytes src/assets/images/pill-icon-2.png | Bin 0 -> 1276 bytes src/assets/images/pill-icon-3.png | Bin 0 -> 1037 bytes src/assets/images/pill-icon-4.png | Bin 0 -> 1249 bytes src/assets/images/purple-tip.png | Bin 0 -> 680 bytes src/constants/constants.ts | 4 + src/routes/tabs/NavigationBar.tsx | 405 ++++++++++++++++++++++++++++++------- src/utils/common.ts | 25 +++ 10 files changed, 361 insertions(+), 77 deletions(-) create mode 100644 src/assets/images/Profile Icon.png create mode 100644 src/assets/images/pill-icon-1.png create mode 100644 src/assets/images/pill-icon-2.png create mode 100644 src/assets/images/pill-icon-3.png create mode 100644 src/assets/images/pill-icon-4.png create mode 100644 src/assets/images/purple-tip.png (limited to 'src') diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ae1e7ceb..cbd13f20 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -335,7 +335,7 @@ PODS: - React-Core - react-native-date-picker (3.3.0): - React-Core - - react-native-document-picker (5.0.3): + - react-native-document-picker (5.0.4): - React-Core - react-native-image-resizer (1.4.4): - React-Core @@ -740,7 +740,7 @@ SPEC CHECKSUMS: react-native-cameraroll: 88f4e62d9ecd0e1f253abe4f685474f2ea14bfa2 react-native-contacts: 931baebf460125c5a7bbce1c4521a96c69795123 react-native-date-picker: 76fc79be2f3cad8ff1b2850fc5601e5f8107979d - react-native-document-picker: 2e6ecd112c48215e36431734d902f35201ffab0a + react-native-document-picker: 1a7518132d4a06b67f459be9bb1464a567d2b3b4 react-native-image-resizer: 13ac4af788f88af36d0353a1324401ebabd04fe4 react-native-netinfo: e849fc21ca2f4128a5726c801a82fc6f4a6db50d react-native-safe-area-context: f0906bf8bc9835ac9a9d3f97e8bde2a997d8da79 diff --git a/src/assets/images/Profile Icon.png b/src/assets/images/Profile Icon.png new file mode 100644 index 00000000..f8eae388 Binary files /dev/null and b/src/assets/images/Profile Icon.png differ diff --git a/src/assets/images/pill-icon-1.png b/src/assets/images/pill-icon-1.png new file mode 100644 index 00000000..06956c6a Binary files /dev/null and b/src/assets/images/pill-icon-1.png differ diff --git a/src/assets/images/pill-icon-2.png b/src/assets/images/pill-icon-2.png new file mode 100644 index 00000000..b2370b80 Binary files /dev/null and b/src/assets/images/pill-icon-2.png differ diff --git a/src/assets/images/pill-icon-3.png b/src/assets/images/pill-icon-3.png new file mode 100644 index 00000000..6cdf0b15 Binary files /dev/null and b/src/assets/images/pill-icon-3.png differ diff --git a/src/assets/images/pill-icon-4.png b/src/assets/images/pill-icon-4.png new file mode 100644 index 00000000..6e132647 Binary files /dev/null and b/src/assets/images/pill-icon-4.png differ diff --git a/src/assets/images/purple-tip.png b/src/assets/images/purple-tip.png new file mode 100644 index 00000000..27f5a89a Binary files /dev/null and b/src/assets/images/purple-tip.png differ diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 99d3901b..e6c23554 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -21,6 +21,9 @@ export const AVATAR_GRADIENT_DIM = 50; export const TAGG_ICON_DIM = 58; export const TAGG_RING_DIM = normalize(60); +// default height of the navigation bar, from react native library, unless on ipad +export const NAV_BAR_HEIGHT = 49; + export const INTEGRATED_SOCIAL_LIST: string[] = [ 'Instagram', 'Facebook', @@ -89,6 +92,7 @@ export const BADGE_GRADIENT_REST = [ 'rgba(78, 54, 41, 1)', 'rgba(236, 32, 39, 1)', ]; +export const NOTIFICATION_ICON_GRADIENT = ['#8F01FF', '#7B02DA']; export const SOCIAL_FONT_COLORS = { INSTAGRAM: INSTAGRAM_FONT_COLOR, diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 000ac614..0e08d834 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -1,12 +1,26 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; -import React, {Fragment, useEffect, useState} from 'react'; +import React, {Fragment, useEffect, useState, useRef} from 'react'; +import {Image, StyleSheet, Text, View} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import {ScreenType} from '../../types'; -import {haveUnreadNotifications} from '../../utils'; +import {ScreenType, NotificationType} from '../../types'; +import { + haveUnreadNotifications, + getUnreadNotifications, + SCREEN_WIDTH, + isIPhoneX, +} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; +import { + NOTIFICATION_ICON_GRADIENT, + CHIN_HEIGHT, + NAV_BAR_HEIGHT, +} from '../../constants'; +import {normalize} from 'react-native-elements'; +import {numberWithCommas} from '../../utils'; const Tabs = createBottomTabNavigator(); @@ -19,8 +33,47 @@ const NavigationBar: React.FC = () => { (state: RootState) => state, ); - const [unreadNotificationsPresent, setUnreadNotificationsPresent] = - useState(false); + const [unread, setUnread] = useState({ + CMT: 4, + FR_REQ: 5, + PR_V: 3, + TAG: 7, + }); + const [showIcon, setShowIcon] = useState(true); + const [iconStart, setIconStart] = useState([0, -100]); + const [tipStart, setTipStart] = useState([0, -100]); + const [complete, setComplete] = useState(false); + const [notificationSets, setNotificationSets] = useState({ + CMT: 412314213123, + FR_REQ: 52131, + PR_V: 3, + TAG: 712321, + }); + const [timeCount, setTimeCount] = useState(false); + const iconRef = useRef(null); + const tipRef = useRef(null); + const pillTip = require('../../assets/images/purple-tip.png'); + + const navBarPos = 20; + const tipSize = 8; + + const [ + unreadNotificationsPresent, + setUnreadNotificationsPresent, + ] = useState(false); + + const countNotifications = ( + notificationsList: NotificationType[], + values: string[], + ) => { + let outputNum = 0; + for (const n of notificationsList) { + if (values.includes(n.notification_type)) { + outputNum++; + } + } + return outputNum; + }; useEffect(() => { const determine = async () => { @@ -28,82 +81,284 @@ const NavigationBar: React.FC = () => { await haveUnreadNotifications(notifications), ); }; + // const establishUnread = async () => { + // setUnread(await getUnreadNotifications(notifications)); + // }; determine(); + // establishUnread(); }, [notifications]); + useEffect(() => { + setTimeout(() => { + console.log('notifications', notifications.length, 'unread', unread); + if (iconRef.current) { + iconRef.current.measure( + ( + _fx: number, + _fy: number, + width: number, + height: number, + _px: number, + _py: number, + ) => { + console.log('HERE 1'); + if (tipRef.current) { + tipRef.current.measure( + ( + __fx: number, + __fy: number, + width2: number, + __height: number, + __px: number, + __py: number, + ) => { + const x = SCREEN_WIDTH / 2 - width / 2; + const y = isIPhoneX() + ? CHIN_HEIGHT + NAV_BAR_HEIGHT + navBarPos + : NAV_BAR_HEIGHT + navBarPos; + setIconStart([x, y]); + setTipStart([width / 2 - width2 / 2, height - 1]); + setTimeout(() => { + setComplete(true); + console.log('HERE 2'); + }, 100); + setTimeCount(true); + }, + ); + } + }, + ); + } else { + console.log('ISSUE', iconRef.current); + } + }, 100); + }, [unread, iconRef, tipRef]); + + useEffect(() => { + if (timeCount) { + setTimeout(() => { + setShowIcon(false); + }, 5000); + } + }, [timeCount]); + + useEffect(() => { + setTimeout(() => { + console.log('complete', complete); + }, 100); + }, [complete]); + + useEffect(() => { + setTimeout(() => { + console.log('iconRef', iconRef); + }, 60000); + }); + return ( - ({ - tabBarIcon: ({focused}) => { - switch (route.name) { - case 'Home': - return ; - case 'Search': - return ; - case 'Upload': - return ; - case 'Notifications': - return ( - + {unread && Object.keys(unread).length !== 0 && showIcon && ( + + + {notificationSets.CMT && ( + <> + - ); - case 'Chat': - return ; - case 'Profile': - return ; - case 'SuggestedPeople': - return ( - - ); - default: - return ; - } - }, - })} - initialRouteName={isOnboardedUser ? 'Profile' : 'SuggestedPeople'} - tabBarOptions={{ - showLabel: false, - style: { - backgroundColor: 'transparent', - position: 'absolute', - borderTopWidth: 0, - left: 0, - right: 0, - bottom: '1%', - }, - }}> - - - - - - + + {numberWithCommas(notificationSets.CMT)} + + + )} + {notificationSets.FR_REQ && ( + <> + + + {numberWithCommas(notificationSets.FR_REQ)} + + + )} + {notificationSets.PR_V && ( + <> + + + {numberWithCommas(notificationSets.PR_V)} + + + )} + {notificationSets.TAG && ( + <> + + + {numberWithCommas(notificationSets.TAG)} + + + )} + + + + )} + ({ + tabBarIcon: ({focused}) => { + switch (route.name) { + case 'Home': + return ; + case 'Search': + return ; + case 'Upload': + return ; + case 'Notifications': + return ( + + ); + case 'Chat': + return ; + case 'Profile': + return ; + case 'SuggestedPeople': + return ( + + ); + default: + return ; + } + }, + })} + initialRouteName={isOnboardedUser ? 'Profile' : 'SuggestedPeople'} + tabBarOptions={{ + showLabel: false, + style: { + backgroundColor: 'transparent', + position: 'absolute', + borderTopWidth: 0, + left: 0, + right: 0, + bottom: '1%', + }, + }}> + { + setShowIcon(true); + }, + }} + /> + { + setShowIcon(true); + }, + }} + /> + { + setShowIcon(false); + }, + }} + /> + { + setShowIcon(true); + }, + }} + /> + { + setShowIcon(true); + }, + }} + /> + + ); }; +const styles = StyleSheet.create({ + purpleContainer: { + // borderWidth: 1, + flex: 1, + justifyContent: 'center', + position: 'absolute', + zIndex: 999, + // flexDirection: 'row', + // bottom: 50, + // height: normalize(20), + }, + iconPurple: { + padding: 5, + borderRadius: 15, + flex: 1, + flexDirection: 'row', + // justifyContent: 'center', + // alignContent: 'center', + alignItems: 'center', + }, + text: { + margin: 2, + color: 'white', + fontSize: normalize(10), + justifyContent: 'center', + alignItems: 'center', + }, + tip: { + // borderWidth: 1, + position: 'absolute', + zIndex: 999, + height: 12, + // aspectRatio: 12 / 8, + flex: 1, + resizeMode: 'contain', + }, + indicationIcon: { + height: 15, + width: 15, + margin: 2, + }, +}); + export default NavigationBar; diff --git a/src/utils/common.ts b/src/utils/common.ts index 95e77f64..9d0de64b 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -101,6 +101,27 @@ export const haveUnreadNotifications = async ( return false; }; +export const getUnreadNotifications = async ( + notifications: NotificationType[], +): Promise => { + const outputNotifications = []; + for (const n of notifications) { + const notificationDate = moment(n.timestamp); + const prevLastViewed = await AsyncStorage.getItem('notificationLastViewed'); + const lastViewed: moment.Moment | undefined = + prevLastViewed == null ? moment.unix(0) : moment(prevLastViewed); + const dateAge = getDateAge(notificationDate); + if (dateAge === 'unknown') { + continue; + } + const unread = lastViewed ? lastViewed.diff(notificationDate) < 0 : false; + if (unread) { + outputNotifications.push(n); + } + } + return outputNotifications; +}; + // https://stackoverflow.com/a/2450976 export const shuffle = (array: any[]) => { var currentIndex = array.length, @@ -197,3 +218,7 @@ export const validateImageLink = async (url: string | undefined) => { return false; }); }; + +export const numberWithCommas = (digits: number) => { + return digits.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); +}; -- cgit v1.2.3-70-g09d2 From 43a420ec518f122b684bb9d2f4dd4043bf65d2d2 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Wed, 2 Jun 2021 11:58:59 -0700 Subject: Some cosmetic changes --- src/assets/images/Group 479.jpg | Bin 0 -> 753 bytes src/assets/images/Group 479.svg | 5 ++ src/routes/tabs/NavigationBar.tsx | 185 +++++++++++++++++--------------------- 3 files changed, 87 insertions(+), 103 deletions(-) create mode 100644 src/assets/images/Group 479.jpg create mode 100644 src/assets/images/Group 479.svg (limited to 'src') diff --git a/src/assets/images/Group 479.jpg b/src/assets/images/Group 479.jpg new file mode 100644 index 00000000..74abad92 Binary files /dev/null and b/src/assets/images/Group 479.jpg differ diff --git a/src/assets/images/Group 479.svg b/src/assets/images/Group 479.svg new file mode 100644 index 00000000..4e1eee01 --- /dev/null +++ b/src/assets/images/Group 479.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 0e08d834..1693d057 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -6,13 +6,8 @@ import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import {ScreenType, NotificationType} from '../../types'; -import { - haveUnreadNotifications, - getUnreadNotifications, - SCREEN_WIDTH, - isIPhoneX, -} from '../../utils'; +import {ScreenType} from '../../types'; +import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; import { NOTIFICATION_ICON_GRADIENT, @@ -21,6 +16,7 @@ import { } from '../../constants'; import {normalize} from 'react-native-elements'; import {numberWithCommas} from '../../utils'; +import PillIcon4 from '../../assets/images/Group 479.svg'; const Tabs = createBottomTabNavigator(); @@ -32,13 +28,6 @@ const NavigationBar: React.FC = () => { const {notifications: {notifications} = NO_NOTIFICATIONS} = useSelector( (state: RootState) => state, ); - - const [unread, setUnread] = useState({ - CMT: 4, - FR_REQ: 5, - PR_V: 3, - TAG: 7, - }); const [showIcon, setShowIcon] = useState(true); const [iconStart, setIconStart] = useState([0, -100]); const [tipStart, setTipStart] = useState([0, -100]); @@ -50,31 +39,18 @@ const NavigationBar: React.FC = () => { TAG: 712321, }); const [timeCount, setTimeCount] = useState(false); + const [timeOut, setTimeOut] = useState(false); const iconRef = useRef(null); const tipRef = useRef(null); const pillTip = require('../../assets/images/purple-tip.png'); const navBarPos = 20; - const tipSize = 8; const [ unreadNotificationsPresent, setUnreadNotificationsPresent, ] = useState(false); - const countNotifications = ( - notificationsList: NotificationType[], - values: string[], - ) => { - let outputNum = 0; - for (const n of notificationsList) { - if (values.includes(n.notification_type)) { - outputNum++; - } - } - return outputNum; - }; - useEffect(() => { const determine = async () => { setUnreadNotificationsPresent( @@ -90,7 +66,12 @@ const NavigationBar: React.FC = () => { useEffect(() => { setTimeout(() => { - console.log('notifications', notifications.length, 'unread', unread); + console.log( + 'notifications', + notifications.length, + 'unread', + notificationSets, + ); if (iconRef.current) { iconRef.current.measure( ( @@ -132,12 +113,12 @@ const NavigationBar: React.FC = () => { console.log('ISSUE', iconRef.current); } }, 100); - }, [unread, iconRef, tipRef]); + }, [notificationSets, iconRef, tipRef]); useEffect(() => { if (timeCount) { setTimeout(() => { - setShowIcon(false); + setTimeOut(true); }, 5000); } }, [timeCount]); @@ -156,68 +137,68 @@ const NavigationBar: React.FC = () => { return ( <> - {unread && Object.keys(unread).length !== 0 && showIcon && ( - - - {notificationSets.CMT && ( - <> - - - {numberWithCommas(notificationSets.CMT)} - - - )} - {notificationSets.FR_REQ && ( - <> - - - {numberWithCommas(notificationSets.FR_REQ)} - - - )} - {notificationSets.PR_V && ( - <> - - - {numberWithCommas(notificationSets.PR_V)} - - - )} - {notificationSets.TAG && ( - <> - - - {numberWithCommas(notificationSets.TAG)} - - - )} - - - - )} + {notificationSets && + Object.keys(notificationSets).length !== 0 && + showIcon && + !timeOut && ( + + + {notificationSets.CMT && ( + <> + + + {numberWithCommas(notificationSets.CMT)} + + + )} + {notificationSets.FR_REQ && ( + <> + + + {numberWithCommas(notificationSets.FR_REQ)} + + + )} + {notificationSets.PR_V && ( + <> + + + {numberWithCommas(notificationSets.PR_V)} + + + )} + {notificationSets.TAG && ( + <> + + + {numberWithCommas(notificationSets.TAG)} + + + )} + + + + )} ({ tabBarIcon: ({focused}) => { @@ -320,22 +301,16 @@ const NavigationBar: React.FC = () => { const styles = StyleSheet.create({ purpleContainer: { - // borderWidth: 1, flex: 1, justifyContent: 'center', position: 'absolute', zIndex: 999, - // flexDirection: 'row', - // bottom: 50, - // height: normalize(20), }, iconPurple: { padding: 5, borderRadius: 15, flex: 1, flexDirection: 'row', - // justifyContent: 'center', - // alignContent: 'center', alignItems: 'center', }, text: { @@ -344,21 +319,25 @@ const styles = StyleSheet.create({ fontSize: normalize(10), justifyContent: 'center', alignItems: 'center', + marginRight: 10, }, tip: { - // borderWidth: 1, position: 'absolute', zIndex: 999, height: 12, - // aspectRatio: 12 / 8, flex: 1, resizeMode: 'contain', }, indicationIcon: { - height: 15, - width: 15, + height: 14, + width: 14, margin: 2, }, + svgIndicationIcon: { + height: 14, + width: 14, + margin: 3, + }, }); export default NavigationBar; -- cgit v1.2.3-70-g09d2 From f26079e3fcae59f0a97fe31fc29a9f4a43811cbb Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Wed, 2 Jun 2021 16:18:25 -0700 Subject: Removed excess function --- src/utils/common.ts | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'src') diff --git a/src/utils/common.ts b/src/utils/common.ts index 9d0de64b..049dae90 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -101,27 +101,6 @@ export const haveUnreadNotifications = async ( return false; }; -export const getUnreadNotifications = async ( - notifications: NotificationType[], -): Promise => { - const outputNotifications = []; - for (const n of notifications) { - const notificationDate = moment(n.timestamp); - const prevLastViewed = await AsyncStorage.getItem('notificationLastViewed'); - const lastViewed: moment.Moment | undefined = - prevLastViewed == null ? moment.unix(0) : moment(prevLastViewed); - const dateAge = getDateAge(notificationDate); - if (dateAge === 'unknown') { - continue; - } - const unread = lastViewed ? lastViewed.diff(notificationDate) < 0 : false; - if (unread) { - outputNotifications.push(n); - } - } - return outputNotifications; -}; - // https://stackoverflow.com/a/2450976 export const shuffle = (array: any[]) => { var currentIndex = array.length, -- cgit v1.2.3-70-g09d2 From 19630f8bc3b4b53244007e08436c5be67a4d7ef1 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Mon, 7 Jun 2021 15:58:08 +0900 Subject: Basic integration with API --- src/constants/api.ts | 1 + src/routes/tabs/NavigationBar.tsx | 31 ++++++------ src/services/NotificationService.ts | 99 +++++++++++++++++++++++++++---------- 3 files changed, 91 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/constants/api.ts b/src/constants/api.ts index f02ee407..8d2e1a1e 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -45,6 +45,7 @@ export const BLOCK_USER_ENDPOINT: string = API_URL + 'block/'; export const PASSWORD_RESET_ENDPOINT: string = API_URL + 'password-reset/'; export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/'; export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/'; +export const NOTIFICATIONS_COUNT_ENDPOINT: string = API_URL + 'notifications/unread_count/' export const DISCOVER_ENDPOINT: string = API_URL + 'discover/'; export const SEARCH_BUTTONS_ENDPOPINT: string = DISCOVER_ENDPOINT + 'search_buttons/'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 1693d057..3359fc0d 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -6,6 +6,7 @@ import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; +import {getNotificationsUnreadCount} from '../../services'; import {ScreenType} from '../../types'; import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; @@ -32,12 +33,7 @@ const NavigationBar: React.FC = () => { const [iconStart, setIconStart] = useState([0, -100]); const [tipStart, setTipStart] = useState([0, -100]); const [complete, setComplete] = useState(false); - const [notificationSets, setNotificationSets] = useState({ - CMT: 412314213123, - FR_REQ: 52131, - PR_V: 3, - TAG: 712321, - }); + const [notificationSets, setNotificationSets] = useState({}); const [timeCount, setTimeCount] = useState(false); const [timeOut, setTimeOut] = useState(false); const iconRef = useRef(null); @@ -130,10 +126,17 @@ const NavigationBar: React.FC = () => { }, [complete]); useEffect(() => { - setTimeout(() => { - console.log('iconRef', iconRef); - }, 60000); - }); + // setTimeout(() => { + // console.log('iconRef', iconRef); + // }, 60000); + + const getCount = async () => { + const data = await getNotificationsUnreadCount(); + setNotificationSets(data); + }; + + getCount(); + }, []); return ( <> @@ -172,22 +175,22 @@ const NavigationBar: React.FC = () => { )} - {notificationSets.PR_V && ( + {notificationSets.P_VIEW && ( <> - {numberWithCommas(notificationSets.PR_V)} + {numberWithCommas(notificationSets.P_VIEW)} )} - {notificationSets.TAG && ( + {notificationSets.MOM_TAG && ( <> - {numberWithCommas(notificationSets.TAG)} + {numberWithCommas(notificationSets.MOM_TAG)} )} diff --git a/src/services/NotificationService.ts b/src/services/NotificationService.ts index c5c843f5..92f1cdd1 100644 --- a/src/services/NotificationService.ts +++ b/src/services/NotificationService.ts @@ -1,31 +1,78 @@ import AsyncStorage from '@react-native-community/async-storage'; -import {NOTIFICATIONS_ENDPOINT} from '../constants'; +import { + NOTIFICATIONS_ENDPOINT, + NOTIFICATIONS_COUNT_ENDPOINT, +} from '../constants'; import {NotificationType} from '../types'; -export const getNotificationsData: () => Promise = - async () => { - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(NOTIFICATIONS_ENDPOINT, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - if (response.status === 200) { - const data: any[] = await response.json(); - let typedData: NotificationType[] = []; - for (const o of data) { - typedData.push({ - ...o.notification, - unread: false, - }); - } - return typedData; +export const getNotificationsData: () => Promise< + NotificationType[] +> = async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_ENDPOINT, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 200) { + const data: any[] = await response.json(); + let typedData: NotificationType[] = []; + for (const o of data) { + typedData.push({ + ...o.notification, + unread: false, + }); } - return []; - } catch (error) { - console.log('Unable to fetch notifications'); - return []; + return typedData; } - }; + return []; + } catch (error) { + console.log('Unable to fetch notifications'); + return []; + } +}; + +export const getNotificationsUnreadCount: () => Promise<{ + CMT?: number; + FRD_REQ?: number; + P_VIEW?: number; + MOM_TAG?: number; +}> = async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_COUNT_ENDPOINT, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 200) { + const data: any = await response.json(); + const typedData: { + CMT?: number; + FRD_REQ?: number; + P_VIEW?: number; + MOM_TAG?: number; + } = {}; + if (data.CMT && data.CMT > 0) { + typedData.CMT = data.CMT; + } + if (data.FRD_REQ && data.FRD_REQ > 0) { + typedData.FRD_REQ = data.FRD_REQ; + } + if (data.P_VIEW && data.P_VIEW > 0) { + typedData.P_VIEW = data.P_VIEW; + } + if (data.MOM_TAG && data.MOM_TAG > 0) { + typedData.MOM_TAG = data.MOM_TAG; + } + return typedData; + } + return []; + } catch (error) { + console.log('Unable to fetch notifications'); + return []; + } +}; -- cgit v1.2.3-70-g09d2 From 2ab67a10be5305ed54464688c4147a493bfed8f6 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 08:14:37 +0900 Subject: Clean up --- src/routes/tabs/NavigationBar.tsx | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 3359fc0d..4b291023 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -32,7 +32,6 @@ const NavigationBar: React.FC = () => { const [showIcon, setShowIcon] = useState(true); const [iconStart, setIconStart] = useState([0, -100]); const [tipStart, setTipStart] = useState([0, -100]); - const [complete, setComplete] = useState(false); const [notificationSets, setNotificationSets] = useState({}); const [timeCount, setTimeCount] = useState(false); const [timeOut, setTimeOut] = useState(false); @@ -53,21 +52,11 @@ const NavigationBar: React.FC = () => { await haveUnreadNotifications(notifications), ); }; - // const establishUnread = async () => { - // setUnread(await getUnreadNotifications(notifications)); - // }; determine(); - // establishUnread(); }, [notifications]); useEffect(() => { setTimeout(() => { - console.log( - 'notifications', - notifications.length, - 'unread', - notificationSets, - ); if (iconRef.current) { iconRef.current.measure( ( @@ -78,7 +67,6 @@ const NavigationBar: React.FC = () => { _px: number, _py: number, ) => { - console.log('HERE 1'); if (tipRef.current) { tipRef.current.measure( ( @@ -95,10 +83,6 @@ const NavigationBar: React.FC = () => { : NAV_BAR_HEIGHT + navBarPos; setIconStart([x, y]); setTipStart([width / 2 - width2 / 2, height - 1]); - setTimeout(() => { - setComplete(true); - console.log('HERE 2'); - }, 100); setTimeCount(true); }, ); @@ -106,7 +90,6 @@ const NavigationBar: React.FC = () => { }, ); } else { - console.log('ISSUE', iconRef.current); } }, 100); }, [notificationSets, iconRef, tipRef]); @@ -120,19 +103,12 @@ const NavigationBar: React.FC = () => { }, [timeCount]); useEffect(() => { - setTimeout(() => { - console.log('complete', complete); - }, 100); - }, [complete]); - - useEffect(() => { - // setTimeout(() => { - // console.log('iconRef', iconRef); - // }, 60000); - const getCount = async () => { - const data = await getNotificationsUnreadCount(); - setNotificationSets(data); + // const data = await getNotificationsUnreadCount(); + const data = {}; + setTimeout(() => { + setNotificationSets(data); + }, 100); }; getCount(); -- cgit v1.2.3-70-g09d2 From 9c48eeee298eacf781f25907c231f503edb4c5a4 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 18:17:21 +0900 Subject: Integrate with backend --- src/constants/api.ts | 3 +- src/routes/tabs/NavigationBar.tsx | 34 ++++++++++-------- src/services/NotificationService.ts | 72 +++++++++++++++++++++++-------------- 3 files changed, 67 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/constants/api.ts b/src/constants/api.ts index 8d2e1a1e..b55489d9 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -45,7 +45,8 @@ export const BLOCK_USER_ENDPOINT: string = API_URL + 'block/'; export const PASSWORD_RESET_ENDPOINT: string = API_URL + 'password-reset/'; export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/'; export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/'; -export const NOTIFICATIONS_COUNT_ENDPOINT: string = API_URL + 'notifications/unread_count/' +export const NOTIFICATIONS_COUNT_ENDPOINT: string = API_URL + 'notifications/unread_count/'; +export const NOTIFICATIONS_DATE: string = API_URL + 'notifications/seen/'; export const DISCOVER_ENDPOINT: string = API_URL + 'discover/'; export const SEARCH_BUTTONS_ENDPOPINT: string = DISCOVER_ENDPOINT + 'search_buttons/'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 4b291023..77131098 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -6,7 +6,10 @@ import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import {getNotificationsUnreadCount} from '../../services'; +import { + getNotificationsUnreadCount, + setNotificationsReadDate, +} from '../../services'; import {ScreenType} from '../../types'; import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; @@ -41,10 +44,8 @@ const NavigationBar: React.FC = () => { const navBarPos = 20; - const [ - unreadNotificationsPresent, - setUnreadNotificationsPresent, - ] = useState(false); + const [unreadNotificationsPresent, setUnreadNotificationsPresent] = + useState(false); useEffect(() => { const determine = async () => { @@ -56,6 +57,7 @@ const NavigationBar: React.FC = () => { }, [notifications]); useEffect(() => { + console.log('notifications', notificationSets); setTimeout(() => { if (iconRef.current) { iconRef.current.measure( @@ -94,18 +96,18 @@ const NavigationBar: React.FC = () => { }, 100); }, [notificationSets, iconRef, tipRef]); - useEffect(() => { - if (timeCount) { - setTimeout(() => { - setTimeOut(true); - }, 5000); - } - }, [timeCount]); + // useEffect(() => { + // if (timeCount) { + // setTimeout(() => { + // setTimeOut(true); + // }, 5000); + // } + // }, [timeCount]); useEffect(() => { const getCount = async () => { - // const data = await getNotificationsUnreadCount(); - const data = {}; + const data = await getNotificationsUnreadCount(); + // const data = {}; setTimeout(() => { setNotificationSets(data); }, 100); @@ -250,6 +252,7 @@ const NavigationBar: React.FC = () => { listeners={{ tabPress: (_) => { setShowIcon(false); + setNotificationsReadDate(); }, }} /> @@ -298,7 +301,7 @@ const styles = StyleSheet.create({ fontSize: normalize(10), justifyContent: 'center', alignItems: 'center', - marginRight: 10, + marginRight: 5, }, tip: { position: 'absolute', @@ -311,6 +314,7 @@ const styles = StyleSheet.create({ height: 14, width: 14, margin: 2, + marginLeft: 5, }, svgIndicationIcon: { height: 14, diff --git a/src/services/NotificationService.ts b/src/services/NotificationService.ts index 92f1cdd1..3c0245a5 100644 --- a/src/services/NotificationService.ts +++ b/src/services/NotificationService.ts @@ -2,37 +2,37 @@ import AsyncStorage from '@react-native-community/async-storage'; import { NOTIFICATIONS_ENDPOINT, NOTIFICATIONS_COUNT_ENDPOINT, + NOTIFICATIONS_DATE, } from '../constants'; import {NotificationType} from '../types'; -export const getNotificationsData: () => Promise< - NotificationType[] -> = async () => { - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(NOTIFICATIONS_ENDPOINT, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - if (response.status === 200) { - const data: any[] = await response.json(); - let typedData: NotificationType[] = []; - for (const o of data) { - typedData.push({ - ...o.notification, - unread: false, - }); +export const getNotificationsData: () => Promise = + async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_ENDPOINT, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 200) { + const data: any[] = await response.json(); + let typedData: NotificationType[] = []; + for (const o of data) { + typedData.push({ + ...o.notification, + unread: false, + }); + } + return typedData; } - return typedData; + return []; + } catch (error) { + console.log('Unable to fetch notifications'); + return []; } - return []; - } catch (error) { - console.log('Unable to fetch notifications'); - return []; - } -}; + }; export const getNotificationsUnreadCount: () => Promise<{ CMT?: number; @@ -76,3 +76,23 @@ export const getNotificationsUnreadCount: () => Promise<{ return []; } }; + +export const setNotificationsReadDate: () => Promise = async () => { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(NOTIFICATIONS_DATE, { + method: 'POST', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 204) { + return true; + } else { + return false; + } + } catch (error) { + console.log('Unable to fetch notifications'); + return false; + } +}; -- cgit v1.2.3-70-g09d2 From 4636694489159c5f9edf0238460bde08e2219f80 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 18:18:14 +0900 Subject: Remove some excess comments --- src/routes/tabs/NavigationBar.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index 77131098..fa129a23 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -96,13 +96,13 @@ const NavigationBar: React.FC = () => { }, 100); }, [notificationSets, iconRef, tipRef]); - // useEffect(() => { - // if (timeCount) { - // setTimeout(() => { - // setTimeOut(true); - // }, 5000); - // } - // }, [timeCount]); + useEffect(() => { + if (timeCount) { + setTimeout(() => { + setTimeOut(true); + }, 5000); + } + }, [timeCount]); useEffect(() => { const getCount = async () => { -- cgit v1.2.3-70-g09d2 From 2f66fec878e9bba15ac7f2397820bb48d3f167bb Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Tue, 8 Jun 2021 18:21:26 +0900 Subject: Add documentation --- src/routes/tabs/NavigationBar.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index fa129a23..e962c8da 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -47,6 +47,8 @@ const NavigationBar: React.FC = () => { const [unreadNotificationsPresent, setUnreadNotificationsPresent] = useState(false); + // Prior to pill inclusion, determines if notification bell + // should have purple dot useEffect(() => { const determine = async () => { setUnreadNotificationsPresent( @@ -56,8 +58,9 @@ const NavigationBar: React.FC = () => { determine(); }, [notifications]); + // If there are notifications, determines the size of the pill + // and sets points for correct placement useEffect(() => { - console.log('notifications', notificationSets); setTimeout(() => { if (iconRef.current) { iconRef.current.measure( @@ -96,6 +99,7 @@ const NavigationBar: React.FC = () => { }, 100); }, [notificationSets, iconRef, tipRef]); + // Used so that pill disappears after 5 seconds useEffect(() => { if (timeCount) { setTimeout(() => { @@ -104,10 +108,10 @@ const NavigationBar: React.FC = () => { } }, [timeCount]); + // Gets data from backend to check for unreads useEffect(() => { const getCount = async () => { const data = await getNotificationsUnreadCount(); - // const data = {}; setTimeout(() => { setNotificationSets(data); }, 100); @@ -229,6 +233,8 @@ const NavigationBar: React.FC = () => { name="SuggestedPeople" component={MainStackScreen} initialParams={{screenType: ScreenType.SuggestedPeople}} + // Added these to as a way to close pill when on + // notification page listeners={{ tabPress: (_) => { setShowIcon(true); @@ -252,6 +258,7 @@ const NavigationBar: React.FC = () => { listeners={{ tabPress: (_) => { setShowIcon(false); + // Updates backend's date of reading notifications setNotificationsReadDate(); }, }} -- cgit v1.2.3-70-g09d2 From fb9aaaa3ff24497ee1a06c6c85c2bbbc835335e0 Mon Sep 17 00:00:00 2001 From: brian-tagg <83606050+brian-tagg@users.noreply.github.com> Date: Wed, 9 Jun 2021 00:47:27 +0900 Subject: Update src/services/NotificationService.ts Co-authored-by: Ivan Chen --- src/services/NotificationService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/services/NotificationService.ts b/src/services/NotificationService.ts index 3c0245a5..2ffc85b2 100644 --- a/src/services/NotificationService.ts +++ b/src/services/NotificationService.ts @@ -56,7 +56,7 @@ export const getNotificationsUnreadCount: () => Promise<{ P_VIEW?: number; MOM_TAG?: number; } = {}; - if (data.CMT && data.CMT > 0) { + if (data.CMT) { typedData.CMT = data.CMT; } if (data.FRD_REQ && data.FRD_REQ > 0) { -- cgit v1.2.3-70-g09d2 From 7316bc3b11d84224ae91a12ec07c97915b0d6c60 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Tue, 8 Jun 2021 11:19:31 -0700 Subject: Add edit option to bottom drawer, Style --- src/components/common/GenericMoreInfoDrawer.tsx | 14 +++++------ src/components/profile/MomentMoreInfoDrawer.tsx | 32 +++++++++++++++++++----- src/components/profile/ProfileMoreInfoDrawer.tsx | 5 ++-- 3 files changed, 35 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/components/common/GenericMoreInfoDrawer.tsx b/src/components/common/GenericMoreInfoDrawer.tsx index 0928ed44..cfc45131 100644 --- a/src/components/common/GenericMoreInfoDrawer.tsx +++ b/src/components/common/GenericMoreInfoDrawer.tsx @@ -3,15 +3,16 @@ import { GestureResponderEvent, StyleSheet, Text, + TextStyle, TouchableOpacity, View, ViewProps, ViewStyle, } from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; -import BottomDrawer from './BottomDrawer'; import {TAGG_LIGHT_BLUE} from '../../constants'; import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; +import BottomDrawer from './BottomDrawer'; // conforms the JSX onPress attribute type type OnPressHandler = (event: GestureResponderEvent) => void; @@ -20,13 +21,12 @@ interface GenericMoreInfoDrawerProps extends ViewProps { isOpen: boolean; setIsOpen: (visible: boolean) => void; showIcons: boolean; - textColor: string; // An array of title, onPressHandler, and icon component - buttons: [string, OnPressHandler, JSX.Element?][]; + buttons: [string, OnPressHandler, JSX.Element?, TextStyle?][]; } const GenericMoreInfoDrawer: React.FC = (props) => { - const {buttons, showIcons, textColor} = props; + const {buttons, showIcons} = props; // each button is 80px high, cancel button is always there const initialSnapPosition = (buttons.length + 1) * 80 + useSafeAreaInsets().bottom; @@ -44,13 +44,11 @@ const GenericMoreInfoDrawer: React.FC = (props) => { showHeader={false} initialSnapPosition={initialSnapPosition}> - {buttons.map(([title, action, icon], index) => ( + {buttons.map(([title, action, icon, textStyle], index) => ( {showIcons && {icon}} - - {title} - + {title} diff --git a/src/components/profile/MomentMoreInfoDrawer.tsx b/src/components/profile/MomentMoreInfoDrawer.tsx index 1265497e..a5411935 100644 --- a/src/components/profile/MomentMoreInfoDrawer.tsx +++ b/src/components/profile/MomentMoreInfoDrawer.tsx @@ -1,20 +1,24 @@ +import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; import { Alert, GestureResponderEvent, StyleSheet, + TextStyle, TouchableOpacity, ViewProps, } from 'react-native'; import MoreIcon from '../../assets/icons/more_horiz-24px.svg'; import {ERROR_DELETE_MOMENT, MOMENT_DELETED_MSG} from '../../constants/strings'; import {deleteMoment, sendReport} from '../../services'; +import {ScreenType} from '../../types/types'; import {GenericMoreInfoDrawer} from '../common'; enum MomentDrawerOptions { DeleteMoment = 'Delete Moment', ReportIssue = 'Report an Issue', RemoveTag = 'Remove yourself from moment', + EditMoment = 'Edit Moment', } interface MomentMoreInfoDrawerProps extends ViewProps { isOpen: boolean; @@ -105,12 +109,27 @@ const MomentMoreInfoDrawer: React.FC = (props) => { }; const [drawerButtons, setDrawerButtons] = useState< - [string, (event: GestureResponderEvent) => void, JSX.Element?][] - >([ + [string, (event: GestureResponderEvent) => void, JSX.Element?, TextStyle?][] + >( isOwnProfile - ? [MomentDrawerOptions.DeleteMoment, handleDeleteMoment] - : [MomentDrawerOptions.ReportIssue, handleReportMoment], - ]); + ? [ + [ + MomentDrawerOptions.DeleteMoment, + handleDeleteMoment, + undefined, + {color: 'red'}, + ], + [MomentDrawerOptions.EditMoment, handleEditMoment], + ] + : [ + [ + MomentDrawerOptions.ReportIssue, + handleReportMoment, + undefined, + {color: 'red'}, + ], + ], + ); /* * Update bottom drawer options to contain/not contain 'remove tag' option @@ -129,6 +148,8 @@ const MomentMoreInfoDrawer: React.FC = (props) => { localDrawerButtons.push([ MomentDrawerOptions.RemoveTag, handleRemoveTag, + undefined, + {color: 'red'}, ]); setDrawerButtons(localDrawerButtons); } else if (momentTagId === '' && present !== -1) { @@ -153,7 +174,6 @@ const MomentMoreInfoDrawer: React.FC = (props) => { diff --git a/src/components/profile/ProfileMoreInfoDrawer.tsx b/src/components/profile/ProfileMoreInfoDrawer.tsx index ecc45211..656f81bb 100644 --- a/src/components/profile/ProfileMoreInfoDrawer.tsx +++ b/src/components/profile/ProfileMoreInfoDrawer.tsx @@ -55,12 +55,12 @@ const ProfileMoreInfoDrawer: React.FC = (props) => { @@ -68,7 +68,6 @@ const ProfileMoreInfoDrawer: React.FC = (props) => { = (props) => { source={require('../../assets/images/settings/settings.png')} style={styles.image} />, + {color: 'black'}, ], [ 'Edit Profile', @@ -85,6 +85,7 @@ const ProfileMoreInfoDrawer: React.FC = (props) => { source={require('../../assets/images/settings/edit-profile.png')} style={styles.image} />, + {color: 'black'}, ], ]} /> -- cgit v1.2.3-70-g09d2 From 65eba8b9be14a397bf49fc3b419d3e64bd0422b7 Mon Sep 17 00:00:00 2001 From: hsalhab Date: Tue, 8 Jun 2021 15:30:35 -0400 Subject: add empty website to submission --- src/screens/profile/EditProfile.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/screens/profile/EditProfile.tsx b/src/screens/profile/EditProfile.tsx index 26802e45..765bbf01 100644 --- a/src/screens/profile/EditProfile.tsx +++ b/src/screens/profile/EditProfile.tsx @@ -305,14 +305,13 @@ const EditProfile: React.FC = ({route, navigation}) => { type: 'image/jpg', }); } - if (form.website) { - if (form.isValidWebsite) { - request.append('website', form.website); - } else { - setForm({...form, attemptedSubmit: false}); - setTimeout(() => setForm({...form, attemptedSubmit: true})); - invalidFields = true; - } + + if (form.isValidWebsite) { + request.append('website', form.website); + } else { + setForm({...form, attemptedSubmit: false}); + setTimeout(() => setForm({...form, attemptedSubmit: true})); + invalidFields = true; } if (form.bio) { -- cgit v1.2.3-70-g09d2 From 17d41145a0791d2687c7f4abd934b83c008e6f12 Mon Sep 17 00:00:00 2001 From: hsalhab Date: Tue, 8 Jun 2021 17:08:26 -0400 Subject: fix regex, forward slash needs escape --- src/constants/regex.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/constants/regex.ts b/src/constants/regex.ts index 61523203..f934185d 100644 --- a/src/constants/regex.ts +++ b/src/constants/regex.ts @@ -36,7 +36,7 @@ export const nameRegex: RegExp = /^[A-Za-z'\-,. ]{2,20}$/; * - match alphanumerics, and special characters used in URLs */ export const websiteRegex: RegExp = - /^$|^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,50}\.[a-zA-Z0-9()]{2,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]{0,35})$/; + /^$|^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,50}\.[a-zA-Z0-9()]{2,6}\b([-a-zA-Z0-9()@:%_+.~#?&\/=]{0,35})$/; /** * The website regex has the following constraints -- cgit v1.2.3-70-g09d2 From 2ddd29120980ebced560dac09bbe270dc4aee0d1 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Wed, 9 Jun 2021 09:24:00 +0900 Subject: Create separate pill component --- src/components/notifications/NotificationPill.tsx | 202 ++++++++++++++++++++ src/components/notifications/index.ts | 1 + src/routes/tabs/NavigationBar.tsx | 221 +--------------------- src/utils/common.ts | 1 + 4 files changed, 211 insertions(+), 214 deletions(-) create mode 100644 src/components/notifications/NotificationPill.tsx (limited to 'src') diff --git a/src/components/notifications/NotificationPill.tsx b/src/components/notifications/NotificationPill.tsx new file mode 100644 index 00000000..7017d2e7 --- /dev/null +++ b/src/components/notifications/NotificationPill.tsx @@ -0,0 +1,202 @@ +import React, {useEffect, useState, useRef} from 'react'; +import {Image, StyleSheet, Text, View} from 'react-native'; +import LinearGradient from 'react-native-linear-gradient'; +import {SCREEN_WIDTH, isIPhoneX, numberWithCommas} from '../../utils'; +import { + NOTIFICATION_ICON_GRADIENT, + CHIN_HEIGHT, + NAV_BAR_HEIGHT, +} from '../../constants'; +import {getNotificationsUnreadCount} from '../../services'; +import {normalize} from 'react-native-elements'; +import PillIcon4 from '../../assets/images/Group 479.svg'; + +interface NotificationPillProps { + showIcon: boolean; +} + +export const NotificationPill: React.FC = ({ + showIcon, +}) => { + const [iconStart, setIconStart] = useState([0, -100]); + const [tipStart, setTipStart] = useState([0, -100]); + const [notificationSets, setNotificationSets] = useState({}); + const [timeCount, setTimeCount] = useState(false); + const [timeOut, setTimeOut] = useState(false); + const iconRef = useRef(null); + const tipRef = useRef(null); + const pillTip = require('../../assets/images/purple-tip.png'); + + const navBarPos = 20; + + // If there are notifications, determines the size of the pill + // and sets points for correct placement + useEffect(() => { + setTimeout(() => { + if (iconRef.current) { + iconRef.current.measure( + ( + _fx: number, + _fy: number, + width: number, + height: number, + _px: number, + _py: number, + ) => { + if (tipRef.current) { + tipRef.current.measure( + ( + __fx: number, + __fy: number, + width2: number, + __height: number, + __px: number, + __py: number, + ) => { + const x = SCREEN_WIDTH / 2 - width / 2; + const y = isIPhoneX() + ? CHIN_HEIGHT + NAV_BAR_HEIGHT + navBarPos + : NAV_BAR_HEIGHT + navBarPos; + setIconStart([x, y]); + setTipStart([width / 2 - width2 / 2, height - 1]); + setTimeCount(true); + }, + ); + } + }, + ); + } else { + } + }, 100); + }, [notificationSets, iconRef, tipRef]); + + // Used so that pill disappears after 5 seconds + useEffect(() => { + if (timeCount) { + setTimeout(() => { + setTimeOut(true); + }, 5000); + } + }, [timeCount]); + + // Gets data from backend to check for unreads + useEffect(() => { + const getCount = async () => { + const data = await getNotificationsUnreadCount(); + setTimeout(() => { + setNotificationSets(data); + }, 100); + }; + + getCount(); + }, []); + + return ( + <> + {notificationSets && + Object.keys(notificationSets).length !== 0 && + showIcon && + !timeOut && ( + + + {notificationSets.CMT && ( + <> + + + {numberWithCommas(notificationSets.CMT)} + + + )} + {notificationSets.FR_REQ && ( + <> + + + {numberWithCommas(notificationSets.FR_REQ)} + + + )} + {notificationSets.P_VIEW && ( + <> + + + {numberWithCommas(notificationSets.P_VIEW)} + + + )} + {notificationSets.MOM_TAG && ( + <> + + + {numberWithCommas(notificationSets.MOM_TAG)} + + + )} + + + + )} + + ); +}; + +const styles = StyleSheet.create({ + purpleContainer: { + flex: 1, + justifyContent: 'center', + position: 'absolute', + zIndex: 999, + }, + iconPurple: { + padding: 5, + borderRadius: 15, + flex: 1, + flexDirection: 'row', + alignItems: 'center', + }, + text: { + margin: 2, + color: 'white', + fontSize: normalize(10), + justifyContent: 'center', + alignItems: 'center', + marginRight: 5, + }, + tip: { + position: 'absolute', + zIndex: 999, + height: 12, + flex: 1, + resizeMode: 'contain', + }, + indicationIcon: { + height: 14, + width: 14, + margin: 2, + marginLeft: 5, + }, + svgIndicationIcon: { + height: 14, + width: 14, + margin: 3, + }, +}); diff --git a/src/components/notifications/index.ts b/src/components/notifications/index.ts index 733b56f1..077c26a4 100644 --- a/src/components/notifications/index.ts +++ b/src/components/notifications/index.ts @@ -1,2 +1,3 @@ export {default as Notification} from './Notification'; export {InviteFriendsPrompt} from './NotificationPrompts'; +export {NotificationPill} from './NotificationPill'; diff --git a/src/routes/tabs/NavigationBar.tsx b/src/routes/tabs/NavigationBar.tsx index e962c8da..c3a42739 100644 --- a/src/routes/tabs/NavigationBar.tsx +++ b/src/routes/tabs/NavigationBar.tsx @@ -1,26 +1,14 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; -import React, {Fragment, useEffect, useState, useRef} from 'react'; -import {Image, StyleSheet, Text, View} from 'react-native'; -import LinearGradient from 'react-native-linear-gradient'; +import React, {Fragment, useEffect, useState} from 'react'; import {useSelector} from 'react-redux'; import {NavigationIcon} from '../../components'; import {NO_NOTIFICATIONS} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; -import { - getNotificationsUnreadCount, - setNotificationsReadDate, -} from '../../services'; +import {setNotificationsReadDate} from '../../services'; import {ScreenType} from '../../types'; -import {haveUnreadNotifications, SCREEN_WIDTH, isIPhoneX} from '../../utils'; +import {haveUnreadNotifications} from '../../utils'; import MainStackScreen from '../main/MainStackScreen'; -import { - NOTIFICATION_ICON_GRADIENT, - CHIN_HEIGHT, - NAV_BAR_HEIGHT, -} from '../../constants'; -import {normalize} from 'react-native-elements'; -import {numberWithCommas} from '../../utils'; -import PillIcon4 from '../../assets/images/Group 479.svg'; +import {NotificationPill} from '../../components/notifications'; const Tabs = createBottomTabNavigator(); @@ -32,17 +20,8 @@ const NavigationBar: React.FC = () => { const {notifications: {notifications} = NO_NOTIFICATIONS} = useSelector( (state: RootState) => state, ); + // Triggered if user clicks on Notifications page to close the pill const [showIcon, setShowIcon] = useState(true); - const [iconStart, setIconStart] = useState([0, -100]); - const [tipStart, setTipStart] = useState([0, -100]); - const [notificationSets, setNotificationSets] = useState({}); - const [timeCount, setTimeCount] = useState(false); - const [timeOut, setTimeOut] = useState(false); - const iconRef = useRef(null); - const tipRef = useRef(null); - const pillTip = require('../../assets/images/purple-tip.png'); - - const navBarPos = 20; const [unreadNotificationsPresent, setUnreadNotificationsPresent] = useState(false); @@ -58,132 +37,9 @@ const NavigationBar: React.FC = () => { determine(); }, [notifications]); - // If there are notifications, determines the size of the pill - // and sets points for correct placement - useEffect(() => { - setTimeout(() => { - if (iconRef.current) { - iconRef.current.measure( - ( - _fx: number, - _fy: number, - width: number, - height: number, - _px: number, - _py: number, - ) => { - if (tipRef.current) { - tipRef.current.measure( - ( - __fx: number, - __fy: number, - width2: number, - __height: number, - __px: number, - __py: number, - ) => { - const x = SCREEN_WIDTH / 2 - width / 2; - const y = isIPhoneX() - ? CHIN_HEIGHT + NAV_BAR_HEIGHT + navBarPos - : NAV_BAR_HEIGHT + navBarPos; - setIconStart([x, y]); - setTipStart([width / 2 - width2 / 2, height - 1]); - setTimeCount(true); - }, - ); - } - }, - ); - } else { - } - }, 100); - }, [notificationSets, iconRef, tipRef]); - - // Used so that pill disappears after 5 seconds - useEffect(() => { - if (timeCount) { - setTimeout(() => { - setTimeOut(true); - }, 5000); - } - }, [timeCount]); - - // Gets data from backend to check for unreads - useEffect(() => { - const getCount = async () => { - const data = await getNotificationsUnreadCount(); - setTimeout(() => { - setNotificationSets(data); - }, 100); - }; - - getCount(); - }, []); - return ( <> - {notificationSets && - Object.keys(notificationSets).length !== 0 && - showIcon && - !timeOut && ( - - - {notificationSets.CMT && ( - <> - - - {numberWithCommas(notificationSets.CMT)} - - - )} - {notificationSets.FR_REQ && ( - <> - - - {numberWithCommas(notificationSets.FR_REQ)} - - - )} - {notificationSets.P_VIEW && ( - <> - - - {numberWithCommas(notificationSets.P_VIEW)} - - - )} - {notificationSets.MOM_TAG && ( - <> - - - {numberWithCommas(notificationSets.MOM_TAG)} - - - )} - - - - )} + ({ tabBarIcon: ({focused}) => { @@ -233,23 +89,11 @@ const NavigationBar: React.FC = () => { name="SuggestedPeople" component={MainStackScreen} initialParams={{screenType: ScreenType.SuggestedPeople}} - // Added these to as a way to close pill when on - // notification page - listeners={{ - tabPress: (_) => { - setShowIcon(true); - }, - }} /> { - setShowIcon(true); - }, - }} /> { initialParams={{screenType: ScreenType.Notifications}} listeners={{ tabPress: (_) => { + // Closes the pill once this screen has been opened setShowIcon(false); // Updates backend's date of reading notifications setNotificationsReadDate(); @@ -267,67 +112,15 @@ const NavigationBar: React.FC = () => { name="Chat" component={MainStackScreen} initialParams={{screenType: ScreenType.Chat}} - listeners={{ - tabPress: (_) => { - setShowIcon(true); - }, - }} /> { - setShowIcon(true); - }, - }} /> ); }; -const styles = StyleSheet.create({ - purpleContainer: { - flex: 1, - justifyContent: 'center', - position: 'absolute', - zIndex: 999, - }, - iconPurple: { - padding: 5, - borderRadius: 15, - flex: 1, - flexDirection: 'row', - alignItems: 'center', - }, - text: { - margin: 2, - color: 'white', - fontSize: normalize(10), - justifyContent: 'center', - alignItems: 'center', - marginRight: 5, - }, - tip: { - position: 'absolute', - zIndex: 999, - height: 12, - flex: 1, - resizeMode: 'contain', - }, - indicationIcon: { - height: 14, - width: 14, - margin: 2, - marginLeft: 5, - }, - svgIndicationIcon: { - height: 14, - width: 14, - margin: 3, - }, -}); - export default NavigationBar; diff --git a/src/utils/common.ts b/src/utils/common.ts index 049dae90..cb0bd62d 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -198,6 +198,7 @@ export const validateImageLink = async (url: string | undefined) => { }); }; +// Documentation: https://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript export const numberWithCommas = (digits: number) => { return digits.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); }; -- cgit v1.2.3-70-g09d2 From 9d7e900a89f343f7752457956f8e1d205774b910 Mon Sep 17 00:00:00 2001 From: Brian Kim Date: Wed, 9 Jun 2021 09:28:38 +0900 Subject: Clean up MomentPostContent --- src/components/moments/MomentPostContent.tsx | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index c00433e7..ecbfb3a2 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -38,12 +38,10 @@ const MomentPostContent: React.FC = ({ const [elapsedTime, setElapsedTime] = useState(''); const [comments_count, setCommentsCount] = useState(''); const [tags, setTags] = useState(momentTags); - // const [visible, setVisible] = useState(false); const state: RootState = useStore().getState(); const navigation = useNavigation(); const dispatch = useDispatch(); const imageRef = useRef(null); - // const [fadeValue, setFadeValue] = useState(new Animated.Value(0)); const [visible, setVisible] = useState(false); const [fadeValue, setFadeValue] = useState>( -- cgit v1.2.3-70-g09d2 From 3f42ed623adf591543bb8b738077e9172781ed09 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 9 Jun 2021 16:36:01 -0400 Subject: Fix malformed code issue --- src/utils/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils/common.ts b/src/utils/common.ts index 645f229a..1956e811 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -237,4 +237,4 @@ export const badgesToDisplayBadges = ( // Documentation: https://stackoverflow.com/questions/2901102/how-to-print-a-number-with-commas-as-thousands-separators-in-javascript export const numberWithCommas = (digits: number) => { return digits.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ','); - \ No newline at end of file +}; -- cgit v1.2.3-70-g09d2 From 587d08dc8f0508b6efa76cc7d57f21ac2a5fd9fb Mon Sep 17 00:00:00 2001 From: Husam Salhab <47015061+hsalhab@users.noreply.github.com> Date: Wed, 9 Jun 2021 16:43:02 -0400 Subject: [TMA-909] Fix Contact Search (#460) * shows proper results and handles null lists * remove unnecessary existing users code * fix height and remove console log * lint --- src/screens/profile/EditProfile.tsx | 2 +- src/screens/profile/InviteFriendsScreen.tsx | 56 ++++++++++++++--------------- 2 files changed, 29 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/screens/profile/EditProfile.tsx b/src/screens/profile/EditProfile.tsx index 765bbf01..20a62b19 100644 --- a/src/screens/profile/EditProfile.tsx +++ b/src/screens/profile/EditProfile.tsx @@ -305,7 +305,7 @@ const EditProfile: React.FC = ({route, navigation}) => { type: 'image/jpg', }); } - + if (form.isValidWebsite) { request.append('website', form.website); } else { diff --git a/src/screens/profile/InviteFriendsScreen.tsx b/src/screens/profile/InviteFriendsScreen.tsx index 89f2e62f..9ee6fb1c 100644 --- a/src/screens/profile/InviteFriendsScreen.tsx +++ b/src/screens/profile/InviteFriendsScreen.tsx @@ -21,7 +21,6 @@ import { getRemainingInviteCount, usersFromContactsService, } from '../../services/UserFriendsService'; -import {ProfilePreviewType} from '../../types'; import { extractContacts, HeaderHeight, @@ -45,11 +44,10 @@ export type SearchResultType = { const InviteFriendsScreen: React.FC = () => { const navigation = useNavigation(); - const [usersFromContacts, setUsersFromContacts] = useState< - ProfilePreviewType[] + const [nonUsersFromContacts, setNonUsersFromContacts] = useState< + InviteContactType[] >([]); - const [nonUsersFromContacts, setNonUsersFromContacts] = useState<[]>([]); - const [pendingUsers] = useState<[]>([]); + const [pendingUsers, setPendingUsers] = useState([]); const [results, setResults] = useState({ nonUsersFromContacts: nonUsersFromContacts, pendingUsers: pendingUsers, @@ -80,8 +78,8 @@ const InviteFriendsScreen: React.FC = () => { const permission = await checkPermission(); if (permission === 'authorized') { let response = await usersFromContactsService(retrievedContacts); - await setUsersFromContacts(response.existing_tagg_users); await setNonUsersFromContacts(response.invite_from_contacts); + await setPendingUsers(response.pending_users); setResults({ nonUsersFromContacts: response.invite_from_contacts, pendingUsers: response.pending_users, @@ -100,30 +98,32 @@ const InviteFriendsScreen: React.FC = () => { useEffect(() => { const search = async () => { if (query.length > 0) { - const searchResultsUsers = usersFromContacts.filter( - (item: ProfilePreviewType) => - (item.first_name + ' ' + item.last_name) - .toLowerCase() - .startsWith(query) || - item.username.toLowerCase().startsWith(query) || - item.last_name.toLowerCase().startsWith(query), - ); - const searchResultsNonUsers = nonUsersFromContacts.filter( - (item: InviteContactType) => - (item.firstName + ' ' + item.lastName) - .toLowerCase() - .startsWith(query) || - item.lastName.toLowerCase().startsWith(query), - ); - const sanitizedResult = { - usersFromContacts: searchResultsUsers, + const searchResultsPendingUsers = pendingUsers + ? pendingUsers.filter( + (item: InviteContactType) => + (item.firstName + ' ' + item.lastName) + .toLowerCase() + .startsWith(query) || + item.lastName.toLowerCase().startsWith(query), + ) + : []; + const searchResultsNonUsers = nonUsersFromContacts + ? nonUsersFromContacts.filter( + (item: InviteContactType) => + (item.firstName + ' ' + item.lastName) + .toLowerCase() + .startsWith(query) || + item.lastName.toLowerCase().startsWith(query), + ) + : []; + setResults({ nonUsersFromContacts: searchResultsNonUsers, - }; - setResults(sanitizedResult); + pendingUsers: searchResultsPendingUsers, + }); } else { setResults({ - nonUsersFromContacts: nonUsersFromContacts, - pendingUsers: pendingUsers, + nonUsersFromContacts: nonUsersFromContacts || [], + pendingUsers: pendingUsers || [], }); } }; @@ -203,7 +203,7 @@ const InviteFriendsScreen: React.FC = () => { styles.subheader, { height: - 72 * + 75 * (results.pendingUsers ? results.pendingUsers.length : 1), }, ]}> -- cgit v1.2.3-70-g09d2 From 93796732be3f5070c0a124d29533396f79736c83 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 9 Jun 2021 17:37:40 -0400 Subject: Cleanup code --- src/components/notifications/NotificationPill.tsx | 15 +++++++++++---- src/services/NotificationService.ts | 10 ++-------- src/types/types.ts | 4 +++- 3 files changed, 16 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/components/notifications/NotificationPill.tsx b/src/components/notifications/NotificationPill.tsx index 7017d2e7..01622a6f 100644 --- a/src/components/notifications/NotificationPill.tsx +++ b/src/components/notifications/NotificationPill.tsx @@ -20,7 +20,12 @@ export const NotificationPill: React.FC = ({ }) => { const [iconStart, setIconStart] = useState([0, -100]); const [tipStart, setTipStart] = useState([0, -100]); - const [notificationSets, setNotificationSets] = useState({}); + const [notificationSets, setNotificationSets] = useState<{ + CMT?: number; + FRD_REQ?: number; + P_VIEW?: number; + MOM_TAG?: number; + }>({}); const [timeCount, setTimeCount] = useState(false); const [timeOut, setTimeOut] = useState(false); const iconRef = useRef(null); @@ -84,7 +89,9 @@ export const NotificationPill: React.FC = ({ const getCount = async () => { const data = await getNotificationsUnreadCount(); setTimeout(() => { - setNotificationSets(data); + if (data) { + setNotificationSets(data); + } }, 100); }; @@ -117,14 +124,14 @@ export const NotificationPill: React.FC = ({ )} - {notificationSets.FR_REQ && ( + {notificationSets.FRD_REQ && ( <> - {numberWithCommas(notificationSets.FR_REQ)} + {numberWithCommas(notificationSets.FRD_REQ)} )} diff --git a/src/services/NotificationService.ts b/src/services/NotificationService.ts index 2ffc85b2..ccaa9135 100644 --- a/src/services/NotificationService.ts +++ b/src/services/NotificationService.ts @@ -34,12 +34,7 @@ export const getNotificationsData: () => Promise = } }; -export const getNotificationsUnreadCount: () => Promise<{ - CMT?: number; - FRD_REQ?: number; - P_VIEW?: number; - MOM_TAG?: number; -}> = async () => { +export const getNotificationsUnreadCount = async () => { try { const token = await AsyncStorage.getItem('token'); const response = await fetch(NOTIFICATIONS_COUNT_ENDPOINT, { @@ -70,11 +65,10 @@ export const getNotificationsUnreadCount: () => Promise<{ } return typedData; } - return []; } catch (error) { console.log('Unable to fetch notifications'); - return []; } + return undefined; }; export const setNotificationsReadDate: () => Promise = async () => { diff --git a/src/types/types.ts b/src/types/types.ts index e54c2201..fd75ab50 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -254,7 +254,9 @@ export type TypeOfNotification = // notification_object is MomentType | 'MOM_TAG' // notification_object is undefined - | 'SYSTEM_MSG'; + | 'SYSTEM_MSG' + // notification_object is undefined + | 'P_VIEW'; export type UniversityBadge = { id: number; -- cgit v1.2.3-70-g09d2 From 189e0cb9f298ff956fc722fdcd4dcd9acd982985 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Wed, 9 Jun 2021 16:03:30 -0700 Subject: Pass moment instead of sub fields --- src/components/moments/MomentPost.tsx | 8 +++----- src/components/moments/MomentPostContent.tsx | 24 +++++++++--------------- src/components/moments/MomentPostHeader.tsx | 12 ++++++++---- 3 files changed, 20 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index 7149a5b4..e744fcd9 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -76,18 +76,16 @@ const MomentPost: React.FC = ({item, userXId, screenType}) => { userXId={userXId} screenType={screenType} username={isOwnProfile ? loggedInUsername : username} - momentId={item.moment_id} style={styles.postHeader} momentTagId={momentTagId} removeTag={removeTag} + moment={item} + tags={tags} /> diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 4a1f3894..153833d7 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -6,7 +6,7 @@ import Animated, {Easing} from 'react-native-reanimated'; import {useDispatch, useStore} from 'react-redux'; import {getCommentsCount} from '../../services'; import {RootState} from '../../store/rootReducer'; -import {MomentTagType, ScreenType, UserType} from '../../types'; +import {MomentTagType, MomentType, ScreenType, UserType} from '../../types'; import { getTimePosted, navigateToProfile, @@ -20,19 +20,13 @@ import {MomentTags} from '../common'; interface MomentPostContentProps extends ViewProps { screenType: ScreenType; - momentId: string; - caption: string; - pathHash: string; - dateTime: string; + moment: MomentType; momentTags: MomentTagType[]; } const MomentPostContent: React.FC = ({ screenType, - momentId, - caption, - pathHash, - dateTime, style, + moment, momentTags, }) => { const state: RootState = useStore().getState(); @@ -54,12 +48,12 @@ const MomentPostContent: React.FC = ({ useEffect(() => { const fetchCommentsCount = async () => { - const count = await getCommentsCount(momentId, false); + const count = await getCommentsCount(moment.moment_id, false); setCommentsCount(count); }; - setElapsedTime(getTimePosted(dateTime)); + setElapsedTime(getTimePosted(moment.date_created)); fetchCommentsCount(); - }, [dateTime, momentId]); + }, [moment.date_created, moment.moment_id]); useEffect(() => { const fade = async () => { @@ -82,7 +76,7 @@ const MomentPostContent: React.FC = ({ {tags.length > 0 && ( @@ -100,13 +94,13 @@ const MomentPostContent: React.FC = ({ {elapsedTime} {renderTextWithMentions({ - value: caption, + value: moment.caption, styles: styles.captionText, partTypes: mentionPartTypes('white'), onPress: (user: UserType) => diff --git a/src/components/moments/MomentPostHeader.tsx b/src/components/moments/MomentPostHeader.tsx index dc6a3cd9..cde7639c 100644 --- a/src/components/moments/MomentPostHeader.tsx +++ b/src/components/moments/MomentPostHeader.tsx @@ -10,7 +10,7 @@ import { import {useDispatch, useSelector, useStore} from 'react-redux'; import {loadUserMoments} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; -import {ScreenType} from '../../types'; +import {MomentTagType, MomentType, ScreenType} from '../../types'; import {fetchUserX, userXInStore} from '../../utils'; import {MomentMoreInfoDrawer} from '../profile'; import TaggAvatar from '../profile/TaggAvatar'; @@ -19,19 +19,21 @@ interface MomentPostHeaderProps extends ViewProps { userXId?: string; screenType: ScreenType; username: string; - momentId: string; momentTagId: string; removeTag: () => Promise; + moment: MomentType; + tags: MomentTagType[]; } const MomentPostHeader: React.FC = ({ userXId, screenType, username, - momentId, style, momentTagId, removeTag, + moment, + tags, }) => { const [drawerVisible, setDrawerVisible] = useState(false); const dispatch = useDispatch(); @@ -68,7 +70,6 @@ const MomentPostHeader: React.FC = ({ = ({ dispatch(loadUserMoments(loggedInUserId)); navigation.pop(); }} + screenType={screenType} + moment={moment} + tags={tags} /> ); -- cgit v1.2.3-70-g09d2 From 2286d1b013b73534537a3265876361527856fd1a Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Wed, 9 Jun 2021 16:08:49 -0700 Subject: Add edit moment functionality to caption screen --- src/screens/moments/TagFriendsScreen.tsx | 4 +- src/screens/profile/CaptionScreen.tsx | 90 +++++++++++++++++++++----------- src/services/MomentService.ts | 32 ++++++++++++ 3 files changed, 94 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/screens/moments/TagFriendsScreen.tsx b/src/screens/moments/TagFriendsScreen.tsx index c8bca9f4..570c3776 100644 --- a/src/screens/moments/TagFriendsScreen.tsx +++ b/src/screens/moments/TagFriendsScreen.tsx @@ -30,7 +30,7 @@ interface TagFriendsScreenProps { route: TagFriendsScreenRouteProps; } const TagFriendsScreen: React.FC = ({route}) => { - const {image, selectedTags} = route.params; + const {imagePath, selectedTags} = route.params; const navigation = useNavigation(); const imageRef = useRef(null); const [tags, setTags] = useState([]); @@ -85,7 +85,7 @@ const TagFriendsScreen: React.FC = ({route}) => { diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx index 8bffd82b..949b61fd 100644 --- a/src/screens/profile/CaptionScreen.tsx +++ b/src/screens/profile/CaptionScreen.tsx @@ -23,7 +23,7 @@ import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator'; import {TAGG_LIGHT_BLUE_2} from '../../constants'; import {ERROR_UPLOAD, SUCCESS_PIC_UPLOAD} from '../../constants/strings'; import {MainStackParams} from '../../routes'; -import {postMoment, postMomentTags} from '../../services'; +import {patchMoment, postMoment, postMomentTags} from '../../services'; import { loadUserMoments, updateProfileCompletionStage, @@ -47,14 +47,16 @@ interface CaptionScreenProps { } const CaptionScreen: React.FC = ({route, navigation}) => { - const {title, image, screenType, selectedTags} = route.params; + const {title, image, screenType, selectedTags, moment} = route.params; const { user: {userId}, } = useSelector((state: RootState) => state.user); const dispatch = useDispatch(); - const [caption, setCaption] = useState(''); + const [caption, setCaption] = useState(moment ? moment.caption : ''); const [loading, setLoading] = useState(false); - const [tags, setTags] = useState([]); + const [tags, setTags] = useState( + selectedTags ? selectedTags : [], + ); const [taggedList, setTaggedList] = useState(''); useEffect(() => { @@ -84,22 +86,32 @@ const CaptionScreen: React.FC = ({route, navigation}) => { }); }; + const handleFailed = () => { + setLoading(false); + setTimeout(() => { + Alert.alert(moment ? 'Error editing moment' : ERROR_UPLOAD); + }, 500); + }; + const handleSuccess = () => { + setLoading(false); + navigateToProfile(); + setTimeout(() => { + Alert.alert(moment ? 'Successfully edited moment!' : SUCCESS_PIC_UPLOAD); + }, 500); + }; + + const formattedTags = () => { + return tags.map((tag) => ({ + x: Math.floor(tag.x), + y: Math.floor(tag.y), + z: Math.floor(tag.z), + user_id: tag.user.id, + })); + }; + const handleShare = async () => { - const handleFailed = () => { - setLoading(false); - setTimeout(() => { - Alert.alert(ERROR_UPLOAD); - }, 500); - }; - const handleSuccess = () => { - setLoading(false); - navigateToProfile(); - setTimeout(() => { - Alert.alert(SUCCESS_PIC_UPLOAD); - }, 500); - }; setLoading(true); - if (!image.filename) { + if (!image?.filename || !title) { return; } const momentResponse = await postMoment( @@ -115,12 +127,7 @@ const CaptionScreen: React.FC = ({route, navigation}) => { } const momentTagResponse = await postMomentTags( momentResponse.moment_id, - tags.map((tag) => ({ - x: Math.floor(tag.x), - y: Math.floor(tag.y), - z: Math.floor(tag.z), - user_id: tag.user.id, - })), + formattedTags(), ); if (!momentTagResponse) { handleFailed(); @@ -133,6 +140,23 @@ const CaptionScreen: React.FC = ({route, navigation}) => { handleSuccess(); }; + const handleDone = async () => { + setLoading(true); + if (moment?.moment_id) { + const success = await patchMoment( + moment.moment_id, + caption, + formattedTags(), + ); + if (success) { + dispatch(loadUserMoments(userId)); + handleSuccess(); + } else { + handleFailed(); + } + } + }; + return ( {loading ? : } @@ -148,17 +172,20 @@ const CaptionScreen: React.FC = ({route, navigation}) => { onPress={() => navigateToProfile()} />