aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/common/MomentTags.tsx77
-rw-r--r--src/components/common/index.ts1
-rw-r--r--src/components/moments/MomentPostContent.tsx27
-rw-r--r--src/components/notifications/Notification.tsx147
-rw-r--r--src/components/taggs/TaggDraggable.tsx2
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';