diff --git a/app/soapbox/actions/chats.js b/app/soapbox/actions/chats.js index 729dc128e..6f8d1c788 100644 --- a/app/soapbox/actions/chats.js +++ b/app/soapbox/actions/chats.js @@ -23,6 +23,10 @@ export const CHAT_READ_REQUEST = 'CHAT_READ_REQUEST'; export const CHAT_READ_SUCCESS = 'CHAT_READ_SUCCESS'; export const CHAT_READ_FAIL = 'CHAT_READ_FAIL'; +export const CHAT_MESSAGE_DELETE_REQUEST = 'CHAT_MESSAGE_DELETE_REQUEST'; +export const CHAT_MESSAGE_DELETE_SUCCESS = 'CHAT_MESSAGE_DELETE_SUCCESS'; +export const CHAT_MESSAGE_DELETE_FAIL = 'CHAT_MESSAGE_DELETE_FAIL'; + export function fetchChats() { return (dispatch, getState) => { dispatch({ type: CHATS_FETCH_REQUEST }); @@ -150,3 +154,14 @@ export function markChatRead(chatId, lastReadId) { }); }; } + +export function deleteChatMessage(chatId, messageId) { + return (dispatch, getState) => { + dispatch({ type: CHAT_MESSAGE_DELETE_REQUEST, chatId, messageId }); + api(getState).delete(`/api/v1/pleroma/chats/${chatId}/messages/${messageId}`).then(({ data }) => { + dispatch({ type: CHAT_MESSAGE_DELETE_SUCCESS, chatId, messageId, chatMessage: data }); + }).catch(error => { + dispatch({ type: CHAT_MESSAGE_DELETE_FAIL, chatId, messageId, error }); + }); + }; +} diff --git a/app/soapbox/features/chats/components/chat_message_list.js b/app/soapbox/features/chats/components/chat_message_list.js index 0c21c6b27..37a7e8ab9 100644 --- a/app/soapbox/features/chats/components/chat_message_list.js +++ b/app/soapbox/features/chats/components/chat_message_list.js @@ -5,16 +5,20 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { injectIntl, defineMessages } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; -import { fetchChatMessages } from 'soapbox/actions/chats'; +import { fetchChatMessages, deleteChatMessage } from 'soapbox/actions/chats'; import emojify from 'soapbox/features/emoji/emoji'; import classNames from 'classnames'; import { openModal } from 'soapbox/actions/modal'; import { escape, throttle } from 'lodash'; import { MediaGallery } from 'soapbox/features/ui/util/async-components'; import Bundle from 'soapbox/features/ui/components/bundle'; +import DropdownMenuContainer from 'soapbox/containers/dropdown_menu_container'; const messages = defineMessages({ today: { id: 'chats.dividers.today', defaultMessage: 'Today' }, + more: { id: 'chats.actions.more', defaultMessage: 'More' }, + delete: { id: 'chats.actions.delete', defaultMessage: 'Delete message' }, + report: { id: 'chats.actions.report', defaultMessage: 'Report user' }, }); const timeChange = (prev, curr) => { @@ -198,7 +202,8 @@ class ChatMessageList extends ImmutablePureComponent { parseContent = chatMessage => { const content = chatMessage.get('content') || ''; const pending = chatMessage.get('pending', false); - const formatted = pending ? this.parsePendingContent(content) : content; + const deleting = chatMessage.get('deleting', false); + const formatted = (pending && !deleting) ? this.parsePendingContent(content) : content; const emojiMap = makeEmojiMap(chatMessage); return emojify(formatted, emojiMap.toJS()); } @@ -211,8 +216,24 @@ class ChatMessageList extends ImmutablePureComponent {
{text}
) + handleDeleteMessage = (chatId, messageId) => { + return () => { + this.props.dispatch(deleteChatMessage(chatId, messageId)); + }; + } + + handleReportUser = (userId) => { + return () => { + console.log(`should report user ${userId}`); + }; + } + renderMessage = (chatMessage) => { - const { me } = this.props; + const { me, intl } = this.props; + const menu = [ + { text: intl.formatMessage(messages.delete), action: this.handleDeleteMessage(chatMessage.get('chat_id'), chatMessage.get('id')) }, + { text: intl.formatMessage(messages.report), action: this.handleReportUser(chatMessage.get('account_id')) }, + ]; return (
+
+ +
); diff --git a/app/soapbox/reducers/chat_message_lists.js b/app/soapbox/reducers/chat_message_lists.js index 3e2d1dbae..8848a8389 100644 --- a/app/soapbox/reducers/chat_message_lists.js +++ b/app/soapbox/reducers/chat_message_lists.js @@ -3,6 +3,7 @@ import { CHAT_MESSAGES_FETCH_SUCCESS, CHAT_MESSAGE_SEND_REQUEST, CHAT_MESSAGE_SEND_SUCCESS, + CHAT_MESSAGE_DELETE_SUCCESS, } from 'soapbox/actions/chats'; import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; import { Map as ImmutableMap, OrderedSet as ImmutableOrderedSet } from 'immutable'; @@ -59,6 +60,8 @@ export default function chatMessageLists(state = initialState, action) { return updateList(state, action.chatId, action.chatMessages.map(chat => chat.id)); case CHAT_MESSAGE_SEND_SUCCESS: return replaceMessage(state, action.chatId, action.uuid, action.chatMessage.id); + case CHAT_MESSAGE_DELETE_SUCCESS: + return state.update(action.chatId, chat => chat.delete(action.messageId)); default: return state; } diff --git a/app/soapbox/reducers/chat_messages.js b/app/soapbox/reducers/chat_messages.js index 74d83ef79..ababe85bd 100644 --- a/app/soapbox/reducers/chat_messages.js +++ b/app/soapbox/reducers/chat_messages.js @@ -3,6 +3,8 @@ import { CHAT_MESSAGES_FETCH_SUCCESS, CHAT_MESSAGE_SEND_REQUEST, CHAT_MESSAGE_SEND_SUCCESS, + CHAT_MESSAGE_DELETE_REQUEST, + CHAT_MESSAGE_DELETE_SUCCESS, } from 'soapbox/actions/chats'; import { STREAMING_CHAT_UPDATE } from 'soapbox/actions/streaming'; import { Map as ImmutableMap, fromJS } from 'immutable'; @@ -43,6 +45,11 @@ export default function chatMessages(state = initialState, action) { return importMessage(state, fromJS(action.chatMessage)).delete(action.uuid); case STREAMING_CHAT_UPDATE: return importLastMessages(state, fromJS([action.chat])); + case CHAT_MESSAGE_DELETE_REQUEST: + return state.update(action.messageId, chatMessage => + chatMessage.set('pending', true).set('deleting', true)); + case CHAT_MESSAGE_DELETE_SUCCESS: + return state.delete(action.messageId); default: return state; }