diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/common/MomentTags.tsx | 77 | ||||
| -rw-r--r-- | src/components/common/index.ts | 1 | ||||
| -rw-r--r-- | src/components/moments/MomentPostContent.tsx | 27 | ||||
| -rw-r--r-- | src/components/notifications/Notification.tsx | 147 | ||||
| -rw-r--r-- | src/components/taggs/TaggDraggable.tsx | 2 |
5 files changed, 177 insertions, 77 deletions
diff --git a/src/components/common/MomentTags.tsx b/src/components/common/MomentTags.tsx new file mode 100644 index 00000000..fb9ef5be --- /dev/null +++ b/src/components/common/MomentTags.tsx @@ -0,0 +1,77 @@ +import React, {MutableRefObject, useEffect, useState} from 'react'; +import {MomentTagType, ProfilePreviewType} from '../../types'; +import TaggDraggable from '../taggs/TaggDraggable'; +import Draggable from './Draggable'; + +interface MomentTagsProps { + editing: boolean; + tags: MomentTagType[]; + imageRef: MutableRefObject<null>; + deleteFromList?: (user: ProfilePreviewType) => void; +} + +const MomentTags: React.FC<MomentTagsProps> = ({ + editing, + tags, + imageRef, + deleteFromList, +}) => { + const [offset, setOffset] = useState([0, 0]); + const [curStart, setCurStart] = useState([0, 0]); + const [imageDimensions, setImageDimensions] = useState([0, 0]); + + useEffect(() => { + imageRef.current.measure((fx, fy, width, height, px, py) => { + setOffset([px, py]); + setImageDimensions([width, height]); + }); + }, []); + + if (!tags) { + return null; + } + + return editing && deleteFromList ? ( + <> + {tags.map((tag) => ( + <Draggable + x={imageDimensions[0] / 2 - curStart[0] / 2 + offset[0]} + y={offset[1] + imageDimensions[1] / 2 - curStart[1] / 2} + minX={offset[0]} + minY={offset[1]} + maxX={imageDimensions[0] + offset[0]} + maxY={imageDimensions[1] + offset[1]} + onDragStart={() => null}> + <TaggDraggable + taggedUser={tag.user} + editingView={true} + deleteFromList={() => deleteFromList(tag.user)} + setStart={setCurStart} + /> + </Draggable> + ))} + </> + ) : ( + <> + {tags.map((tag) => ( + <Draggable + x={imageDimensions[0] / 2 - curStart[0] / 2 + tag.x} + y={imageDimensions[0] / 2 - curStart[0] / 2 + tag.y} + minX={offset[0]} + minY={offset[1]} + maxX={imageDimensions[0] + offset[0]} + maxY={imageDimensions[1] + offset[1]} + onDragStart={() => null}> + <TaggDraggable + taggedUser={tag.user} + editingView={editing} + deleteFromList={() => null} + setStart={setCurStart} + /> + </Draggable> + ))} + </> + ); +}; + +export default MomentTags; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 48abb8b8..692c9f8a 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -27,3 +27,4 @@ export {default as Avatar} from './Avatar'; export {default as TaggTypeahead} from './TaggTypeahead'; export {default as TaggUserRowCell} from './TaggUserRowCell'; export {default as LikeButton} from './LikeButton'; +export {default as MomentTags} from './MomentTags'; diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 193bf40c..e702cb68 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -1,19 +1,20 @@ import {useNavigation} from '@react-navigation/native'; -import React, {useEffect} from 'react'; +import React, {useEffect, useRef, useState} from 'react'; import {Image, StyleSheet, Text, View, ViewProps} from 'react-native'; import {useDispatch, useStore} from 'react-redux'; -import {getCommentsCount} from '../../services'; +import {getCommentsCount, loadMomentTags} from '../../services'; import {RootState} from '../../store/rootReducer'; -import {ScreenType, UserType} from '../../types'; +import {MomentTagType, ScreenType, UserType} from '../../types'; import { getTimePosted, navigateToProfile, + normalize, SCREEN_HEIGHT, SCREEN_WIDTH, - normalize, } from '../../utils'; import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments'; import {CommentsCount} from '../comments'; +import {MomentTags} from '../common'; interface MomentPostContentProps extends ViewProps { screenType: ScreenType; @@ -30,11 +31,23 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ dateTime, style, }) => { - const [elapsedTime, setElapsedTime] = React.useState<string>(); - const [comments_count, setCommentsCount] = React.useState(''); + const [elapsedTime, setElapsedTime] = useState(''); + const [comments_count, setCommentsCount] = useState(''); + const [tags, setTags] = useState<MomentTagType[]>([]); const state: RootState = useStore().getState(); const navigation = useNavigation(); const dispatch = useDispatch(); + const imageRef = useRef(null); + + useEffect(() => { + const loadTags = async () => { + const response = await loadMomentTags(momentId); + if (response) { + setTags(response); + } + }; + loadTags(); + }, []); useEffect(() => { const fetchCommentsCount = async () => { @@ -48,10 +61,12 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ return ( <View style={[styles.container, style]}> <Image + ref={imageRef} style={styles.image} source={{uri: pathHash}} resizeMode={'cover'} /> + <MomentTags editing={false} tags={tags} imageRef={imageRef} /> <View style={styles.footerContainer}> <CommentsCount commentsCount={comments_count} diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index cb62047a..3f9cc56a 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -84,7 +84,8 @@ const Notification: React.FC<NotificationProps> = (props) => { let obj; if ( notification_type === 'MOM_3+' || - notification_type === 'MOM_FRIEND' + notification_type === 'MOM_FRIEND' || + notification_type === 'MOM_TAG' ) { obj = notification_object as MomentType; url = obj.thumbnail_url; @@ -185,6 +186,7 @@ const Notification: React.FC<NotificationProps> = (props) => { break; case 'MOM_3+': case 'MOM_FRIEND': + case 'MOM_TAG': const object = notification_object as MomentType; await fetchUserX( dispatch, @@ -236,83 +238,88 @@ const Notification: React.FC<NotificationProps> = (props) => { style={styles.avatarContainer}> <Avatar style={styles.avatar} uri={avatar} /> </TouchableWithoutFeedback> - {notification_type === 'SYSTEM_MSG' ? ( - // Only verbage + {notification_type === 'SYSTEM_MSG' || notification_type === 'MOM_TAG' ? ( + // Single-line body text with timestamp <View style={styles.contentContainer}> <View style={styles.textContainerStyles}> - <Text style={styles.actorName}>{verbage}</Text> - <Text style={styles.timeStampStyles}> - {getTimeInShorthand(timestamp)} - </Text> - </View> - </View> - ) : ( - <> - {/* Text content: Actor name and verbage*/} - <View style={styles.contentContainer}> - <TouchableWithoutFeedback onPress={navigateToProfile}> - <Text style={styles.actorName}>{notification_title}</Text> - </TouchableWithoutFeedback> - <TouchableWithoutFeedback - style={styles.textContainerStyles} - onPress={onNotificationTap}> - <Text style={styles.verbageStyles}> - {verbage} + {notification_type === 'SYSTEM_MSG' ? ( + <Text style={styles.actorName}>{verbage}</Text> + ) : ( + <Text> + <Text style={styles.actorName}>{notification_title} </Text> + <Text style={styles.verbageStyles}>{verbage} </Text> <Text style={styles.timeStampStyles}> - {' '} {getTimeInShorthand(timestamp)} </Text> </Text> - {/* <Text style={styles.verbageStyles}>{verbage}</Text> */} - </TouchableWithoutFeedback> - </View> - {/* Friend request accept/decline button */} - {notification_type === 'FRD_REQ' && ( - <View style={styles.buttonsContainer}> - <AcceptDeclineButtons - requester={{id, username, first_name, last_name}} - onAccept={handleAcceptRequest} - onReject={handleDeclineFriendRequest} - /> - </View> - )} - {notification_type === 'FRD_ACPT' && ( - <View style={styles.buttonsContainer}> - <MessageButton - userXId={id} - isBlocked={false} - friendship_status={'friends'} - externalStyles={{ - container: { - width: normalize(63), - height: normalize(21), - marginTop: '7%', - }, - buttonTitle: { - fontSize: normalize(11), - lineHeight: normalize(13.13), - letterSpacing: normalize(0.5), - fontWeight: '700', - textAlign: 'center', - }, - }} - solid - /> - </View> - )} - {/* Moment Image Preview */} - {(notification_type === 'CMT' || - notification_type === 'MOM_3+' || - notification_type === 'MOM_FRIEND') && - notification_object && ( - <TouchableWithoutFeedback - style={styles.moment} - onPress={onNotificationTap}> - <Image style={styles.imageFlex} source={{uri: momentURI}} /> - </TouchableWithoutFeedback> )} - </> + </View> + </View> + ) : ( + // Two-line title and body text with timestamp + <View style={styles.contentContainer}> + <TouchableWithoutFeedback onPress={navigateToProfile}> + <Text style={styles.actorName}>{notification_title}</Text> + </TouchableWithoutFeedback> + <TouchableWithoutFeedback + style={styles.textContainerStyles} + onPress={onNotificationTap}> + <Text> + <Text style={styles.verbageStyles}>{verbage} </Text> + <Text style={styles.timeStampStyles}> + {getTimeInShorthand(timestamp)} + </Text> + </Text> + </TouchableWithoutFeedback> + </View> + )} + {/* Friend request accept/decline button */} + {notification_type === 'FRD_REQ' && ( + <View style={styles.buttonsContainer}> + <AcceptDeclineButtons + requester={{id, username, first_name, last_name}} + onAccept={handleAcceptRequest} + onReject={handleDeclineFriendRequest} + /> + </View> + )} + {/* Message button when user accepts friend request */} + {notification_type === 'FRD_ACPT' && ( + <View style={styles.buttonsContainer}> + <MessageButton + userXId={id} + isBlocked={false} + friendship_status={'friends'} + externalStyles={{ + container: { + width: normalize(63), + height: normalize(21), + marginTop: '7%', + }, + buttonTitle: { + fontSize: normalize(11), + lineHeight: normalize(13.13), + letterSpacing: normalize(0.5), + fontWeight: '700', + textAlign: 'center', + }, + }} + solid + /> + </View> )} + {/* Moment Image Preview */} + {(notification_type === 'CMT' || + notification_type === 'MOM_3+' || + notification_type === 'MOM_TAG' || + notification_type === 'MOM_FRIEND') && + notification_object && ( + <TouchableWithoutFeedback + style={styles.moment} + onPress={onNotificationTap}> + <Image style={styles.imageFlex} source={{uri: momentURI}} /> + </TouchableWithoutFeedback> + )} </View> ); diff --git a/src/components/taggs/TaggDraggable.tsx b/src/components/taggs/TaggDraggable.tsx index a6ffb1ef..e4448642 100644 --- a/src/components/taggs/TaggDraggable.tsx +++ b/src/components/taggs/TaggDraggable.tsx @@ -9,8 +9,8 @@ import { View, } from 'react-native'; import {useDispatch, useSelector} from 'react-redux'; -import {RootState} from 'src/store/rootReducer'; import Avatar from '../../components/common/Avatar'; +import {RootState} from '../../store/rootReducer'; import {ProfilePreviewType, ScreenType, UserType} from '../../types'; import {normalize} from '../../utils'; import {navigateToProfile} from '../../utils/users'; |
