From 0beb47e5972bb01569fa7c49190702bbfc1b5aeb Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 17 Nov 2020 13:30:24 +1100 Subject: [PATCH] add messageDeleted redux action --- js/models/conversations.js | 16 ++++-- js/models/messages.js | 3 -- ts/components/session/SessionInboxView.tsx | 18 ++++--- .../conversation/SessionConversation.tsx | 4 ++ ts/state/ducks/conversations.ts | 53 ++++++++++++++++++- 5 files changed, 79 insertions(+), 15 deletions(-) diff --git a/js/models/conversations.js b/js/models/conversations.js index 7e991a41d..29fec15be 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -2214,15 +2214,15 @@ return false; } - const invalidMessages = messages.filter(m => !m.getServerId()); - const pendingMessages = messages.filter(m => m.getServerId()); + const invalidMessages = messages.filter(m => !m.attributes.serverId); + const pendingMessages = messages.filter(m => m.attributes.serverId); let deletedServerIds = []; let ignoredServerIds = []; if (pendingMessages.length > 0) { const result = await channelAPI.deleteMessages( - pendingMessages.map(m => m.getServerId()) + pendingMessages.map(m => m.attributes.serverId) ); deletedServerIds = result.deletedIds; ignoredServerIds = result.ignoredIds; @@ -2233,7 +2233,7 @@ ignoredServerIds ); let toDeleteLocally = messages.filter(m => - toDeleteLocallyServerIds.includes(m.getServerId()) + toDeleteLocallyServerIds.includes(m.attributes.serverId) ); toDeleteLocally = _.union(toDeleteLocally, invalidMessages); @@ -2249,6 +2249,13 @@ if (message) { message.trigger('unload'); this.messageCollection.remove(messageId); + window.Signal.Data.removeMessage(message.id, { + Message: Whisper.Message, + }); + window.Whisper.events.trigger('messageDeleted', { + conversationKey: this.id, + messageId, + }); } }, @@ -2275,6 +2282,7 @@ }); this.messageCollection.reset([]); + // no need to do the trigger 'messageDeleted' here // destroy message keeps the active timestamp set so the // conversation still appears on the conversation list but is empty diff --git a/js/models/messages.js b/js/models/messages.js index ca59df0e9..cde3964f4 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -1430,9 +1430,6 @@ await this.commit(); }, - getServerId() { - return this.get('serverId'); - }, async setServerId(serverId) { if (_.isEqual(this.get('serverId'), serverId)) { return; diff --git a/ts/components/session/SessionInboxView.tsx b/ts/components/session/SessionInboxView.tsx index d0ea5fa86..10bab024a 100644 --- a/ts/components/session/SessionInboxView.tsx +++ b/ts/components/session/SessionInboxView.tsx @@ -3,7 +3,8 @@ import { Provider } from 'react-redux'; import { bindActionCreators } from 'redux'; import { getMessageQueue } from '../../session'; import { createStore } from '../../state/createStore'; -import { StateType } from '../../state/reducer'; +import { actions as conversationActions } from '../../state/ducks/conversations'; +import { actions as userActions } from '../../state/ducks/user'; import { SmartLeftPane } from '../../state/smart/LeftPane'; import { SmartSessionConversation } from '../../state/smart/SessionConversation'; import { @@ -204,13 +205,15 @@ export class SessionInboxView extends React.Component { window.inboxStore = this.store; // Enables our redux store to be updated by backbone events in the outside world - const { messageExpired, messageAdded, messageChanged } = bindActionCreators( - window.Signal.State.Ducks.conversations.actions, - this.store.dispatch - ); - window.actionsCreators = window.Signal.State.Ducks.conversations.actions; + const { + messageExpired, + messageAdded, + messageChanged, + messageDeleted, + } = bindActionCreators(conversationActions, this.store.dispatch); + window.actionsCreators = conversationActions; const { userChanged } = bindActionCreators( - window.Signal.State.Ducks.user.actions, + userActions, this.store.dispatch ); @@ -230,6 +233,7 @@ export class SessionInboxView extends React.Component { window.Whisper.events.on('messageExpired', messageExpired); window.Whisper.events.on('messageChanged', messageChanged); window.Whisper.events.on('messageAdded', messageAdded); + window.Whisper.events.on('messageDeleted', messageDeleted); window.Whisper.events.on('userChanged', userChanged); this.setState({ isInitialLoadComplete: true }); diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index 9a6590c0b..d7e427e29 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -664,6 +664,10 @@ export class SessionConversation extends React.Component { await window.Signal.Data.removeMessage(message.id, { Message: window.Whisper.Message, }); + window.Whisper.events.trigger('messageDeleted', { + conversationKey, + messageId: message.id, + }); }) ); diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 66e833836..9f4e98e52 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -203,6 +203,13 @@ export type MessageAddedActionType = { messageModel: MessageModel; }; }; +export type MessageDeletedActionType = { + type: 'MESSAGE_DELETED'; + payload: { + conversationKey: string; + messageId: string; + }; +}; export type SelectedConversationChangedActionType = { type: 'SELECTED_CONVERSATION_CHANGED'; payload: { @@ -226,6 +233,7 @@ export type ConversationActionType = | RemoveAllConversationsActionType | MessageExpiredActionType | MessageAddedActionType + | MessageDeletedActionType | MessageChangedActionType | SelectedConversationChangedActionType | SelectedConversationChangedActionType @@ -240,6 +248,7 @@ export const actions = { removeAllConversations, messageExpired, messageAdded, + messageDeleted, messageChanged, fetchMessagesForConversation, openConversationExternal, @@ -320,6 +329,22 @@ function messageAdded({ }; } +function messageDeleted({ + conversationKey, + messageId, +}: { + conversationKey: string; + messageId: string; +}): MessageDeletedActionType { + return { + type: 'MESSAGE_DELETED', + payload: { + conversationKey, + messageId, + }, + }; +} + function openConversationExternal( id: string, messageId?: string @@ -357,7 +382,8 @@ function getEmptyState(): ConversationsStateType { }; } -// tslint:disable-next-line: cyclomatic-complexity +// tslint:disable: cyclomatic-complexity +// tslint:disable: max-func-body-length export function reducer( state: ConversationsStateType = getEmptyState(), action: ConversationActionType @@ -501,5 +527,30 @@ export function reducer( return state; } + if (action.type === 'MESSAGE_DELETED') { + const { conversationKey, messageId } = action.payload; + if (conversationKey === state.selectedConversation) { + // search if we find this message id. + // we might have not loaded yet, so this case might not happen + const messageInStoreIndex = state?.messages.findIndex( + m => m.id === messageId + ); + if (messageInStoreIndex >= 0) { + // we cannot edit the array directly, so slice the first part, and slice the second part + const editedMessages = [ + ...state.messages.slice(0, messageInStoreIndex), + ...state.messages.slice(messageInStoreIndex + 1), + ]; + return { + ...state, + messages: editedMessages, + }; + } + + return state; + } + return state; + } + return state; }