Conversation: store lastMessage/lastMessageStatus in memory only

This commit is contained in:
Scott Nonnenberg 2018-07-25 15:02:37 -07:00
parent f39a96bc76
commit 61f7b8360b
8 changed files with 126 additions and 85 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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