diff options
author | Ivan Chen <ivan@tagg.id> | 2021-01-27 16:15:00 -0500 |
---|---|---|
committer | Ivan Chen <ivan@tagg.id> | 2021-01-27 16:15:00 -0500 |
commit | fb69ccebb05d2ec54d85576d23989e7309349830 (patch) | |
tree | 35a4997f848bfc681bb50bd2eebb397ba85026e5 /src | |
parent | 3cbfdc6026ef886b7919181b69a2f252723a6bd8 (diff) |
finished delete
Diffstat (limited to 'src')
-rw-r--r-- | src/assets/ionicons/trash-outline.svg | 1 | ||||
-rw-r--r-- | src/components/comments/CommentTile.tsx | 115 | ||||
-rw-r--r-- | src/components/comments/CommentsContainer.tsx | 14 | ||||
-rw-r--r-- | src/constants/strings.ts | 2 | ||||
-rw-r--r-- | src/services/CommentService.ts | 18 |
5 files changed, 114 insertions, 36 deletions
diff --git a/src/assets/ionicons/trash-outline.svg b/src/assets/ionicons/trash-outline.svg new file mode 100644 index 00000000..4920b56a --- /dev/null +++ b/src/assets/ionicons/trash-outline.svg @@ -0,0 +1 @@ +<svg xmlns='http://www.w3.org/2000/svg' class='ionicon' viewBox='0 0 512 512'><title>Trash</title><path d='M112 112l20 320c.95 18.49 14.4 32 32 32h184c17.67 0 30.87-13.51 32-32l20-320' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='32'/><path stroke='currentColor' stroke-linecap='round' stroke-miterlimit='10' stroke-width='32' d='M80 112h352'/><path d='M192 112V72h0a23.93 23.93 0 0124-24h80a23.93 23.93 0 0124 24h0v40M256 176v224M184 176l8 224M328 176l-8 224' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='32'/></svg>
\ No newline at end of file diff --git a/src/components/comments/CommentTile.tsx b/src/components/comments/CommentTile.tsx index 39605f2c..e12276a9 100644 --- a/src/components/comments/CommentTile.tsx +++ b/src/components/comments/CommentTile.tsx @@ -1,14 +1,18 @@ -import React, {useState} from 'react'; +import React, {Fragment, useRef, useState} from 'react'; import {Text, View} from 'react-native-animatable'; import {ProfilePreview} from '../profile'; import {CommentType, ScreenType, TypeOfComment} from '../../types'; -import {StyleSheet} from 'react-native'; +import {Alert, Animated, StyleSheet} from 'react-native'; import ClockIcon from '../../assets/icons/clock-icon-01.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; -import {TouchableOpacity} from 'react-native-gesture-handler'; +import {RectButton, TouchableOpacity} from 'react-native-gesture-handler'; import {getTimePosted, normalize, SCREEN_WIDTH} from '../../utils'; import Arrow from '../../assets/icons/back-arrow-colored.svg'; +import Trash from '../../assets/ionicons/trash-outline.svg'; import CommentsContainer from './CommentsContainer'; +import Swipeable from 'react-native-gesture-handler/Swipeable'; +import {deleteComment} from '../../services'; +import {ERROR_FAILED_TO_DELETE_COMMENT} from '../../constants/strings'; /** * Displays users's profile picture, comment posted by them and the time difference between now and when a comment was posted. @@ -19,6 +23,8 @@ interface CommentTileProps { screenType: ScreenType; typeOfComment: TypeOfComment; setCommentObjectInFocus?: (comment: CommentType | undefined) => void; + setNewCommentsAvailable: (available: boolean) => void; + canDelete: boolean; } const CommentTile: React.FC<CommentTileProps> = ({ @@ -26,9 +32,13 @@ const CommentTile: React.FC<CommentTileProps> = ({ screenType, typeOfComment, setCommentObjectInFocus, + setNewCommentsAvailable, + canDelete, }) => { const timePosted = getTimePosted(comment_object.date_created); const [showReplies, setShowReplies] = useState<boolean>(false); + const swipeRef = useRef<Swipeable>(null); + const isThread = typeOfComment === 'Thread'; /** * Case : A COMMENT IS IN FOCUS && REPLY SECTION IS HIDDEN @@ -58,13 +68,46 @@ const CommentTile: React.FC<CommentTileProps> = ({ ? `Replies (${comment_object.replies_count})` : 'Replies'; + const renderRightAction = (text: string, color: string, progress) => { + const pressHandler = async () => { + swipeRef.current?.close(); + const success = await deleteComment(comment_object.comment_id, isThread); + if (success) { + setNewCommentsAvailable(true); + } else { + Alert.alert(ERROR_FAILED_TO_DELETE_COMMENT); + } + }; + return ( + <Animated.View> + <RectButton + style={[styles.rightAction, {backgroundColor: color}]} + onPress={pressHandler}> + <Trash width={normalize(25)} height={normalize(25)} color={'white'} /> + <Text style={styles.actionText}>{text}</Text> + </RectButton> + </Animated.View> + ); + }; + + const renderRightActions = (progress) => + canDelete ? ( + <View style={styles.swipeActions}> + {renderRightAction('Delete', '#c42634', progress)} + </View> + ) : ( + <Fragment /> + ); + return ( - <> + <Swipeable + ref={swipeRef} + renderRightActions={renderRightActions} + rightThreshold={40} + friction={2} + containerStyle={styles.swipableContainer}> <View - style={[ - styles.container, - typeOfComment === 'Thread' ? styles.moreMarginWithThread : {}, - ]}> + style={[styles.container, isThread ? styles.moreMarginWithThread : {}]}> <ProfilePreview profilePreview={{ id: comment_object.commenter.id, @@ -104,40 +147,40 @@ const CommentTile: React.FC<CommentTileProps> = ({ {/*** Show replies if toggle state is true */} {showReplies && ( - <View - style={{ - width: SCREEN_WIDTH, - }}> - <CommentsContainer - objectId={comment_object.comment_id} - screenType={screenType} - setNewCommentsAvailable={() => {}} - newCommentsAvailable={true} - typeOfComment={'Thread'} - /> - </View> + <CommentsContainer + objectId={comment_object.comment_id} + screenType={screenType} + setNewCommentsAvailable={() => {}} + newCommentsAvailable={true} + typeOfComment={'Thread'} + /> )} - </> + </Swipeable> ); }; const styles = StyleSheet.create({ container: { - marginHorizontal: '3%', borderBottomWidth: 1, borderColor: 'lightgray', - marginBottom: '3%', + backgroundColor: 'white', + paddingTop: '3%', flexDirection: 'column', flex: 1, + marginLeft: '7%', + }, + swipeActions: { + flexDirection: 'row', }, moreMarginWithThread: { - marginHorizontal: '7%', + marginLeft: '14%', }, body: { marginLeft: 56, }, comment: { marginBottom: '2%', + marginRight: '2%', top: -5, }, date_time: { @@ -153,35 +196,47 @@ const styles = StyleSheet.create({ flexDirection: 'row', marginBottom: '3%', }, - flexer: { flex: 1, }, - repliesTextAndIconContainer: { flexDirection: 'row', alignItems: 'center', }, - repliesText: { color: TAGG_LIGHT_BLUE, fontWeight: '500', fontSize: normalize(12), - marginRight: '3%', + marginRight: '5%', }, repliesBody: { width: SCREEN_WIDTH, }, - repliesDownArrow: { transform: [{rotate: '270deg'}], marginTop: '7%', }, - repliesUpArrow: { transform: [{rotate: '90deg'}], marginTop: '7%', }, + actionText: { + color: 'white', + fontSize: normalize(12), + fontWeight: '500', + backgroundColor: 'transparent', + paddingHorizontal: '5%', + marginTop: '5%', + }, + rightAction: { + alignItems: 'center', + flex: 1, + justifyContent: 'center', + flexDirection: 'column', + }, + swipableContainer: { + backgroundColor: 'white', + }, }); export default CommentTile; diff --git a/src/components/comments/CommentsContainer.tsx b/src/components/comments/CommentsContainer.tsx index 0a19694b..fd4b32af 100644 --- a/src/components/comments/CommentsContainer.tsx +++ b/src/components/comments/CommentsContainer.tsx @@ -1,9 +1,10 @@ -import React, {useRef, useEffect, useState} from 'react'; +import React, {useEffect, useRef, useState} from 'react'; import {StyleSheet} from 'react-native'; import {ScrollView} from 'react-native-gesture-handler'; -import {useDispatch} from 'react-redux'; +import {useDispatch, useSelector} from 'react-redux'; import {CommentTile} from '.'; import {getComments} from '../../services'; +import {RootState} from '../../store/rootReducer'; import {CommentType, ScreenType, TypeOfComment} from '../../types'; export type CommentsContainerProps = { screenType: ScreenType; @@ -32,6 +33,9 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({ setCommentObjectInFocus, commentObjectInFocus, }) => { + const {username: loggedInUsername} = useSelector( + (state: RootState) => state.user.user, + ); const [commentsList, setCommentsList] = useState<CommentType[]>([]); const dispatch = useDispatch(); const ref = useRef<ScrollView>(null); @@ -79,6 +83,8 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({ screenType={screenType} typeOfComment={typeOfComment} setCommentObjectInFocus={setCommentObjectInFocus} + setNewCommentsAvailable={setNewCommentsAvailable} + canDelete={comment.commenter.username === loggedInUsername} /> ))} </ScrollView> @@ -86,9 +92,7 @@ const CommentsContainer: React.FC<CommentsContainerProps> = ({ }; const styles = StyleSheet.create({ - scrollView: { - paddingHorizontal: 20, - }, + scrollView: {}, scrollViewContent: { justifyContent: 'center', }, diff --git a/src/constants/strings.ts b/src/constants/strings.ts index 77ded7be..d3c81622 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -1,4 +1,3 @@ - /* eslint-disable */ // Below is the regex to convert this into a csv for the Google Sheet // export const (.*) = .*?(['|"|`])(.*)\2; @@ -15,6 +14,7 @@ export const ERROR_DUP_OLD_PWD = 'You may not use a previously used password'; export const ERROR_EMAIL_IN_USE = 'Email already in use, please try another one'; export const ERROR_FAILED_LOGIN_INFO = 'Login failed, please try re-entering your login information'; export const ERROR_FAILED_TO_COMMENT = 'Unable to post comment, refresh and try again!'; +export const ERROR_FAILED_TO_DELETE_COMMENT = 'Unable to delete comment, refresh and try again!'; export const ERROR_INVALID_INVITATION_CODE = 'Invitation code invalid, try again or talk to the friend that sent it 😬'; export const ERROR_INVALID_LOGIN = 'Invalid login, Please login again'; export const ERROR_INVALID_PWD_CODE = 'Looks like you have entered the wrong code, please try again'; diff --git a/src/services/CommentService.ts b/src/services/CommentService.ts index 3baf0305..a9a01d77 100644 --- a/src/services/CommentService.ts +++ b/src/services/CommentService.ts @@ -99,3 +99,21 @@ export const getCommentsCount = async ( } return comments_count; }; + +export const deleteComment = async (id: string, isThread: boolean) => { + try { + const token = await AsyncStorage.getItem('token'); + const url = isThread ? COMMENT_THREAD_ENDPOINT : COMMENTS_ENDPOINT; + const response = await fetch(url + `${id}/`, { + method: 'DELETE', + headers: { + Authorization: 'Token ' + token, + }, + }); + return response.status === 200; + } catch (error) { + console.log('Failed to delete a comment'); + console.log(error); + return false; + } +}; |