aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/assets/ionicons/trash-outline.svg1
-rw-r--r--src/components/comments/CommentTile.tsx115
-rw-r--r--src/components/comments/CommentsContainer.tsx14
-rw-r--r--src/constants/strings.ts2
-rw-r--r--src/services/CommentService.ts18
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;
+ }
+};