diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 3dc0c81fc..92df95024 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -164,7 +164,7 @@ class MessageInner extends React.PureComponent { public checkExpired() { const now = Date.now(); - const { isExpired, expirationTimestamp, expirationLength } = this.props; + const { isExpired, expirationTimestamp, expirationLength, convoId, id } = this.props; if (!expirationTimestamp || !expirationLength) { return; @@ -178,17 +178,23 @@ class MessageInner extends React.PureComponent { expiring: true, }); - const setExpired = () => { + const setExpired = async () => { this.setState({ expired: true, }); + await window.Signal.Data.removeMessage(id); window.inboxStore?.dispatch( - messageExpired({ messageId: this.props.id, conversationKey: this.props.convoId }) + messageExpired({ + conversationKey: convoId, + messageId: id, + }) ); - getConversationController() - .get(this.props.convoId) - ?.updateLastMessage(); + const convo = getConversationController().get(convoId); + convo?.updateLastMessage(); }; + // as 'checkExpired' is potentially called more than once (componentDidUpdate & componentDidMount), + // we need to clear the timeout call to 'setExpired' first to avoid multiple calls to 'setExpired'. + global.clearTimeout(this.expiredTimeout); this.expiredTimeout = setTimeout(setExpired, EXPIRED_DELAY); } } diff --git a/ts/data/data.ts b/ts/data/data.ts index a6882607d..52c652fcf 100644 --- a/ts/data/data.ts +++ b/ts/data/data.ts @@ -625,7 +625,7 @@ export async function saveMessages(arrayOfMessages: Array): P } export async function removeMessage(id: string): Promise { - const message = await getMessageById(id); + const message = await getMessageById(id, true); // Note: It's important to have a fully database-hydrated model to delete here because // it needs to delete all associated on-disk files along with the database delete. @@ -647,11 +647,17 @@ export async function getMessageIdsFromServerIds( return channels.getMessageIdsFromServerIds(serverIds, conversationId); } -export async function getMessageById(id: string): Promise { +export async function getMessageById( + id: string, + skipTimerInit: boolean = false +): Promise { const message = await channels.getMessageById(id); if (!message) { return null; } + if (skipTimerInit) { + message.skipTimerInit = skipTimerInit; + } return new MessageModel(message); } @@ -725,13 +731,18 @@ export async function getUnreadCountByConversation(conversationId: string): Prom export async function getMessagesByConversation( conversationId: string, - { limit = 100, receivedAt = Number.MAX_VALUE, type = '%' } + { limit = 100, receivedAt = Number.MAX_VALUE, type = '%', skipTimerInit = false } ): Promise { const messages = await channels.getMessagesByConversation(conversationId, { limit, receivedAt, type, }); + if (skipTimerInit) { + for (const message of messages) { + message.skipTimerInit = skipTimerInit; + } + } return new MessageCollection(messages); } diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts index e9082230d..6a11be9e9 100644 --- a/ts/interactions/conversationInteractions.ts +++ b/ts/interactions/conversationInteractions.ts @@ -439,7 +439,9 @@ export async function deleteMessagesById( askUserForConfirmation: boolean ) { const conversationModel = getConversationController().getOrThrow(conversationId); - const selectedMessages = _.compact(await Promise.all(messageIds.map(getMessageById))); + const selectedMessages = _.compact( + await Promise.all(messageIds.map(m => getMessageById(m, false))) + ); const moreThanOne = selectedMessages.length > 1; diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 8d3edfab1..d28515b14 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -785,6 +785,7 @@ export class ConversationModel extends Backbone.Model { } const messages = await getMessagesByConversation(this.id, { limit: 1, + skipTimerInit: true, }); const lastMessageModel = messages.at(0); const lastMessageJSON = lastMessageModel ? lastMessageModel.toJSON() : null; diff --git a/ts/models/message.ts b/ts/models/message.ts index b5fd0c501..405fc0180 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -57,7 +57,7 @@ import { perfEnd, perfStart } from '../session/utils/Performance'; import { AttachmentTypeWithPath } from '../types/Attachment'; export class MessageModel extends Backbone.Model { - constructor(attributes: MessageAttributesOptionals) { + constructor(attributes: MessageAttributesOptionals & { skipTimerInit?: boolean }) { const filledAttrs = fillMessageAttributesWithDefaults(attributes); super(filledAttrs); @@ -76,7 +76,9 @@ export class MessageModel extends Backbone.Model { } // this.on('expired', this.onExpired); - void this.setToExpire(); + if (!attributes.skipTimerInit) { + void this.setToExpire(); + } autoBind(this); this.dispatchMessageUpdate = _.throttle(this.dispatchMessageUpdate, 300);