Fixup delivery receipts

Uses app-level timestamps for outgoing messages.
Adds timestamp property to the outgoing jsonData.
Triggers a runtime event to notify frontend on delivery receipts.
Renders delivered messages with a 'delivered' class.
This commit is contained in:
lilia 2014-12-21 21:01:21 -08:00
parent 348b5a53b1
commit ccc98d2f3d
5 changed files with 25 additions and 16 deletions

View file

@ -215,6 +215,7 @@ window.textsecure.api = function () {
var jsonData = { messages: messageArray }; var jsonData = { messages: messageArray };
if (messageArray[0].relay !== undefined) if (messageArray[0].relay !== undefined)
jsonData.relay = messageArray[0].relay; jsonData.relay = messageArray[0].relay;
jsonData.timestamp = messageArray[0].timestamp;
return doAjax({ return doAjax({
call : 'messages', call : 'messages',

View file

@ -157,17 +157,20 @@
} }
function onDeliveryReceipt(pushMessage) { function onDeliveryReceipt(pushMessage) {
console.log('delivery receipt', pushMessage.source, timestamp);
var timestamp = pushMessage.timestamp.toNumber(); var timestamp = pushMessage.timestamp.toNumber();
var messages = new Whisper.MessageCollection(); var messages = new Whisper.MessageCollection();
var groups = new Whisper.ConversationCollection(); var groups = new Whisper.ConversationCollection();
console.log('delivery receipt', pushMessage.source, timestamp);
messages.fetchSentAt(timestamp).then(function() { messages.fetchSentAt(timestamp).then(function() {
groups.fetchGroups(pushMessage.source).then(function() { groups.fetchGroups(pushMessage.source).then(function() {
for (var message in messages.where({type: 'outgoing'})) { for (var i in messages.where({type: 'outgoing'})) {
var message = messages.at(i);
var deliveries = message.get('delivered') || 0; var deliveries = message.get('delivered') || 0;
var conversationId = message.get('conversationId'); var conversationId = message.get('conversationId');
if (conversationId === pushMessage.source || groups.get(conversationId)) { if (conversationId === pushMessage.source || groups.get(conversationId)) {
message.save({delivered: deliveries + 1}); message.save({delivered: deliveries + 1}).then(function() {
extension.trigger('message', message); // notify frontend listeners
});
return; return;
// TODO: consider keeping a list of numbers we've // TODO: consider keeping a list of numbers we've
// successfully delivered to? // successfully delivered to?

View file

@ -66,7 +66,7 @@
else { else {
sendFunc = textsecure.messaging.sendMessageToGroup; sendFunc = textsecure.messaging.sendMessageToGroup;
} }
sendFunc(this.get('id'), body, attachments).catch(function(e) { sendFunc(this.get('id'), body, attachments, now).catch(function(e) {
if (e.name === 'OutgoingIdentityKeyError') { if (e.name === 'OutgoingIdentityKeyError') {
e.args.push(message.id); e.args.push(message.id);
message.save({ errors : [e] }).then(function() { message.save({ errors : [e] }).then(function() {

View file

@ -47,7 +47,7 @@ window.textsecure.messaging = function() {
// success_callback(server success/failure map), error_callback(error_msg) // success_callback(server success/failure map), error_callback(error_msg)
// message == PushMessageContentProto (NOT STRING) // message == PushMessageContentProto (NOT STRING)
function sendMessageToDevices(number, deviceObjectList, message, success_callback, error_callback) { function sendMessageToDevices(timestamp, number, deviceObjectList, message, success_callback, error_callback) {
var jsonData = []; var jsonData = [];
var relay = undefined; var relay = undefined;
var promises = []; var promises = [];
@ -71,7 +71,7 @@ window.textsecure.messaging = function() {
destinationDeviceId: textsecure.utils.unencodeNumber(deviceObjectList[i].encodedNumber)[1], destinationDeviceId: textsecure.utils.unencodeNumber(deviceObjectList[i].encodedNumber)[1],
destinationRegistrationId: deviceObjectList[i].registrationId, destinationRegistrationId: deviceObjectList[i].registrationId,
body: encryptedMsg.body, body: encryptedMsg.body,
timestamp: new Date().getTime() timestamp: timestamp
}; };
if (deviceObjectList[i].relay !== undefined) if (deviceObjectList[i].relay !== undefined)
@ -136,7 +136,7 @@ window.textsecure.messaging = function() {
}; };
textsecure.replay.registerFunction(tryMessageAgain, textsecure.replay.Type.SEND_MESSAGE); textsecure.replay.registerFunction(tryMessageAgain, textsecure.replay.Type.SEND_MESSAGE);
var sendMessageProto = function(numbers, message, callback) { var sendMessageProto = function(timestamp, numbers, message, callback) {
var numbersCompleted = 0; var numbersCompleted = 0;
var errors = []; var errors = [];
var successfulNumbers = []; var successfulNumbers = [];
@ -170,7 +170,7 @@ window.textsecure.messaging = function() {
} }
doSendMessage = function(number, devicesForNumber, recurse) { doSendMessage = function(number, devicesForNumber, recurse) {
return sendMessageToDevices(number, devicesForNumber, message).then(function(result) { return sendMessageToDevices(timestamp, number, devicesForNumber, message).then(function(result) {
successfulNumbers[successfulNumbers.length] = number; successfulNumbers[successfulNumbers.length] = number;
numberCompleted(); numberCompleted();
}).catch(function(error) { }).catch(function(error) {
@ -234,9 +234,9 @@ window.textsecure.messaging = function() {
}); });
} }
var sendIndividualProto = function(number, proto) { var sendIndividualProto = function(number, proto, timestamp) {
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
sendMessageProto([number], proto, function(res) { sendMessageProto(timestamp, [number], proto, function(res) {
if (res.failure.length > 0) if (res.failure.length > 0)
reject(res.failure[0].error); reject(res.failure[0].error);
else else
@ -245,12 +245,13 @@ window.textsecure.messaging = function() {
}); });
} }
sendGroupProto = function(numbers, proto) { sendGroupProto = function(numbers, proto, timestamp) {
timestamp = timestamp || Date.now();
var me = textsecure.utils.unencodeNumber(textsecure.storage.getUnencrypted("number_id"))[0]; var me = textsecure.utils.unencodeNumber(textsecure.storage.getUnencrypted("number_id"))[0];
numbers = numbers.filter(function(number) { return number != me; }); numbers = numbers.filter(function(number) { return number != me; });
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
sendMessageProto(numbers, proto, function(res) { sendMessageProto(timestamp, numbers, proto, function(res) {
if (res.failure.length > 0) if (res.failure.length > 0)
reject(res.failure); reject(res.failure);
else else
@ -259,7 +260,7 @@ window.textsecure.messaging = function() {
}); });
} }
self.sendMessageToNumber = function(number, messageText, attachments) { self.sendMessageToNumber = function(number, messageText, attachments, timestamp) {
var proto = new textsecure.protobuf.PushMessageContent(); var proto = new textsecure.protobuf.PushMessageContent();
proto.body = messageText; proto.body = messageText;
@ -268,7 +269,7 @@ window.textsecure.messaging = function() {
promises.push(makeAttachmentPointer(attachments[i])); promises.push(makeAttachmentPointer(attachments[i]));
return Promise.all(promises).then(function(attachmentsArray) { return Promise.all(promises).then(function(attachmentsArray) {
proto.attachments = attachmentsArray; proto.attachments = attachmentsArray;
return sendIndividualProto(number, proto); return sendIndividualProto(number, proto, timestamp);
}); });
} }
@ -285,7 +286,7 @@ window.textsecure.messaging = function() {
}); });
} }
self.sendMessageToGroup = function(groupId, messageText, attachments) { self.sendMessageToGroup = function(groupId, messageText, attachments, timestamp) {
var proto = new textsecure.protobuf.PushMessageContent(); var proto = new textsecure.protobuf.PushMessageContent();
proto.body = messageText; proto.body = messageText;
proto.group = new textsecure.protobuf.PushMessageContent.GroupContext(); proto.group = new textsecure.protobuf.PushMessageContent.GroupContext();
@ -301,7 +302,7 @@ window.textsecure.messaging = function() {
promises.push(makeAttachmentPointer(attachments[i])); promises.push(makeAttachmentPointer(attachments[i]));
return Promise.all(promises).then(function(attachmentsArray) { return Promise.all(promises).then(function(attachmentsArray) {
proto.attachments = attachmentsArray; proto.attachments = attachmentsArray;
return sendGroupProto(numbers, proto); return sendGroupProto(numbers, proto, timestamp);
}); });
} }

View file

@ -85,6 +85,10 @@
}) })
); );
if (this.model.get('delivered')) {
this.$el.addClass('delivered');
}
var errors = this.model.get('errors'); var errors = this.model.get('errors');
if (errors && errors.length) { if (errors && errors.length) {
this.$el.find('.message').append( this.$el.find('.message').append(