diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/App.tsx | 19 | ||||
-rw-r--r-- | src/components/comments/AddComment.tsx | 5 | ||||
-rw-r--r-- | src/components/moments/IndividualMomentTitleBar.tsx | 11 | ||||
-rw-r--r-- | src/components/moments/MomentPost.tsx | 3 | ||||
-rw-r--r-- | src/components/moments/MomentPostContent.tsx | 52 | ||||
-rw-r--r-- | src/screens/profile/IndividualMoment.tsx | 102 | ||||
-rw-r--r-- | src/screens/profile/MomentCommentsScreen.tsx | 5 |
7 files changed, 135 insertions, 62 deletions
diff --git a/src/App.tsx b/src/App.tsx index 92e7abee..64f40bae 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -27,16 +27,15 @@ export const ChatContext = React.createContext({} as ChatContextType); const App = () => { const routeNameRef = useRef(); const [channel, setChannel] = useState<ChannelGroupedType>(); - const chatClient = - StreamChat.getInstance< - LocalAttachmentType, - LocalChannelType, - LocalCommandType, - LocalEventType, - LocalMessageType, - LocalResponseType, - LocalUserType - >(STREAM_CHAT_API); + const chatClient = StreamChat.getInstance< + LocalAttachmentType, + LocalChannelType, + LocalCommandType, + LocalEventType, + LocalMessageType, + LocalResponseType, + LocalUserType + >(STREAM_CHAT_API); return ( <Provider store={store}> <NavigationContainer diff --git a/src/components/comments/AddComment.tsx b/src/components/comments/AddComment.tsx index 18b9c24e..9d9824db 100644 --- a/src/components/comments/AddComment.tsx +++ b/src/components/comments/AddComment.tsx @@ -25,13 +25,15 @@ export interface AddCommentProps { momentId: string; placeholderText: string; callback?: (message: string) => void; + onFocus?: () => void; theme?: 'dark' | 'white'; } const AddComment: React.FC<AddCommentProps> = ({ momentId, placeholderText, - callback = (msg) => null, + callback = (_) => null, + onFocus = () => null, theme = 'white', }) => { const {setShouldUpdateAllComments = () => null, commentTapped} = @@ -125,6 +127,7 @@ const AddComment: React.FC<AddCommentProps> = ({ placeholderTextColor={theme === 'dark' ? '#828282' : undefined} placeholder={placeholderText} value={inReplyToMention + comment} + onFocus={onFocus} onChange={(newText: string) => { // skipping the `inReplyToMention` text setComment( diff --git a/src/components/moments/IndividualMomentTitleBar.tsx b/src/components/moments/IndividualMomentTitleBar.tsx index 2bebafa7..4ae9471f 100644 --- a/src/components/moments/IndividualMomentTitleBar.tsx +++ b/src/components/moments/IndividualMomentTitleBar.tsx @@ -1,8 +1,13 @@ import React from 'react'; -import {TouchableOpacity} from 'react-native'; -import {Text, View, StyleSheet, ViewProps} from 'react-native'; -import {normalize} from '../../utils'; +import { + StyleSheet, + Text, + TouchableOpacity, + View, + ViewProps, +} from 'react-native'; import CloseIcon from '../../assets/ionicons/close-outline.svg'; +import {normalize} from '../../utils'; interface IndividualMomentTitleBarProps extends ViewProps { title: string; diff --git a/src/components/moments/MomentPost.tsx b/src/components/moments/MomentPost.tsx index 02dbffa3..7a588325 100644 --- a/src/components/moments/MomentPost.tsx +++ b/src/components/moments/MomentPost.tsx @@ -11,12 +11,14 @@ interface MomentPostProps { moment: MomentPostType; userXId: string | undefined; screenType: ScreenType; + index: number; } const MomentPost: React.FC<MomentPostProps> = ({ moment, userXId, screenType, + index, }) => { const {userId: loggedInUserId, username: loggedInUsername} = useSelector( (state: RootState) => state.user.user, @@ -88,6 +90,7 @@ const MomentPost: React.FC<MomentPostProps> = ({ moment={moment} screenType={screenType} momentTags={tags} + index={index} /> </> ); diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 5192fdf0..eb89fd03 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -1,9 +1,10 @@ import {useNavigation} from '@react-navigation/native'; -import React, {useEffect, useRef, useState} from 'react'; +import React, {useContext, useEffect, useRef, useState} from 'react'; import {Image, StyleSheet, Text, View, ViewProps} from 'react-native'; import {TouchableWithoutFeedback} from 'react-native-gesture-handler'; import Animated, {EasingNode} from 'react-native-reanimated'; import {useDispatch, useStore} from 'react-redux'; +import {MomentContext} from '../../screens/profile/IndividualMoment'; import {RootState} from '../../store/rootReducer'; import { MomentCommentPreviewType, @@ -13,11 +14,11 @@ import { UserType, } from '../../types'; import { + getLoggedInUserAsProfilePreview, getTimePosted, navigateToProfile, normalize, SCREEN_WIDTH, - getLoggedInUserAsProfilePreview, } from '../../utils'; import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments'; import {AddComment} from '../comments'; @@ -28,12 +29,14 @@ interface MomentPostContentProps extends ViewProps { screenType: ScreenType; moment: MomentPostType; momentTags: MomentTagType[]; + index: number; } const MomentPostContent: React.FC<MomentPostContentProps> = ({ screenType, moment, style, momentTags, + index, }) => { const state: RootState = useStore().getState(); const navigation = useNavigation(); @@ -46,6 +49,7 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ ); const [commentPreview, setCommentPreview] = useState<MomentCommentPreviewType | null>(moment.comment_preview); + const {keyboardVisible, setScrollToTargetIndex} = useContext(MomentContext); useEffect(() => { setTags(momentTags); @@ -92,20 +96,30 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ /> </Animated.View> )} - {moment.caption !== '' && - renderTextWithMentions({ - value: moment.caption, - styles: styles.captionText, - partTypes: mentionPartTypes('momentCaption'), - onPress: (user: UserType) => - navigateToProfile(state, dispatch, navigation, screenType, user), - })} - <MomentCommentPreview - momentId={moment.moment_id} - commentsCount={moment.comments_count} - commentPreview={commentPreview} - screenType={screenType} - /> + {!keyboardVisible && ( + <> + {moment.caption !== '' && + renderTextWithMentions({ + value: moment.caption, + styles: styles.captionText, + partTypes: mentionPartTypes('momentCaption'), + onPress: (user: UserType) => + navigateToProfile( + state, + dispatch, + navigation, + screenType, + user, + ), + })} + <MomentCommentPreview + momentId={moment.moment_id} + commentsCount={moment.comments_count} + commentPreview={commentPreview} + screenType={screenType} + /> + </> + )} <AddComment placeholderText={'Add a comment here!'} momentId={moment.moment_id} @@ -115,6 +129,7 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ comment: message, }) } + onFocus={() => setScrollToTargetIndex(index)} theme={'dark'} /> <Text style={styles.text}>{getTimePosted(moment.date_created)}</Text> @@ -123,9 +138,7 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ }; const styles = StyleSheet.create({ - container: { - borderWidth: 1, - }, + container: {}, image: { width: SCREEN_WIDTH, aspectRatio: 1, @@ -147,7 +160,6 @@ const styles = StyleSheet.create({ lineHeight: normalize(15.51), letterSpacing: normalize(0.6), marginBottom: normalize(18), - borderWidth: 1, }, tapTag: { position: 'absolute', diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx index 447ba2a9..a91f1913 100644 --- a/src/screens/profile/IndividualMoment.tsx +++ b/src/screens/profile/IndividualMoment.tsx @@ -1,10 +1,11 @@ import {BlurView} from '@react-native-community/blur'; import {RouteProp} from '@react-navigation/native'; import {StackNavigationProp} from '@react-navigation/stack'; -import React from 'react'; -import {FlatList, StyleSheet} from 'react-native'; +import React, {useEffect, useRef, useState} from 'react'; +import {FlatList, Keyboard, StyleSheet} from 'react-native'; import {useSelector} from 'react-redux'; import {IndividualMomentTitleBar, MomentPost} from '../../components'; +import {AVATAR_DIM} from '../../constants'; import {MainStackParams} from '../../routes'; import {RootState} from '../../store/rootreducer'; import {MomentPostType} from '../../types'; @@ -13,11 +14,21 @@ import {normalize, StatusBarHeight} from '../../utils'; /** * Individual moment view opened when user clicks on a moment tile */ + +type MomentContextType = { + keyboardVisible: boolean; + setScrollToTargetIndex: (index: number) => void; +}; + +export const MomentContext = React.createContext({} as MomentContextType); + type IndividualMomentRouteProp = RouteProp<MainStackParams, 'IndividualMoment'>; + type IndividualMomentNavigationProp = StackNavigationProp< MainStackParams, 'IndividualMoment' >; + interface IndividualMomentProps { route: IndividualMomentRouteProp; navigation: IndividualMomentNavigationProp; @@ -27,39 +38,78 @@ const IndividualMoment: React.FC<IndividualMomentProps> = ({ route, navigation, }) => { - const {moment_category, moment_id} = route.params.moment; - const {userXId, screenType} = route.params; - + const { + userXId, + screenType, + moment: {moment_category, moment_id}, + } = route.params; const {moments} = useSelector((state: RootState) => userXId ? state.userX[screenType][userXId] : state.moments, ); - + const scrollRef = useRef<FlatList<MomentPostType>>(null); const momentData = moments.filter( (m) => m.moment_category === moment_category, ); const initialIndex = momentData.findIndex((m) => m.moment_id === moment_id); + const [scrollToTargetIndex, setScrollToTargetIndex] = + useState<number>(initialIndex); + const [keyboardVisible, setKeyboardVisible] = React.useState(false); + + 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); + }, []); + + useEffect(() => { + if (keyboardVisible) { + scrollRef.current?.scrollToIndex({ + index: scrollToTargetIndex, + // viewOffset: -(AVATAR_DIM + normalize(120)), + viewOffset: -(AVATAR_DIM + normalize(90)), + }); + } + }, [scrollToTargetIndex, keyboardVisible]); return ( - <BlurView - blurType="light" - blurAmount={30} - reducedTransparencyFallbackColor="white" - style={styles.contentContainer}> - <IndividualMomentTitleBar - style={styles.header} - close={() => navigation.goBack()} - title={moment_category} - /> - <FlatList - data={momentData} - renderItem={({item}: {item: MomentPostType}) => ( - <MomentPost moment={item} userXId={userXId} screenType={screenType} /> - )} - keyExtractor={(item, _) => item.moment_id} - showsVerticalScrollIndicator={false} - initialScrollIndex={initialIndex} - /> - </BlurView> + <MomentContext.Provider + value={{ + keyboardVisible, + setScrollToTargetIndex, + }}> + <BlurView + blurType="light" + blurAmount={30} + reducedTransparencyFallbackColor="white" + style={styles.contentContainer}> + <IndividualMomentTitleBar + style={styles.header} + close={() => navigation.goBack()} + title={moment_category} + /> + <FlatList + ref={scrollRef} + data={momentData} + renderItem={({item, index}) => ( + <MomentPost + moment={item} + userXId={userXId} + screenType={screenType} + index={index} + /> + )} + keyExtractor={(item, _) => item.moment_id} + showsVerticalScrollIndicator={false} + initialScrollIndex={initialIndex} + /> + </BlurView> + </MomentContext.Provider> ); }; const styles = StyleSheet.create({ diff --git a/src/screens/profile/MomentCommentsScreen.tsx b/src/screens/profile/MomentCommentsScreen.tsx index 402e5f44..7dfe8ae9 100644 --- a/src/screens/profile/MomentCommentsScreen.tsx +++ b/src/screens/profile/MomentCommentsScreen.tsx @@ -48,8 +48,9 @@ const MomentCommentsScreen: React.FC<MomentCommentsScreenProps> = ({route}) => { 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 [commentTapped, setCommentTapped] = - useState<CommentType | CommentThreadType | undefined>(); + const [commentTapped, setCommentTapped] = useState< + CommentType | CommentThreadType | undefined + >(); useEffect(() => { navigation.setOptions({ |