From faecd66faf9d8c106259860da1817d6059938ccd Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Thu, 21 Jan 2021 02:45:51 -0800 Subject: switched from modal to full screen view --- src/components/comments/AddComment.tsx | 22 +++++++++++++++++----- src/components/onboarding/TaggBigInput.tsx | 16 ++++++++++++---- 2 files changed, 29 insertions(+), 9 deletions(-) (limited to 'src/components') diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index f8c0b6bc..c6c816b9 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -12,6 +12,7 @@ import {postMomentComment} from '../../services'; import {logout} from '../../store/actions'; import {useSelector, useDispatch} from 'react-redux'; import {RootState} from '../../store/rootreducer'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; /** * This file provides the add comment view for a user. @@ -69,7 +70,7 @@ const AddComment: React.FC = ({ return ( + keyboardVerticalOffset={(1 / 9) * SCREEN_HEIGHT}> = ({ : require('../../assets/images/avatar-placeholder.png') } /> + = ({ ); }; const styles = StyleSheet.create({ - container: {flexDirection: 'row'}, + container: { + flexDirection: 'row', + justifyContent: 'flex-start', + width: SCREEN_WIDTH, + marginTop: '5%', + }, + textContainer: { + width: '100%', + alignItems: 'flex-start', + marginVertical: 11, + }, text: { - position: 'relative', - right: '18%', backgroundColor: 'white', width: '70%', paddingLeft: '2%', @@ -109,7 +120,8 @@ const styles = StyleSheet.create({ height: 40, width: 40, borderRadius: 30, - marginRight: 15, + marginRight: 10, + marginLeft: 20, }, }); diff --git a/src/components/onboarding/TaggBigInput.tsx b/src/components/onboarding/TaggBigInput.tsx index 4e8e1ef7..4212afd1 100644 --- a/src/components/onboarding/TaggBigInput.tsx +++ b/src/components/onboarding/TaggBigInput.tsx @@ -1,22 +1,30 @@ import React from 'react'; -import {View, TextInput, StyleSheet, TextInputProps} from 'react-native'; +import { + View, + TextInput, + StyleSheet, + TextInputProps, + ViewStyle, +} from 'react-native'; import * as Animatable from 'react-native-animatable'; -import {TAGG_LIGHT_PURPLE} from '../../constants'; +import { TAGG_LIGHT_PURPLE } from '../../constants'; interface TaggBigInputProps extends TextInputProps { valid?: boolean; invalidWarning?: string; attemptedSubmit?: boolean; width?: number | string; + containerStyle?: ViewStyle; } /** * An input component that receives all props a normal TextInput component does. TaggInput components grow to 60% of their parent's width by default, but this can be set using the `width` prop. */ const TaggBigInput = React.forwardRef((props: TaggBigInputProps, ref: any) => { return ( - + Date: Thu, 21 Jan 2021 15:00:39 -0500 Subject: fixed isIPhoneX and adjusted spacing --- src/components/profile/Content.tsx | 9 +++++---- src/components/profile/ProfileBody.tsx | 1 - src/components/profile/ProfileHeader.tsx | 3 ++- src/constants/constants.ts | 12 +++++++----- src/screens/search/SearchScreen.tsx | 8 +++++++- src/utils/statusBarHeight.ts | 13 ++++++------- 6 files changed, 27 insertions(+), 19 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index e7fb566b..82803a7a 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -113,9 +113,10 @@ const Content: React.FC = ({y, userXId, screenType}) => { const [isStageOnePromptClosed, setIsStageOnePromptClosed] = useState( false, ); - const [isStageThreePromptClosed, setIsStageThreePromptClosed] = useState< - boolean - >(false); + const [ + isStageThreePromptClosed, + setIsStageThreePromptClosed, + ] = useState(false); const onRefresh = useCallback(() => { const refrestState = async () => { @@ -284,7 +285,7 @@ const Content: React.FC = ({y, userXId, screenType}) => { momentCategories.filter((mc) => mc !== category), false, ), - ) + ); dispatch(deleteUserMomentsForCategory(category)); }, }, diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 6284ff59..0b00481b 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -162,7 +162,6 @@ const styles = StyleSheet.create({ fontWeight: '600', fontSize: 16.5, marginBottom: '1%', - marginTop: '-3%', }, biography: { fontSize: 16, diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index 8d502d97..9c91c079 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -2,6 +2,7 @@ import React, {useState} from 'react'; import {StyleSheet, Text, View} from 'react-native'; import {useSelector} from 'react-redux'; import {UniversityIcon} from '.'; +import {PROFILE_CUTOUT_TOP_Y} from '../../constants'; import {NO_MOMENTS} from '../../store/initialStates'; import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; @@ -78,7 +79,7 @@ const ProfileHeader: React.FC = ({ const styles = StyleSheet.create({ container: { - top: SCREEN_HEIGHT / 2.4, + top: PROFILE_CUTOUT_TOP_Y * 0.96, width: '100%', position: 'absolute', }, diff --git a/src/constants/constants.ts b/src/constants/constants.ts index b96d9438..0346c45f 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -1,13 +1,15 @@ import {ReactText} from 'react'; import {BackgroundGradientType, ExploreSectionType} from './../types/'; -import {SCREEN_WIDTH, SCREEN_HEIGHT} from '../utils'; +import {SCREEN_WIDTH, SCREEN_HEIGHT, isIPhoneX} from '../utils'; export const CHIN_HEIGHT = 34; -export const PROFILE_CUTOUT_TOP_Y = SCREEN_HEIGHT / 2.3; -export const PROFILE_CUTOUT_BOTTOM_Y = SCREEN_HEIGHT / 1.76; -export const PROFILE_CUTOUT_CORNER_X = SCREEN_WIDTH / 2.9; -export const PROFILE_CUTOUT_CORNER_Y = SCREEN_HEIGHT / 1.95; +export const PROFILE_CUTOUT_TOP_Y = SCREEN_HEIGHT * 0.435; +export const PROFILE_CUTOUT_BOTTOM_Y = isIPhoneX() + ? SCREEN_HEIGHT * 0.54 + : SCREEN_HEIGHT * 0.58; +export const PROFILE_CUTOUT_CORNER_X = SCREEN_WIDTH * 0.344; +export const PROFILE_CUTOUT_CORNER_Y = SCREEN_HEIGHT * 0.513; export const IMAGE_WIDTH = SCREEN_WIDTH; export const IMAGE_HEIGHT = SCREEN_WIDTH; diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index 9f98b4d7..5072e13a 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -2,6 +2,7 @@ import AsyncStorage from '@react-native-community/async-storage'; import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useState} from 'react'; import { + Dimensions, Keyboard, RefreshControl, ScrollView, @@ -24,7 +25,12 @@ import {SEARCH_ENDPOINT, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; import {loadRecentlySearched, resetScreenType} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType, UserType} from '../../types'; -import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; +import { + isIPhoneX, + SCREEN_HEIGHT, + SCREEN_WIDTH, + StatusBarHeight, +} from '../../utils'; const NO_USER: UserType = { userId: '', username: '', diff --git a/src/utils/statusBarHeight.ts b/src/utils/statusBarHeight.ts index b8eb7b33..c5509376 100644 --- a/src/utils/statusBarHeight.ts +++ b/src/utils/statusBarHeight.ts @@ -1,15 +1,14 @@ import {Platform, StatusBar} from 'react-native'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from './screenDimensions'; -const X_WIDTH = 375; -const X_HEIGHT = 812; -const XSMAX_WIDTH = 414; -const XSMAX_HEIGHT = 896; - +/** + * Working as of Q1 2021, latest iPhone is 12 + * iPhone 8/SE has a logical screen ratio of about 1.77 + * Rest has a logical screen ratio of about 2.16 + */ export const isIPhoneX = () => Platform.OS === 'ios' && !Platform.isPad && !Platform.isTVOS - ? (SCREEN_WIDTH === X_WIDTH && SCREEN_HEIGHT === X_HEIGHT) || - (SCREEN_WIDTH === XSMAX_WIDTH && SCREEN_HEIGHT === XSMAX_HEIGHT) + ? SCREEN_HEIGHT / SCREEN_WIDTH > 2 : false; // Taken from: https://github.com/react-navigation/react-navigation/issues/283 -- cgit v1.2.3-70-g09d2 From 238bc768a1610b558263b449b2938e1244450b92 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 21 Jan 2021 16:11:00 -0500 Subject: updated profile header styling --- src/components/profile/ProfileHeader.tsx | 32 +++++++++++++----------- src/components/profile/ProfileMoreInfoDrawer.tsx | 1 - src/components/profile/UniversityIcon.tsx | 7 ++++-- 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index 9c91c079..8c7a3301 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -79,44 +79,46 @@ const ProfileHeader: React.FC = ({ const styles = StyleSheet.create({ container: { - top: PROFILE_CUTOUT_TOP_Y * 0.96, + top: PROFILE_CUTOUT_TOP_Y * 1.02, width: '100%', position: 'absolute', + // borderWidth: 1, }, row: { flexDirection: 'row', }, header: { flexDirection: 'column', - justifyContent: 'center', + justifyContent: 'space-evenly', alignItems: 'center', - marginTop: SCREEN_WIDTH / 18.2, - marginLeft: SCREEN_WIDTH / 8, - marginBottom: SCREEN_WIDTH / 50, + marginRight: '15%', + marginLeft: '5%', + flex: 1, + // borderWidth: 1, }, avatar: { - bottom: SCREEN_WIDTH / 80, - left: '10%', + marginLeft: '3%', + top: '-8%', }, name: { - marginLeft: SCREEN_WIDTH / 8, fontSize: 17, fontWeight: '500', alignSelf: 'center', + // borderWidth: 1, }, friends: { - alignSelf: 'flex-start', - marginRight: SCREEN_WIDTH / 20, + // borderWidth: 1, }, university: { - alignSelf: 'flex-end', - bottom: 3, + // borderWidth: 1, }, friendsAndUniversity: { flexDirection: 'row', - flex: 1, - marginLeft: SCREEN_WIDTH / 10, - marginTop: SCREEN_WIDTH / 40, + alignItems: 'center', + justifyContent: 'space-evenly', + width: '100%', + height: 50, + // borderWidth: 1, }, }); diff --git a/src/components/profile/ProfileMoreInfoDrawer.tsx b/src/components/profile/ProfileMoreInfoDrawer.tsx index 76f0f27f..26a4756a 100644 --- a/src/components/profile/ProfileMoreInfoDrawer.tsx +++ b/src/components/profile/ProfileMoreInfoDrawer.tsx @@ -107,7 +107,6 @@ const styles = StyleSheet.create({ more: { position: 'absolute', right: '5%', - marginTop: '4%', zIndex: 1, }, }); diff --git a/src/components/profile/UniversityIcon.tsx b/src/components/profile/UniversityIcon.tsx index 13586359..a901998f 100644 --- a/src/components/profile/UniversityIcon.tsx +++ b/src/components/profile/UniversityIcon.tsx @@ -38,19 +38,22 @@ const UniversityIcon: React.FC = ({ const styles = StyleSheet.create({ container: { - flex: 1, flexDirection: 'column', flexWrap: 'wrap', justifyContent: 'center', + alignItems: 'center', + height: '100%', }, univClass: { fontSize: 13, fontWeight: '500', }, icon: { - alignSelf: 'center', + // alignSelf: 'center', + // width: '5%', width: 17, height: 19, + // aspectRatio: 17 / 19, }, }); -- cgit v1.2.3-70-g09d2 From 27af1338ae8e735c831659fab8e51b795b368be4 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 21 Jan 2021 16:16:07 -0500 Subject: linting --- src/components/profile/Content.tsx | 11 +---------- src/components/profile/ProfileHeader.tsx | 2 -- src/screens/profile/MomentCommentsScreen.tsx | 2 +- 3 files changed, 2 insertions(+), 13 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index 82803a7a..a2bd3cf3 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -10,16 +10,7 @@ import { View, } from 'react-native'; import Animated from 'react-native-reanimated'; -import { - CategorySelectionScreenType, - FriendshipStatusType, - MomentCategoryType, - MomentType, - ProfilePreviewType, - ProfileType, - ScreenType, - UserType, -} from '../../types'; +import {CategorySelectionScreenType, MomentType, ScreenType} from '../../types'; import {COVER_HEIGHT, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; import { fetchUserX, diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index 8c7a3301..26bbbc90 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -3,10 +3,8 @@ import {StyleSheet, Text, View} from 'react-native'; import {useSelector} from 'react-redux'; import {UniversityIcon} from '.'; import {PROFILE_CUTOUT_TOP_Y} from '../../constants'; -import {NO_MOMENTS} from '../../store/initialStates'; import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; -import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import Avatar from './Avatar'; import FriendsCount from './FriendsCount'; import ProfileMoreInfoDrawer from './ProfileMoreInfoDrawer'; diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index ebe4da28..1d27929e 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -4,7 +4,7 @@ import {ProfileStackParams} from '../../routes/main'; import {CenteredView, CommentTile} from '../../components'; import {CommentType} from '../../types'; import {ScrollView, StyleSheet, Text, View} from 'react-native'; -import {SCREEN_WIDTH} from '../../utils/screenDimensions'; +import {SCREEN_WIDTH} from '../../utils'; import {Button} from 'react-native-elements'; import {AddComment} from '../../components/'; import {useEffect} from 'react'; -- cgit v1.2.3-70-g09d2 From d6714bec669becb4132035ffdf7b9b87e9c6ce7b Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 21 Jan 2021 16:59:30 -0500 Subject: normalize function and normalized all fonts on profile page --- src/components/moments/Moment.tsx | 9 ++------- src/components/profile/Content.tsx | 5 +++-- src/components/profile/FriendsCount.tsx | 5 +++-- src/components/profile/ProfileBody.tsx | 8 ++++---- src/components/profile/ProfileHeader.tsx | 16 ++++------------ src/components/profile/UniversityIcon.tsx | 11 ++++------- src/constants/constants.ts | 2 +- src/utils/layouts.ts | 21 +++++++++++++++++++-- 8 files changed, 40 insertions(+), 37 deletions(-) (limited to 'src/components') diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index 7905e8a9..b08eb574 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -13,7 +13,7 @@ import BigPlusIcon from '../../assets/icons/plus_icon-02.svg'; import UpIcon from '../../assets/icons/up_icon.svg'; import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; import {ERROR_UPLOAD_MOMENT_SHORT} from '../../constants/strings'; -import {SCREEN_WIDTH} from '../../utils'; +import {normalize, SCREEN_WIDTH} from '../../utils'; import MomentTile from './MomentTile'; interface MomentProps { @@ -171,15 +171,10 @@ const styles = StyleSheet.create({ alignItems: 'center', }, titleText: { - fontSize: 16, + fontSize: normalize(16), fontWeight: 'bold', color: TAGG_TEXT_LIGHT_BLUE, }, - // titleContainer: { - // flex: 1, - // flexDirection: 'row', - // justifyContent: 'flex-end', - // }, flexer: { flex: 1, }, diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index a2bd3cf3..140c911c 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -16,6 +16,7 @@ import { fetchUserX, getUserAsProfilePreviewType, moveCategory, + normalize, SCREEN_HEIGHT, userLogin, } from '../../utils'; @@ -424,7 +425,7 @@ const styles = StyleSheet.create({ alignSelf: 'center', }, createCategoryButtonLabel: { - fontSize: 16, + fontSize: normalize(16), fontWeight: '500', color: 'white', }, @@ -435,7 +436,7 @@ const styles = StyleSheet.create({ marginVertical: '10%', }, noMomentsText: { - fontSize: 14, + fontSize: normalize(14), fontWeight: 'bold', color: 'gray', marginVertical: '8%', diff --git a/src/components/profile/FriendsCount.tsx b/src/components/profile/FriendsCount.tsx index 23a24787..9647710e 100644 --- a/src/components/profile/FriendsCount.tsx +++ b/src/components/profile/FriendsCount.tsx @@ -5,6 +5,7 @@ import {useNavigation} from '@react-navigation/native'; import {RootState} from '../../store/rootReducer'; import {useSelector} from 'react-redux'; import {ScreenType} from '../../types'; +import {normalize} from '../../utils'; interface FriendsCountProps extends ViewProps { userXId: string | undefined; @@ -55,11 +56,11 @@ const styles = StyleSheet.create({ }, count: { fontWeight: '700', - fontSize: 13, + fontSize: normalize(14), }, label: { fontWeight: '500', - fontSize: 13, + fontSize: normalize(14), }, }); diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 0b00481b..7bc927c1 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {StyleSheet, View, Text, LayoutChangeEvent, Linking} from 'react-native'; -import {Button} from 'react-native-elements'; +import {Button, normalize} from 'react-native-elements'; import { TAGG_DARK_BLUE, TAGG_TEXT_LIGHT_BLUE, @@ -160,15 +160,15 @@ const styles = StyleSheet.create({ }, username: { fontWeight: '600', - fontSize: 16.5, + fontSize: normalize(12), marginBottom: '1%', }, biography: { - fontSize: 16, + fontSize: normalize(12), marginBottom: '1.5%', }, website: { - fontSize: 16, + fontSize: normalize(12), color: TAGG_DARK_BLUE, marginBottom: '1%', }, diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index 26bbbc90..7fc90257 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -5,6 +5,7 @@ import {UniversityIcon} from '.'; import {PROFILE_CUTOUT_TOP_Y} from '../../constants'; import {RootState} from '../../store/rootreducer'; import {ScreenType} from '../../types'; +import {normalize} from '../../utils'; import Avatar from './Avatar'; import FriendsCount from './FriendsCount'; import ProfileMoreInfoDrawer from './ProfileMoreInfoDrawer'; @@ -30,7 +31,6 @@ const ProfileHeader: React.FC = ({ : useSelector((state: RootState) => state.user); const [drawerVisible, setDrawerVisible] = useState(false); const [firstName, lastName] = [...name.split(' ')]; - return ( Platform.OS === 'ios' && !Platform.isPad && !Platform.isTVOS - ? SCREEN_HEIGHT / SCREEN_WIDTH > 2 + ? SCREEN_RATIO > 2 : false; // Taken from: https://github.com/react-navigation/react-navigation/issues/283 @@ -29,3 +31,18 @@ export const StatusBarHeight = Platform.select({ }); export const AvatarHeaderHeight = (HeaderHeight + StatusBarHeight) * 1.3; + +/** + * This is a function for normalizing the font size for different devices, based on iphone 8. + * + * E.g. font size 13 on an iphone 8 is 13, but on an iPhone 11 is + * 14.5 + */ +export const normalize = (fontSize: number) => { + // based on iphone 8 logical screen width + const scale = SCREEN_WIDTH / 375; + let newSize = fontSize * scale; + // round to the nearest 0.5 + newSize = Math.round(PixelRatio.roundToNearestPixel(newSize) * 2) / 2; + return newSize; +}; -- cgit v1.2.3-70-g09d2 From ad321571af78b5ea58a8e3e35820d5c3cf1c607b Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Thu, 21 Jan 2021 17:13:21 -0500 Subject: linting and normalizing tagg icons --- src/components/profile/ProfilePreview.tsx | 33 ++++++++++++++-------------- src/components/search/Explore.tsx | 4 ++-- src/components/search/ExploreSection.tsx | 3 ++- src/components/search/ExploreSectionUser.tsx | 6 ++--- src/components/taggs/Tagg.tsx | 3 ++- src/constants/constants.ts | 4 ++-- src/screens/search/SearchScreen.tsx | 7 +----- 7 files changed, 28 insertions(+), 32 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index b2c0a24d..389ca367 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -1,27 +1,26 @@ -import React, {useEffect, useState, useContext} from 'react'; -import {ProfilePreviewType, ScreenType} from '../../types'; +import AsyncStorage from '@react-native-community/async-storage'; +import {useNavigation} from '@react-navigation/native'; +import React, {useEffect, useState} from 'react'; import { - View, - Text, + Alert, Image, StyleSheet, - ViewProps, + Text, TouchableOpacity, - Alert, + View, + ViewProps, } from 'react-native'; -import {useNavigation} from '@react-navigation/native'; -import RNFetchBlob from 'rn-fetch-blob'; -import AsyncStorage from '@react-native-community/async-storage'; -import {PROFILE_PHOTO_THUMBNAIL_ENDPOINT} from '../../constants'; -import {UserType, PreviewType} from '../../types'; -import {isUserBlocked, loadAvatar} from '../../services'; -import {useSelector, useDispatch, useStore} from 'react-redux'; +import {useDispatch, useSelector, useStore} from 'react-redux'; +import {ERROR_UNABLE_TO_VIEW_PROFILE} from '../../constants/strings'; +import {loadAvatar} from '../../services'; import {RootState} from '../../store/rootreducer'; -import {logout} from '../../store/actions'; +import { + PreviewType, + ProfilePreviewType, + ScreenType, + UserType, +} from '../../types'; import {checkIfUserIsBlocked, fetchUserX, userXInStore} from '../../utils'; -import {SearchResultsBackground} from '../search'; -import NavigationBar from 'src/routes/tabs'; -import {ERROR_UNABLE_TO_VIEW_PROFILE} from '../../constants/strings'; const NO_USER: UserType = { userId: '', diff --git a/src/components/search/Explore.tsx b/src/components/search/Explore.tsx index c07c66b8..4a71249b 100644 --- a/src/components/search/Explore.tsx +++ b/src/components/search/Explore.tsx @@ -4,6 +4,7 @@ import {useSelector} from 'react-redux'; import {EXPLORE_SECTION_TITLES} from '../../constants'; import {RootState} from '../../store/rootReducer'; import {ExploreSectionType} from '../../types'; +import {normalize} from '../../utils'; import ExploreSection from './ExploreSection'; const Explore: React.FC = () => { @@ -21,11 +22,10 @@ const Explore: React.FC = () => { const styles = StyleSheet.create({ container: { zIndex: 0, - // margin: '5%', }, header: { fontWeight: '700', - fontSize: 22, + fontSize: normalize(22), color: '#fff', marginBottom: '2%', margin: '5%', diff --git a/src/components/search/ExploreSection.tsx b/src/components/search/ExploreSection.tsx index 8e8b4988..17079e77 100644 --- a/src/components/search/ExploreSection.tsx +++ b/src/components/search/ExploreSection.tsx @@ -1,6 +1,7 @@ import React, {Fragment} from 'react'; import {ScrollView, StyleSheet, Text, View} from 'react-native'; import {ProfilePreviewType} from '../../types'; +import {normalize} from '../../utils'; import ExploreSectionUser from './ExploreSectionUser'; /** @@ -34,7 +35,7 @@ const styles = StyleSheet.create({ }, header: { fontWeight: '600', - fontSize: 20, + fontSize: normalize(18), color: '#fff', marginLeft: '5%', marginBottom: '5%', diff --git a/src/components/search/ExploreSectionUser.tsx b/src/components/search/ExploreSectionUser.tsx index 0bf68a20..68e077e3 100644 --- a/src/components/search/ExploreSectionUser.tsx +++ b/src/components/search/ExploreSectionUser.tsx @@ -12,7 +12,7 @@ import {useDispatch, useSelector, useStore} from 'react-redux'; import {loadAvatar} from '../../services'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType} from '../../types'; -import {fetchUserX, userXInStore} from '../../utils'; +import {fetchUserX, normalize, userXInStore} from '../../utils'; /** * Search Screen for user recommendations and a search @@ -110,13 +110,13 @@ const styles = StyleSheet.create({ name: { fontWeight: '600', flexWrap: 'wrap', - fontSize: 16, + fontSize: normalize(16), color: '#fff', textAlign: 'center', }, username: { fontWeight: '400', - fontSize: 14, + fontSize: normalize(14), color: '#fff', }, }); diff --git a/src/components/taggs/Tagg.tsx b/src/components/taggs/Tagg.tsx index 82ac07df..5fa8b395 100644 --- a/src/components/taggs/Tagg.tsx +++ b/src/components/taggs/Tagg.tsx @@ -22,6 +22,7 @@ import { ERROR_UNABLE_TO_FIND_PROFILE, SUCCESS_LINK, } from '../../constants/strings'; +import {normalize} from '../../utils'; interface TaggProps { social: string; @@ -165,7 +166,7 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', alignItems: 'center', marginHorizontal: 15, - height: 90, + height: normalize(90), }, iconTap: { justifyContent: 'center', diff --git a/src/constants/constants.ts b/src/constants/constants.ts index 557eef3a..9abfc702 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -1,6 +1,6 @@ import {ReactText} from 'react'; import {BackgroundGradientType, ExploreSectionType} from './../types/'; -import {SCREEN_WIDTH, SCREEN_HEIGHT, isIPhoneX} from '../utils'; +import {SCREEN_WIDTH, SCREEN_HEIGHT, isIPhoneX, normalize} from '../utils'; export const CHIN_HEIGHT = 34; @@ -19,7 +19,7 @@ export const AVATAR_DIM = 44; export const AVATAR_GRADIENT_DIM = 50; export const TAGG_ICON_DIM = 58; -export const TAGG_RING_DIM = 65; +export const TAGG_RING_DIM = normalize(60); export const INTEGRATED_SOCIAL_LIST: string[] = [ 'Instagram', diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index 5072e13a..f1bdbea2 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -25,12 +25,7 @@ import {SEARCH_ENDPOINT, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; import {loadRecentlySearched, resetScreenType} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType, UserType} from '../../types'; -import { - isIPhoneX, - SCREEN_HEIGHT, - SCREEN_WIDTH, - StatusBarHeight, -} from '../../utils'; +import {SCREEN_HEIGHT, SCREEN_WIDTH, StatusBarHeight} from '../../utils'; const NO_USER: UserType = { userId: '', username: '', -- cgit v1.2.3-70-g09d2 From 2da3a183e49ef0a99d9f5d0420ed99db82a6204d Mon Sep 17 00:00:00 2001 From: Ashm Walia Date: Thu, 21 Jan 2021 14:45:25 -0800 Subject: done --- src/components/profile/Content.tsx | 20 +++-- src/constants/strings.ts | 105 ++++++++++++++++------- src/routes/Routes.tsx | 2 +- src/screens/profile/MomentUploadPromptScreen.tsx | 8 +- 4 files changed, 89 insertions(+), 46 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/Content.tsx b/src/components/profile/Content.tsx index e7fb566b..345079ad 100644 --- a/src/components/profile/Content.tsx +++ b/src/components/profile/Content.tsx @@ -55,6 +55,12 @@ import {TouchableOpacity} from 'react-native-gesture-handler'; import {useFocusEffect, useNavigation} from '@react-navigation/native'; import GreyPlusLogo from '../../assets/icons/grey-plus-logo.svg'; import {TaggPrompt} from '../common'; +import { + UPLOAD_MOMENT_PROMPT_THREE_HEADER, + UPLOAD_MOMENT_PROMPT_THREE_MESSAGE, + UPLOAD_MOMENT_PROMPT_TWO_HEADER, + UPLOAD_MOMENT_PROMPT_TWO_MESSAGE, +} from '../../constants/strings'; interface ContentProps { y: Animated.Value; @@ -284,7 +290,7 @@ const Content: React.FC = ({y, userXId, screenType}) => { momentCategories.filter((mc) => mc !== category), false, ), - ) + ); dispatch(deleteUserMomentsForCategory(category)); }, }, @@ -352,10 +358,8 @@ const Content: React.FC = ({y, userXId, screenType}) => { profile.profile_completion_stage === 2 && !isStageTwoPromptClosed && ( { setIsStageTwoPromptClosed(true); @@ -366,10 +370,8 @@ const Content: React.FC = ({y, userXId, screenType}) => { profile.profile_completion_stage === 3 && !isStageThreePromptClosed && ( { setIsStageThreePromptClosed(true); diff --git a/src/constants/strings.ts b/src/constants/strings.ts index b5344afd..e40398bb 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -2,46 +2,87 @@ // Below is the regex to convert this into a csv for the Google Sheet // export const (.*) = .*?(['|"|`])(.*)\2; // replace with: $1\t$3 -export const COMING_SOON_MSG = 'Creating more fun things for you, surprises coming soon πŸ˜‰'; -export const ERROR_AUTHENTICATION = 'An error occurred during authentication. Please login again!'; -export const ERROR_CATEGORY_CREATION = 'There was a problem creating your categories. Please refresh and try again.'; -export const ERROR_CATEGORY_UPDATE = 'There was a problem updating your categories. Please refresh and try again'; -export const ERROR_DELETE_CATEGORY = 'There was a problem while deleting category. Please try again'; -export const ERROR_DELETE_MOMENT = 'Unable to delete moment, please try again later!'; -export const ERROR_DOUBLE_CHECK_CONNECTION = 'Please double-check your network connection and retry'; +export const COMING_SOON_MSG = + 'Creating more fun things for you, surprises coming soon πŸ˜‰'; +export const ERROR_AUTHENTICATION = + 'An error occurred during authentication. Please login again!'; +export const ERROR_CATEGORY_CREATION = + 'There was a problem creating your categories. Please refresh and try again.'; +export const ERROR_CATEGORY_UPDATE = + 'There was a problem updating your categories. Please refresh and try again'; +export const ERROR_DELETE_CATEGORY = + 'There was a problem while deleting category. Please try again'; +export const ERROR_DELETE_MOMENT = + 'Unable to delete moment, please try again later!'; +export const ERROR_DOUBLE_CHECK_CONNECTION = + 'Please double-check your network connection and retry'; export const ERROR_DUP_OLD_PWD = 'You may not use a previously used password'; -export const ERROR_EMAIL_IN_USE = 'Email already in use, please try another one'; -export const ERROR_FAILED_LOGIN_INFO = 'Login failed, please try re-entering your login information'; -export const ERROR_FAILED_TO_COMMENT = 'Unable to post comment, refresh and try again!'; -export const ERROR_INVALID_INVITATION_CODE = 'Invitation code invalid, try again or talk to the friend that sent it 😬'; +export const ERROR_EMAIL_IN_USE = + 'Email already in use, please try another one'; +export const ERROR_FAILED_LOGIN_INFO = + 'Login failed, please try re-entering your login information'; +export const ERROR_FAILED_TO_COMMENT = + 'Unable to post comment, refresh and try again!'; +export const ERROR_INVALID_INVITATION_CODE = + 'Invitation code invalid, try again or talk to the friend that sent it 😬'; export const ERROR_INVALID_LOGIN = 'Invalid login, Please login again'; -export const ERROR_INVALID_PWD_CODE = 'Looks like you have entered the wrong code, please try again'; -export const ERROR_INVALID_VERIFICATION_CODE = 'Invalid verification code, try re-entering or tap the resend code button for a new code'; -export const ERROR_INVALID_VERIFICATION_CODE_FORMAT = 'Please enter the 6 digit code sent to your phone'; +export const ERROR_INVALID_PWD_CODE = + 'Looks like you have entered the wrong code, please try again'; +export const ERROR_INVALID_VERIFICATION_CODE = + 'Invalid verification code, try re-entering or tap the resend code button for a new code'; +export const ERROR_INVALID_VERIFICATION_CODE_FORMAT = + 'Please enter the 6 digit code sent to your phone'; export const ERROR_INVLAID_CODE = 'The code entered is not valid!'; -export const ERROR_LINK = (str: string) => `Unable to link with ${str}, Please check your login and try again`; -export const ERROR_LOGIN = 'There was a problem logging you in, please refresh and try again'; -export const ERROR_LOGIN_FAILED = 'Login failed. Check your username and passoword, and try again'; -export const ERROR_NEXT_PAGE = 'There was a problem while loading the next page πŸ˜“, try again in a couple minutes'; +export const ERROR_LINK = (str: string) => + `Unable to link with ${str}, Please check your login and try again`; +export const ERROR_LOGIN = + 'There was a problem logging you in, please refresh and try again'; +export const ERROR_LOGIN_FAILED = + 'Login failed. Check your username and passoword, and try again'; +export const ERROR_NEXT_PAGE = + 'There was a problem while loading the next page πŸ˜“, try again in a couple minutes'; export const ERROR_PROFILE_CREATION_SHORT = 'Profile creation failed πŸ˜“'; -export const ERROR_PWD_ACCOUNT = (str: string) => `Please make sure that the email / username entered is registered with us. You may contact our customer support at ${str}`; -export const ERROR_REGISTRATION = (str: string) => `Registration failed πŸ˜”, ${str}`; +export const ERROR_PWD_ACCOUNT = (str: string) => + `Please make sure that the email / username entered is registered with us. You may contact our customer support at ${str}`; +export const ERROR_REGISTRATION = (str: string) => + `Registration failed πŸ˜”, ${str}`; export const ERROR_SELECT_CLASS_YEAR = 'Please select your Class Year'; -export const ERROR_SERVER_DOWN = 'mhm, looks like our servers are down, please refresh and try again in a few mins'; -export const ERROR_SOMETHING_WENT_WRONG = "Oh dear, don’t worry someone will be held responsible for this error, In the meantime refresh the app"; -export const ERROR_SOMETHING_WENT_WRONG_REFRESH = "Ha, looks like this one's on us, please refresh and try again"; -export const ERROR_SOMETHING_WENT_WRONG_RELOAD = "You broke it, Just kidding! we don't know what happened... Please reload the app and try again"; -export const ERROR_UNABLE_TO_FIND_PROFILE = 'We were unable to find this profile. Please check username and try again'; +export const ERROR_SERVER_DOWN = + 'mhm, looks like our servers are down, please refresh and try again in a few mins'; +export const ERROR_SOMETHING_WENT_WRONG = + 'Oh dear, don’t worry someone will be held responsible for this error, In the meantime refresh the app'; +export const ERROR_SOMETHING_WENT_WRONG_REFRESH = + "Ha, looks like this one's on us, please refresh and try again"; +export const ERROR_SOMETHING_WENT_WRONG_RELOAD = + "You broke it, Just kidding! we don't know what happened... Please reload the app and try again"; +export const ERROR_UNABLE_TO_FIND_PROFILE = + 'We were unable to find this profile. Please check username and try again'; export const ERROR_UNABLE_TO_VIEW_PROFILE = 'Unable to view this profile'; -export const ERROR_UPLOAD = 'An error occurred while uploading. Please try again!'; -export const ERROR_UPLOAD_LARGE_PROFILE_PIC = "Can't have the first image seen on the profile be blank, please upload a large picture"; +export const ERROR_UPLOAD = + 'An error occurred while uploading. Please try again!'; +export const ERROR_UPLOAD_LARGE_PROFILE_PIC = + "Can't have the first image seen on the profile be blank, please upload a large picture"; export const ERROR_UPLOAD_MOMENT = 'Unable to upload moment. Please retry'; -export const ERROR_UPLOAD_SMALL_PROFILE_PIC = "Can't have a profile without a pic to represent you, please upload a small profile picture"; +export const ERROR_UPLOAD_SMALL_PROFILE_PIC = + "Can't have a profile without a pic to represent you, please upload a small profile picture"; export const ERROR_VERIFICATION_FAILED_SHORT = 'Verification failed πŸ˜“'; export const MARKED_AS_MSG = (str: string) => `Marked as ${str}`; -export const MOMENT_DELETED_MSG = 'Moment deleted....Some moments have to go, to create space for greater ones'; -export const SUCCESS_CATEGORY_DELETE = 'Category successfully deleted, but its memory will live on'; +export const MOMENT_DELETED_MSG = + 'Moment deleted....Some moments have to go, to create space for greater ones'; +export const SUCCESS_CATEGORY_DELETE = + 'Category successfully deleted, but its memory will live on'; export const SUCCESS_LINK = (str: string) => `Successfully linked ${str} πŸŽ‰`; -export const SUCCESS_PIC_UPLOAD = 'Beautiful, the picture was uploaded successfully!'; +export const SUCCESS_PIC_UPLOAD = + 'Beautiful, the picture was uploaded successfully!'; export const SUCCESS_PWD_RESET = 'Your password was reset successfully!'; -export const SUCCESS_VERIFICATION_CODE_SENT = 'New verification code sent! Check your phone messages for your code'; +export const SUCCESS_VERIFICATION_CODE_SENT = + 'New verification code sent! Check your phone messages for your code'; +export const UPLOAD_MOMENT_PROMPT_ONE_MESSAGE = + "Post your first moment to {'\n'} continue building your digital {'\n'}{' '}identity!"; +export const UPLOAD_MOMENT_PROMPT_TWO_HEADER = 'Create a new category'; +export const UPLOAD_MOMENT_PROMPT_TWO_MESSAGE = + 'You can now create new categories \nand continue to fill your profile with moments!'; +export const UPLOAD_MOMENT_PROMPT_THREE_HEADER = + 'Continue to build your profile'; +export const UPLOAD_MOMENT_PROMPT_THREE_MESSAGE = + 'Continue to personalize your own digital space in\nthis community by filling your profile with\ncategories and moments!'; diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx index a14f1576..536c7d04 100644 --- a/src/routes/Routes.tsx +++ b/src/routes/Routes.tsx @@ -33,7 +33,7 @@ const Routes: React.FC = () => { }); if (!userId) { - userLogin(dispatch, {userId: '', username: ''}); + // userLogin(dispatch, {userId: '', username: ''}); } else { SplashScreen.hide(); } diff --git a/src/screens/profile/MomentUploadPromptScreen.tsx b/src/screens/profile/MomentUploadPromptScreen.tsx index 6111985d..9d46c1e9 100644 --- a/src/screens/profile/MomentUploadPromptScreen.tsx +++ b/src/screens/profile/MomentUploadPromptScreen.tsx @@ -6,6 +6,7 @@ import CloseIcon from '../../assets/ionicons/close-outline.svg'; import {StyleSheet, Text, View} from 'react-native'; import {Moment} from '../../components'; import {Image} from 'react-native-animatable'; +import {UPLOAD_MOMENT_PROMPT_ONE_MESSAGE} from '../../constants/strings'; type MomentUploadPromptScreenRouteProp = RouteProp< MainStackParams, @@ -38,10 +39,7 @@ const MomentUploadPromptScreen: React.FC = ({ }} /> - - Post your first moment to {'\n'} continue building your digital {'\n'}{' '} - identity! - + {UPLOAD_MOMENT_PROMPT_ONE_MESSAGE} = ({ screenType={screenType} handleMomentCategoryDelete={() => {}} shouldAllowDeletion={false} + showDownButton={false} + showUpButton={false} externalStyles={{ container: styles.momentContainer, titleText: styles.momentHeaderText, -- cgit v1.2.3-70-g09d2 From d667654caf1aa4e5f4814fa927e835f13efc0650 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 22 Jan 2021 16:30:46 -0500 Subject: changed constant name --- src/components/common/AcceptDeclineButtons.tsx | 8 +-- src/components/common/GenericMoreInfoDrawer.tsx | 4 +- src/components/common/SocialLinkModal.tsx | 4 +- src/components/moments/Moment.tsx | 10 ++-- src/components/moments/MomentPostContent.tsx | 1 + src/components/onboarding/TaggBigInput.tsx | 4 +- src/components/profile/Content.tsx | 68 +++++++++++------------- src/components/profile/ProfileBody.tsx | 8 +-- src/components/profile/ProfileMoreInfoDrawer.tsx | 4 +- src/components/profile/ToggleButton.tsx | 8 +-- src/components/search/RecentSearches.tsx | 4 +- src/components/taggs/TwitterTaggPost.tsx | 4 +- src/constants/constants.ts | 2 +- src/screens/search/SearchScreen.tsx | 4 +- 14 files changed, 63 insertions(+), 70 deletions(-) (limited to 'src/components') diff --git a/src/components/common/AcceptDeclineButtons.tsx b/src/components/common/AcceptDeclineButtons.tsx index 221056c0..9caaffca 100644 --- a/src/components/common/AcceptDeclineButtons.tsx +++ b/src/components/common/AcceptDeclineButtons.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {StyleProp, StyleSheet, Text, View, ViewStyle} from 'react-native'; -import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {TAGG_LIGHT_BLUE} from '../../constants'; import {ProfilePreviewType} from '../../types'; import {SCREEN_WIDTH} from '../../utils'; import {TouchableOpacity} from 'react-native-gesture-handler'; @@ -55,18 +55,18 @@ const styles = StyleSheet.create({ }, acceptButton: { padding: 0, - backgroundColor: TAGG_TEXT_LIGHT_BLUE, + backgroundColor: TAGG_LIGHT_BLUE, }, rejectButton: { borderWidth: 1, backgroundColor: 'white', - borderColor: TAGG_TEXT_LIGHT_BLUE, + borderColor: TAGG_LIGHT_BLUE, }, acceptButtonTitleColor: { color: 'white', }, rejectButtonTitleColor: { - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, buttonTitle: { padding: 0, diff --git a/src/components/common/GenericMoreInfoDrawer.tsx b/src/components/common/GenericMoreInfoDrawer.tsx index 098482ae..a23d7736 100644 --- a/src/components/common/GenericMoreInfoDrawer.tsx +++ b/src/components/common/GenericMoreInfoDrawer.tsx @@ -10,7 +10,7 @@ import { } from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; import {BottomDrawer} from '.'; -import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {TAGG_LIGHT_BLUE} from '../../constants'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; // conforms the JSX onPress attribute type @@ -87,7 +87,7 @@ const styles = StyleSheet.create({ panelButtonTitleCancel: { fontSize: 18, fontWeight: 'bold', - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, divider: {height: 1, borderWidth: 1, borderColor: '#e7e7e7'}, }); diff --git a/src/components/common/SocialLinkModal.tsx b/src/components/common/SocialLinkModal.tsx index b307a62c..41b044fe 100644 --- a/src/components/common/SocialLinkModal.tsx +++ b/src/components/common/SocialLinkModal.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {Modal, StyleSheet, Text, TouchableHighlight, View} from 'react-native'; import {TextInput} from 'react-native-gesture-handler'; -import { TAGG_TEXT_LIGHT_BLUE } from '../../constants'; +import { TAGG_LIGHT_BLUE } from '../../constants'; import {SCREEN_WIDTH} from '../../utils'; interface SocialLinkModalProps { @@ -105,7 +105,7 @@ const styles = StyleSheet.create({ fontSize: 14, /* identical to box height */ textAlign: 'center', - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, textInput: { height: 20, diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index 7905e8a9..c591d973 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -11,7 +11,7 @@ import DownIcon from '../../assets/icons/down_icon.svg'; import PlusIcon from '../../assets/icons/plus_icon-01.svg'; import BigPlusIcon from '../../assets/icons/plus_icon-02.svg'; import UpIcon from '../../assets/icons/up_icon.svg'; -import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {TAGG_LIGHT_BLUE} from '../../constants'; import {ERROR_UPLOAD_MOMENT_SHORT} from '../../constants/strings'; import {SCREEN_WIDTH} from '../../utils'; import MomentTile from './MomentTile'; @@ -87,7 +87,7 @@ const Moment: React.FC = ({ width={19} height={19} onPress={() => move('up', title)} - color={TAGG_TEXT_LIGHT_BLUE} + color={TAGG_LIGHT_BLUE} style={{marginLeft: 5}} /> )} @@ -96,7 +96,7 @@ const Moment: React.FC = ({ width={19} height={19} onPress={() => move('down', title)} - color={TAGG_TEXT_LIGHT_BLUE} + color={TAGG_LIGHT_BLUE} style={{marginLeft: 5}} /> )} @@ -111,7 +111,7 @@ const Moment: React.FC = ({ width={21} height={21} onPress={() => navigateToImagePicker()} - color={TAGG_TEXT_LIGHT_BLUE} + color={TAGG_LIGHT_BLUE} style={{marginRight: 10}} /> {shouldAllowDeletion && ( @@ -173,7 +173,7 @@ const styles = StyleSheet.create({ titleText: { fontSize: 16, fontWeight: 'bold', - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, // titleContainer: { // flex: 1, diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 93271fa1..508b6d9f 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -27,6 +27,7 @@ const MomentPostContent: React.FC = ({ setElapsedTime(getTimePosted(dateTime)); getMomentCommentsCount(momentId, setCommentsCount); }, [dateTime, momentId]); + return ( { ; @@ -113,9 +104,10 @@ const Content: React.FC = ({y, userXId, screenType}) => { const [isStageOnePromptClosed, setIsStageOnePromptClosed] = useState( false, ); - const [isStageThreePromptClosed, setIsStageThreePromptClosed] = useState< - boolean - >(false); + const [ + isStageThreePromptClosed, + setIsStageThreePromptClosed, + ] = useState(false); const onRefresh = useCallback(() => { const refrestState = async () => { @@ -284,7 +276,7 @@ const Content: React.FC = ({y, userXId, screenType}) => { momentCategories.filter((mc) => mc !== category), false, ), - ) + ); dispatch(deleteUserMomentsForCategory(category)); }, }, @@ -423,7 +415,7 @@ const styles = StyleSheet.create({ flexDirection: 'column', }, createCategoryButton: { - backgroundColor: TAGG_TEXT_LIGHT_BLUE, + backgroundColor: TAGG_LIGHT_BLUE, justifyContent: 'center', alignItems: 'center', width: '70%', diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 6284ff59..a45e9e43 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -3,7 +3,7 @@ import {StyleSheet, View, Text, LayoutChangeEvent, Linking} from 'react-native'; import {Button} from 'react-native-elements'; import { TAGG_DARK_BLUE, - TAGG_TEXT_LIGHT_BLUE, + TAGG_LIGHT_BLUE, TOGGLE_BUTTON_TYPE, } from '../../constants'; import ToggleButton from './ToggleButton'; @@ -178,7 +178,7 @@ const styles = StyleSheet.create({ alignItems: 'center', width: SCREEN_WIDTH * 0.4, height: SCREEN_WIDTH * 0.09, - borderColor: TAGG_TEXT_LIGHT_BLUE, + borderColor: TAGG_LIGHT_BLUE, borderWidth: 3, borderRadius: 5, marginRight: '2%', @@ -186,7 +186,7 @@ const styles = StyleSheet.create({ backgroundColor: 'transparent', }, requestedButtonTitle: { - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, padding: 0, fontSize: 14, fontWeight: '700', @@ -205,7 +205,7 @@ const styles = StyleSheet.create({ padding: 0, borderRadius: 5, marginRight: '2%', - backgroundColor: TAGG_TEXT_LIGHT_BLUE, + backgroundColor: TAGG_LIGHT_BLUE, }, }); diff --git a/src/components/profile/ProfileMoreInfoDrawer.tsx b/src/components/profile/ProfileMoreInfoDrawer.tsx index 76f0f27f..9fe36ae1 100644 --- a/src/components/profile/ProfileMoreInfoDrawer.tsx +++ b/src/components/profile/ProfileMoreInfoDrawer.tsx @@ -4,7 +4,7 @@ import {StyleSheet, TouchableOpacity} from 'react-native'; import {useSelector} from 'react-redux'; import MoreIcon from '../../assets/icons/more_horiz-24px.svg'; import PersonOutline from '../../assets/ionicons/person-outline.svg'; -import {TAGG_DARK_BLUE, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {TAGG_DARK_BLUE, TAGG_LIGHT_BLUE} from '../../constants'; import {RootState} from '../../store/rootreducer'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import {GenericMoreInfoDrawer} from '../common'; @@ -101,7 +101,7 @@ const styles = StyleSheet.create({ panelButtonTitleCancel: { fontSize: 18, fontWeight: 'bold', - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, divider: {height: 1, borderWidth: 1, borderColor: '#e7e7e7'}, more: { diff --git a/src/components/profile/ToggleButton.tsx b/src/components/profile/ToggleButton.tsx index 5d8f7874..236d811c 100644 --- a/src/components/profile/ToggleButton.tsx +++ b/src/components/profile/ToggleButton.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import {StyleSheet, Text} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; -import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {TAGG_LIGHT_BLUE} from '../../constants'; import {getToggleButtonText, SCREEN_WIDTH} from '../../utils'; type ToggleButtonProps = { @@ -36,7 +36,7 @@ const styles = StyleSheet.create({ alignItems: 'center', width: SCREEN_WIDTH * 0.4, height: SCREEN_WIDTH * 0.08, - borderColor: TAGG_TEXT_LIGHT_BLUE, + borderColor: TAGG_LIGHT_BLUE, borderWidth: 3, borderRadius: 5, marginRight: '2%', @@ -45,10 +45,10 @@ const styles = StyleSheet.create({ fontWeight: 'bold', }, buttonColor: { - backgroundColor: TAGG_TEXT_LIGHT_BLUE, + backgroundColor: TAGG_LIGHT_BLUE, }, textColor: {color: 'white'}, buttonColorToggled: {backgroundColor: 'white'}, - textColorToggled: {color: TAGG_TEXT_LIGHT_BLUE}, + textColorToggled: {color: TAGG_LIGHT_BLUE}, }); export default ToggleButton; diff --git a/src/components/search/RecentSearches.tsx b/src/components/search/RecentSearches.tsx index 8a06017c..bdbd5773 100644 --- a/src/components/search/RecentSearches.tsx +++ b/src/components/search/RecentSearches.tsx @@ -7,7 +7,7 @@ import { TouchableOpacityProps, } from 'react-native'; import {PreviewType, ProfilePreviewType, ScreenType} from 'src/types'; -import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {TAGG_LIGHT_BLUE} from '../../constants'; import SearchResults from './SearchResults'; interface RecentSearchesProps extends TouchableOpacityProps { @@ -55,7 +55,7 @@ const styles = StyleSheet.create({ clear: { fontSize: 18, fontWeight: 'bold', - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, }); diff --git a/src/components/taggs/TwitterTaggPost.tsx b/src/components/taggs/TwitterTaggPost.tsx index c971a82c..0cfde857 100644 --- a/src/components/taggs/TwitterTaggPost.tsx +++ b/src/components/taggs/TwitterTaggPost.tsx @@ -6,7 +6,7 @@ import LinearGradient from 'react-native-linear-gradient'; import { AVATAR_DIM, TAGGS_GRADIENT, - TAGG_TEXT_LIGHT_BLUE, + TAGG_LIGHT_BLUE, } from '../../constants'; import {TwitterPostType} from '../../types'; import {handleOpenSocialUrlOnBrowser, SCREEN_WIDTH} from '../../utils'; @@ -237,7 +237,7 @@ const styles = StyleSheet.create({ }, replyShowThisThread: { fontSize: 15, - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, }); diff --git a/src/constants/constants.ts b/src/constants/constants.ts index b96d9438..37b6e038 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -59,7 +59,7 @@ export const SNAPCHAT_FONT_COLOR: string = '#FFFC00'; export const YOUTUBE_FONT_COLOR: string = '#FCA4A4'; export const TAGG_DARK_BLUE = '#4E699C'; -export const TAGG_TEXT_LIGHT_BLUE: string = '#698DD3'; +export const TAGG_LIGHT_BLUE: string = '#698DD3'; export const TAGG_LIGHT_PURPLE = '#F4DDFF'; export const TAGGS_GRADIENT = { diff --git a/src/screens/search/SearchScreen.tsx b/src/screens/search/SearchScreen.tsx index 9f98b4d7..f231cb78 100644 --- a/src/screens/search/SearchScreen.tsx +++ b/src/screens/search/SearchScreen.tsx @@ -20,7 +20,7 @@ import { SearchResultsBackground, TabsGradient, } from '../../components'; -import {SEARCH_ENDPOINT, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {SEARCH_ENDPOINT, TAGG_LIGHT_BLUE} from '../../constants'; import {loadRecentlySearched, resetScreenType} from '../../store/actions'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType, UserType} from '../../types'; @@ -213,7 +213,7 @@ const styles = StyleSheet.create({ clear: { fontSize: 17, fontWeight: 'bold', - color: TAGG_TEXT_LIGHT_BLUE, + color: TAGG_LIGHT_BLUE, }, image: { width: SCREEN_WIDTH, -- cgit v1.2.3-70-g09d2 From 5f2159489e75a05dbe6bede792cb8a97971b824a Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 22 Jan 2021 16:31:35 -0500 Subject: finished styling the input box --- src/assets/icons/up_arrow.svg | 1 + src/components/comments/AddComment.tsx | 153 +++++++++++++++------------ src/screens/profile/MomentCommentsScreen.tsx | 46 ++++---- src/services/MomentServices.ts | 7 +- 4 files changed, 114 insertions(+), 93 deletions(-) create mode 100644 src/assets/icons/up_arrow.svg (limited to 'src/components') diff --git a/src/assets/icons/up_arrow.svg b/src/assets/icons/up_arrow.svg new file mode 100644 index 00000000..fc92b551 --- /dev/null +++ b/src/assets/icons/up_arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index c6c816b9..24b3473c 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -1,16 +1,17 @@ -import * as React from 'react'; +import React, {useEffect} from 'react'; import { Image, + Keyboard, KeyboardAvoidingView, Platform, StyleSheet, View, } from 'react-native'; -import AsyncStorage from '@react-native-community/async-storage'; -import {TaggBigInput} from '../onboarding'; +import {TextInput, TouchableOpacity} from 'react-native-gesture-handler'; +import {useSelector} from 'react-redux'; +import UpArrowIcon from '../../assets/icons/up_arrow.svg'; +import {TAGG_LIGHT_BLUE} from '../../constants'; import {postMomentComment} from '../../services'; -import {logout} from '../../store/actions'; -import {useSelector, useDispatch} from 'react-redux'; import {RootState} from '../../store/rootreducer'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; @@ -30,98 +31,114 @@ const AddComment: React.FC = ({ moment_id, }) => { const [comment, setComment] = React.useState(''); + const [keyboardVisible, setKeyboardVisible] = React.useState(false); - const dispatch = useDispatch(); const { avatar, user: {userId}, } = useSelector((state: RootState) => state.user); - const handleCommentUpdate = (comment: string) => { - setComment(comment); - }; - const postComment = async () => { - try { - const token = await AsyncStorage.getItem('token'); - if (!token) { - dispatch(logout()); - return; - } - const postedComment = await postMomentComment( - userId, - comment, - moment_id, - token, - ); - - if (postedComment) { - //Set the current comment to en empty string if the comment was posted successfully. - handleCommentUpdate(''); + const postedComment = await postMomentComment( + userId, + comment.trim(), + moment_id, + ); - //Indicate the MomentCommentsScreen that it needs to download the new comments again - setNewCommentsAvailable(true); - } - } catch (err) { - console.log('Error while posting comment!'); + if (postedComment) { + setComment(''); + setNewCommentsAvailable(true); } }; + useEffect(() => { + const showKeyboard = () => setKeyboardVisible(true); + Keyboard.addListener('keyboardWillShow', showKeyboard); + return () => Keyboard.removeListener('keyboardWillShow', showKeyboard); + }, []); + + useEffect(() => { + const hideKeyboard = () => setKeyboardVisible(false); + Keyboard.addListener('keyboardWillHide', hideKeyboard); + return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard); + }, []); + return ( - - - - + keyboardVerticalOffset={SCREEN_HEIGHT * 0.1}> + + + + + + + + + + ); }; const styles = StyleSheet.create({ container: { - flexDirection: 'row', - justifyContent: 'flex-start', + backgroundColor: '#f7f7f7', + alignItems: 'center', width: SCREEN_WIDTH, - marginTop: '5%', }, textContainer: { - width: '100%', - alignItems: 'flex-start', - marginVertical: 11, + width: '95%', + flexDirection: 'row', + backgroundColor: '#e8e8e8', + alignItems: 'center', + justifyContent: 'space-between', + margin: '3%', + borderRadius: 25, }, text: { - backgroundColor: 'white', - width: '70%', - paddingLeft: '2%', - paddingRight: '2%', - paddingBottom: '1%', - paddingTop: '1%', - height: 60, + flex: 1, + padding: '1%', + marginHorizontal: '1%', }, avatar: { - height: 40, - width: 40, + height: 35, + width: 35, borderRadius: 30, marginRight: 10, - marginLeft: 20, + marginLeft: '3%', + marginVertical: '2%', + alignSelf: 'flex-end', + }, + submitButton: { + height: 35, + width: 35, + backgroundColor: TAGG_LIGHT_BLUE, + borderRadius: 999, + justifyContent: 'center', + alignItems: 'center', + marginRight: '3%', + marginVertical: '2%', + alignSelf: 'flex-end', }, }); diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index b2611b62..6434477e 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -1,19 +1,21 @@ -import * as React from 'react'; import {RouteProp, useNavigation} from '@react-navigation/native'; -import {ProfileStackParams} from '../../routes/main'; +import React, {useEffect, useRef} from 'react'; +import { + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native'; +import {SafeAreaView} from 'react-native-safe-area-context'; +import {useDispatch} from 'react-redux'; +import {getMomentComments} from '../..//services'; +import BackIcon from '../../assets/icons/back-arrow.svg'; import {CommentTile, TabsGradient} from '../../components'; +import {AddComment} from '../../components/'; +import {ProfileStackParams} from '../../routes/main'; import {CommentType} from '../../types'; -import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils/screenDimensions'; -import {AddComment} from '../../components/'; -import {useEffect} from 'react'; -import AsyncStorage from '@react-native-community/async-storage'; -import {getMomentComments} from '../..//services'; -import {useDispatch} from 'react-redux'; -import {logout} from '../../store/actions'; -import {SafeAreaView} from 'react-native-safe-area-context'; -import Animated from 'react-native-reanimated'; -import BackIcon from '../../assets/icons/back-arrow.svg'; /** * Comments Screen for an image uploaded @@ -36,19 +38,20 @@ const MomentCommentsScreen: React.FC = ({route}) => { const [commentsList, setCommentsList] = React.useState([]); const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true); const dispatch = useDispatch(); + const ref = useRef(null); useEffect(() => { const loadComments = async () => { - const token = await AsyncStorage.getItem('token'); - if (!token) { - dispatch(logout()); - return; - } - getMomentComments(moment_id, setCommentsList, token); + getMomentComments(moment_id, setCommentsList); setNewCommentsAvailable(false); }; if (newCommentsAvailable) { loadComments(); + setTimeout(() => { + ref.current?.scrollToEnd({ + animated: true, + }); + }, 500); } }, [dispatch, moment_id, newCommentsAvailable]); @@ -68,7 +71,8 @@ const MomentCommentsScreen: React.FC = ({route}) => { - {commentsList && @@ -79,7 +83,7 @@ const MomentCommentsScreen: React.FC = ({route}) => { screenType={screenType} /> ))} - + { try { + const token = await AsyncStorage.getItem('token'); const response = await fetch(COMMENTS_ENDPOINT + '?moment_id=' + momentId, { method: 'GET', headers: { @@ -35,14 +35,13 @@ export const getMomentComments = async ( } }; -//Post a comment on a moment export const postMomentComment = async ( commenter: string, comment: string, momentId: string, - token: string, ) => { try { + const token = await AsyncStorage.getItem('token'); const request = new FormData(); request.append('moment_id', momentId); request.append('commenter', commenter); @@ -60,7 +59,7 @@ export const postMomentComment = async ( return await response.json(); } catch (error) { Alert.alert(ERROR_FAILED_TO_COMMENT); - return {}; + return undefined; } }; -- cgit v1.2.3-70-g09d2 From cf420db54deb32be1e6bc4092eef105cc23d93e4 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Fri, 22 Jan 2021 18:31:55 -0500 Subject: fixed merge issue and addressed review --- src/components/profile/ProfileHeader.tsx | 9 +-------- src/screens/profile/MomentCommentsScreen.tsx | 3 +-- 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index 7fc90257..7dad2a68 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -58,13 +58,8 @@ const ProfileHeader: React.FC = ({ )} - + @@ -101,8 +96,6 @@ const styles = StyleSheet.create({ fontWeight: '500', alignSelf: 'center', }, - friends: {}, - university: {}, friendsAndUniversity: { flexDirection: 'row', alignItems: 'center', diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index dee86e15..fa35a33b 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -13,8 +13,7 @@ import {AddComment} from '../../components/'; import {ProfileStackParams} from '../../routes/main'; import {logout} from '../../store/actions'; import {CommentType} from '../../types'; -import {SCREEN_WIDTH} from '../../utils'; -import {SCREEN_HEIGHT} from '../../utils/screenDimensions'; +import {SCREEN_WIDTH, SCREEN_HEIGHT} from '../../utils'; /** * Comments Screen for an image uploaded -- cgit v1.2.3-70-g09d2 From 3a68870bb64f49041e8412bd2b27ba52d58775d5 Mon Sep 17 00:00:00 2001 From: Tanmay Bhatia Date: Fri, 22 Jan 2021 16:47:23 -0800 Subject: Changed date order during onboarding --- src/components/common/TaggDatePicker.tsx | 2 +- src/components/onboarding/BirthDatePicker.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/components') diff --git a/src/components/common/TaggDatePicker.tsx b/src/components/common/TaggDatePicker.tsx index 059bf620..f929b41d 100644 --- a/src/components/common/TaggDatePicker.tsx +++ b/src/components/common/TaggDatePicker.tsx @@ -12,7 +12,7 @@ interface TaggDatePickerProps { const TaggDatePicker: React.FC = (props) => { const [date, setDate] = useState( props.date - ? new Date(moment(props.date).add(1, 'day').format('YYYY-MM-DD')) + ? new Date(moment(props.date).add(1, 'day').format('MM-DD-YYYY')) : undefined, ); return ( diff --git a/src/components/onboarding/BirthDatePicker.tsx b/src/components/onboarding/BirthDatePicker.tsx index 0fc597c3..6bef5798 100644 --- a/src/components/onboarding/BirthDatePicker.tsx +++ b/src/components/onboarding/BirthDatePicker.tsx @@ -45,7 +45,7 @@ const BirthDatePicker = React.forwardRef( ref={ref} {...props}> {(updated || props.showPresetdate) && date - ? moment(date).format('YYYY-MM-DD') + ? moment(date).format('MM-DD-YYYY') : 'Date of Birth'} -- cgit v1.2.3-70-g09d2 From 755f4f540d3e759ff9ad3bc35c64b6f7fc83998b Mon Sep 17 00:00:00 2001 From: Ashm Walia Date: Mon, 25 Jan 2021 18:00:44 -0800 Subject: Add provision to show and hide replies --- src/assets/icons/back-arrow-colored.svg | 1 + src/components/comments/AddComment.tsx | 4 +- src/components/comments/CommentTile.tsx | 122 +++++++++++++++++++++----- src/components/comments/CommentsContainer.tsx | 83 ++++++++++++++++++ src/constants/constants.ts | 1 + src/screens/profile/MomentCommentsScreen.tsx | 67 ++++---------- src/services/MomentServices.ts | 9 +- src/types/types.ts | 2 + 8 files changed, 215 insertions(+), 74 deletions(-) create mode 100644 src/assets/icons/back-arrow-colored.svg create mode 100644 src/components/comments/CommentsContainer.tsx (limited to 'src/components') diff --git a/src/assets/icons/back-arrow-colored.svg b/src/assets/icons/back-arrow-colored.svg new file mode 100644 index 00000000..123426d7 --- /dev/null +++ b/src/assets/icons/back-arrow-colored.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 24b3473c..7b04085d 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -24,11 +24,13 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; export interface AddCommentProps { setNewCommentsAvailable: Function; moment_id: string; + placeholderText: string; } const AddComment: React.FC = ({ setNewCommentsAvailable, moment_id, + placeholderText, }) => { const [comment, setComment] = React.useState(''); const [keyboardVisible, setKeyboardVisible] = React.useState(false); @@ -83,7 +85,7 @@ const AddComment: React.FC = ({ /> = ({ comment_object, screenType, + typeOfComment, }) => { const timePosted = getTimePosted(comment_object.date_created); + const [showReplies, setShowReplies] = useState(false); + + const isThread = typeOfComment === 'Thread'; + return ( - - - - {comment_object.comment} - - - {' ' + timePosted} + <> + + + + {comment_object.comment} + + + {' ' + timePosted} + {typeOfComment === 'Comment' && ( + <> + { + setShowReplies(!showReplies); + }}> + + + {showReplies ? 'Hide' : 'Replies'} + + + + + + )} + - + {/* {showReplies && ( + + { + console.log(value); + }} + newCommentsAvailable={true} + typeOfComment={'Thread'} + /> + + )} */} + ); }; @@ -61,6 +115,7 @@ const styles = StyleSheet.create({ }, date_time: { color: 'gray', + fontSize: normalize(12), }, clockIcon: { width: 12, @@ -71,6 +126,33 @@ const styles = StyleSheet.create({ flexDirection: 'row', marginBottom: '3%', }, + + repliesTextAndIconContainer: { + marginLeft: SCREEN_WIDTH * 0.37, + flexDirection: 'row', + }, + + repliesText: { + color: COMMENT_REPLIES, + fontWeight: '500', + fontSize: normalize(12), + marginRight: '3%', + }, + + repliesBody: { + width: SCREEN_WIDTH, + height: SCREEN_HEIGHT * 0.8, + }, + + repliesDownArrow: { + transform: [{rotate: '270deg'}], + marginTop: '7%', + }, + + repliesUpArrow: { + transform: [{rotate: '90deg'}], + marginTop: '7%', + }, }); export default CommentTile; diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx new file mode 100644 index 00000000..81ae8e1e --- /dev/null +++ b/src/components/comments/CommentsContainer.tsx @@ -0,0 +1,83 @@ +import React, {useRef, useEffect, useState} from 'react'; +import {StyleSheet} from 'react-native'; +import {ScrollView} from 'react-native-gesture-handler'; +import {useDispatch} from 'react-redux'; +import {CommentTile} from '.'; +import {getMomentComments} from '../../services'; +import {CommentType, ScreenType, TypeOfComment} from '../../types'; +export type CommentsContainerProps = { + screenType: ScreenType; + moment_id: string; + setCommentsLength?: (count: number) => void; + newCommentsAvailable: boolean; + setNewCommentsAvailable: (value: boolean) => void; + typeOfComment: TypeOfComment; +}; + +const CommentsContainer: React.FC = ({ + screenType, + moment_id, + setCommentsLength, + newCommentsAvailable, + setNewCommentsAvailable, + typeOfComment, +}) => { + const [commentsList, setCommentsList] = useState([]); + const dispatch = useDispatch(); + const ref = useRef(null); + + useEffect(() => { + const loadComments = async () => { + console.log(moment_id); + const comments = await getMomentComments(moment_id); + setCommentsList(comments); + if (setCommentsLength) { + setCommentsLength(comments.length); + } + console.log(comments); + setNewCommentsAvailable(false); + }; + if (newCommentsAvailable) { + loadComments(); + setTimeout(() => { + ref.current?.scrollToEnd({ + animated: true, + }); + }, 500); + } + }, [ + dispatch, + moment_id, + newCommentsAvailable, + setNewCommentsAvailable, + setCommentsLength, + ]); + + return ( + + {commentsList && + commentsList.map((comment: CommentType) => ( + + ))} + + ); +}; + +const styles = StyleSheet.create({ + scrollView: { + paddingHorizontal: 20, + }, + scrollViewContent: { + justifyContent: 'center', + }, +}); + +export default CommentsContainer; diff --git a/src/constants/constants.ts b/src/constants/constants.ts index ad43c337..6a94f51f 100644 --- a/src/constants/constants.ts +++ b/src/constants/constants.ts @@ -63,6 +63,7 @@ export const YOUTUBE_FONT_COLOR: string = '#FCA4A4'; export const TAGG_DARK_BLUE = '#4E699C'; export const TAGG_LIGHT_BLUE: string = '#698DD3'; export const TAGG_LIGHT_PURPLE = '#F4DDFF'; +export const COMMENT_REPLIES = '#698DD3'; export const TAGGS_GRADIENT = { start: '#9F00FF', diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index 2bceafc9..9fd5aaa0 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -1,20 +1,12 @@ import {RouteProp, useNavigation} from '@react-navigation/native'; -import React, {useEffect, useRef} from 'react'; -import { - ScrollView, - StyleSheet, - Text, - TouchableOpacity, - View, -} from 'react-native'; +import React, {useState} from 'react'; +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; -import {useDispatch} from 'react-redux'; -import {getMomentComments} from '../..//services'; import BackIcon from '../../assets/icons/back-arrow.svg'; -import {CommentTile, TabsGradient} from '../../components'; +import {TabsGradient} from '../../components'; import {AddComment} from '../../components/'; -import {ProfileStackParams} from '../../routes/main'; -import {CommentType} from '../../types'; +import CommentsContainer from '../../components/comments/CommentsContainer'; +import {MainStackParams} from '../../routes/main'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; /** @@ -24,7 +16,7 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; */ type MomentCommentsScreenRouteProps = RouteProp< - ProfileStackParams, + MainStackParams, 'MomentCommentsScreen' >; @@ -35,25 +27,8 @@ interface MomentCommentsScreenProps { const MomentCommentsScreen: React.FC = ({route}) => { const navigation = useNavigation(); const {moment_id, screenType} = route.params; - const [commentsList, setCommentsList] = React.useState([]); - const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true); - const dispatch = useDispatch(); - const ref = useRef(null); - - useEffect(() => { - const loadComments = async () => { - getMomentComments(moment_id, setCommentsList); - setNewCommentsAvailable(false); - }; - if (newCommentsAvailable) { - loadComments(); - setTimeout(() => { - ref.current?.scrollToEnd({ - animated: true, - }); - }, 500); - } - }, [dispatch, moment_id, newCommentsAvailable]); + const [newCommentsAvailable, setNewCommentsAvailable] = useState(true); + const [commentsLength, setCommentsLength] = useState(0); return ( @@ -66,25 +41,19 @@ const MomentCommentsScreen: React.FC = ({route}) => { }}> - - {commentsList.length + ' Comments'} - + {commentsLength + ' Comments'} - - {commentsList && - commentsList.map((comment: CommentType) => ( - - ))} - + diff --git a/src/services/MomentServices.ts b/src/services/MomentServices.ts index 7bad6d4c..77740e7e 100644 --- a/src/services/MomentServices.ts +++ b/src/services/MomentServices.ts @@ -1,3 +1,4 @@ +import {CommentType} from './../types/types'; import AsyncStorage from '@react-native-community/async-storage'; import {Alert} from 'react-native'; import RNFetchBlob from 'rn-fetch-blob'; @@ -13,8 +14,8 @@ import {checkImageUploadStatus} from '../utils'; //Get all comments for a moment export const getMomentComments = async ( momentId: string, - callback: Function, -) => { +): Promise => { + let comments: CommentType[] = []; try { const token = await AsyncStorage.getItem('token'); const response = await fetch(COMMENTS_ENDPOINT + '?moment_id=' + momentId, { @@ -25,14 +26,14 @@ export const getMomentComments = async ( }); const status = response.status; if (status === 200) { - const comments = await response.json(); - callback(comments); + comments = await response.json(); } else { console.log('Could not load comments'); } } catch (error) { console.log('Could not load comments', error); } + return comments; }; export const postMomentComment = async ( diff --git a/src/types/types.ts b/src/types/types.ts index d9d0b56b..b29ecbd9 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -174,3 +174,5 @@ export type NotificationType = { timestamp: string; unread: boolean; }; + +export type TypeOfComment = 'Comment' | 'Thread'; -- cgit v1.2.3-70-g09d2 From f7ed1dae99761eb4647d3b6cb68f009fd467ad8a Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Tue, 26 Jan 2021 18:10:12 -0500 Subject: thumbnail for explore --- src/components/search/ExploreSection.tsx | 15 +++++++++------ src/components/search/ExploreSectionUser.tsx | 18 ++++++------------ 2 files changed, 15 insertions(+), 18 deletions(-) (limited to 'src/components') diff --git a/src/components/search/ExploreSection.tsx b/src/components/search/ExploreSection.tsx index 17079e77..025c8c3c 100644 --- a/src/components/search/ExploreSection.tsx +++ b/src/components/search/ExploreSection.tsx @@ -1,5 +1,5 @@ import React, {Fragment} from 'react'; -import {ScrollView, StyleSheet, Text, View} from 'react-native'; +import {FlatList, StyleSheet, Text, View} from 'react-native'; import {ProfilePreviewType} from '../../types'; import {normalize} from '../../utils'; import ExploreSectionUser from './ExploreSectionUser'; @@ -17,12 +17,15 @@ const ExploreSection: React.FC = ({title, users}) => { return users.length !== 0 ? ( {title} - - - {users.map((user) => ( + } + renderItem={({item: user}: {item: ProfilePreviewType}) => ( - ))} - + )} + showsHorizontalScrollIndicator={false} + horizontal + /> ) : ( diff --git a/src/components/search/ExploreSectionUser.tsx b/src/components/search/ExploreSectionUser.tsx index 68e077e3..b0cfe5c6 100644 --- a/src/components/search/ExploreSectionUser.tsx +++ b/src/components/search/ExploreSectionUser.tsx @@ -9,7 +9,7 @@ import { } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; import {useDispatch, useSelector, useStore} from 'react-redux'; -import {loadAvatar} from '../../services'; +import {loadImageFromURL} from '../../services'; import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType} from '../../types'; import {fetchUserX, normalize, userXInStore} from '../../utils'; @@ -36,18 +36,13 @@ const ExploreSectionUser: React.FC = ({ const dispatch = useDispatch(); useEffect(() => { - let mounted = true; - const loadAvatarImage = async () => { - const response = await loadAvatar(id, true); - if (mounted) { + (async () => { + const response = await loadImageFromURL(user.thumbnail_url); + if (response) { setAvatar(response); } - }; - loadAvatarImage(); - return () => { - mounted = false; - }; - }, [user]); + })(); + }, []); const handlePress = async () => { if (!userXInStore(state, screenType, user.id)) { @@ -63,7 +58,6 @@ const ExploreSectionUser: React.FC = ({ screenType, }); }; - return ( Date: Tue, 26 Jan 2021 18:10:23 -0500 Subject: thumbnail for profile preview and moments --- src/components/moments/MomentTile.tsx | 3 +-- src/components/profile/ProfilePreview.tsx | 43 +++++++++++-------------------- 2 files changed, 16 insertions(+), 30 deletions(-) (limited to 'src/components') diff --git a/src/components/moments/MomentTile.tsx b/src/components/moments/MomentTile.tsx index 16e91c82..69701192 100644 --- a/src/components/moments/MomentTile.tsx +++ b/src/components/moments/MomentTile.tsx @@ -15,7 +15,6 @@ const MomentTile: React.FC = ({ }) => { const navigation = useNavigation(); - const {path_hash} = moment; return ( { @@ -26,7 +25,7 @@ const MomentTile: React.FC = ({ }); }}> - + ); diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index 389ca367..000dd5c5 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -12,21 +12,11 @@ import { } from 'react-native'; import {useDispatch, useSelector, useStore} from 'react-redux'; import {ERROR_UNABLE_TO_VIEW_PROFILE} from '../../constants/strings'; -import {loadAvatar} from '../../services'; +import {loadImageFromURL} from '../../services'; import {RootState} from '../../store/rootreducer'; -import { - PreviewType, - ProfilePreviewType, - ScreenType, - UserType, -} from '../../types'; +import {PreviewType, ProfilePreviewType, ScreenType} from '../../types'; import {checkIfUserIsBlocked, fetchUserX, userXInStore} from '../../utils'; -const NO_USER: UserType = { - userId: '', - username: '', -}; - /** * This component returns user's profile picture friended by username as a touchable component. * What happens when someone clicks on this component is partly decided by the prop isComment. @@ -43,28 +33,24 @@ interface ProfilePreviewProps extends ViewProps { } const ProfilePreview: React.FC = ({ - profilePreview: {username, first_name, last_name, id}, + profilePreview: {username, first_name, last_name, id, thumbnail_url}, previewType, screenType, }) => { const navigation = useNavigation(); const {user: loggedInUser} = useSelector((state: RootState) => state.user); - const [avatarURI, setAvatarURI] = useState(null); - const [user, setUser] = useState(NO_USER); + const [avatar, setAvatar] = useState(null); const dispatch = useDispatch(); + useEffect(() => { - let mounted = true; - const loadAvatarImage = async () => { - const response = await loadAvatar(id, true); - if (mounted) { - setAvatarURI(response); + (async () => { + console.log(thumbnail_url); + const response = await loadImageFromURL(thumbnail_url); + if (response) { + setAvatar(response); } - }; - loadAvatarImage(); - return () => { - mounted = false; - }; - }, [id]); + })(); + }, []); /** * Adds a searched user to the recently searched cache if they're tapped on. @@ -80,6 +66,7 @@ const ProfilePreview: React.FC = ({ username, first_name, last_name, + thumbnail_url, }; try { @@ -211,8 +198,8 @@ const ProfilePreview: React.FC = ({ -- cgit v1.2.3-70-g09d2 From d70ade2e653ee93aca09d62ab7822b8d0f6dc2b5 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Tue, 26 Jan 2021 18:23:44 -0500 Subject: fixed no internet app crash --- src/components/profile/FriendsCount.tsx | 6 +++--- src/components/search/Explore.tsx | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/FriendsCount.tsx b/src/components/profile/FriendsCount.tsx index 9647710e..851dbc3b 100644 --- a/src/components/profile/FriendsCount.tsx +++ b/src/components/profile/FriendsCount.tsx @@ -17,10 +17,10 @@ const FriendsCount: React.FC = ({ userXId, screenType, }) => { - const count = (userXId + const {friends} = userXId ? useSelector((state: RootState) => state.userX[screenType][userXId]) - : useSelector((state: RootState) => state.friends) - )?.friends.length; + : useSelector((state: RootState) => state.friends); + const count = friends ? friends.length : 0; const displayedCount: string = count < 5e3 diff --git a/src/components/search/Explore.tsx b/src/components/search/Explore.tsx index 4a71249b..2a3bc749 100644 --- a/src/components/search/Explore.tsx +++ b/src/components/search/Explore.tsx @@ -12,9 +12,10 @@ const Explore: React.FC = () => { return ( Search Profiles - {EXPLORE_SECTION_TITLES.map((title: ExploreSectionType) => ( - - ))} + {explores && + EXPLORE_SECTION_TITLES.map((title: ExploreSectionType) => ( + + ))} ); }; -- cgit v1.2.3-70-g09d2 From e897fdbbbe8442f05000645395753ff008a19bf4 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Tue, 26 Jan 2021 18:35:41 -0500 Subject: use thumbnails for notification screen --- src/components/notifications/Notification.tsx | 46 +++++++++++---------------- src/components/profile/ProfilePreview.tsx | 1 - 2 files changed, 18 insertions(+), 29 deletions(-) (limited to 'src/components') diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index e6d16f82..e648b554 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -1,25 +1,19 @@ import {useNavigation} from '@react-navigation/native'; import React, {useEffect, useState} from 'react'; import {Image, StyleSheet, Text, View} from 'react-native'; -import {Button} from 'react-native-elements'; import {TouchableWithoutFeedback} from 'react-native-gesture-handler'; import {useDispatch, useStore} from 'react-redux'; +import {loadImageFromURL, loadMomentThumbnail} from '../../services'; import { + acceptFriendRequest, declineFriendRequest, loadUserNotifications, updateUserXFriends, } from '../../store/actions'; -import {acceptFriendRequest} from '../../store/actions'; -import {NotificationType, ProfilePreviewType, ScreenType, MomentType} from '../../types'; -import { - fetchUserX, - SCREEN_HEIGHT, - SCREEN_WIDTH, - userXInStore, -} from '../../utils'; +import {RootState} from '../../store/rootReducer'; +import {MomentType, NotificationType, ScreenType} from '../../types'; +import {fetchUserX, SCREEN_HEIGHT, userXInStore} from '../../utils'; import AcceptDeclineButtons from '../common/AcceptDeclineButtons'; -import {loadAvatar, loadMomentThumbnail} from '../../services'; - interface NotificationProps { item: NotificationType; @@ -30,7 +24,7 @@ interface NotificationProps { const Notification: React.FC = (props) => { const { item: { - actor: {id, username, first_name, last_name}, + actor: {id, username, first_name, last_name, thumbnail_url}, verbage, notification_type, notification_object, @@ -44,22 +38,18 @@ const Notification: React.FC = (props) => { const state: RootState = useStore().getState(); const dispatch = useDispatch(); - const [avatarURI, setAvatarURI] = useState(undefined); + const [avatar, setAvatar] = useState(undefined); const [momentURI, setMomentURI] = useState(undefined); const backgroundColor = unread ? '#DCF1F1' : 'rgba(0,0,0,0)'; + useEffect(() => { - let mounted = true; - const loadAvatarImage = async (user_id: string) => { - const response = await loadAvatar(user_id, true); - if (mounted) { - setAvatarURI(response); + (async () => { + const response = await loadImageFromURL(thumbnail_url); + if (response) { + setAvatar(response); } - }; - loadAvatarImage(id); - return () => { - mounted = false; - }; - }, [id]); + })(); + }, []); useEffect(() => { let mounted = true; @@ -137,8 +127,8 @@ const Notification: React.FC = (props) => { @@ -159,8 +149,8 @@ const Notification: React.FC = (props) => { )} {notification_type === 'CMT' && notification_object && ( - - )} + + )} ); diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index 000dd5c5..38defb8d 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -44,7 +44,6 @@ const ProfilePreview: React.FC = ({ useEffect(() => { (async () => { - console.log(thumbnail_url); const response = await loadImageFromURL(thumbnail_url); if (response) { setAvatar(response); -- cgit v1.2.3-70-g09d2 From 85c0f668665696ba8127ee1ea436d10ec0af955f Mon Sep 17 00:00:00 2001 From: Ashm Walia Date: Wed, 27 Jan 2021 08:24:43 -0800 Subject: Pre-final --- src/components/comments/AddComment.tsx | 34 +++++--- src/components/comments/CommentTile.tsx | 113 +++++++++++++++------------ src/components/moments/MomentPostContent.tsx | 8 +- src/constants/api.ts | 1 + src/routes/Routes.tsx | 2 +- src/screens/profile/MomentCommentsScreen.tsx | 23 +++++- src/services/MomentServices.ts | 8 ++ src/services/index.ts | 1 + src/types/types.ts | 1 + 9 files changed, 122 insertions(+), 69 deletions(-) (limited to 'src/components') diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 7b04085d..86f4170c 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -1,4 +1,4 @@ -import React, {useEffect} from 'react'; +import React, {useEffect, useRef} from 'react'; import { Image, Keyboard, @@ -11,7 +11,7 @@ import {TextInput, TouchableOpacity} from 'react-native-gesture-handler'; import {useSelector} from 'react-redux'; import UpArrowIcon from '../../assets/icons/up_arrow.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; -import {postMomentComment} from '../../services'; +import {postComment} from '../../services'; import {RootState} from '../../store/rootreducer'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; @@ -23,28 +23,27 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; export interface AddCommentProps { setNewCommentsAvailable: Function; - moment_id: string; + objectId: string; placeholderText: string; + isThreadInFocus: boolean; } const AddComment: React.FC = ({ setNewCommentsAvailable, - moment_id, + objectId, placeholderText, + isThreadInFocus, }) => { const [comment, setComment] = React.useState(''); const [keyboardVisible, setKeyboardVisible] = React.useState(false); - const { - avatar, - user: {userId}, - } = useSelector((state: RootState) => state.user); + const {avatar} = useSelector((state: RootState) => state.user); - const postComment = async () => { - const postedComment = await postMomentComment( - userId, + const addComment = async () => { + const postedComment = await postComment( comment.trim(), - moment_id, + objectId, + isThreadInFocus, ); if (postedComment) { @@ -65,6 +64,13 @@ const AddComment: React.FC = ({ return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard); }, []); + const ref = useRef(null); + useEffect(() => { + if (isThreadInFocus) { + ref.current?.focus(); + } + }, [isThreadInFocus]); + return ( = ({ value={comment} autoCorrect={false} multiline={true} + ref={ref} /> - + @@ -102,6 +109,7 @@ const AddComment: React.FC = ({ ); }; + const styles = StyleSheet.create({ container: { backgroundColor: '#f7f7f7', diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 4221fd54..f11c5e33 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -3,17 +3,12 @@ import {Text, View} from 'react-native-animatable'; import {ProfilePreview} from '../profile'; import {CommentType, ScreenType, TypeOfComment} from '../../types'; import {StyleSheet} from 'react-native'; -import { - getTimePosted, - normalize, - SCREEN_HEIGHT, - SCREEN_WIDTH, -} from '../../utils'; import ClockIcon from '../../assets/icons/clock-icon-01.svg'; import {COMMENT_REPLIES} from '../../constants'; -import BackIcon from '../../assets/icons/back-arrow-colored.svg'; import {TouchableOpacity} from 'react-native-gesture-handler'; -// import CommentsContainer from './CommentsContainer'; +import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils'; +import Arrow from '../../assets/icons/back-arrow-colored.svg'; +import CommentsContainer from './CommentsContainer'; /** * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted. @@ -23,21 +18,43 @@ interface CommentTileProps { comment_object: CommentType; screenType: ScreenType; typeOfComment: TypeOfComment; + setCommentObjectInFocus?: (comment: CommentType | undefined) => void; } const CommentTile: React.FC = ({ comment_object, screenType, typeOfComment, + setCommentObjectInFocus, }) => { const timePosted = getTimePosted(comment_object.date_created); const [showReplies, setShowReplies] = useState(false); - const isThread = typeOfComment === 'Thread'; + const toggleReplies = () => { + if (setCommentObjectInFocus) { + if (!showReplies) { + setCommentObjectInFocus(comment_object); + } else { + setCommentObjectInFocus(undefined); + } + } + setShowReplies(!showReplies); + }; + + const getRepliesText = () => + showReplies + ? 'Hide' + : comment_object.replies_count > 0 + ? `Replies (${comment_object.replies_count})` + : 'Replies'; return ( <> - + = ({ previewType={'Comment'} screenType={screenType} /> - + {comment_object.comment} {' ' + timePosted} - {typeOfComment === 'Comment' && ( - <> - { - setShowReplies(!showReplies); - }}> - - - {showReplies ? 'Hide' : 'Replies'} - - - - - + + {typeOfComment === 'Comment' && comment_object.replies_count > 0 && ( + + {getRepliesText()} + + )} - + - {/* {showReplies && ( - + {showReplies && ( + { - console.log(value); - }} + setNewCommentsAvailable={() => {}} newCommentsAvailable={true} typeOfComment={'Thread'} /> - )} */} + )} ); }; const styles = StyleSheet.create({ container: { - marginLeft: '3%', - marginRight: '3%', + marginHorizontal: '3%', borderBottomWidth: 1, borderColor: 'lightgray', marginBottom: '3%', + flexDirection: 'column', + flex: 1, + }, + moreMarginWithThread: { + marginHorizontal: '7%', }, body: { marginLeft: 56, }, comment: { - position: 'relative', - top: -5, marginBottom: '2%', + top: -5, }, date_time: { color: 'gray', @@ -127,9 +140,13 @@ const styles = StyleSheet.create({ marginBottom: '3%', }, + flexer: { + flex: 1, + }, + repliesTextAndIconContainer: { - marginLeft: SCREEN_WIDTH * 0.37, flexDirection: 'row', + alignItems: 'center', }, repliesText: { @@ -138,10 +155,8 @@ const styles = StyleSheet.create({ fontSize: normalize(12), marginRight: '3%', }, - repliesBody: { width: SCREEN_WIDTH, - height: SCREEN_HEIGHT * 0.8, }, repliesDownArrow: { diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 508b6d9f..d68ceaa3 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -1,6 +1,6 @@ import React, {useEffect} from 'react'; import {Image, StyleSheet, Text, View, ViewProps} from 'react-native'; -import {getMomentCommentsCount} from '../../services'; +import {getCommentsCount} from '../../services'; import {ScreenType} from '../../types'; import {getTimePosted, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import {CommentsCount} from '../comments'; @@ -24,8 +24,12 @@ const MomentPostContent: React.FC = ({ const [comments_count, setCommentsCount] = React.useState(''); useEffect(() => { + const fetchCommentsCount = async () => { + const count = await getCommentsCount(momentId, false); + setCommentsCount(count); + }; setElapsedTime(getTimePosted(dateTime)); - getMomentCommentsCount(momentId, setCommentsCount); + fetchCommentsCount(); }, [dateTime, momentId]); return ( diff --git a/src/constants/api.ts b/src/constants/api.ts index 701070eb..32631be0 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -30,6 +30,7 @@ export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/'; export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/'; export const DISCOVER_ENDPOINT: string = API_URL + 'discover/'; export const WAITLIST_USER_ENDPOINT: string = API_URL + 'waitlist-user/'; +export const COMMENT_THREAD_ENDPOINT: string = API_URL + 'reply/'; // Register as FCM device export const FCM_ENDPOINT: string = API_URL + 'fcm/'; diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx index a14f1576..536c7d04 100644 --- a/src/routes/Routes.tsx +++ b/src/routes/Routes.tsx @@ -33,7 +33,7 @@ const Routes: React.FC = () => { }); if (!userId) { - userLogin(dispatch, {userId: '', username: ''}); + // userLogin(dispatch, {userId: '', username: ''}); } else { SplashScreen.hide(); } diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index 9fd5aaa0..764b9228 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -6,7 +6,9 @@ import BackIcon from '../../assets/icons/back-arrow.svg'; import {TabsGradient} from '../../components'; import {AddComment} from '../../components/'; import CommentsContainer from '../../components/comments/CommentsContainer'; +import {ADD_COMMENT_TEXT} from '../../constants/strings'; import {MainStackParams} from '../../routes/main'; +import {CommentType} from '../../types'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; /** @@ -27,8 +29,12 @@ interface MomentCommentsScreenProps { const MomentCommentsScreen: React.FC = ({route}) => { const navigation = useNavigation(); const {moment_id, screenType} = route.params; - const [newCommentsAvailable, setNewCommentsAvailable] = useState(true); + const [commentsLength, setCommentsLength] = useState(0); + const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true); + const [commentObjectInFocus, setCommentObjectInFocus] = useState< + CommentType | undefined + >(undefined); return ( @@ -45,17 +51,26 @@ const MomentCommentsScreen: React.FC = ({route}) => { diff --git a/src/services/MomentServices.ts b/src/services/MomentServices.ts index 77740e7e..8399eea3 100644 --- a/src/services/MomentServices.ts +++ b/src/services/MomentServices.ts @@ -1,5 +1,6 @@ import {CommentType} from './../types/types'; import AsyncStorage from '@react-native-community/async-storage'; +<<<<<<< Updated upstream import {Alert} from 'react-native'; import RNFetchBlob from 'rn-fetch-blob'; import { @@ -96,6 +97,13 @@ export const getMomentCommentsCount = async ( } }; +======= +import RNFetchBlob from 'rn-fetch-blob'; +import {MOMENTS_ENDPOINT, MOMENT_THUMBNAIL_ENDPOINT} from '../constants'; +import {MomentType} from '../types'; +import {checkImageUploadStatus} from '../utils'; + +>>>>>>> Stashed changes export const postMoment: ( fileName: string, uri: string, diff --git a/src/services/index.ts b/src/services/index.ts index 56cefddd..f558247f 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -9,3 +9,4 @@ export * from './MomentCategoryService'; export * from './NotificationService'; export * from './FCMService'; export * from './WaitlistUserService'; +export * from './CommentService'; diff --git a/src/types/types.ts b/src/types/types.ts index b29ecbd9..0c0f9d8b 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -91,6 +91,7 @@ export interface CommentType { comment: string; date_created: string; moment_id: string; + replies_count: number; commenter: ProfilePreviewType; } -- cgit v1.2.3-70-g09d2 From 2f5f9df6dec1e905f3abf37d124ecd92d0e3a3d9 Mon Sep 17 00:00:00 2001 From: Ashm Walia Date: Wed, 27 Jan 2021 08:29:56 -0800 Subject: Pre-final --- src/components/comments/AddComment.tsx | 17 +++-- src/components/comments/CommentTile.tsx | 14 ++++ src/components/comments/CommentsContainer.tsx | 37 +++++++--- src/constants/strings.ts | 2 + src/routes/Routes.tsx | 2 +- src/screens/profile/MomentCommentsScreen.tsx | 5 +- src/services/CommentService.ts | 101 ++++++++++++++++++++++++++ src/services/MomentServices.ts | 100 ------------------------- 8 files changed, 158 insertions(+), 120 deletions(-) create mode 100644 src/services/CommentService.ts (limited to 'src/components') diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 86f4170c..46086e81 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -25,14 +25,14 @@ export interface AddCommentProps { setNewCommentsAvailable: Function; objectId: string; placeholderText: string; - isThreadInFocus: boolean; + isCommentInFocus: boolean; } const AddComment: React.FC = ({ setNewCommentsAvailable, objectId, placeholderText, - isThreadInFocus, + isCommentInFocus, }) => { const [comment, setComment] = React.useState(''); const [keyboardVisible, setKeyboardVisible] = React.useState(false); @@ -43,7 +43,7 @@ const AddComment: React.FC = ({ const postedComment = await postComment( comment.trim(), objectId, - isThreadInFocus, + isCommentInFocus, ); if (postedComment) { @@ -65,11 +65,13 @@ const AddComment: React.FC = ({ }, []); const ref = useRef(null); + + //If a comment is in Focus, bring the keyboard up so user is able to type in a reply useEffect(() => { - if (isThreadInFocus) { + if (isCommentInFocus) { ref.current?.focus(); } - }, [isThreadInFocus]); + }, [isCommentInFocus]); return ( = ({ = ({ const timePosted = getTimePosted(comment_object.date_created); const [showReplies, setShowReplies] = useState(false); + /** + * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN + * Bring the current comment to focus + * Case : No COMMENT IS IN FOCUS && REPLY SECTION IS SHOWN + * Unfocus comment in focus + * In any case toggle value of showReplies + */ const toggleReplies = () => { if (setCommentObjectInFocus) { if (!showReplies) { @@ -41,6 +48,9 @@ const CommentTile: React.FC = ({ setShowReplies(!showReplies); }; + /** + * Method to compute text to be shown for replies button + */ const getRepliesText = () => showReplies ? 'Hide' @@ -71,6 +81,8 @@ const CommentTile: React.FC = ({ {' ' + timePosted} + + {/*** Show replies text only if there are some replies present */} {typeOfComment === 'Comment' && comment_object.replies_count > 0 && ( {getRepliesText()} @@ -89,6 +101,8 @@ const CommentTile: React.FC = ({ + + {/*** Show replies if toggle state is true */} {showReplies && ( void; newCommentsAvailable: boolean; setNewCommentsAvailable: (value: boolean) => void; typeOfComment: TypeOfComment; + setCommentObjectInFocus?: (comment: CommentType | undefined) => void; + commentObjectInFocus?: CommentType; }; +/** + * Comments Container to be used for both comments and replies + */ + const CommentsContainer: React.FC = ({ screenType, - moment_id, + objectId, setCommentsLength, newCommentsAvailable, setNewCommentsAvailable, typeOfComment, + setCommentObjectInFocus, + commentObjectInFocus, }) => { const [commentsList, setCommentsList] = useState([]); const dispatch = useDispatch(); const ref = useRef(null); useEffect(() => { + //Scroll only if a new comment and not a reply was posted + const shouldScroll = () => + typeOfComment === 'Comment' && !commentObjectInFocus; const loadComments = async () => { - console.log(moment_id); - const comments = await getMomentComments(moment_id); + const comments = await getComments(objectId, typeOfComment === 'Thread'); setCommentsList(comments); if (setCommentsLength) { setCommentsLength(comments.length); } - console.log(comments); setNewCommentsAvailable(false); }; if (newCommentsAvailable) { loadComments(); - setTimeout(() => { - ref.current?.scrollToEnd({ - animated: true, - }); - }, 500); + if (shouldScroll()) { + setTimeout(() => { + ref.current?.scrollToEnd(); + }, 500); + } } }, [ dispatch, - moment_id, + objectId, newCommentsAvailable, setNewCommentsAvailable, setCommentsLength, + typeOfComment, ]); return ( @@ -65,6 +77,7 @@ const CommentsContainer: React.FC = ({ comment_object={comment} screenType={screenType} typeOfComment={typeOfComment} + setCommentObjectInFocus={setCommentObjectInFocus} /> ))} diff --git a/src/constants/strings.ts b/src/constants/strings.ts index a1793658..77ded7be 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -1,7 +1,9 @@ + /* eslint-disable */ // Below is the regex to convert this into a csv for the Google Sheet // export const (.*) = .*?(['|"|`])(.*)\2; // replace with: $1\t$3 +export const ADD_COMMENT_TEXT = (username?: string) => username ? `Reply to ${username}` : 'Add a comment...' export const COMING_SOON_MSG = 'Creating more fun things for you, surprises coming soon πŸ˜‰'; export const ERROR_AUTHENTICATION = 'An error occurred during authentication. Please login again!'; export const ERROR_CATEGORY_CREATION = 'There was a problem creating your categories. Please refresh and try again.'; diff --git a/src/routes/Routes.tsx b/src/routes/Routes.tsx index 536c7d04..a14f1576 100644 --- a/src/routes/Routes.tsx +++ b/src/routes/Routes.tsx @@ -33,7 +33,7 @@ const Routes: React.FC = () => { }); if (!userId) { - // userLogin(dispatch, {userId: '', username: ''}); + userLogin(dispatch, {userId: '', username: ''}); } else { SplashScreen.hide(); } diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index 764b9228..58422f0f 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -30,8 +30,11 @@ const MomentCommentsScreen: React.FC = ({route}) => { const navigation = useNavigation(); const {moment_id, screenType} = route.params; + //Receives comment length from child CommentsContainer const [commentsLength, setCommentsLength] = useState(0); const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true); + + //Keeps track of the current comments object in focus so that the application knows which comment to post a reply to const [commentObjectInFocus, setCommentObjectInFocus] = useState< CommentType | undefined >(undefined); @@ -70,7 +73,7 @@ const MomentCommentsScreen: React.FC = ({route}) => { objectId={ commentObjectInFocus ? commentObjectInFocus.comment_id : moment_id } - isThreadInFocus={commentObjectInFocus ? true : false} + isCommentInFocus={commentObjectInFocus ? true : false} /> diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts new file mode 100644 index 00000000..3baf0305 --- /dev/null +++ b/src/services/CommentService.ts @@ -0,0 +1,101 @@ +import AsyncStorage from '@react-native-community/async-storage'; +import {Alert} from 'react-native'; +import {COMMENTS_ENDPOINT, COMMENT_THREAD_ENDPOINT} from '../constants'; +import {ERROR_FAILED_TO_COMMENT} from '../constants/strings'; +import {CommentType} from '../types'; + +export const getComments = async ( + objectId: string, + fetchThreads: boolean, +): Promise => { + let comments: CommentType[] = []; + try { + const token = await AsyncStorage.getItem('token'); + const endpoint = fetchThreads + ? COMMENT_THREAD_ENDPOINT + '?comment_id=' + : COMMENTS_ENDPOINT + '?moment_id='; + const response = await fetch(endpoint + objectId, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + const status = response.status; + if (status === 200) { + comments = await response.json(); + console.log(comments[0]); + } else { + console.log('Could not load comments'); + } + } catch (error) { + console.log('Could not load comments', error); + } + return comments; +}; + +export const postComment = async ( + comment: string, + objectId: string, + postThread: boolean, +) => { + try { + const token = await AsyncStorage.getItem('token'); + const request = new FormData(); + request.append('comment', comment); + if (postThread) { + request.append('comment_id', objectId); + } else { + request.append('moment_id', objectId); + } + const endpoint = postThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT; + const response = await fetch(endpoint, { + method: 'POST', + headers: { + Authorization: 'Token ' + token, + }, + body: request, + }); + if (response.status !== 200) { + throw 'server error'; + } + return await response.json(); + } catch (error) { + Alert.alert(ERROR_FAILED_TO_COMMENT); + return undefined; + } +}; + +//Get count of comments for a moment +export const getCommentsCount = async ( + objectId: string, + fetchThread: boolean, +): Promise => { + let comments_count: string = ''; + try { + const token = await AsyncStorage.getItem('token'); + const endpoint = fetchThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT; + const response = await fetch(endpoint + `${objectId}/`, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + const status = response.status; + if (status === 200) { + const response_data = await response.json(); + comments_count = response_data.count; + } else { + console.log( + 'Something went wrong! 😭', + 'Not able to retrieve comments count', + ); + } + } catch (error) { + console.log( + 'Something went wrong! 😭', + 'Not able to retrieve comments count', + error, + ); + } + return comments_count; +}; diff --git a/src/services/MomentServices.ts b/src/services/MomentServices.ts index 8399eea3..0110a0d6 100644 --- a/src/services/MomentServices.ts +++ b/src/services/MomentServices.ts @@ -1,109 +1,9 @@ -import {CommentType} from './../types/types'; import AsyncStorage from '@react-native-community/async-storage'; -<<<<<<< Updated upstream -import {Alert} from 'react-native'; -import RNFetchBlob from 'rn-fetch-blob'; -import { - COMMENTS_ENDPOINT, - MOMENTS_ENDPOINT, - MOMENT_THUMBNAIL_ENDPOINT, -} from '../constants'; -import {ERROR_FAILED_TO_COMMENT} from '../constants/strings'; -import {MomentType} from '../types'; -import {checkImageUploadStatus} from '../utils'; - -//Get all comments for a moment -export const getMomentComments = async ( - momentId: string, -): Promise => { - let comments: CommentType[] = []; - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(COMMENTS_ENDPOINT + '?moment_id=' + momentId, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - const status = response.status; - if (status === 200) { - comments = await response.json(); - } else { - console.log('Could not load comments'); - } - } catch (error) { - console.log('Could not load comments', error); - } - return comments; -}; - -export const postMomentComment = async ( - commenter: string, - comment: string, - momentId: string, -) => { - try { - const token = await AsyncStorage.getItem('token'); - const request = new FormData(); - request.append('moment_id', momentId); - request.append('commenter', commenter); - request.append('comment', comment); - const response = await fetch(COMMENTS_ENDPOINT, { - method: 'POST', - headers: { - Authorization: 'Token ' + token, - }, - body: request, - }); - if (response.status !== 200) { - throw 'server error'; - } - return await response.json(); - } catch (error) { - Alert.alert(ERROR_FAILED_TO_COMMENT); - return undefined; - } -}; - -//Get count of comments for a moment -export const getMomentCommentsCount = async ( - momentId: string, - callback: Function, -) => { - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(COMMENTS_ENDPOINT + `${momentId}/`, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - const status = response.status; - if (status === 200) { - const response_data = await response.json(); - callback(response_data.count); - } else { - console.log( - 'Something went wrong! 😭', - 'Not able to retrieve comments count', - ); - } - } catch (error) { - console.log( - 'Something went wrong! 😭', - 'Not able to retrieve comments count', - error, - ); - } -}; - -======= import RNFetchBlob from 'rn-fetch-blob'; import {MOMENTS_ENDPOINT, MOMENT_THUMBNAIL_ENDPOINT} from '../constants'; import {MomentType} from '../types'; import {checkImageUploadStatus} from '../utils'; ->>>>>>> Stashed changes export const postMoment: ( fileName: string, uri: string, -- cgit v1.2.3-70-g09d2 From 2a93a92521d989664ebb8dfebe011d8df67ad40f Mon Sep 17 00:00:00 2001 From: Ashm Walia Date: Wed, 27 Jan 2021 08:58:24 -0800 Subject: Sc --- src/components/comments/CommentsContainer.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/components') diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx index 5aa32511..0a19694b 100644 --- a/src/components/comments/CommentsContainer.tsx +++ b/src/components/comments/CommentsContainer.tsx @@ -63,6 +63,7 @@ const CommentsContainer: React.FC = ({ setNewCommentsAvailable, setCommentsLength, typeOfComment, + commentObjectInFocus, ]); return ( -- cgit v1.2.3-70-g09d2 From 9298f8a31ca25f53d7fb6a0a90af783b9b01f46c Mon Sep 17 00:00:00 2001 From: Ashm Walia Date: Wed, 27 Jan 2021 09:00:16 -0800 Subject: Removed redundancy --- src/components/comments/CommentTile.tsx | 6 +++--- src/constants/constants.ts | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/components') diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 9a1607f7..39605f2c 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -4,7 +4,7 @@ import {ProfilePreview} from '../profile'; import {CommentType, ScreenType, TypeOfComment} from '../../types'; import {StyleSheet} from 'react-native'; import ClockIcon from '../../assets/icons/clock-icon-01.svg'; -import {COMMENT_REPLIES} from '../../constants'; +import {TAGG_LIGHT_BLUE} from '../../constants'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils'; import Arrow from '../../assets/icons/back-arrow-colored.svg'; @@ -89,7 +89,7 @@ const CommentTile: React.FC = ({ Date: Wed, 27 Jan 2021 14:18:00 -0500 Subject: Squashed commit of the following: commit 9298f8a31ca25f53d7fb6a0a90af783b9b01f46c Author: Ashm Walia Date: Wed Jan 27 09:00:16 2021 -0800 Removed redundancy commit 2a93a92521d989664ebb8dfebe011d8df67ad40f Author: Ashm Walia Date: Wed Jan 27 08:58:24 2021 -0800 Sc commit 2f5f9df6dec1e905f3abf37d124ecd92d0e3a3d9 Author: Ashm Walia Date: Wed Jan 27 08:29:56 2021 -0800 Pre-final commit 85c0f668665696ba8127ee1ea436d10ec0af955f Author: Ashm Walia Date: Wed Jan 27 08:24:43 2021 -0800 Pre-final commit 755f4f540d3e759ff9ad3bc35c64b6f7fc83998b Author: Ashm Walia Date: Mon Jan 25 18:00:44 2021 -0800 Add provision to show and hide replies --- src/assets/icons/back-arrow-colored.svg | 1 + src/components/comments/AddComment.tsx | 45 ++++--- src/components/comments/CommentTile.tsx | 161 ++++++++++++++++++++++---- src/components/comments/CommentsContainer.tsx | 97 ++++++++++++++++ src/components/moments/MomentPostContent.tsx | 8 +- src/constants/api.ts | 1 + src/constants/strings.ts | 2 + src/screens/profile/MomentCommentsScreen.tsx | 81 ++++++------- src/services/CommentService.ts | 101 ++++++++++++++++ src/services/MomentServices.ts | 93 +-------------- src/services/index.ts | 1 + src/types/types.ts | 3 + 12 files changed, 413 insertions(+), 181 deletions(-) create mode 100644 src/assets/icons/back-arrow-colored.svg create mode 100644 src/components/comments/CommentsContainer.tsx create mode 100644 src/services/CommentService.ts (limited to 'src/components') diff --git a/src/assets/icons/back-arrow-colored.svg b/src/assets/icons/back-arrow-colored.svg new file mode 100644 index 00000000..123426d7 --- /dev/null +++ b/src/assets/icons/back-arrow-colored.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 24b3473c..46086e81 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -1,4 +1,4 @@ -import React, {useEffect} from 'react'; +import React, {useEffect, useRef} from 'react'; import { Image, Keyboard, @@ -11,7 +11,7 @@ import {TextInput, TouchableOpacity} from 'react-native-gesture-handler'; import {useSelector} from 'react-redux'; import UpArrowIcon from '../../assets/icons/up_arrow.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; -import {postMomentComment} from '../../services'; +import {postComment} from '../../services'; import {RootState} from '../../store/rootreducer'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; @@ -23,26 +23,27 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; export interface AddCommentProps { setNewCommentsAvailable: Function; - moment_id: string; + objectId: string; + placeholderText: string; + isCommentInFocus: boolean; } const AddComment: React.FC = ({ setNewCommentsAvailable, - moment_id, + objectId, + placeholderText, + isCommentInFocus, }) => { const [comment, setComment] = React.useState(''); const [keyboardVisible, setKeyboardVisible] = React.useState(false); - const { - avatar, - user: {userId}, - } = useSelector((state: RootState) => state.user); + const {avatar} = useSelector((state: RootState) => state.user); - const postComment = async () => { - const postedComment = await postMomentComment( - userId, + const addComment = async () => { + const postedComment = await postComment( comment.trim(), - moment_id, + objectId, + isCommentInFocus, ); if (postedComment) { @@ -63,6 +64,15 @@ const AddComment: React.FC = ({ return () => Keyboard.removeListener('keyboardWillHide', hideKeyboard); }, []); + const ref = useRef(null); + + //If a comment is in Focus, bring the keyboard up so user is able to type in a reply + useEffect(() => { + if (isCommentInFocus) { + ref.current?.focus(); + } + }, [isCommentInFocus]); + return ( = ({ = ({ /> - + @@ -100,6 +111,7 @@ const AddComment: React.FC = ({ ); }; + const styles = StyleSheet.create({ container: { backgroundColor: '#f7f7f7', @@ -140,6 +152,9 @@ const styles = StyleSheet.create({ marginVertical: '2%', alignSelf: 'flex-end', }, + whiteBackround: { + backgroundColor: '#fff', + }, }); export default AddComment; diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 47f25a53..39605f2c 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -1,10 +1,14 @@ -import React from 'react'; +import React, {useState} from 'react'; import {Text, View} from 'react-native-animatable'; import {ProfilePreview} from '../profile'; -import {CommentType, ScreenType} from '../../types'; +import {CommentType, ScreenType, TypeOfComment} from '../../types'; import {StyleSheet} from 'react-native'; -import {getTimePosted} from '../../utils'; import ClockIcon from '../../assets/icons/clock-icon-01.svg'; +import {TAGG_LIGHT_BLUE} from '../../constants'; +import {TouchableOpacity} from 'react-native-gesture-handler'; +import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils'; +import Arrow from '../../assets/icons/back-arrow-colored.svg'; +import CommentsContainer from './CommentsContainer'; /** * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted. @@ -13,54 +17,132 @@ import ClockIcon from '../../assets/icons/clock-icon-01.svg'; interface CommentTileProps { comment_object: CommentType; screenType: ScreenType; + typeOfComment: TypeOfComment; + setCommentObjectInFocus?: (comment: CommentType | undefined) => void; } const CommentTile: React.FC = ({ comment_object, screenType, + typeOfComment, + setCommentObjectInFocus, }) => { const timePosted = getTimePosted(comment_object.date_created); + const [showReplies, setShowReplies] = useState(false); + + /** + * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN + * Bring the current comment to focus + * Case : No COMMENT IS IN FOCUS && REPLY SECTION IS SHOWN + * Unfocus comment in focus + * In any case toggle value of showReplies + */ + const toggleReplies = () => { + if (setCommentObjectInFocus) { + if (!showReplies) { + setCommentObjectInFocus(comment_object); + } else { + setCommentObjectInFocus(undefined); + } + } + setShowReplies(!showReplies); + }; + + /** + * Method to compute text to be shown for replies button + */ + const getRepliesText = () => + showReplies + ? 'Hide' + : comment_object.replies_count > 0 + ? `Replies (${comment_object.replies_count})` + : 'Replies'; + return ( - - - - {comment_object.comment} - - - {' ' + timePosted} - + <> + + + + {comment_object.comment} + + + {' ' + timePosted} + + + {/*** Show replies text only if there are some replies present */} + {typeOfComment === 'Comment' && comment_object.replies_count > 0 && ( + + {getRepliesText()} + + + )} + + - + + {/*** Show replies if toggle state is true */} + {showReplies && ( + + {}} + newCommentsAvailable={true} + typeOfComment={'Thread'} + /> + + )} + ); }; const styles = StyleSheet.create({ container: { - marginLeft: '3%', - marginRight: '3%', + marginHorizontal: '3%', borderBottomWidth: 1, borderColor: 'lightgray', marginBottom: '3%', + flexDirection: 'column', + flex: 1, + }, + moreMarginWithThread: { + marginHorizontal: '7%', }, body: { marginLeft: 56, }, comment: { - position: 'relative', - top: -5, marginBottom: '2%', + top: -5, }, date_time: { color: 'gray', + fontSize: normalize(12), }, clockIcon: { width: 12, @@ -71,6 +153,35 @@ const styles = StyleSheet.create({ flexDirection: 'row', marginBottom: '3%', }, + + flexer: { + flex: 1, + }, + + repliesTextAndIconContainer: { + flexDirection: 'row', + alignItems: 'center', + }, + + repliesText: { + color: TAGG_LIGHT_BLUE, + fontWeight: '500', + fontSize: normalize(12), + marginRight: '3%', + }, + repliesBody: { + width: SCREEN_WIDTH, + }, + + repliesDownArrow: { + transform: [{rotate: '270deg'}], + marginTop: '7%', + }, + + repliesUpArrow: { + transform: [{rotate: '90deg'}], + marginTop: '7%', + }, }); export default CommentTile; diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx new file mode 100644 index 00000000..0a19694b --- /dev/null +++ b/src/components/comments/CommentsContainer.tsx @@ -0,0 +1,97 @@ +import React, {useRef, useEffect, useState} from 'react'; +import {StyleSheet} from 'react-native'; +import {ScrollView} from 'react-native-gesture-handler'; +import {useDispatch} from 'react-redux'; +import {CommentTile} from '.'; +import {getComments} from '../../services'; +import {CommentType, ScreenType, TypeOfComment} from '../../types'; +export type CommentsContainerProps = { + screenType: ScreenType; + + //objectId can be either moment_id or comment_id + objectId: string; + setCommentsLength?: (count: number) => void; + newCommentsAvailable: boolean; + setNewCommentsAvailable: (value: boolean) => void; + typeOfComment: TypeOfComment; + setCommentObjectInFocus?: (comment: CommentType | undefined) => void; + commentObjectInFocus?: CommentType; +}; + +/** + * Comments Container to be used for both comments and replies + */ + +const CommentsContainer: React.FC = ({ + screenType, + objectId, + setCommentsLength, + newCommentsAvailable, + setNewCommentsAvailable, + typeOfComment, + setCommentObjectInFocus, + commentObjectInFocus, +}) => { + const [commentsList, setCommentsList] = useState([]); + const dispatch = useDispatch(); + const ref = useRef(null); + + useEffect(() => { + //Scroll only if a new comment and not a reply was posted + const shouldScroll = () => + typeOfComment === 'Comment' && !commentObjectInFocus; + const loadComments = async () => { + const comments = await getComments(objectId, typeOfComment === 'Thread'); + setCommentsList(comments); + if (setCommentsLength) { + setCommentsLength(comments.length); + } + setNewCommentsAvailable(false); + }; + if (newCommentsAvailable) { + loadComments(); + if (shouldScroll()) { + setTimeout(() => { + ref.current?.scrollToEnd(); + }, 500); + } + } + }, [ + dispatch, + objectId, + newCommentsAvailable, + setNewCommentsAvailable, + setCommentsLength, + typeOfComment, + commentObjectInFocus, + ]); + + return ( + + {commentsList && + commentsList.map((comment: CommentType) => ( + + ))} + + ); +}; + +const styles = StyleSheet.create({ + scrollView: { + paddingHorizontal: 20, + }, + scrollViewContent: { + justifyContent: 'center', + }, +}); + +export default CommentsContainer; diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 508b6d9f..d68ceaa3 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -1,6 +1,6 @@ import React, {useEffect} from 'react'; import {Image, StyleSheet, Text, View, ViewProps} from 'react-native'; -import {getMomentCommentsCount} from '../../services'; +import {getCommentsCount} from '../../services'; import {ScreenType} from '../../types'; import {getTimePosted, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import {CommentsCount} from '../comments'; @@ -24,8 +24,12 @@ const MomentPostContent: React.FC = ({ const [comments_count, setCommentsCount] = React.useState(''); useEffect(() => { + const fetchCommentsCount = async () => { + const count = await getCommentsCount(momentId, false); + setCommentsCount(count); + }; setElapsedTime(getTimePosted(dateTime)); - getMomentCommentsCount(momentId, setCommentsCount); + fetchCommentsCount(); }, [dateTime, momentId]); return ( diff --git a/src/constants/api.ts b/src/constants/api.ts index 701070eb..32631be0 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -30,6 +30,7 @@ export const MOMENT_CATEGORY_ENDPOINT: string = API_URL + 'moment-category/'; export const NOTIFICATIONS_ENDPOINT: string = API_URL + 'notifications/'; export const DISCOVER_ENDPOINT: string = API_URL + 'discover/'; export const WAITLIST_USER_ENDPOINT: string = API_URL + 'waitlist-user/'; +export const COMMENT_THREAD_ENDPOINT: string = API_URL + 'reply/'; // Register as FCM device export const FCM_ENDPOINT: string = API_URL + 'fcm/'; diff --git a/src/constants/strings.ts b/src/constants/strings.ts index a1793658..77ded7be 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -1,7 +1,9 @@ + /* eslint-disable */ // Below is the regex to convert this into a csv for the Google Sheet // export const (.*) = .*?(['|"|`])(.*)\2; // replace with: $1\t$3 +export const ADD_COMMENT_TEXT = (username?: string) => username ? `Reply to ${username}` : 'Add a comment...' export const COMING_SOON_MSG = 'Creating more fun things for you, surprises coming soon πŸ˜‰'; export const ERROR_AUTHENTICATION = 'An error occurred during authentication. Please login again!'; export const ERROR_CATEGORY_CREATION = 'There was a problem creating your categories. Please refresh and try again.'; diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index 2bceafc9..58422f0f 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -1,19 +1,13 @@ import {RouteProp, useNavigation} from '@react-navigation/native'; -import React, {useEffect, useRef} from 'react'; -import { - ScrollView, - StyleSheet, - Text, - TouchableOpacity, - View, -} from 'react-native'; +import React, {useState} from 'react'; +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; -import {useDispatch} from 'react-redux'; -import {getMomentComments} from '../..//services'; import BackIcon from '../../assets/icons/back-arrow.svg'; -import {CommentTile, TabsGradient} from '../../components'; +import {TabsGradient} from '../../components'; import {AddComment} from '../../components/'; -import {ProfileStackParams} from '../../routes/main'; +import CommentsContainer from '../../components/comments/CommentsContainer'; +import {ADD_COMMENT_TEXT} from '../../constants/strings'; +import {MainStackParams} from '../../routes/main'; import {CommentType} from '../../types'; import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; @@ -24,7 +18,7 @@ import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; */ type MomentCommentsScreenRouteProps = RouteProp< - ProfileStackParams, + MainStackParams, 'MomentCommentsScreen' >; @@ -35,25 +29,15 @@ interface MomentCommentsScreenProps { const MomentCommentsScreen: React.FC = ({route}) => { const navigation = useNavigation(); const {moment_id, screenType} = route.params; - const [commentsList, setCommentsList] = React.useState([]); + + //Receives comment length from child CommentsContainer + const [commentsLength, setCommentsLength] = useState(0); const [newCommentsAvailable, setNewCommentsAvailable] = React.useState(true); - const dispatch = useDispatch(); - const ref = useRef(null); - useEffect(() => { - const loadComments = async () => { - getMomentComments(moment_id, setCommentsList); - setNewCommentsAvailable(false); - }; - if (newCommentsAvailable) { - loadComments(); - setTimeout(() => { - ref.current?.scrollToEnd({ - animated: true, - }); - }, 500); - } - }, [dispatch, moment_id, newCommentsAvailable]); + //Keeps track of the current comments object in focus so that the application knows which comment to post a reply to + const [commentObjectInFocus, setCommentObjectInFocus] = useState< + CommentType | undefined + >(undefined); return ( @@ -66,27 +50,30 @@ const MomentCommentsScreen: React.FC = ({route}) => { }}> - - {commentsList.length + ' Comments'} - + {commentsLength + ' Comments'} - - {commentsList && - commentsList.map((comment: CommentType) => ( - - ))} - + diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts new file mode 100644 index 00000000..3baf0305 --- /dev/null +++ b/src/services/CommentService.ts @@ -0,0 +1,101 @@ +import AsyncStorage from '@react-native-community/async-storage'; +import {Alert} from 'react-native'; +import {COMMENTS_ENDPOINT, COMMENT_THREAD_ENDPOINT} from '../constants'; +import {ERROR_FAILED_TO_COMMENT} from '../constants/strings'; +import {CommentType} from '../types'; + +export const getComments = async ( + objectId: string, + fetchThreads: boolean, +): Promise => { + let comments: CommentType[] = []; + try { + const token = await AsyncStorage.getItem('token'); + const endpoint = fetchThreads + ? COMMENT_THREAD_ENDPOINT + '?comment_id=' + : COMMENTS_ENDPOINT + '?moment_id='; + const response = await fetch(endpoint + objectId, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + const status = response.status; + if (status === 200) { + comments = await response.json(); + console.log(comments[0]); + } else { + console.log('Could not load comments'); + } + } catch (error) { + console.log('Could not load comments', error); + } + return comments; +}; + +export const postComment = async ( + comment: string, + objectId: string, + postThread: boolean, +) => { + try { + const token = await AsyncStorage.getItem('token'); + const request = new FormData(); + request.append('comment', comment); + if (postThread) { + request.append('comment_id', objectId); + } else { + request.append('moment_id', objectId); + } + const endpoint = postThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT; + const response = await fetch(endpoint, { + method: 'POST', + headers: { + Authorization: 'Token ' + token, + }, + body: request, + }); + if (response.status !== 200) { + throw 'server error'; + } + return await response.json(); + } catch (error) { + Alert.alert(ERROR_FAILED_TO_COMMENT); + return undefined; + } +}; + +//Get count of comments for a moment +export const getCommentsCount = async ( + objectId: string, + fetchThread: boolean, +): Promise => { + let comments_count: string = ''; + try { + const token = await AsyncStorage.getItem('token'); + const endpoint = fetchThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT; + const response = await fetch(endpoint + `${objectId}/`, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + const status = response.status; + if (status === 200) { + const response_data = await response.json(); + comments_count = response_data.count; + } else { + console.log( + 'Something went wrong! 😭', + 'Not able to retrieve comments count', + ); + } + } catch (error) { + console.log( + 'Something went wrong! 😭', + 'Not able to retrieve comments count', + error, + ); + } + return comments_count; +}; diff --git a/src/services/MomentServices.ts b/src/services/MomentServices.ts index 7bad6d4c..0110a0d6 100644 --- a/src/services/MomentServices.ts +++ b/src/services/MomentServices.ts @@ -1,100 +1,9 @@ import AsyncStorage from '@react-native-community/async-storage'; -import {Alert} from 'react-native'; import RNFetchBlob from 'rn-fetch-blob'; -import { - COMMENTS_ENDPOINT, - MOMENTS_ENDPOINT, - MOMENT_THUMBNAIL_ENDPOINT, -} from '../constants'; -import {ERROR_FAILED_TO_COMMENT} from '../constants/strings'; +import {MOMENTS_ENDPOINT, MOMENT_THUMBNAIL_ENDPOINT} from '../constants'; import {MomentType} from '../types'; import {checkImageUploadStatus} from '../utils'; -//Get all comments for a moment -export const getMomentComments = async ( - momentId: string, - callback: Function, -) => { - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(COMMENTS_ENDPOINT + '?moment_id=' + momentId, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - const status = response.status; - if (status === 200) { - const comments = await response.json(); - callback(comments); - } else { - console.log('Could not load comments'); - } - } catch (error) { - console.log('Could not load comments', error); - } -}; - -export const postMomentComment = async ( - commenter: string, - comment: string, - momentId: string, -) => { - try { - const token = await AsyncStorage.getItem('token'); - const request = new FormData(); - request.append('moment_id', momentId); - request.append('commenter', commenter); - request.append('comment', comment); - const response = await fetch(COMMENTS_ENDPOINT, { - method: 'POST', - headers: { - Authorization: 'Token ' + token, - }, - body: request, - }); - if (response.status !== 200) { - throw 'server error'; - } - return await response.json(); - } catch (error) { - Alert.alert(ERROR_FAILED_TO_COMMENT); - return undefined; - } -}; - -//Get count of comments for a moment -export const getMomentCommentsCount = async ( - momentId: string, - callback: Function, -) => { - try { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(COMMENTS_ENDPOINT + `${momentId}/`, { - method: 'GET', - headers: { - Authorization: 'Token ' + token, - }, - }); - const status = response.status; - if (status === 200) { - const response_data = await response.json(); - callback(response_data.count); - } else { - console.log( - 'Something went wrong! 😭', - 'Not able to retrieve comments count', - ); - } - } catch (error) { - console.log( - 'Something went wrong! 😭', - 'Not able to retrieve comments count', - error, - ); - } -}; - export const postMoment: ( fileName: string, uri: string, diff --git a/src/services/index.ts b/src/services/index.ts index 56cefddd..f558247f 100644 --- a/src/services/index.ts +++ b/src/services/index.ts @@ -9,3 +9,4 @@ export * from './MomentCategoryService'; export * from './NotificationService'; export * from './FCMService'; export * from './WaitlistUserService'; +export * from './CommentService'; diff --git a/src/types/types.ts b/src/types/types.ts index d9d0b56b..0c0f9d8b 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -91,6 +91,7 @@ export interface CommentType { comment: string; date_created: string; moment_id: string; + replies_count: number; commenter: ProfilePreviewType; } @@ -174,3 +175,5 @@ export type NotificationType = { timestamp: string; unread: boolean; }; + +export type TypeOfComment = 'Comment' | 'Thread'; -- cgit v1.2.3-70-g09d2 From fb69ccebb05d2ec54d85576d23989e7309349830 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 27 Jan 2021 16:15:00 -0500 Subject: finished delete --- src/assets/ionicons/trash-outline.svg | 1 + src/components/comments/CommentTile.tsx | 115 +++++++++++++++++++------- src/components/comments/CommentsContainer.tsx | 14 ++-- src/constants/strings.ts | 2 +- src/services/CommentService.ts | 18 ++++ 5 files changed, 114 insertions(+), 36 deletions(-) create mode 100644 src/assets/ionicons/trash-outline.svg (limited to 'src/components') diff --git a/src/assets/ionicons/trash-outline.svg b/src/assets/ionicons/trash-outline.svg new file mode 100644 index 00000000..4920b56a --- /dev/null +++ b/src/assets/ionicons/trash-outline.svg @@ -0,0 +1 @@ +Trash \ No newline at end of file diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 39605f2c..e12276a9 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -1,14 +1,18 @@ -import React, {useState} from 'react'; +import React, {Fragment, useRef, useState} from 'react'; import {Text, View} from 'react-native-animatable'; import {ProfilePreview} from '../profile'; import {CommentType, ScreenType, TypeOfComment} from '../../types'; -import {StyleSheet} from 'react-native'; +import {Alert, Animated, StyleSheet} from 'react-native'; import ClockIcon from '../../assets/icons/clock-icon-01.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; -import {TouchableOpacity} from 'react-native-gesture-handler'; +import {RectButton, TouchableOpacity} from 'react-native-gesture-handler'; import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils'; import Arrow from '../../assets/icons/back-arrow-colored.svg'; +import Trash from '../../assets/ionicons/trash-outline.svg'; import CommentsContainer from './CommentsContainer'; +import Swipeable from 'react-native-gesture-handler/Swipeable'; +import {deleteComment} from '../../services'; +import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings'; /** * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted. @@ -19,6 +23,8 @@ interface CommentTileProps { screenType: ScreenType; typeOfComment: TypeOfComment; setCommentObjectInFocus?: (comment: CommentType | undefined) => void; + setNewCommentsAvailable: (available: boolean) => void; + canDelete: boolean; } const CommentTile: React.FC = ({ @@ -26,9 +32,13 @@ const CommentTile: React.FC = ({ screenType, typeOfComment, setCommentObjectInFocus, + setNewCommentsAvailable, + canDelete, }) => { const timePosted = getTimePosted(comment_object.date_created); const [showReplies, setShowReplies] = useState(false); + const swipeRef = useRef(null); + const isThread = typeOfComment === 'Thread'; /** * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN @@ -58,13 +68,46 @@ const CommentTile: React.FC = ({ ? `Replies (${comment_object.replies_count})` : 'Replies'; + const renderRightAction = (text: string, color: string, progress) => { + const pressHandler = async () => { + swipeRef.current?.close(); + const success = await deleteComment(comment_object.comment_id, isThread); + if (success) { + setNewCommentsAvailable(true); + } else { + Alert.alert(ERROR_FAILED_TO_DELETE_COMMENT); + } + }; + return ( + + + + {text} + + + ); + }; + + const renderRightActions = (progress) => + canDelete ? ( + + {renderRightAction('Delete', '#c42634', progress)} + + ) : ( + + ); + return ( - <> + + style={[styles.container, isThread ? styles.moreMarginWithThread : {}]}> = ({ {/*** Show replies if toggle state is true */} {showReplies && ( - - {}} - newCommentsAvailable={true} - typeOfComment={'Thread'} - /> - + {}} + newCommentsAvailable={true} + typeOfComment={'Thread'} + /> )} - + ); }; const styles = StyleSheet.create({ container: { - marginHorizontal: '3%', borderBottomWidth: 1, borderColor: 'lightgray', - marginBottom: '3%', + backgroundColor: 'white', + paddingTop: '3%', flexDirection: 'column', flex: 1, + marginLeft: '7%', + }, + swipeActions: { + flexDirection: 'row', }, moreMarginWithThread: { - marginHorizontal: '7%', + marginLeft: '14%', }, body: { marginLeft: 56, }, comment: { marginBottom: '2%', + marginRight: '2%', top: -5, }, date_time: { @@ -153,35 +196,47 @@ const styles = StyleSheet.create({ flexDirection: 'row', marginBottom: '3%', }, - flexer: { flex: 1, }, - repliesTextAndIconContainer: { flexDirection: 'row', alignItems: 'center', }, - repliesText: { color: TAGG_LIGHT_BLUE, fontWeight: '500', fontSize: normalize(12), - marginRight: '3%', + marginRight: '5%', }, repliesBody: { width: SCREEN_WIDTH, }, - repliesDownArrow: { transform: [{rotate: '270deg'}], marginTop: '7%', }, - repliesUpArrow: { transform: [{rotate: '90deg'}], marginTop: '7%', }, + actionText: { + color: 'white', + fontSize: normalize(12), + fontWeight: '500', + backgroundColor: 'transparent', + paddingHorizontal: '5%', + marginTop: '5%', + }, + rightAction: { + alignItems: 'center', + flex: 1, + justifyContent: 'center', + flexDirection: 'column', + }, + swipableContainer: { + backgroundColor: 'white', + }, }); export default CommentTile; diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx index 0a19694b..fd4b32af 100644 --- a/src/components/comments/CommentsContainer.tsx +++ b/src/components/comments/CommentsContainer.tsx @@ -1,9 +1,10 @@ -import React, {useRef, useEffect, useState} from 'react'; +import React, {useEffect, useRef, useState} from 'react'; import {StyleSheet} from 'react-native'; import {ScrollView} from 'react-native-gesture-handler'; -import {useDispatch} from 'react-redux'; +import {useDispatch, useSelector} from 'react-redux'; import {CommentTile} from '.'; import {getComments} from '../../services'; +import {RootState} from '../../store/rootReducer'; import {CommentType, ScreenType, TypeOfComment} from '../../types'; export type CommentsContainerProps = { screenType: ScreenType; @@ -32,6 +33,9 @@ const CommentsContainer: React.FC = ({ setCommentObjectInFocus, commentObjectInFocus, }) => { + const {username: loggedInUsername} = useSelector( + (state: RootState) => state.user.user, + ); const [commentsList, setCommentsList] = useState([]); const dispatch = useDispatch(); const ref = useRef(null); @@ -79,6 +83,8 @@ const CommentsContainer: React.FC = ({ screenType={screenType} typeOfComment={typeOfComment} setCommentObjectInFocus={setCommentObjectInFocus} + setNewCommentsAvailable={setNewCommentsAvailable} + canDelete={comment.commenter.username === loggedInUsername} /> ))} @@ -86,9 +92,7 @@ const CommentsContainer: React.FC = ({ }; const styles = StyleSheet.create({ - scrollView: { - paddingHorizontal: 20, - }, + scrollView: {}, scrollViewContent: { justifyContent: 'center', }, diff --git a/src/constants/strings.ts b/src/constants/strings.ts index 77ded7be..d3c81622 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -1,4 +1,3 @@ - /* eslint-disable */ // Below is the regex to convert this into a csv for the Google Sheet // export const (.*) = .*?(['|"|`])(.*)\2; @@ -15,6 +14,7 @@ export const ERROR_DUP_OLD_PWD = 'You may not use a previously used password'; export const ERROR_EMAIL_IN_USE = 'Email already in use, please try another one'; export const ERROR_FAILED_LOGIN_INFO = 'Login failed, please try re-entering your login information'; export const ERROR_FAILED_TO_COMMENT = 'Unable to post comment, refresh and try again!'; +export const ERROR_FAILED_TO_DELETE_COMMENT = 'Unable to delete comment, refresh and try again!'; export const ERROR_INVALID_INVITATION_CODE = 'Invitation code invalid, try again or talk to the friend that sent it 😬'; export const ERROR_INVALID_LOGIN = 'Invalid login, Please login again'; export const ERROR_INVALID_PWD_CODE = 'Looks like you have entered the wrong code, please try again'; diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts index 3baf0305..a9a01d77 100644 --- a/src/services/CommentService.ts +++ b/src/services/CommentService.ts @@ -99,3 +99,21 @@ export const getCommentsCount = async ( } return comments_count; }; + +export const deleteComment = async (id: string, isThread: boolean) => { + try { + const token = await AsyncStorage.getItem('token'); + const url = isThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT; + const response = await fetch(url + `${id}/`, { + method: 'DELETE', + headers: { + Authorization: 'Token ' + token, + }, + }); + return response.status === 200; + } catch (error) { + console.log('Failed to delete a comment'); + console.log(error); + return false; + } +}; -- cgit v1.2.3-70-g09d2 From 56612885167c07462363aab6b606c807f58eeba5 Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 27 Jan 2021 16:27:17 -0500 Subject: fixed not refreshing --- src/components/comments/CommentTile.tsx | 19 ++++++++++++++++--- src/components/comments/CommentsContainer.tsx | 1 + src/services/CommentService.ts | 1 - 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src/components') diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index e12276a9..58d2be25 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -1,4 +1,4 @@ -import React, {Fragment, useRef, useState} from 'react'; +import React, {Fragment, useEffect, useRef, useState} from 'react'; import {Text, View} from 'react-native-animatable'; import {ProfilePreview} from '../profile'; import {CommentType, ScreenType, TypeOfComment} from '../../types'; @@ -23,6 +23,7 @@ interface CommentTileProps { screenType: ScreenType; typeOfComment: TypeOfComment; setCommentObjectInFocus?: (comment: CommentType | undefined) => void; + newCommentsAvailable: boolean; setNewCommentsAvailable: (available: boolean) => void; canDelete: boolean; } @@ -32,14 +33,25 @@ const CommentTile: React.FC = ({ screenType, typeOfComment, setCommentObjectInFocus, + newCommentsAvailable, setNewCommentsAvailable, canDelete, }) => { const timePosted = getTimePosted(comment_object.date_created); const [showReplies, setShowReplies] = useState(false); + const [newThreadAvailable, setNewThreadAvailable] = useState(true); const swipeRef = useRef(null); const isThread = typeOfComment === 'Thread'; + /** + * Bubbling up, for handling a new comment in a thread. + */ + useEffect(() => { + if (newCommentsAvailable) { + setNewThreadAvailable(true); + } + }, [newCommentsAvailable]); + /** * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN * Bring the current comment to focus @@ -52,6 +64,7 @@ const CommentTile: React.FC = ({ if (!showReplies) { setCommentObjectInFocus(comment_object); } else { + setNewThreadAvailable(true); setCommentObjectInFocus(undefined); } } @@ -150,8 +163,8 @@ const CommentTile: React.FC = ({ {}} - newCommentsAvailable={true} + setNewCommentsAvailable={setNewThreadAvailable} + newCommentsAvailable={newThreadAvailable} typeOfComment={'Thread'} /> )} diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx index fd4b32af..d8134caf 100644 --- a/src/components/comments/CommentsContainer.tsx +++ b/src/components/comments/CommentsContainer.tsx @@ -83,6 +83,7 @@ const CommentsContainer: React.FC = ({ screenType={screenType} typeOfComment={typeOfComment} setCommentObjectInFocus={setCommentObjectInFocus} + newCommentsAvailable={newCommentsAvailable} setNewCommentsAvailable={setNewCommentsAvailable} canDelete={comment.commenter.username === loggedInUsername} /> diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts index a9a01d77..2faaa8db 100644 --- a/src/services/CommentService.ts +++ b/src/services/CommentService.ts @@ -23,7 +23,6 @@ export const getComments = async ( const status = response.status; if (status === 200) { comments = await response.json(); - console.log(comments[0]); } else { console.log('Could not load comments'); } -- cgit v1.2.3-70-g09d2 From 01b31b3f54ed58093df8e3f98e95268c0ace5f8a Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 27 Jan 2021 17:03:38 -0500 Subject: fixed bug to update replies count --- src/components/comments/CommentTile.tsx | 1 + 1 file changed, 1 insertion(+) (limited to 'src/components') diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 58d2be25..c6dd9fc1 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -65,6 +65,7 @@ const CommentTile: React.FC = ({ setCommentObjectInFocus(comment_object); } else { setNewThreadAvailable(true); + setNewCommentsAvailable(true); setCommentObjectInFocus(undefined); } } -- cgit v1.2.3-70-g09d2 From ff3d1e51a1f9d175cfe460e6a16497a6226f450f Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 27 Jan 2021 17:03:50 -0500 Subject: fixed bug to submit with empty string --- src/components/comments/AddComment.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/components') diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 46086e81..44f49748 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -40,8 +40,12 @@ const AddComment: React.FC = ({ const {avatar} = useSelector((state: RootState) => state.user); const addComment = async () => { + const trimmed = comment.trim(); + if (trimmed === '') { + return; + } const postedComment = await postComment( - comment.trim(), + trimmed, objectId, isCommentInFocus, ); -- cgit v1.2.3-70-g09d2 From 614fbcd8b0180b328019e6952ee1fc0de4643eaa Mon Sep 17 00:00:00 2001 From: Ivan Chen Date: Wed, 27 Jan 2021 18:43:57 -0500 Subject: fixed thumbnail for comments --- src/components/comments/CommentTile.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/components') diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 39605f2c..1247e89a 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -67,10 +67,7 @@ const CommentTile: React.FC = ({ ]}> Date: Wed, 27 Jan 2021 18:44:40 -0500 Subject: even better code --- src/components/comments/CommentTile.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/components') diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 1247e89a..237c65fc 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -66,9 +66,7 @@ const CommentTile: React.FC = ({ typeOfComment === 'Thread' ? styles.moreMarginWithThread : {}, ]}> -- cgit v1.2.3-70-g09d2 From 23ddb03d6fc114903439c39f546dcb8ce9a08858 Mon Sep 17 00:00:00 2001 From: Shravya Ramesh Date: Wed, 27 Jan 2021 15:55:37 -0800 Subject: style change minor --- src/components/profile/ProfileBody.tsx | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/components') diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index d10e2e15..8a07ac72 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -105,8 +105,8 @@ const ProfileBody: React.FC = ({ {friendship_status === 'friends' && (