diff --git a/js/models/conversations.js b/js/models/conversations.js index d1af016a3..510ab6cb4 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -166,15 +166,18 @@ this.updateLastMessage(); const removeMessage = () => { - const existing = this.messageCollection.get(message.id); + const { id } = message; + const existing = this.messageCollection.get(id); if (!existing) { return; } window.log.info('Remove expired message from collection', { - sentAt: message.get('sent_at'), + sentAt: existing.get('sent_at'), }); - this.messageCollection.remove(message.id); + + this.messageCollection.remove(id); + existing.trigger('expired'); }; // If a fetch is in progress, then we need to wait until that's complete to diff --git a/js/models/messages.js b/js/models/messages.js index 1a77e6bd7..f2ac0e4d6 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -83,6 +83,7 @@ this.on('change:expirationStartTimestamp', this.setToExpire); this.on('change:expireTimer', this.setToExpire); this.on('unload', this.unload); + this.on('expired', this.onExpired); this.setToExpire(); }, idForLogging() { @@ -233,7 +234,9 @@ this.quotedMessage = null; } }, - + onExpired() { + this.hasExpired = true; + }, getPropsForTimerNotification() { const { expireTimer, fromSync, source } = this.get( 'expirationTimerUpdate' @@ -424,6 +427,7 @@ attachment: this.getPropsForAttachment(firstAttachment), quote: this.getPropsForQuote(), authorAvatarPath, + isExpired: this.hasExpired, expirationLength, expirationTimestamp, onReply: () => this.trigger('reply', this), diff --git a/js/views/message_view.js b/js/views/message_view.js index 26f5e74ba..11fd2efbd 100644 --- a/js/views/message_view.js +++ b/js/views/message_view.js @@ -15,6 +15,7 @@ this.listenTo(this.model, 'change', this.onChange); this.listenTo(this.model, 'destroy', this.onDestroy); this.listenTo(this.model, 'unload', this.onUnload); + this.listenTo(this.model, 'expired', this.onExpired); }, onChange() { this.addId(); @@ -27,6 +28,9 @@ const { id } = this.model; this.$el.attr('id', id); }, + onExpired() { + setTimeout(() => this.onUnload(), 1000); + }, onUnload() { if (this.childView) { this.childView.remove(); @@ -93,6 +97,7 @@ }; this.listenTo(this.model, 'change', update); + this.listenTo(this.model, 'expired', update); this.conversation = this.model.getConversation(); this.listenTo(this.conversation, 'change', update); diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 61fbd2bc0..c3fe2a72c 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -81,6 +81,7 @@ export interface Props { referencedMessageNotFound: boolean; }; authorAvatarPath?: string; + isExpired: boolean; expirationLength?: number; expirationTimestamp?: number; onClickAttachment?: () => void; @@ -211,15 +212,22 @@ export class Message extends React.Component { } } + public componentDidUpdate() { + this.checkExpired(); + } + public checkExpired() { const now = Date.now(); - const { expirationTimestamp, expirationLength } = this.props; + const { isExpired, expirationTimestamp, expirationLength } = this.props; if (!expirationTimestamp || !expirationLength) { return; } + if (this.expiredTimeout) { + return; + } - if (now >= expirationTimestamp) { + if (isExpired || now >= expirationTimestamp) { this.setState({ expiring: true, });