diff --git a/app/soapbox/features/chats/components/chat-composer.tsx b/app/soapbox/features/chats/components/chat-composer.tsx index 2ad75e51a5..6d09d1e12c 100644 --- a/app/soapbox/features/chats/components/chat-composer.tsx +++ b/app/soapbox/features/chats/components/chat-composer.tsx @@ -1,13 +1,23 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import { HStack, IconButton, Stack, Text, Textarea } from 'soapbox/components/ui'; +import { unblockAccount } from 'soapbox/actions/accounts'; +import { openModal } from 'soapbox/actions/modals'; +import { Button, HStack, IconButton, Stack, Text, Textarea } from 'soapbox/components/ui'; +import { useChatContext } from 'soapbox/contexts/chat-context'; +import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; const messages = defineMessages({ placeholder: { id: 'chat.input.placeholder', defaultMessage: 'Type a message' }, send: { id: 'chat.actions.send', defaultMessage: 'Send' }, failedToSend: { id: 'chat.failed_to_send', defaultMessage: 'Message failed to send.' }, retry: { id: 'chat.retry', defaultMessage: 'Retry?' }, + blockedBy: { id: 'chat_message_list.blockedBy', defaultMessage: 'You are blocked by' }, + blocked: { id: 'chat_message_list.blocked', defaultMessage: 'You blocked this user' }, + unblock: { id: 'chat_composer.unblock', defaultMessage: 'Unblock' }, + unblockMessage: { id: 'chat_settings.unblock.message', defaultMessage: 'Unblocking will allow you to resume messaging with the user.' }, + unblockHeading: { id: 'chat_settings.unblock.heading', defaultMessage: 'Unblock @{acct}' }, + unblockConfirm: { id: 'chat_settings.unblock.confirm', defaultMessage: 'Unblock' }, }); interface IChatComposer extends Pick, 'onKeyDown' | 'onChange' | 'disabled'> { @@ -25,10 +35,55 @@ const ChatComposer = React.forwardRef hasErrorSubmittingMessage = false, disabled = false, }, ref) => { + const dispatch = useAppDispatch(); const intl = useIntl(); + const { chat } = useChatContext(); + const isBlocked = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocked_by'])); + const isBlocking = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocking'])); + const isSubmitDisabled = disabled || value.length === 0; + const handleUnblockUser = () => { + dispatch(openModal('CONFIRM', { + heading: intl.formatMessage(messages.unblockHeading, { acct: chat?.account.acct }), + message: intl.formatMessage(messages.unblockMessage), + confirm: intl.formatMessage(messages.unblockConfirm), + confirmationTheme: 'primary', + onConfirm: () => dispatch(unblockAccount(chat?.account.id as string)), + })); + }; + + if (isBlocking) { + return ( +
+ + + {intl.formatMessage(messages.blocked)} + + + + +
+ ); + } + + if (isBlocked) { + return ( +
+ + <> + {intl.formatMessage(messages.blockedBy)} + {' '} + @{chat?.account?.acct} + + +
+ ); + } + return (
diff --git a/app/soapbox/features/chats/components/chat-message-list.tsx b/app/soapbox/features/chats/components/chat-message-list.tsx index 46b506d033..63d57b6ed6 100644 --- a/app/soapbox/features/chats/components/chat-message-list.tsx +++ b/app/soapbox/features/chats/components/chat-message-list.tsx @@ -35,7 +35,6 @@ const messages = defineMessages({ copy: { id: 'chats.actions.copy', defaultMessage: 'Copy' }, report: { id: 'chats.actions.report', defaultMessage: 'Report' }, deleteForMe: { id: 'chats.actions.deleteForMe', defaultMessage: 'Delete for me' }, - blockedBy: { id: 'chat_message_list.blockedBy', defaultMessage: 'You are blocked by' }, networkFailureTitle: { id: 'chat_message_list.network_failure.title', defaultMessage: 'Whoops!' }, networkFailureSubtitle: { id: 'chat_message_list.network_failure.subtitle', defaultMessage: 'We encountered a network failure.' }, networkFailureAction: { id: 'chat_message_list.network_failure.action', defaultMessage: 'Try again' }, @@ -92,7 +91,6 @@ const ChatMessageList: React.FC = ({ chat, autosize }) => { const formattedChatMessages = chatMessages || []; const me = useAppSelector((state) => state.me); - const isBlocked = useAppSelector((state) => state.getIn(['relationships', chat.account.id, 'blocked_by'])); const handleDeleteMessage = useMutation((chatMessageId: string) => deleteChatMessage(chatMessageId), { onSettled: () => { @@ -351,23 +349,6 @@ const ChatMessageList: React.FC = ({ chat, autosize }) => { } }, [formattedChatMessages.length]); - if (isBlocked) { - return ( - - - - - <> - {intl.formatMessage(messages.blockedBy)} - {' '} - @{chat.account.acct} - - - - - ); - } - if (isError) { return ( diff --git a/app/soapbox/features/chats/components/chat-page/components/chat-page-main.tsx b/app/soapbox/features/chats/components/chat-page/components/chat-page-main.tsx index 1e12d8ba22..505a4c1f3c 100644 --- a/app/soapbox/features/chats/components/chat-page/components/chat-page-main.tsx +++ b/app/soapbox/features/chats/components/chat-page/components/chat-page-main.tsx @@ -1,12 +1,12 @@ import React, { useRef } from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import { blockAccount } from 'soapbox/actions/accounts'; +import { blockAccount, unblockAccount } from 'soapbox/actions/accounts'; import { openModal } from 'soapbox/actions/modals'; import { Avatar, Divider, HStack, Icon, IconButton, Menu, MenuButton, MenuItem, MenuList, Stack, Text } from 'soapbox/components/ui'; import VerificationBadge from 'soapbox/components/verification_badge'; import { useChatContext } from 'soapbox/contexts/chat-context'; -import { useAppDispatch, useOwnAccount } from 'soapbox/hooks'; +import { useAppDispatch, useAppSelector, useOwnAccount } from 'soapbox/hooks'; import { useChatActions } from 'soapbox/queries/chats'; import Chat from '../../chat'; @@ -18,10 +18,14 @@ const messages = defineMessages({ blockMessage: { id: 'chat_settings.block.message', defaultMessage: 'Blocking will prevent this profile from direct messaging you and viewing your content. You can unblock later.' }, blockHeading: { id: 'chat_settings.block.heading', defaultMessage: 'Block @{acct}' }, blockConfirm: { id: 'chat_settings.block.confirm', defaultMessage: 'Block' }, + unblockMessage: { id: 'chat_settings.unblock.message', defaultMessage: 'Unblocking will allow you to resume messaging with the user.' }, + unblockHeading: { id: 'chat_settings.unblock.heading', defaultMessage: 'Unblock @{acct}' }, + unblockConfirm: { id: 'chat_settings.unblock.confirm', defaultMessage: 'Unblock' }, leaveMessage: { id: 'chat_settings.leave.message', defaultMessage: 'Are you sure you want to leave this chat? Messages will be deleted for you and this chat will be removed from your inbox.' }, leaveHeading: { id: 'chat_settings.leave.heading', defaultMessage: 'Leave Chat' }, leaveConfirm: { id: 'chat_settings.leave.confirm', defaultMessage: 'Leave Chat' }, blockUser: { id: 'chat_settings.options.block_user', defaultMessage: 'Block @{acct}' }, + unblockUser: { id: 'chat_settings.options.unblock_user', defaultMessage: 'Unblock @{acct}' }, reportUser: { id: 'chat_settings.options.report_user', defaultMessage: 'Report @{acct}' }, leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave Chat' }, }); @@ -36,6 +40,8 @@ const ChatPageMain = () => { const { chat, setChat } = useChatContext(); const { deleteChat } = useChatActions(chat?.id as string); + const isBlocking = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocking'])); + const handleBlockUser = () => { dispatch(openModal('CONFIRM', { heading: intl.formatMessage(messages.blockHeading, { acct: chat?.account.acct }), @@ -46,6 +52,16 @@ const ChatPageMain = () => { })); }; + const handleUnblockUser = () => { + dispatch(openModal('CONFIRM', { + heading: intl.formatMessage(messages.unblockHeading, { acct: chat?.account.acct }), + message: intl.formatMessage(messages.unblockMessage), + confirm: intl.formatMessage(messages.unblockConfirm), + confirmationTheme: 'primary', + onConfirm: () => dispatch(unblockAccount(chat?.account.id as string)), + })); + }; + const handleLeaveChat = () => { dispatch(openModal('CONFIRM', { heading: intl.formatMessage(messages.leaveHeading), @@ -122,12 +138,12 @@ const ChatPageMain = () => {
- {intl.formatMessage(messages.blockUser, { acct: chat.account.acct })} + {intl.formatMessage(isBlocking ? messages.unblockUser : messages.blockUser, { acct: chat.account.acct })}
diff --git a/app/soapbox/features/chats/components/chat-widget/chat-settings.tsx b/app/soapbox/features/chats/components/chat-widget/chat-settings.tsx index 06f365ee26..442e5af255 100644 --- a/app/soapbox/features/chats/components/chat-widget/chat-settings.tsx +++ b/app/soapbox/features/chats/components/chat-widget/chat-settings.tsx @@ -1,11 +1,11 @@ import React from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import { blockAccount } from 'soapbox/actions/accounts'; +import { blockAccount, unblockAccount } from 'soapbox/actions/accounts'; import { openModal } from 'soapbox/actions/modals'; import { Avatar, Divider, HStack, Icon, Stack, Text } from 'soapbox/components/ui'; import { useChatContext } from 'soapbox/contexts/chat-context'; -import { useAppDispatch } from 'soapbox/hooks'; +import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { useChatActions } from 'soapbox/queries/chats'; import ChatPaneHeader from './chat-pane-header'; @@ -14,11 +14,15 @@ const messages = defineMessages({ blockMessage: { id: 'chat_settings.block.message', defaultMessage: 'Blocking will prevent this profile from direct messaging you and viewing your content. You can unblock later.' }, blockHeading: { id: 'chat_settings.block.heading', defaultMessage: 'Block @{acct}' }, blockConfirm: { id: 'chat_settings.block.confirm', defaultMessage: 'Block' }, + unblockMessage: { id: 'chat_settings.unblock.message', defaultMessage: 'Unblocking will allow you to resume messaging with the user.' }, + unblockHeading: { id: 'chat_settings.unblock.heading', defaultMessage: 'Unblock @{acct}' }, + unblockConfirm: { id: 'chat_settings.unblock.confirm', defaultMessage: 'Unblock' }, leaveMessage: { id: 'chat_settings.leave.message', defaultMessage: 'Are you sure you want to leave this chat? Messages will be deleted for you and this chat will be removed from your inbox.' }, leaveHeading: { id: 'chat_settings.leave.heading', defaultMessage: 'Leave Chat' }, leaveConfirm: { id: 'chat_settings.leave.confirm', defaultMessage: 'Leave Chat' }, title: { id: 'chat_settings.title', defaultMessage: 'Chat Details' }, blockUser: { id: 'chat_settings.options.block_user', defaultMessage: 'Block @{acct}' }, + unblockUser: { id: 'chat_settings.options.unblock_user', defaultMessage: 'Unblock @{acct}' }, leaveChat: { id: 'chat_settings.options.leave_chat', defaultMessage: 'Leave Chat' }, }); @@ -29,6 +33,8 @@ const ChatSettings = () => { const { chat, setEditing, toggleChatPane } = useChatContext(); const { deleteChat } = useChatActions(chat?.id as string); + const isBlocking = useAppSelector((state) => state.getIn(['relationships', chat?.account?.id, 'blocking'])); + const closeSettings = () => setEditing(false); const minimizeChatPane = () => { @@ -46,6 +52,16 @@ const ChatSettings = () => { })); }; + const handleUnblockUser = () => { + dispatch(openModal('CONFIRM', { + heading: intl.formatMessage(messages.unblockHeading, { acct: chat?.account.acct }), + message: intl.formatMessage(messages.unblockMessage), + confirm: intl.formatMessage(messages.unblockConfirm), + confirmationTheme: 'primary', + onConfirm: () => dispatch(unblockAccount(chat?.account.id as string)), + })); + }; + const handleLeaveChat = () => { dispatch(openModal('CONFIRM', { heading: intl.formatMessage(messages.leaveHeading), @@ -94,9 +110,9 @@ const ChatSettings = () => { -