diff options
-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/taggs/TaggDraggable.tsx | 2 | ||||
-rw-r--r-- | src/constants/api.ts | 1 | ||||
-rw-r--r-- | src/screens/profile/CaptionScreen.tsx | 53 | ||||
-rw-r--r-- | src/screens/profile/IndividualMoment.tsx | 5 | ||||
-rw-r--r-- | src/services/MomentService.ts | 30 | ||||
-rw-r--r-- | src/types/types.ts | 8 |
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; |