diff --git a/js/models/messages.js b/js/models/messages.js index 7fa919d01..fe7710149 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -1015,9 +1015,7 @@ } this.set({ errors: null }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); try { const conversation = this.getConversation(); const intendedRecipients = this.get('recipients') || []; @@ -1055,9 +1053,8 @@ if (!recipients.length) { window.log.warn('retrySend: Nobody to send to!'); - return window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + return this.commit(); + } const { body, attachments, preview, quote } = await this.uploadData(); @@ -1324,9 +1321,8 @@ // unidentifiedDeliveries: result.unidentifiedDeliveries, }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + this.getConversation().updateLastMessage(); this.trigger('sent', this); @@ -1354,9 +1350,8 @@ expirationStartTimestamp, // unidentifiedDeliveries: result.unidentifiedDeliveries, }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + this.trigger('change', this); this.getConversation().updateLastMessage(); @@ -1455,9 +1450,8 @@ calculatingPoW: true, }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + }, getServerId() { return this.get('serverId'); @@ -1471,9 +1465,8 @@ serverId, }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + }, async setServerTimestamp(serverTimestamp) { if (_.isEqual(this.get('serverTimestamp'), serverTimestamp)) { @@ -1484,9 +1477,8 @@ serverTimestamp, }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + }, async setIsPublic(isPublic) { if (_.isEqual(this.get('isPublic'), isPublic)) { @@ -1497,9 +1489,8 @@ isPublic: !!isPublic, }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + }, async sendSyncMessageOnly(dataMessage) { @@ -1509,9 +1500,8 @@ expirationStartTimestamp: Date.now(), }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + const data = dataMessage instanceof libsession.Messages.Outgoing.DataMessage @@ -1543,9 +1533,8 @@ await libsession.getMessageQueue().sendSyncMessage(syncMessage); this.set({ sentSync: true }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); + }, someRecipientsFailed() { @@ -1576,9 +1565,7 @@ expirationStartTimestamp: Date.now(), }); - return window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); }, async saveErrors(providedErrors) { @@ -1611,9 +1598,7 @@ } this.set({ errors }); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); }, hasNetworkError() { const error = _.find( @@ -1625,6 +1610,12 @@ ); return !!error; }, + async commit() { + await window.Signal.Data.saveMessage(this.attributes, { + Message: Whisper.Message, + }); + this.trigger('change'); + }, async markRead(readAt) { this.unset('unread'); @@ -1642,9 +1633,7 @@ }) ); - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); }, isExpiring() { return this.get('expireTimer') && this.get('expirationStartTimestamp'); @@ -1674,9 +1663,7 @@ this.set({ expires_at: expiresAt }); const id = this.get('id'); if (id) { - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); + await this.commit(); } window.log.info('Set message expiration', { diff --git a/js/views/conversation_view.js b/js/views/conversation_view.js index bef9b1c89..eac946c70 100644 --- a/js/views/conversation_view.js +++ b/js/views/conversation_view.js @@ -116,13 +116,6 @@ this.toggleMicrophone() ); - this.view = new Whisper.MessageListView({ - collection: this.model.messageCollection, - window: this.window, - }); - this.$('.discussion-container').append(this.view.el); - this.view.render(); - this.memberView = new Whisper.MemberListView({ el: this.$('.member-list-container'), onClicked: this.selectMember.bind(this), @@ -193,11 +186,6 @@ 'focus .send-message': 'focusBottomBar', 'change .file-input': 'toggleMicrophone', 'blur .send-message': 'unfocusBottomBar', - 'loadMore .message-list': 'loadMoreMessages', - 'newOffscreenMessage .message-list': 'addScrollDownButtonWithCount', - 'atBottom .message-list': 'removeScrollDownButton', - 'farFromBottom .message-list': 'addScrollDownButton', - 'lazyScroll .message-list': 'onLazyScroll', 'force-resize': 'forceUpdateMessageFieldSize', 'click button.paperclip': 'onChooseAttachment', @@ -401,36 +389,6 @@ this.typingBubbleView.remove(); this.typingBubbleView = null; } - if (!mostRecent) { - return; - } - - const { sender } = mostRecent; - const contact = ConversationController.getOrCreate(sender, 'private'); - // we need the opposite theme - const color = - window.Events.getThemeSetting() === 'light' ? 'dark' : 'light'; - const props = { - ...contact.format(), - conversationType: this.model.isPrivate() ? 'direct' : 'group', - color, - }; - - if (this.typingBubbleView) { - this.typingBubbleView.update(props); - return; - } - - this.typingBubbleView = new Whisper.ReactWrapperView({ - className: 'message-wrapper typing-bubble-wrapper', - Component: Signal.Components.TypingBubble, - props, - }); - this.typingBubbleView.$el.appendTo(this.$('.typing-container')); - - if (this.view.atBottom()) { - this.typingBubbleView.el.scrollIntoView(); - } }, async toggleMicrophone() { diff --git a/js/views/inbox_view.js b/js/views/inbox_view.js index d0f0dd357..fcfa39c94 100644 --- a/js/views/inbox_view.js +++ b/js/views/inbox_view.js @@ -196,16 +196,21 @@ tmpMsg.get('conversationId') ); + if (!conv) { + return null; + } + // then, find in this conversation the very same message - const msg = conv.messageCollection.models.find( - convMsg => convMsg.id === tmpMsg.id - ); + // const msg = conv.messageCollection.models.find( + // convMsg => convMsg.id === tmpMsg.id + // ); + const msg = window.MessageController._get()[m.identifier]; - if (!msg) { + if (!msg || !msg.message) { return null; } - return { msg }; + return { msg: msg.message }; }, async handleMessageSentSuccess(sentMessage, wrappedEnvelope) { diff --git a/js/views/message_list_view.js b/js/views/message_list_view.js deleted file mode 100644 index 13ac989d5..000000000 --- a/js/views/message_list_view.js +++ /dev/null @@ -1,143 +0,0 @@ -/* global Whisper, Backbone, _, $ */ - -// eslint-disable-next-line func-names -(function() { - 'use strict'; - - window.Whisper = window.Whisper || {}; - - Whisper.MessageListView = Backbone.View.extend({ - tagName: 'ul', - className: 'message-list', - - template: $('#message-list').html(), - itemView: Whisper.MessageView, - - events: { - scroll: 'onScroll', - }, - - // Here we reimplement Whisper.ListView so we can override addAll - render() { - this.addAll(); - return this; - }, - - // The key is that we don't erase all inner HTML, we re-render our template. - // And then we keep a reference to .messages - addAll() { - Whisper.View.prototype.render.call(this); - this.$messages = this.$('.messages'); - this.collection.each(this.addOne, this); - }, - - initialize() { - this.listenTo(this.collection, 'add', this.addOne); - this.listenTo(this.collection, 'reset', this.addAll); - - this.render(); - - this.triggerLazyScroll = _.debounce(() => { - this.$el.trigger('lazyScroll'); - }, 500); - }, - onScroll() { - this.measureScrollPosition(); - if (this.$el.scrollTop() === 0) { - this.$el.trigger('loadMore'); - } - if (this.atBottom()) { - this.$el.trigger('atBottom'); - } else if (this.bottomOffset > this.outerHeight) { - this.$el.trigger('farFromBottom'); - } - - this.triggerLazyScroll(); - }, - atBottom() { - return this.bottomOffset ? this.bottomOffset < 30 : true; - }, - measureScrollPosition() { - if (this.el.scrollHeight === 0) { - // hidden - return; - } - this.outerHeight = this.$el.outerHeight(); - this.scrollPosition = this.$el.scrollTop() + this.outerHeight; - this.scrollHeight = this.el.scrollHeight; - this.bottomOffset = this.scrollHeight - this.scrollPosition; - }, - resetScrollPosition() { - this.$el.scrollTop(this.scrollPosition - this.$el.outerHeight()); - }, - restoreBottomOffset() { - if (_.isNumber(this.bottomOffset)) { - // + 10 is necessary to account for padding - const height = this.$el.height() + 10; - - const topOfBottomScreen = this.el.scrollHeight - height; - this.$el.scrollTop(topOfBottomScreen - this.bottomOffset); - } - }, - scrollToBottomIfNeeded() { - // This is counter-intuitive. Our current bottomOffset is reflective of what - // we last measured, not necessarily the current state. And this is called - // after we just made a change to the DOM: inserting a message, or an image - // finished loading. So if we were near the bottom before, we _need_ to be - // at the bottom again. So we scroll to the bottom. - if (this.atBottom()) { - this.scrollToBottom(); - } - }, - scrollToBottom() { - this.$el.scrollTop(this.el.scrollHeight); - this.measureScrollPosition(); - }, - addOne(model) { - // eslint-disable-next-line new-cap - const view = new this.itemView({ model }).render(); - this.listenTo(view, 'beforeChangeHeight', this.measureScrollPosition); - this.listenTo(view, 'afterChangeHeight', this.scrollToBottomIfNeeded); - - const index = this.collection.indexOf(model); - this.measureScrollPosition(); - - if (model.get('unread') && !this.atBottom()) { - this.$el.trigger('newOffscreenMessage'); - } - - if (index === this.collection.length - 1) { - // add to the bottom. - this.$messages.append(view.el); - } else if (index === 0) { - // add to top - this.$messages.prepend(view.el); - } else { - // insert - const next = this.$(`#${this.collection.at(index + 1).id}`); - const prev = this.$(`#${this.collection.at(index - 1).id}`); - if (next.length > 0) { - view.$el.insertBefore(next); - } else if (prev.length > 0) { - view.$el.insertAfter(prev); - } else { - // scan for the right spot - const elements = this.$messages.children(); - if (elements.length > 0) { - for (let i = 0; i < elements.length; i += 1) { - const m = this.collection.get(elements[i].id); - const mIndex = this.collection.indexOf(m); - if (mIndex > index) { - view.$el.insertBefore(elements[i]); - break; - } - } - } else { - this.$messages.append(view.el); - } - } - } - this.scrollToBottomIfNeeded(); - }, - }); -})(); diff --git a/stylesheets/_conversation.scss b/stylesheets/_conversation.scss index 43545d4ae..b87137734 100644 --- a/stylesheets/_conversation.scss +++ b/stylesheets/_conversation.scss @@ -4,8 +4,7 @@ overflow-y: auto; } -.message-container, -.message-list { +.message-container{ list-style: none; li { diff --git a/ts/components/session/conversation/SessionConversationMessagesList.tsx b/ts/components/session/conversation/SessionConversationMessagesList.tsx index 3de86b07a..4cdfab532 100644 --- a/ts/components/session/conversation/SessionConversationMessagesList.tsx +++ b/ts/components/session/conversation/SessionConversationMessagesList.tsx @@ -138,12 +138,6 @@ export class SessionConversationMessagesList extends React.Component< if (conversation.unreadCount === 0) { findFirstUnreadIndex = -1; } - // console.log( - // 'findFirstUnreadIndex', - // findFirstUnreadIndex, - // 'unreadCount', - // conversation.unreadCount - // ); return ( <>