aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Chen <ivan@tagg.id>2021-05-21 20:10:14 -0400
committerGitHub <noreply@github.com>2021-05-21 20:10:14 -0400
commit4849c65ff2163e1a77dcb26a12ff68840df225e7 (patch)
tree8efb8f40c23156551a3628c3eac93945980a7325 /src
parent9315aa31ad4d6c305e62853a3ab7e4a484ecce98 (diff)
parent4434d06df897f844832a92d66956825ea58c2b01 (diff)
Merge pull request #440 from grusuTagg/tma884-moment-view-tags
Fetch momentTag objects from the backend
Diffstat (limited to 'src')
-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/taggs/TaggDraggable.tsx2
-rw-r--r--src/constants/api.ts1
-rw-r--r--src/screens/profile/CaptionScreen.tsx53
-rw-r--r--src/screens/profile/IndividualMoment.tsx5
-rw-r--r--src/services/MomentService.ts30
-rw-r--r--src/types/types.ts8
9 files changed, 156 insertions, 48 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/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';
diff --git a/src/constants/api.ts b/src/constants/api.ts
index 6cc357f5..d52fc203 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -31,6 +31,7 @@ export const SEARCH_ENDPOINT: string = API_URL + 'search/';
export const SEARCH_ENDPOINT_MESSAGES: string = API_URL + 'search/messages/';
export const SEARCH_ENDPOINT_SUGGESTED: string = API_URL + 'search/suggested/';
export const MOMENTS_ENDPOINT: string = API_URL + 'moments/';
+export const MOMENT_TAGS_ENDPOINT: string = API_URL + 'moments/tags/';
export const MOMENT_THUMBNAIL_ENDPOINT: string = API_URL + 'moment-thumbnail/';
export const VERIFY_INVITATION_CODE_ENDPOUNT: string = API_URL + 'verify-code/';
export const COMMENTS_ENDPOINT: string = API_URL + 'comments/';
diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx
index 8e972e07..56fe672e 100644
--- a/src/screens/profile/CaptionScreen.tsx
+++ b/src/screens/profile/CaptionScreen.tsx
@@ -1,6 +1,6 @@
import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp} from '@react-navigation/stack';
-import React, {Fragment, useEffect, useRef, useState} from 'react';
+import React, {Fragment, useRef, useState} from 'react';
import {
Alert,
Image,
@@ -14,11 +14,9 @@ import {
import {MentionInput} from 'react-native-controlled-mentions';
import {Button} from 'react-native-elements';
import {useDispatch, useSelector} from 'react-redux';
-import {SearchBackground} from '../../components';
+import {MomentTags, SearchBackground} from '../../components';
import {CaptionScreenHeader} from '../../components/';
-import Draggable from '../../components/common/Draggable';
import TaggLoadingIndicator from '../../components/common/TaggLoadingIndicator';
-import TaggDraggable from '../../components/taggs/TaggDraggable';
import {TAGG_LIGHT_BLUE_2} from '../../constants';
import {ERROR_UPLOAD, SUCCESS_PIC_UPLOAD} from '../../constants/strings';
import {MainStackParams} from '../../routes';
@@ -54,11 +52,6 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
const [loading, setLoading] = useState(false);
const imageRef = useRef(null);
- // state variables used to position draggables
- const [offset, setOffset] = useState([0, 0]);
- const [curStart, setCurStart] = useState([0, 0]);
- const [imageDimensions, setImageDimensions] = useState([0, 0]);
-
const [taggList, setTaggList] = useState([
{
first_name: 'Ivan',
@@ -94,16 +87,6 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
});
};
- /**
- * need a handler to take care of creating a tagged user object, append that object to the taggList state variable.
- */
- useEffect(() => {
- imageRef.current.measure((fx, fy, width, height, px, py) => {
- setOffset([px, py]);
- setImageDimensions([width, height]);
- });
- }, []);
-
const handleShare = async () => {
setLoading(true);
if (!image.filename) {
@@ -165,25 +148,19 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => {
onChange={setCaption}
partTypes={mentionPartTypes('blue')}
/>
- {taggList.map((user) => (
- <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={user}
- editingView={true}
- deleteFromList={() =>
- setTaggList(taggList.filter((u) => u.id !== user.id))
- }
- setStart={setCurStart}
- />
- </Draggable>
- ))}
+ <MomentTags
+ editing={true}
+ tags={taggList.map((user) => ({
+ id: '',
+ x: 0,
+ y: 0,
+ user,
+ }))}
+ imageRef={imageRef}
+ deleteFromList={(user) =>
+ setTaggList(taggList.filter((u) => u.id !== user.id))
+ }
+ />
</View>
</KeyboardAvoidingView>
</TouchableWithoutFeedback>
diff --git a/src/screens/profile/IndividualMoment.tsx b/src/screens/profile/IndividualMoment.tsx
index 515cbacf..4baca5b2 100644
--- a/src/screens/profile/IndividualMoment.tsx
+++ b/src/screens/profile/IndividualMoment.tsx
@@ -1,14 +1,17 @@
+import AsyncStorage from '@react-native-community/async-storage';
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, View} from 'react-native';
+import {Alert, FlatList, StyleSheet, View} from 'react-native';
import {useSelector} from 'react-redux';
import {
IndividualMomentTitleBar,
MomentPostContent,
MomentPostHeader,
} from '../../components';
+import {MOMENT_TAGS_ENDPOINT} from '../../constants';
+import {ERROR_SOMETHING_WENT_WRONG_REFRESH} from '../../constants/strings';
import {MainStackParams} from '../../routes';
import {RootState} from '../../store/rootreducer';
import {MomentType} from '../../types';
diff --git a/src/services/MomentService.ts b/src/services/MomentService.ts
index 2354d18e..a26a1abb 100644
--- a/src/services/MomentService.ts
+++ b/src/services/MomentService.ts
@@ -1,7 +1,11 @@
import AsyncStorage from '@react-native-community/async-storage';
import RNFetchBlob from 'rn-fetch-blob';
-import {MOMENTS_ENDPOINT, MOMENT_THUMBNAIL_ENDPOINT} from '../constants';
-import {MomentType} from '../types';
+import {
+ MOMENTS_ENDPOINT,
+ MOMENT_TAGS_ENDPOINT,
+ MOMENT_THUMBNAIL_ENDPOINT,
+} from '../constants';
+import {MomentTagType, MomentType} from '../types';
import {checkImageUploadStatus} from '../utils';
export const postMoment: (
@@ -116,3 +120,25 @@ export const loadMomentThumbnail = async (momentId: string) => {
return undefined;
}
};
+
+export const loadMomentTags = async (moment_id: string) => {
+ try {
+ const token = await AsyncStorage.getItem('token');
+ const response = await fetch(
+ MOMENT_TAGS_ENDPOINT + `?moment_id=${moment_id}`,
+ {
+ method: 'GET',
+ headers: {
+ Authorization: 'Token ' + token,
+ },
+ },
+ );
+ if (response.status === 200) {
+ const tags: MomentTagType[] = await response.json();
+ return tags;
+ }
+ } catch (error) {
+ console.error(error);
+ return [];
+ }
+};
diff --git a/src/types/types.ts b/src/types/types.ts
index e1935d26..1b4b7ecf 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -117,6 +117,14 @@ export interface MomentType {
moment_url: string;
thumbnail_url: string;
}
+
+export interface MomentTagType {
+ id: string;
+ user: ProfilePreviewType;
+ x: number;
+ y: number;
+}
+
export interface CommentBaseType {
comment_id: string;
comment: string;