diff options
author | Ivan Chen <ivan@tagg.id> | 2021-05-27 11:00:46 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-27 11:00:46 -0400 |
commit | 0e31510f9f1669c766195d1d245fcee6a745bf93 (patch) | |
tree | 83eb093863c73f47de1936c91066279ec23e31d2 /src | |
parent | 928b94f77581216e1e6d2d180986a4260f040c93 (diff) | |
parent | b87ad0f18d491a27bbb458887abdd2ab09e64d1e (diff) |
Merge pull request #449 from grusuTagg/tma883-Layered-Taggs
[TMA-883] Layered Tags
Diffstat (limited to 'src')
-rw-r--r-- | src/components/common/Draggable.tsx | 34 | ||||
-rw-r--r-- | src/components/common/MomentTags.tsx | 100 | ||||
-rw-r--r-- | src/components/common/TaggUserSelectionCell.tsx | 37 | ||||
-rw-r--r-- | src/components/moments/MomentPostContent.tsx | 2 | ||||
-rw-r--r-- | src/components/moments/TagFriendsFoooter.tsx | 130 | ||||
-rw-r--r-- | src/components/profile/ProfilePreview.tsx | 4 | ||||
-rw-r--r-- | src/components/taggs/TaggDraggable.tsx | 17 | ||||
-rw-r--r-- | src/routes/main/MainStackNavigator.tsx | 20 | ||||
-rw-r--r-- | src/screens/moments/TagFriendsScreen.tsx | 33 | ||||
-rw-r--r-- | src/screens/moments/TagSelectionScreen.tsx | 20 | ||||
-rw-r--r-- | src/screens/profile/CaptionScreen.tsx | 27 | ||||
-rw-r--r-- | src/services/MomentService.ts | 16 | ||||
-rw-r--r-- | src/services/SearchService.ts | 9 | ||||
-rw-r--r-- | src/types/types.ts | 1 | ||||
-rw-r--r-- | src/utils/search.ts | 2 |
15 files changed, 267 insertions, 185 deletions
diff --git a/src/components/common/Draggable.tsx b/src/components/common/Draggable.tsx index edd29b78..15ba3325 100644 --- a/src/components/common/Draggable.tsx +++ b/src/components/common/Draggable.tsx @@ -59,7 +59,7 @@ interface IProps { minY?: number; maxX?: number; maxY?: number; - onDragStart?: () => void; + onDragStart?: () => number; } export default function Draggable(props: IProps) { @@ -103,8 +103,8 @@ export default function Draggable(props: IProps) { // Whether we're currently dragging or not const isDragging = React.useRef(false); - // const [zIndex, setZIndex] = React.useState(z); - const zIndex = z; + const [zIndex, setZIndex] = React.useState(z); + // const zIndex = z; const getBounds = React.useCallback(() => { const left = x + offsetFromStart.current.x; @@ -136,7 +136,9 @@ export default function Draggable(props: IProps) { isDragging.current = false; if (onDragRelease) { onDragRelease(e, gestureState); - onRelease(e, true); + } + if (onRelease) { + onRelease(e, gestureState); } if (!shouldReverse) { pan.current.flattenOffset(); @@ -147,18 +149,17 @@ export default function Draggable(props: IProps) { [onDragRelease, shouldReverse, onRelease, reversePosition], ); - const onPanResponderGrant = React.useCallback( - (_: GestureResponderEvent) => { - startBounds.current = getBounds(); - isDragging.current = true; - if (!shouldReverse) { - pan.current.setOffset(offsetFromStart.current); - pan.current.setValue({x: 0, y: 0}); - } - onDragStart(); - }, - [getBounds, shouldReverse], - ); + const onPanResponderGrant = (_: GestureResponderEvent) => { + startBounds.current = getBounds(); + isDragging.current = true; + if (!shouldReverse) { + pan.current.setOffset(offsetFromStart.current); + pan.current.setValue({x: 0, y: 0}); + } + if (onDragStart) { + setZIndex(onDragStart()); + } + }; const handleOnDrag = React.useCallback( (e: GestureResponderEvent, gestureState: PanResponderGestureState) => { @@ -194,6 +195,7 @@ export default function Draggable(props: IProps) { listener: handleOnDrag, useNativeDriver: false, }), + onPanResponderRelease, // onPanResponderRelease: (_) => { // // console.log('end'); // // setZIndex(1); diff --git a/src/components/common/MomentTags.tsx b/src/components/common/MomentTags.tsx index defd4b4b..bdd1fbeb 100644 --- a/src/components/common/MomentTags.tsx +++ b/src/components/common/MomentTags.tsx @@ -1,4 +1,4 @@ -import React, {MutableRefObject, useEffect, useState} from 'react'; +import React, {createRef, MutableRefObject, useEffect, useState} from 'react'; import {MomentTagType, ProfilePreviewType} from '../../types'; import TaggDraggable from '../taggs/TaggDraggable'; import Draggable from './Draggable'; @@ -6,6 +6,7 @@ import Draggable from './Draggable'; interface MomentTagsProps { editing: boolean; tags: MomentTagType[]; + setTags: (tag: MomentTagType[]) => void; imageRef: MutableRefObject<null>; deleteFromList?: (user: ProfilePreviewType) => void; } @@ -13,60 +14,127 @@ interface MomentTagsProps { const MomentTags: React.FC<MomentTagsProps> = ({ editing, tags, + setTags, imageRef, deleteFromList, }) => { const [offset, setOffset] = useState([0, 0]); - const [curStart, setCurStart] = useState([0, 0]); const [imageDimensions, setImageDimensions] = useState([0, 0]); + const [maxZIndex, setMaxZIndex] = useState(1); + const [draggableRefs, setDraggableRefs] = useState< + React.MutableRefObject<null>[] + >([]); + + const updateTagPosition = ( + ref: React.MutableRefObject<null>, + userId: string, + ) => { + if (ref !== null && ref.current !== null) { + ref.current.measure( + ( + _fx: number, // location of ref relative to parent element + _fy: number, + _width: number, + _height: number, + px: number, // location of ref relative to entire screen + py: number, + ) => { + const x = ((px - offset[0]) / imageDimensions[0]) * 100; + const y = ((py - offset[1]) / imageDimensions[1]) * 100; + setTags( + tags.map((tag) => + tag.user.id === userId + ? { + id: '', + x, + y, + z: maxZIndex - 1, // TODO: change this + user: tag.user, + } + : tag, + ), + ); + }, + ); + } + }; + + useEffect(() => { + setDraggableRefs(tags.map((_) => createRef())); + }, [tags]); useEffect(() => { - imageRef.current.measure((fx, fy, width, height, px, py) => { - setOffset([px, py]); - setImageDimensions([width, height]); - }); + setTimeout( + () => { + imageRef.current.measure( + ( + fx: number, // location of ref relative to parent element + fy: number, + width: number, + height: number, + _x: number, // location of ref relative to entire screen + _y: number, + ) => { + setOffset([fx, fy]); + setImageDimensions([width, height]); + }, + ); + }, + editing ? 100 : 0, + ); }, []); if (!tags) { return null; } + return editing && deleteFromList ? ( <> - {tags.map((tag) => ( + {tags.map((tag, index) => ( <Draggable - x={imageDimensions[0] / 2 - curStart[0] / 2 + offset[0]} - y={offset[1] + imageDimensions[1] / 2 - curStart[1] / 2} + key={tag.user.id + tag.x + tag.y} + x={(imageDimensions[0] * tag.x) / 100 + offset[0]} + y={(imageDimensions[1] * tag.y) / 100 + offset[1]} + z={tag.z} minX={offset[0]} minY={offset[1]} maxX={imageDimensions[0] + offset[0]} maxY={imageDimensions[1] + offset[1]} - onDragStart={() => null}> + onDragStart={() => { + const currZIndex = maxZIndex; + setMaxZIndex(currZIndex + 1); + return currZIndex; + }} + onDragRelease={() => + updateTagPosition(draggableRefs[index], tag.user.id) + }> <TaggDraggable + draggableRef={draggableRefs[index]} taggedUser={tag.user} editingView={true} deleteFromList={() => deleteFromList(tag.user)} - setStart={setCurStart} /> </Draggable> ))} </> ) : ( <> - {tags.map((tag) => ( + {tags.map((tag, index) => ( <Draggable - x={imageDimensions[0] / 2 - curStart[0] / 2 + tag.x} - y={imageDimensions[0] / 2 - curStart[0] / 2 + tag.y} + key={tag.user.id} + x={(imageDimensions[0] * tag.x) / 100 + offset[0]} + y={(imageDimensions[1] * tag.y) / 100 + offset[1]} + z={tag.z} minX={offset[0]} minY={offset[1]} maxX={imageDimensions[0] + offset[0]} maxY={imageDimensions[1] + offset[1]} - onDragStart={() => null} disabled={true}> <TaggDraggable + draggableRef={draggableRefs[index]} taggedUser={tag.user} editingView={editing} deleteFromList={() => null} - setStart={setCurStart} /> </Draggable> ))} diff --git a/src/components/common/TaggUserSelectionCell.tsx b/src/components/common/TaggUserSelectionCell.tsx index 2ea1e4ce..72c98822 100644 --- a/src/components/common/TaggUserSelectionCell.tsx +++ b/src/components/common/TaggUserSelectionCell.tsx @@ -1,19 +1,20 @@ import React, {useEffect, useState} from 'react'; import {StyleSheet, View} from 'react-native'; +import {TouchableWithoutFeedback} from 'react-native-gesture-handler'; import {ProfilePreview} from '..'; -import {ProfilePreviewType, ScreenType} from '../../types'; +import {MomentTagType, ProfilePreviewType, ScreenType} from '../../types'; import {SCREEN_WIDTH} from '../../utils'; import TaggRadioButton from './TaggRadioButton'; interface TaggUserSelectionCellProps { item: ProfilePreviewType; - selectedUsers: ProfilePreviewType[]; - setSelectedUsers: Function; + tags: MomentTagType[]; + setTags: (tags: MomentTagType[]) => void; } const TaggUserSelectionCell: React.FC<TaggUserSelectionCellProps> = ({ item, - selectedUsers, - setSelectedUsers, + tags, + setTags, }) => { const [pressed, setPressed] = useState<boolean>(false); @@ -22,9 +23,7 @@ const TaggUserSelectionCell: React.FC<TaggUserSelectionCellProps> = ({ */ useEffect(() => { const updatePressed = () => { - const userSelected = selectedUsers.findIndex( - (selectedUser) => item.id === selectedUser.id, - ); + const userSelected = tags.findIndex((tag) => item.id === tag.user.id); setPressed(userSelected !== -1); }; updatePressed(); @@ -37,18 +36,24 @@ const TaggUserSelectionCell: React.FC<TaggUserSelectionCellProps> = ({ const handlePress = () => { // Add to selected list of users if (pressed === false) { - setSelectedUsers([...selectedUsers, item]); + setTags([ + ...tags, + { + id: '', + x: 50, + y: 50, + z: 1, + user: item, + }, + ]); } // Remove item from selected list of users else { - const filteredSelection = selectedUsers.filter( - (user) => user.id !== item.id, - ); - setSelectedUsers(filteredSelection); + setTags(tags.filter((tag) => tag.user.id !== item.id)); } }; return ( - <View style={styles.container}> + <TouchableWithoutFeedback onPress={handlePress} style={styles.container}> <View style={{width: SCREEN_WIDTH * 0.8}}> <ProfilePreview profilePreview={item} @@ -56,8 +61,8 @@ const TaggUserSelectionCell: React.FC<TaggUserSelectionCellProps> = ({ screenType={ScreenType.Profile} /> </View> - <TaggRadioButton pressed={pressed} onPress={handlePress} /> - </View> + <TaggRadioButton pressed={pressed} onPress={() => null} /> + </TouchableWithoutFeedback> ); }; diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 6953dca4..67c086d3 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -41,6 +41,8 @@ const MomentPostContent: React.FC<MomentPostContentProps> = ({ const navigation = useNavigation(); const dispatch = useDispatch(); const imageRef = useRef(null); + const [fadeValue, setFadeValue] = useState(new Animated.Value(0)); + const [visible, setVisible] = useState(false); const [fadeValue, setFadeValue] = useState<Animated.Value<number>>( new Animated.Value(0), diff --git a/src/components/moments/TagFriendsFoooter.tsx b/src/components/moments/TagFriendsFoooter.tsx index 7b109877..365d709d 100644 --- a/src/components/moments/TagFriendsFoooter.tsx +++ b/src/components/moments/TagFriendsFoooter.tsx @@ -1,39 +1,47 @@ import {useNavigation} from '@react-navigation/native'; -import React, {Dispatch, SetStateAction} from 'react'; -import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native'; +import React, {useMemo} from 'react'; +import { + Image, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native'; import {ProfilePreview} from '..'; -import {ProfilePreviewType, ScreenType} from '../../types'; -import {normalize} from '../../utils/layouts'; +import {MomentTagType, ProfilePreviewType, ScreenType} from '../../types'; +import {normalize, SCREEN_HEIGHT} from '../../utils/layouts'; interface TagFriendsFooterProps { - taggedUsers: ProfilePreviewType[]; - setTaggedUsers: Dispatch<SetStateAction<ProfilePreviewType[]>>; + tags: MomentTagType[]; + setTags: (tags: MomentTagType[]) => void; } -const TagFriendsFooter: React.FC<TagFriendsFooterProps> = ({ - taggedUsers, - setTaggedUsers, -}) => { +const TagFriendsFooter: React.FC<TagFriendsFooterProps> = ({tags, setTags}) => { const navigation = useNavigation(); const handleRemoveTag = (user: ProfilePreviewType) => { - const filteredSelection = taggedUsers.filter((item) => user.id !== item.id); - setTaggedUsers(filteredSelection); + setTags(tags.filter((tag) => tag.user.id !== user.id)); }; - const TaggMoreButton = () => ( - <TouchableOpacity - onPress={() => - navigation.navigate('TagSelectionScreen', { - selectedUsers: taggedUsers, - }) - } - style={styles.tagMoreContainer}> - <Image - source={require('../../assets/icons/tagging/white-plus-icon.png')} - style={styles.tagMoreIcon} - /> - <Text style={styles.tagMoreLabel}>{'Tagg More'}</Text> - </TouchableOpacity> + const goToSelectionScreen = () => { + navigation.navigate('TagSelectionScreen', { + selectedTags: tags, + }); + }; + + const taggMoreButton = useMemo( + () => ( + <TouchableOpacity + onPress={goToSelectionScreen} + style={styles.tagMoreContainer}> + <Image + source={require('../../assets/icons/tagging/white-plus-icon.png')} + style={styles.tagMoreIcon} + /> + <Text style={styles.tagMoreLabel}>{'Tagg More'}</Text> + </TouchableOpacity> + ), + [tags], ); const TaggedUser = (user: ProfilePreviewType) => ( @@ -59,31 +67,36 @@ const TagFriendsFooter: React.FC<TagFriendsFooterProps> = ({ * If taggUsers is empty, title acts as a button * Else, gets disabled and TaggMore button appears */ - const TagFriendsTitle = () => ( - <TouchableOpacity - style={styles.tagFriendsTitleContainer} - disabled={taggedUsers.length !== 0} - onPress={() => - navigation.navigate('TagSelectionScreen', { - selectedUsers: taggedUsers, - }) - }> - <Image - source={require('../../assets/icons/tagging/tag-icon.png')} - style={styles.tagIcon} - /> - <Text style={styles.tagFriendsTitle}>Tag Friends</Text> - </TouchableOpacity> + const tagFriendsTitle = useMemo( + () => ( + <TouchableOpacity + style={styles.tagFriendsTitleContainer} + disabled={tags.length !== 0} + onPress={() => + navigation.navigate('TagSelectionScreen', { + selectedTags: tags, + }) + }> + <Image + source={require('../../assets/icons/tagging/tag-icon.png')} + style={styles.tagIcon} + /> + <Text style={styles.tagFriendsTitle}>Tag Friends</Text> + </TouchableOpacity> + ), + [tags.length], ); return ( <> - <TagFriendsTitle /> + {tagFriendsTitle} <View style={styles.tagFriendsContainer}> - {taggedUsers.map((user) => ( - <TaggedUser {...user} /> - ))} - {taggedUsers.length !== 0 && <TaggMoreButton />} + <ScrollView horizontal> + {tags.map((tag) => ( + <TaggedUser key={tag.user.id} {...tag.user} /> + ))} + {tags.length !== 0 && taggMoreButton} + </ScrollView> </View> </> ); @@ -99,10 +112,9 @@ const styles = StyleSheet.create({ fontWeight: '600', }, tagFriendsContainer: { - flexDirection: 'row', - marginTop: '3%', - flexWrap: 'wrap', - justifyContent: 'flex-start', + height: SCREEN_HEIGHT * 0.1, + marginTop: 2, + marginBottom: 5, }, tagMoreLabel: { fontWeight: '500', @@ -111,7 +123,6 @@ const styles = StyleSheet.create({ letterSpacing: normalize(0.2), color: 'white', textAlign: 'center', - marginVertical: '5%', }, closeIconContainer: { width: 20, @@ -120,14 +131,25 @@ const styles = StyleSheet.create({ zIndex: 1, }, tagMoreContainer: { - flexDirection: 'column', + width: 60, alignItems: 'center', + justifyContent: 'flex-start', + marginTop: -12, + }, + tagMoreIcon: { + width: 38, + height: 38, + marginTop: 13, + marginBottom: '10%', + }, + taggedUserContainer: { + marginTop: -12, }, - tagMoreIcon: {width: 38, height: 38, top: -2}, - taggedUserContainer: {flexDirection: 'row-reverse'}, closeIcon: { width: 20, height: 20, + left: 15, + top: 10, }, tagFriendsTitleContainer: { flexDirection: 'row', diff --git a/src/components/profile/ProfilePreview.tsx b/src/components/profile/ProfilePreview.tsx index 88c075e2..dd93a5fd 100644 --- a/src/components/profile/ProfilePreview.tsx +++ b/src/components/profile/ProfilePreview.tsx @@ -377,10 +377,8 @@ const styles = StyleSheet.create({ }, tagSelectionContainer: { width: 60, - flexDirection: 'column', alignItems: 'center', justifyContent: 'flex-start', - margin: '1%', }, tagSelectionAvatar: { width: 34, @@ -389,7 +387,7 @@ const styles = StyleSheet.create({ }, tagSelectionNameContainer: { width: '100%', - marginVertical: '10%', + marginVertical: normalize(5), }, tagSelectionUsername: { fontWeight: '500', diff --git a/src/components/taggs/TaggDraggable.tsx b/src/components/taggs/TaggDraggable.tsx index 12e8e1e1..d458fab6 100644 --- a/src/components/taggs/TaggDraggable.tsx +++ b/src/components/taggs/TaggDraggable.tsx @@ -1,5 +1,5 @@ import {useNavigation} from '@react-navigation/native'; -import React, {useEffect, useRef} from 'react'; +import React from 'react'; import { Image, StyleSheet, @@ -7,6 +7,7 @@ import { TouchableOpacity, TouchableWithoutFeedback, View, + ViewProps, } from 'react-native'; import {useDispatch, useSelector} from 'react-redux'; import Avatar from '../../components/common/Avatar'; @@ -15,31 +16,23 @@ import {ProfilePreviewType, ScreenType, UserType} from '../../types'; import {normalize} from '../../utils'; import {navigateToProfile} from '../../utils/users'; -interface TaggDraggableProps { +interface TaggDraggableProps extends ViewProps { + draggableRef: React.MutableRefObject<null>; taggedUser: ProfilePreviewType; editingView: boolean; deleteFromList: () => void; - setStart: Function; } const TaggDraggable: React.FC<TaggDraggableProps> = ( props: TaggDraggableProps, ) => { + const {draggableRef, taggedUser, editingView, deleteFromList} = props; const navigation = useNavigation(); const dispatch = useDispatch(); const state = useSelector((rs: RootState) => rs); - const {taggedUser, editingView, deleteFromList, setStart} = props; let uriX = require('../../assets/images/draggableX.png'); let uriTip = require('../../assets/images/Tagg-Triangle.png'); - const draggableRef = useRef(null); - - useEffect(() => { - draggableRef.current.measure((width: number, height: number) => { - setStart([width, height]); - }); - }, []); - const user: UserType = { userId: taggedUser.id, username: taggedUser.username, diff --git a/src/routes/main/MainStackNavigator.tsx b/src/routes/main/MainStackNavigator.tsx index aeead38d..d22c1874 100644 --- a/src/routes/main/MainStackNavigator.tsx +++ b/src/routes/main/MainStackNavigator.tsx @@ -5,8 +5,8 @@ import {createStackNavigator} from '@react-navigation/stack'; import {Image} from 'react-native-image-crop-picker'; import { CommentBaseType, + MomentTagType, MomentType, - ProfilePreviewType, ScreenType, SearchCategoryType, } from '../../types'; @@ -40,7 +40,15 @@ export type MainStackParams = { title: string; image: Image; screenType: ScreenType; - selectedUsers?: ProfilePreviewType[]; + selectedTags?: MomentTagType[]; + }; + TagFriendsScreen: { + image: Image; + screenType: ScreenType; + selectedTags?: MomentTagType[]; + }; + TagSelectionScreen: { + selectedTags: MomentTagType[]; }; IndividualMoment: { moment: MomentType; @@ -99,14 +107,6 @@ export type MainStackParams = { ChatList: undefined; Chat: undefined; NewChatModal: undefined; - TagSelectionScreen: { - selectedUsers: ProfilePreviewType[]; - }; - TagFriendsScreen: { - image: Image; - screenType: ScreenType; - selectedUsers?: ProfilePreviewType[]; - }; }; export const MainStack = createStackNavigator<MainStackParams>(); diff --git a/src/screens/moments/TagFriendsScreen.tsx b/src/screens/moments/TagFriendsScreen.tsx index b2a8586a..d960f3b9 100644 --- a/src/screens/moments/TagFriendsScreen.tsx +++ b/src/screens/moments/TagFriendsScreen.tsx @@ -19,7 +19,7 @@ import { } from '../../components'; import {TagFriendsFooter} from '../../components/moments'; import {TAGG_LIGHT_BLUE_2} from '../../constants'; -import {ProfilePreviewType} from '../../types'; +import {MomentTagType} from '../../types'; import {SCREEN_WIDTH, StatusBarHeight} from '../../utils'; type TagFriendsScreenRouteProps = RouteProp< @@ -30,19 +30,17 @@ interface TagFriendsScreenProps { route: TagFriendsScreenRouteProps; } const TagFriendsScreen: React.FC<TagFriendsScreenProps> = ({route}) => { - const {image, selectedUsers} = route.params; + const {image, selectedTags} = route.params; const navigation = useNavigation(); const imageRef = useRef(null); - const [taggedUsers, setTaggedUsers] = useState<ProfilePreviewType[]>([]); + const [tags, setTags] = useState<MomentTagType[]>([]); /* * Update list of tagged users from route params */ useEffect(() => { - if (selectedUsers !== undefined) { - setTaggedUsers(selectedUsers); - } - }, [selectedUsers]); + setTags(selectedTags ? selectedTags : []); + }, [selectedTags]); /* * Navigate back to Tag Users Screen, send selected users @@ -50,7 +48,7 @@ const TagFriendsScreen: React.FC<TagFriendsScreenProps> = ({route}) => { const handleDone = () => { navigation.navigate('CaptionScreen', { ...route.params, - selectedUsers: taggedUsers, + selectedTags: tags, }); }; @@ -79,7 +77,7 @@ const TagFriendsScreen: React.FC<TagFriendsScreenProps> = ({route}) => { title={'Tap on photo to Tag friends!'} /> <TouchableWithoutFeedback - disabled={taggedUsers.length > 0} + disabled={tags.length > 0} onPress={() => navigation.navigate('TagSelectionScreen', { selectedUsers: [], @@ -92,26 +90,19 @@ const TagFriendsScreen: React.FC<TagFriendsScreenProps> = ({route}) => { resizeMode={'cover'} /> </TouchableWithoutFeedback> - {taggedUsers.length !== 0 && ( + {tags.length !== 0 && ( <MomentTags + tags={tags} + setTags={setTags} editing={true} - tags={taggedUsers.map((user) => ({ - id: '', - x: 0, - y: 0, - user, - }))} imageRef={imageRef} deleteFromList={(user) => - setTaggedUsers(taggedUsers.filter((u) => u.id !== user.id)) + setTags(tags.filter((tag) => tag.user.id !== user.id)) } /> )} <View style={styles.footerContainer}> - <TagFriendsFooter - taggedUsers={taggedUsers} - setTaggedUsers={setTaggedUsers} - /> + <TagFriendsFooter tags={tags} setTags={setTags} /> </View> </View> </KeyboardAvoidingView> diff --git a/src/screens/moments/TagSelectionScreen.tsx b/src/screens/moments/TagSelectionScreen.tsx index a698a07b..3177b638 100644 --- a/src/screens/moments/TagSelectionScreen.tsx +++ b/src/screens/moments/TagSelectionScreen.tsx @@ -9,7 +9,7 @@ import {SearchBar, TaggUserSelectionCell} from '../../components'; import {SEARCH_ENDPOINT_MESSAGES} from '../../constants'; import {MainStackParams} from '../../routes'; import {loadSearchResults} from '../../services'; -import {ProfilePreviewType} from '../../types'; +import {MomentTagType, ProfilePreviewType} from '../../types'; import { isIPhoneX, loadTaggUserSuggestions, @@ -30,9 +30,7 @@ interface TagSelectionScreenProps { const TagSelectionScreen: React.FC<TagSelectionScreenProps> = ({route}) => { const navigation = useNavigation(); const [users, setUsers] = useState<ProfilePreviewType[]>([]); - const [selectedUsers, setSelectedUsers] = useState<ProfilePreviewType[]>( - route.params.selectedUsers, - ); + const [tags, setTags] = useState<MomentTagType[]>(route.params.selectedTags); const [searching, setSearching] = useState(false); const [query, setQuery] = useState<string>(''); const [label, setLabel] = useState<string>('Recent'); @@ -48,7 +46,7 @@ const TagSelectionScreen: React.FC<TagSelectionScreenProps> = ({route}) => { onPress={() => { navigation.navigate('TagFriendsScreen', { ...route.params, - selectedUsers: selectedUsers, + selectedTags: tags, }); }}> <BackIcon @@ -67,12 +65,12 @@ const TagSelectionScreen: React.FC<TagSelectionScreenProps> = ({route}) => { * that the loggedInUser might want to select */ const loadUsers = async () => { - const data: ProfilePreviewType[] = await loadTaggUserSuggestions(); + const data = await loadTaggUserSuggestions(); const filteredData: ProfilePreviewType[] = data.filter((user) => { - const index = selectedUsers.findIndex((s) => s.id === user.id); + const index = tags.findIndex((tag) => tag.user.id === user.id); return index === -1; }); - setUsers([...filteredData, ...selectedUsers]); + setUsers([...filteredData, ...tags.map((tag) => tag.user)]); }; /* @@ -83,7 +81,7 @@ const TagSelectionScreen: React.FC<TagSelectionScreenProps> = ({route}) => { const searchResults = await loadSearchResults( `${SEARCH_ENDPOINT_MESSAGES}?query=${query}`, ); - setUsers(searchResults?.users); + setUsers(searchResults ? searchResults.users : []); } else { setUsers([]); } @@ -130,8 +128,8 @@ const TagSelectionScreen: React.FC<TagSelectionScreenProps> = ({route}) => { <TaggUserSelectionCell key={item.item.id} item={item.item} - selectedUsers={selectedUsers} - setSelectedUsers={setSelectedUsers} + tags={tags} + setTags={setTags} /> )} /> diff --git a/src/screens/profile/CaptionScreen.tsx b/src/screens/profile/CaptionScreen.tsx index 43665428..8bffd82b 100644 --- a/src/screens/profile/CaptionScreen.tsx +++ b/src/screens/profile/CaptionScreen.tsx @@ -29,7 +29,7 @@ import { updateProfileCompletionStage, } from '../../store/actions'; import {RootState} from '../../store/rootReducer'; -import {ProfilePreviewType} from '../../types'; +import {MomentTagType} from '../../types'; import {SCREEN_WIDTH, StatusBarHeight} from '../../utils'; import {mentionPartTypes} from '../../utils/comments'; @@ -47,26 +47,26 @@ interface CaptionScreenProps { } const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { - const {title, image, screenType, selectedUsers} = route.params; + const {title, image, screenType, selectedTags} = route.params; const { user: {userId}, } = useSelector((state: RootState) => state.user); const dispatch = useDispatch(); const [caption, setCaption] = useState(''); const [loading, setLoading] = useState(false); - const [taggedUsers, setTaggedUsers] = useState<ProfilePreviewType[]>([]); + const [tags, setTags] = useState<MomentTagType[]>([]); const [taggedList, setTaggedList] = useState<string>(''); useEffect(() => { - setTaggedUsers(selectedUsers ? selectedUsers : []); - }, [route.params]); + setTags(selectedTags ? selectedTags : []); + }, [selectedTags]); useEffect(() => { const getTaggedUsersListString = () => { let listString = ''; - for (let i = 0; i < taggedUsers.length; i++) { + for (let i = 0; i < tags.length; i++) { if (listString.length < 21) { - listString = listString.concat(`@${taggedUsers[i].username} `); + listString = listString.concat(`@${tags[i].user.username} `); } else { break; } @@ -74,7 +74,7 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { setTaggedList(listString); }; getTaggedUsersListString(); - }, [taggedUsers]); + }, [tags]); const navigateToProfile = () => { //Since the logged In User is navigating to own profile, useXId is not required @@ -115,10 +115,11 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { } const momentTagResponse = await postMomentTags( momentResponse.moment_id, - taggedUsers.map((u, index) => ({ - x: index * 50 - 150, - y: index * 50 - 150, - user_id: u.id, + tags.map((tag) => ({ + x: Math.floor(tag.x), + y: Math.floor(tag.y), + z: Math.floor(tag.z), + user_id: tag.user.id, })), ); if (!momentTagResponse) { @@ -173,7 +174,7 @@ const CaptionScreen: React.FC<CaptionScreenProps> = ({route, navigation}) => { navigation.navigate('TagFriendsScreen', { image: image, screenType: screenType, - selectedUsers: taggedUsers, + selectedTags: tags, }) } style={styles.tagFriendsContainer}> diff --git a/src/services/MomentService.ts b/src/services/MomentService.ts index 46b55066..423d962c 100644 --- a/src/services/MomentService.ts +++ b/src/services/MomentService.ts @@ -147,6 +147,7 @@ export const postMomentTags = async ( tags: { x: number; y: number; + z: number; user_id: string; }[], ) => { @@ -155,16 +156,13 @@ export const postMomentTags = async ( const form = new FormData(); form.append('moment_id', moment_id); form.append('tags', JSON.stringify(tags)); - const response = await fetch( - MOMENTTAG_ENDPOINT + `?moment_id=${moment_id}`, - { - method: 'POST', - headers: { - Authorization: 'Token ' + token, - }, - body: form, + const response = await fetch(MOMENTTAG_ENDPOINT, { + method: 'POST', + headers: { + Authorization: 'Token ' + token, }, - ); + body: form, + }); return response.status === 201 || response.status === 200; } catch (error) { console.error(error); diff --git a/src/services/SearchService.ts b/src/services/SearchService.ts index 7b97f9a7..672c1ec6 100644 --- a/src/services/SearchService.ts +++ b/src/services/SearchService.ts @@ -1,4 +1,5 @@ import AsyncStorage from '@react-native-community/async-storage'; +import {ProfilePreviewType} from '../types'; export const loadSearchResults = async (url: string) => { try { @@ -11,12 +12,14 @@ export const loadSearchResults = async (url: string) => { }); const {status} = response; if (status === 200) { - const searchResults = await response.json(); + const searchResults: { + users: ProfilePreviewType[]; + } = await response.json(); return searchResults; } } catch (error) { console.log(error); - throw error; + return undefined; } - return {}; + return undefined; }; diff --git a/src/types/types.ts b/src/types/types.ts index e957483b..b294e3f1 100644 --- a/src/types/types.ts +++ b/src/types/types.ts @@ -123,6 +123,7 @@ export interface MomentTagType { user: ProfilePreviewType; x: number; y: number; + z: number; } export interface CommentBaseType { diff --git a/src/utils/search.ts b/src/utils/search.ts index 789acbc3..c3246c41 100644 --- a/src/utils/search.ts +++ b/src/utils/search.ts @@ -147,5 +147,5 @@ export const loadTaggUserSuggestions = async (): Promise< ProfilePreviewType[] > => { const searchResults = await loadSearchResults(`${SEARCH_ENDPOINT_SUGGESTED}`); - return searchResults?.users; + return searchResults ? searchResults.users : []; }; |