Conversation: store lastMessage/lastMessageStatus in memory only

pull/1/head
Scott Nonnenberg 7 years ago
parent f39a96bc76
commit 61f7b8360b

@ -135,6 +135,8 @@
this.on('read', this.updateLastMessage); this.on('read', this.updateLastMessage);
this.on('sent', this.updateLastMessage); this.on('sent', this.updateLastMessage);
this.on('expired', this.onExpired); this.on('expired', this.onExpired);
this.updateLastMessage();
}, },
isMe() { isMe() {
@ -198,8 +200,8 @@
isSelected: this.isSelected, isSelected: this.isSelected,
lastMessage: { lastMessage: {
status: this.get('lastMessageStatus'), status: this.lastMessageStatus,
text: this.get('lastMessage'), text: this.lastMessage,
}, },
onClick: () => this.trigger('select', this), onClick: () => this.trigger('select', this),
@ -899,6 +901,10 @@
}, },
async updateLastMessage() { async updateLastMessage() {
if (!this.id) {
return;
}
const messages = await window.Signal.Data.getMessagesByConversation( const messages = await window.Signal.Data.getMessagesByConversation(
this.id, this.id,
{ limit: 1, MessageCollection: Whisper.MessageCollection } { limit: 1, MessageCollection: Whisper.MessageCollection }
@ -907,26 +913,41 @@
return; return;
} }
const lastMessage = messages.at(0); const lastMessageModel = messages.at(0);
const lastMessageJSON = lastMessage ? lastMessage.toJSON() : null; const lastMessageJSON = lastMessageModel
const lastMessageStatus = lastMessage ? lastMessageModel.toJSON()
? lastMessage.getMessagePropStatus() : null;
const lastMessageStatusModel = lastMessageModel
? lastMessageModel.getMessagePropStatus()
: null; : null;
const lastMessageUpdate = Conversation.createLastMessageUpdate({ const lastMessageUpdate = Conversation.createLastMessageUpdate({
currentLastMessageText: this.get('lastMessage') || null, currentLastMessageText: this.get('lastMessage') || null,
currentTimestamp: this.get('timestamp') || null, currentTimestamp: this.get('timestamp') || null,
lastMessage: lastMessageJSON, lastMessage: lastMessageJSON,
lastMessageStatus, lastMessageStatus: lastMessageStatusModel,
lastMessageNotificationText: lastMessage lastMessageNotificationText: lastMessageModel
? lastMessage.getNotificationText() ? lastMessageModel.getNotificationText()
: null, : null,
}); });
let hasChanged = false;
const { lastMessage, lastMessageStatus } = lastMessageUpdate;
lastMessageUpdate.lastMessage = null;
lastMessageUpdate.lastMessageStatus = null;
hasChanged = hasChanged || lastMessage !== this.lastMessage;
this.lastMessage = lastMessage;
hasChanged = hasChanged || lastMessageStatus !== this.lastMessageStatus;
this.lastMessageStatus = lastMessageStatus;
this.set(lastMessageUpdate); this.set(lastMessageUpdate);
if (this.hasChanged('lastMessage') || this.hasChanged('timestamp')) { if (this.hasChanged()) {
this.save(); this.save();
} else if (hasChanged) {
this.trigger('change');
} }
}, },

@ -15,7 +15,6 @@
templateName: 'conversation-preview', templateName: 'conversation-preview',
initialize() { initialize() {
this.listenTo(this.model, 'destroy', this.remove); this.listenTo(this.model, 'destroy', this.remove);
this.model.updateLastMessage();
}, },
remove() { remove() {

@ -60,25 +60,26 @@ function hexToArrayBuffer(str) {
return ret; return ret;
} }
function deleteDatabase() {
return new Promise((resolve, reject) => {
var idbReq = indexedDB.deleteDatabase('test');
idbReq.onsuccess = resolve;
idbReq.error = reject;
});
}
/* Delete the database before running any tests */ /* Delete the database before running any tests */
before(function(done) { before(async () => {
var idbReq = indexedDB.deleteDatabase('test'); await deleteDatabase();
idbReq.onsuccess = function() {
done();
};
});
async function clearDatabase() {
await Signal.Migrations.Migrations0DatabaseWithAttachmentData.run({ await Signal.Migrations.Migrations0DatabaseWithAttachmentData.run({
Backbone, Backbone,
databaseName: Whisper.Database.id, databaseName: Whisper.Database.id,
logger: window.log, logger: window.log,
}); });
});
const convos = new Whisper.ConversationCollection(); async function clearDatabase() {
await wrapDeferred(convos.fetch()); const db = await Whisper.Database.open();
await wrapDeferred(convos.destroyAll()); await Whisper.Database.clear();
const messages = new Whisper.MessageCollection();
await wrapDeferred(messages.fetch());
await wrapDeferred(messages.destroyAll());
} }

@ -1,32 +1,26 @@
'use strict'; 'use strict';
describe('Fixtures', function() { describe('Fixtures', function() {
before(function(done) { before(function() {
// NetworkStatusView checks this method every five seconds while showing // NetworkStatusView checks this method every five seconds while showing
window.getSocketStatus = function() { window.getSocketStatus = function() {
return WebSocket.OPEN; return WebSocket.OPEN;
}; };
Whisper.Fixtures()
.saveAll()
.then(function() {
done();
});
}); });
it('renders', function(done) { it('renders', async () => {
await Whisper.Fixtures().saveAll();
ConversationController.reset(); ConversationController.reset();
ConversationController.load() await ConversationController.load();
.then(function() {
var view = new Whisper.InboxView({ window: window }); var view = new Whisper.InboxView({ window: window });
view.onEmpty(); view.onEmpty();
view.$el.prependTo($('#render-light-theme')); view.$el.prependTo($('#render-light-theme'));
var view = new Whisper.InboxView({ window: window }); var view = new Whisper.InboxView({ window: window });
view.$el.removeClass('light-theme').addClass('dark-theme'); view.$el.removeClass('light-theme').addClass('dark-theme');
view.onEmpty(); view.onEmpty();
view.$el.prependTo($('#render-dark-theme')); view.$el.prependTo($('#render-dark-theme'));
})
.then(done, done);
}); });
}); });

@ -36,15 +36,15 @@
.then(done); .then(done);
}); });
it('fetches persistent convos', function(done) { it('fetches persistent convos', async () => {
var convos = new Whisper.ConversationCollection(); var convos = new Whisper.ConversationCollection();
assert.strictEqual(convos.length, 0); assert.strictEqual(convos.length, 0);
convos.fetch().then(function() {
var m = convos.at(0).attributes; await wrapDeferred(convos.fetch());
_.each(conversation_attributes, function(val, key) {
assert.deepEqual(m[key], val); var m = convos.at(0).attributes;
}); _.each(conversation_attributes, function(val, key) {
done(); assert.deepEqual(m[key], val);
}); });
}); });
@ -226,14 +226,18 @@
}); });
describe('Conversation search', function() { describe('Conversation search', function() {
var convo = new Whisper.ConversationCollection().add({ let convo;
id: '+14155555555',
type: 'private', beforeEach(function(done) {
name: 'John Doe', convo = new Whisper.ConversationCollection().add({
}); id: '+14155555555',
before(function(done) { type: 'private',
name: 'John Doe',
});
convo.save().then(done); convo.save().then(done);
}); });
afterEach(clearDatabase);
function testSearch(queries, done) { function testSearch(queries, done) {
return Promise.all( return Promise.all(
queries.map(function(query) { queries.map(function(query) {

@ -9,6 +9,7 @@ describe('AttachmentView', () => {
before(async () => { before(async () => {
await clearDatabase(); await clearDatabase();
convo = new Whisper.Conversation({ id: 'foo' }); convo = new Whisper.Conversation({ id: 'foo' });
message = convo.messageCollection.add({ message = convo.messageCollection.add({
conversationId: convo.id, conversationId: convo.id,

@ -24,20 +24,26 @@ describe('ConversationSearchView', function() {
}); });
}); });
describe('Searching for left groups', function() { describe('Searching for left groups', function() {
var convo = new Whisper.ConversationCollection().add({ let convo;
id: 'a-left-group',
name: 'i left this group',
members: [],
type: 'group',
left: true,
});
before(() => { before(() => {
convo = new Whisper.ConversationCollection().add({
id: 'a-left-group',
name: 'i left this group',
members: [],
type: 'group',
left: true,
});
return wrapDeferred(convo.save()); return wrapDeferred(convo.save());
}); });
describe('with no messages', function() { describe('with no messages', function() {
var input = $('<input>'); var input;
var view = new Whisper.ConversationSearchView({ input: input }).render(); var view;
before(function(done) { before(function(done) {
input = $('<input>');
view = new Whisper.ConversationSearchView({ input: input }).render();
view.$input.val('left'); view.$input.val('left');
view.filterContacts(); view.filterContacts();
view.typeahead_view.collection.on('reset', function() { view.typeahead_view.collection.on('reset', function() {
@ -52,9 +58,11 @@ describe('ConversationSearchView', function() {
}); });
}); });
describe('with messages', function() { describe('with messages', function() {
var input = $('<input>'); var input;
var view = new Whisper.ConversationSearchView({ input: input }).render(); var view;
before(function(done) { before(function(done) {
input = $('<input>');
view = new Whisper.ConversationSearchView({ input: input }).render();
convo.save({ lastMessage: 'asdf' }).then(function() { convo.save({ lastMessage: 'asdf' }).then(function() {
view.$input.val('left'); view.$input.val('left');
view.filterContacts(); view.filterContacts();
@ -72,17 +80,22 @@ describe('ConversationSearchView', function() {
}); });
}); });
describe('Showing all contacts', function() { describe('Showing all contacts', function() {
var input = $('<input>'); let input;
var view = new Whisper.ConversationSearchView({ input: input }).render(); let view;
view.showAllContacts = true; let convo;
var convo = new Whisper.ConversationCollection().add({
id: 'a-left-group',
name: 'i left this group',
members: [],
type: 'group',
left: true,
});
before(() => { before(() => {
input = $('<input>');
view = new Whisper.ConversationSearchView({ input: input }).render();
view.showAllContacts = true;
convo = new Whisper.ConversationCollection().add({
id: 'a-left-group',
name: 'i left this group',
members: [],
type: 'group',
left: true,
});
return wrapDeferred(convo.save()); return wrapDeferred(convo.save());
}); });
describe('with no messages', function() { describe('with no messages', function() {

@ -1,11 +1,19 @@
describe('InboxView', function() { describe('InboxView', function() {
var inboxView = new Whisper.InboxView({ let inboxView;
model: {}, let conversation;
window: window,
initialLoadComplete: function() {}, before(() => {
}).render(); inboxView = new Whisper.InboxView({
model: {},
var conversation = new Whisper.Conversation({ id: '1234', type: 'private' }); window: window,
initialLoadComplete: function() {},
}).render();
conversation = new Whisper.Conversation({
id: '1234',
type: 'private',
});
});
describe('the conversation stack', function() { describe('the conversation stack', function() {
it('should be rendered', function() { it('should be rendered', function() {

Loading…
Cancel
Save