Skip to content

Commit

Permalink
[PAY-1516] Chat report abuse flow (#3636)
Browse files Browse the repository at this point in the history
  • Loading branch information
dharit-tan authored Jun 22, 2023
1 parent 82204ec commit 394cacb
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 28 deletions.
19 changes: 19 additions & 0 deletions packages/common/src/store/pages/chat/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const {
fetchBlockersSucceeded,
unblockUser,
blockUser,
reportUser,
fetchPermissions,
fetchPermissionsSucceeded,
fetchLinkUnfurl,
Expand Down Expand Up @@ -517,6 +518,19 @@ function* doUnblockUser(action: ReturnType<typeof unblockUser>) {
}
}

function* doReportUser(action: ReturnType<typeof reportUser>) {
try {
console.log('reportUser', action.payload)
} catch (e) {
console.error('reportUserFailed', e)
const reportToSentry = yield* getContext('reportToSentry')
reportToSentry({
level: ErrorLevel.Error,
error: e as Error
})
}
}

function* doFetchPermissions(action: ReturnType<typeof fetchPermissions>) {
try {
const currentUserId = yield* select(getUserId)
Expand Down Expand Up @@ -667,6 +681,10 @@ function* watchUnblockUser() {
yield takeEvery(unblockUser, doUnblockUser)
}

function* watchReportUser() {
yield takeEvery(reportUser, doReportUser)
}

function* watchFetchPermissions() {
yield takeEvery(fetchPermissions, doFetchPermissions)
}
Expand Down Expand Up @@ -694,6 +712,7 @@ export const sagas = () => {
watchFetchBlockers,
watchBlockUser,
watchUnblockUser,
watchReportUser,
watchFetchPermissions,
watchFetchLinkUnfurlMetadata,
watchDeleteChat
Expand Down
3 changes: 3 additions & 0 deletions packages/common/src/store/pages/chat/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,9 @@ const slice = createSlice({
unblockUser: (_state, _action: PayloadAction<{ userId: ID }>) => {
// triggers saga
},
reportUser: (_state, _action: PayloadAction<{ userId: ID }>) => {
// triggers saga
},
fetchPermissions: (_state, _action: PayloadAction<{ userIds: ID[] }>) => {
// triggers saga
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ import { useColor } from 'app/utils/theme'

const { getUser } = cacheUsersSelectors
const { getDoesBlockUser, getCanCreateChat } = chatSelectors
const { blockUser, unblockUser, createChat } = chatActions
const { blockUser, unblockUser, createChat, reportUser } = chatActions

const BLOCK_MESSAGES_MODAL_NAME = 'BlockMessages'

const messages = {
title: 'Are you sure?',
confirmBlock: (userName?: string) => (
confirmBlock: (userName?: string, isReportAbuse?: boolean) => (
<>
{'Are you sure you want to block '}
{'Are you sure you want to '}
{isReportAbuse ? 'report ' : 'block '}
{userName}
{' from sending messages to your inbox? '}
{isReportAbuse
? ' for abuse? They will be blocked from sending you new messages.'
: ' from sending messages to your inbox?'}
</>
),
confirmUnblock: (userName?: string) => (
Expand All @@ -39,6 +42,7 @@ const messages = {
info: 'This will not affect their ability to view your profile or interact with your content.',
blockUser: 'Block User',
unblockUser: 'Unblock User',
reportUser: 'Report & Block',
cancel: 'Cancel'
}

Expand Down Expand Up @@ -106,7 +110,7 @@ export const BlockMessagesDrawer = () => {
const neutral = useColor('neutral')
const dispatch = useDispatch()
const { data } = useDrawer('BlockMessages')
const { userId, shouldOpenChat } = data
const { userId, shouldOpenChat, isReportAbuse } = data
const user = useSelector((state) => getUser(state, { id: userId }))
// Assuming blockees have already been fetched in ProfileActionsDrawer.
const doesBlockUser = useSelector((state) => getDoesBlockUser(state, userId))
Expand All @@ -122,14 +126,24 @@ export const BlockMessagesDrawer = () => {
}
} else {
dispatch(blockUser({ userId }))
if (isReportAbuse) {
dispatch(reportUser({ userId }))
}
}
dispatch(
setVisibility({
drawer: 'BlockMessages',
visible: false
})
)
}, [canCreateChat, dispatch, doesBlockUser, shouldOpenChat, userId])
}, [
canCreateChat,
dispatch,
doesBlockUser,
isReportAbuse,
shouldOpenChat,
userId
])

const handleCancelPress = useCallback(() => {
dispatch(
Expand All @@ -150,7 +164,7 @@ export const BlockMessagesDrawer = () => {
<Text style={styles.confirm}>
{doesBlockUser
? messages.confirmUnblock(user?.name)
: messages.confirmBlock(user?.name)}
: messages.confirmBlock(user?.name, isReportAbuse)}
</Text>
{doesBlockUser ? null : (
<View style={styles.infoContainer}>
Expand All @@ -164,7 +178,13 @@ export const BlockMessagesDrawer = () => {
</View>
)}
<Button
title={doesBlockUser ? messages.unblockUser : messages.blockUser}
title={
isReportAbuse
? messages.reportUser
: doesBlockUser
? messages.unblockUser
: messages.blockUser
}
onPress={handleConfirmPress}
variant={doesBlockUser ? 'primary' : 'destructive'}
styles={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const messages = {
visitProfile: 'Visit Profile',
blockMessages: 'Block Messages',
unblockMessages: 'Unblock Messages',
reportAbuse: 'Report Abuse',
deleteConversation: 'Delete Conversation'
}

Expand Down Expand Up @@ -81,6 +82,17 @@ export const ChatActionsDrawer = () => {
)
}, [closeDrawer, dispatch, userId])

const handleReportPress = useCallback(() => {
closeDrawer()
dispatch(
setVisibility({
drawer: 'BlockMessages',
visible: true,
data: { userId, isReportAbuse: true }
})
)
}, [closeDrawer, dispatch, userId])

const handleDeletePress = useCallback(() => {
closeDrawer()
dispatch(
Expand Down Expand Up @@ -109,6 +121,11 @@ export const ChatActionsDrawer = () => {
</Text>
</TouchableOpacity>
</View>
<View style={styles.row}>
<TouchableOpacity onPress={handleReportPress}>
<Text style={styles.text}>{messages.reportAbuse}</Text>
</TouchableOpacity>
</View>
<View style={styles.row}>
<TouchableOpacity onPress={handleDeletePress}>
<Text style={[styles.text, styles.deleteText]}>
Expand Down
6 changes: 5 additions & 1 deletion packages/mobile/src/store/drawers/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ export type DrawerData = {
ChatActions: { userId: number; chatId: string }
CreateChatActions: { userId: number }
ProfileActions: undefined
BlockMessages: { userId: number; shouldOpenChat: boolean }
BlockMessages: {
userId: number
shouldOpenChat: boolean
isReportAbuse: boolean
}
DeleteChat: { chatId: string }
SupportersInfo: undefined
InboxUnavailable: { userId: number; shouldOpenChat: boolean }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,20 @@ import { UserNameAndBadges } from 'components/user-name-and-badges/UserNameAndBa

import styles from './BlockUserConfirmationModal.module.css'

const { blockUser } = chatActions
const { blockUser, reportUser } = chatActions

const messages = {
title: 'Are you sure?',
confirm: 'Block User',
confirmBlock: 'Block User',
confirmReport: 'Report & Block',
cancel: 'Cancel',
content: (user: User) => (
content: (user: User, isReport?: boolean) => (
<>
Are you sure you want to block <UserNameAndBadges user={user} /> from
sending messages to your inbox?
Are you sure you want to {isReport ? 'report' : 'block'}{' '}
<UserNameAndBadges user={user} />{' '}
{isReport
? 'for abuse? They will be blocked from sending you new messages.'
: 'from sending messages to your inbox?'}
</>
),
callout:
Expand All @@ -39,18 +43,23 @@ type BlockUserConfirmationModalProps = {
isVisible: boolean
onClose: () => void
user: User
isReportAbuse?: boolean
}

export const BlockUserConfirmationModal = ({
isVisible,
onClose,
user
user,
isReportAbuse
}: BlockUserConfirmationModalProps) => {
const dispatch = useDispatch()
const handleConfirmClicked = useCallback(() => {
dispatch(blockUser({ userId: user.user_id }))
if (isReportAbuse) {
dispatch(reportUser({ userId: user.user_id }))
}
onClose()
}, [dispatch, onClose, user])
}, [dispatch, isReportAbuse, onClose, user.user_id])

return (
<Modal bodyClassName={styles.root} isOpen={isVisible} onClose={onClose}>
Expand All @@ -62,7 +71,7 @@ export const BlockUserConfirmationModal = ({
/>
</ModalHeader>
<ModalContent className={styles.content}>
<div>{messages.content(user)}</div>
<div>{messages.content(user, isReportAbuse)}</div>
<HelpCallout icon={<IconInfo />} content={messages.callout} />
</ModalContent>
<ModalFooter className={styles.footer}>
Expand All @@ -75,7 +84,7 @@ export const BlockUserConfirmationModal = ({
<Button
className={styles.button}
type={ButtonType.DESTRUCTIVE}
text={messages.confirm}
text={isReportAbuse ? messages.confirmReport : messages.confirmBlock}
onClick={handleConfirmClicked}
/>
</ModalFooter>
Expand Down
39 changes: 29 additions & 10 deletions packages/web/src/pages/chat-page/components/ChatHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
IconBlockMessages,
IconUnblockMessages,
IconUser,
IconTrash
IconTrash,
IconError
} from '@audius/stems'
import { push as pushRoute } from 'connected-react-router'
import { useDispatch, useSelector } from 'react-redux'
Expand All @@ -32,6 +33,7 @@ const messages = {
chatSettings: 'Chat Settings',
block: 'Block Messages',
unblock: 'Unblock Messages',
report: 'Report Abuse',
delete: 'Delete Conversation',
visit: "Visit User's Profile"
}
Expand All @@ -57,6 +59,7 @@ export const ChatHeader = forwardRef<HTMLDivElement, ChatHeaderProps>(
useState(false)
const [isBlockUserModalVisible, setIsBlockUserModalVisible] =
useState(false)
const [isReportAbuse, setIsReportAbuse] = useState(false)
const [isDeleteChatModalVisible, setIsDeleteChatModalVisible] =
useState(false)
const users = useProxySelector(
Expand All @@ -83,6 +86,16 @@ export const ChatHeader = forwardRef<HTMLDivElement, ChatHeaderProps>(
setIsBlockUserModalVisible(true)
}, [setIsBlockUserModalVisible])

const handleReportClicked = useCallback(() => {
setIsReportAbuse(true)
setIsBlockUserModalVisible(true)
}, [setIsReportAbuse])

const handleCloseBlockModal = useCallback(() => {
setIsReportAbuse(false)
setIsBlockUserModalVisible(false)
}, [setIsReportAbuse])

const handleVisitClicked = useCallback(() => {
dispatch(pushRoute(profilePage(user.handle)))
}, [dispatch, user])
Expand All @@ -92,6 +105,16 @@ export const ChatHeader = forwardRef<HTMLDivElement, ChatHeaderProps>(
}, [setIsDeleteChatModalVisible])

const overflowItems = [
{
text: messages.delete,
icon: <IconTrash />,
onClick: handleDeleteClicked
},
{
text: messages.visit,
icon: <IconUser />,
onClick: handleVisitClicked
},
isBlocked
? {
text: messages.unblock,
Expand All @@ -104,14 +127,9 @@ export const ChatHeader = forwardRef<HTMLDivElement, ChatHeaderProps>(
onClick: handleBlockClicked
},
{
text: messages.delete,
icon: <IconTrash />,
onClick: handleDeleteClicked
},
{
text: messages.visit,
icon: <IconUser />,
onClick: handleVisitClicked
text: messages.report,
icon: <IconError />,
onClick: handleReportClicked
}
]

Expand Down Expand Up @@ -164,7 +182,8 @@ export const ChatHeader = forwardRef<HTMLDivElement, ChatHeaderProps>(
<BlockUserConfirmationModal
user={user}
isVisible={isBlockUserModalVisible}
onClose={() => setIsBlockUserModalVisible(false)}
onClose={handleCloseBlockModal}
isReportAbuse={isReportAbuse}
/>
<DeleteChatConfirmationModal
chatId={currentChatId}
Expand Down

0 comments on commit 394cacb

Please sign in to comment.