More work on replayable errors
Expose a button that does that retries outgoing messages if possible. // FREEBIE
This commit is contained in:
parent
bc0c9bd133
commit
a32f3ff1f6
8 changed files with 131 additions and 55 deletions
|
@ -248,6 +248,10 @@
|
|||
{{ #conflict }}
|
||||
<button class='conflict'><span>Verify</span></button>
|
||||
{{ /conflict }}
|
||||
{{ #retry }}
|
||||
<button class='retry'><span>Retry</span></button>
|
||||
<span class='error-message'>{{message}}</span>
|
||||
{{ /retry }}
|
||||
{{ #errors }}
|
||||
<div>
|
||||
<span class='error-message'>{{message}}</span>
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
|
||||
var registeredFunctions = {};
|
||||
var Type = {
|
||||
SEND_MESSAGE: 1,
|
||||
ENCRYPT_MESSAGE: 1,
|
||||
INIT_SESSION: 2,
|
||||
NETWORK_REQUEST: 3,
|
||||
TRANSMIT_MESSAGE: 3,
|
||||
};
|
||||
window.textsecure = window.textsecure || {};
|
||||
window.textsecure.replay = {
|
||||
|
@ -48,7 +48,7 @@
|
|||
|
||||
function OutgoingIdentityKeyError(number, message, timestamp, identityKey) {
|
||||
ReplayableError.call(this, {
|
||||
functionCode : Type.SEND_MESSAGE,
|
||||
functionCode : Type.ENCRYPT_MESSAGE,
|
||||
args : [number, message, timestamp]
|
||||
});
|
||||
this.name = 'OutgoingIdentityKeyError';
|
||||
|
@ -59,23 +59,40 @@
|
|||
OutgoingIdentityKeyError.prototype = new ReplayableError();
|
||||
OutgoingIdentityKeyError.prototype.constructor = OutgoingIdentityKeyError;
|
||||
|
||||
function NetworkError(number, jsonData, legacy, code) {
|
||||
function OutgoingMessageError(number, message, timestamp, httpError) {
|
||||
ReplayableError.call(this, {
|
||||
functionCode : Type.NETWORK_REQUEST,
|
||||
functionCode : Type.ENCRYPT_MESSAGE,
|
||||
args : [number, message, timestamp]
|
||||
});
|
||||
this.name = 'OutgoingMessageError';
|
||||
if (httpError) {
|
||||
this.code = httpError.code;
|
||||
this.message = httpError.message;
|
||||
this.stack = httpError.stack;
|
||||
}
|
||||
}
|
||||
OutgoingMessageError.prototype = new ReplayableError();
|
||||
OutgoingMessageError.prototype.constructor = OutgoingMessageError;
|
||||
|
||||
function SendMessageNetworkError(number, jsonData, legacy, httpError) {
|
||||
ReplayableError.call(this, {
|
||||
functionCode : Type.TRANSMIT_MESSAGE,
|
||||
args : [number, jsonData, legacy]
|
||||
});
|
||||
this.name = 'NetworkError';
|
||||
this.message = 'Network request failed'
|
||||
this.code = code;
|
||||
this.name = 'SendMessageNetworkError';
|
||||
this.number = number;
|
||||
this.code = httpError.code;
|
||||
this.message = httpError.message;
|
||||
this.stack = httpError.stack;
|
||||
}
|
||||
NetworkError.prototype = new ReplayableError();
|
||||
NetworkError.prototype.constructor = NetworkError;
|
||||
SendMessageNetworkError.prototype = new ReplayableError();
|
||||
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
||||
|
||||
window.textsecure.NetworkError = NetworkError;
|
||||
window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
|
||||
window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
|
||||
window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
|
||||
window.textsecure.ReplayableError = ReplayableError;
|
||||
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
||||
|
||||
})();
|
||||
|
||||
|
@ -39637,14 +39654,14 @@ MessageSender.prototype = {
|
|||
});
|
||||
})).then(function(jsonData) {
|
||||
var legacy = (message instanceof textsecure.protobuf.DataMessage);
|
||||
return this.sendRequest(number, jsonData, legacy);
|
||||
return this.sendMessageRequest(number, jsonData, legacy);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
sendRequest: function(number, jsonData, legacy) {
|
||||
sendMessageRequest: function(number, jsonData, legacy) {
|
||||
return this.server.sendMessages(number, jsonData, legacy).catch(function(e) {
|
||||
if (e.name === 'HTTPError' && e.code === -1) {
|
||||
throw new NetworkError(number, jsonData, legacy);
|
||||
if (e.name === 'HTTPError' && (e.code !== 409 && e.code !== 410)) {
|
||||
throw new textsecure.SendMessageNetworkError(number, jsonData, legacy, e);
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
|
@ -39684,9 +39701,10 @@ MessageSender.prototype = {
|
|||
};
|
||||
|
||||
var registerError = function(number, reason, error) {
|
||||
if (!error) {
|
||||
error = new Error(reason);
|
||||
if (!error || error.name === 'HTTPError') {
|
||||
error = new textsecure.OutgoingMessageError(number, message.toArrayBuffer(), timestamp, error);
|
||||
}
|
||||
|
||||
error.number = number;
|
||||
error.reason = reason;
|
||||
errors[errors.length] = error;
|
||||
|
@ -40025,8 +40043,8 @@ window.textsecure = window.textsecure || {};
|
|||
|
||||
textsecure.MessageSender = function(url, username, password) {
|
||||
var sender = new MessageSender(url, username, password);
|
||||
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.SEND_MESSAGE);
|
||||
textsecure.replay.registerFunction(sender.sendRequest.bind(sender), textsecure.replay.Type.NETWORK_REQUEST);
|
||||
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE);
|
||||
textsecure.replay.registerFunction(sender.sendMessageRequest.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE);
|
||||
|
||||
this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender);
|
||||
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender);
|
||||
|
|
|
@ -175,8 +175,18 @@
|
|||
this.set({errors: errors});
|
||||
},
|
||||
|
||||
removeOutgoingErrors: function(number) {
|
||||
var errors = _.partition(this.get('errors'), function(e) {
|
||||
return e.number === number &&
|
||||
(e.name === 'OutgoingMessageError' ||
|
||||
e.name === 'SendMessageNetworkError');
|
||||
});
|
||||
this.set({errors: errors[1]});
|
||||
return errors[0][0];
|
||||
},
|
||||
|
||||
resend: function(number) {
|
||||
var error = this.getSendError(number);
|
||||
var error = this.removeOutgoingErrors(number);
|
||||
if (error) {
|
||||
var promise = new textsecure.ReplayableError(error).replay();
|
||||
this.send(promise);
|
||||
|
|
|
@ -10,22 +10,33 @@
|
|||
templateName: 'contact-detail',
|
||||
initialize: function(options) {
|
||||
this.conflict = options.conflict;
|
||||
this.retry = _.find(options.errors, function(e) {
|
||||
return (e.name === 'OutgoingMessageError' ||
|
||||
e.name === 'SendMessageNetworkError');
|
||||
});
|
||||
this.errors = _.reject(options.errors, function(e) {
|
||||
return (e.name === 'IncomingIdentityKeyError' ||
|
||||
e.name === 'OutgoingIdentityKeyError');
|
||||
e.name === 'OutgoingIdentityKeyError' ||
|
||||
e.name === 'OutgoingMessageError' ||
|
||||
e.name === 'SendMessageNetworkError');
|
||||
});
|
||||
},
|
||||
events: {
|
||||
'click .conflict': 'triggerConflict'
|
||||
'click .conflict': 'triggerConflict',
|
||||
'click .retry': 'triggerRetry'
|
||||
},
|
||||
triggerConflict: function() {
|
||||
this.$el.trigger('conflict', {conflict: this.conflict});
|
||||
},
|
||||
triggerRetry: function() {
|
||||
this.$el.trigger('retry', {error: this.retry});
|
||||
},
|
||||
render_attributes: function() {
|
||||
return {
|
||||
name : this.model.getTitle(),
|
||||
avatar : this.model.getAvatar(),
|
||||
conflict : this.conflict,
|
||||
retry : this.retry,
|
||||
errors : this.errors
|
||||
};
|
||||
}
|
||||
|
@ -43,7 +54,8 @@
|
|||
},
|
||||
events: {
|
||||
'click .back': 'goBack',
|
||||
'conflict': 'conflictDialogue'
|
||||
'conflict': 'conflictDialogue',
|
||||
'retry': 'retryMessage',
|
||||
},
|
||||
goBack: function() {
|
||||
this.trigger('back');
|
||||
|
@ -82,6 +94,9 @@
|
|||
this.render();
|
||||
});
|
||||
},
|
||||
retryMessage: function(e, data) {
|
||||
this.model.resend(data.error.number);
|
||||
},
|
||||
renderContact: function(contact) {
|
||||
var v = new ContactView({
|
||||
model: contact,
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
var registeredFunctions = {};
|
||||
var Type = {
|
||||
SEND_MESSAGE: 1,
|
||||
ENCRYPT_MESSAGE: 1,
|
||||
INIT_SESSION: 2,
|
||||
NETWORK_REQUEST: 3,
|
||||
TRANSMIT_MESSAGE: 3,
|
||||
};
|
||||
window.textsecure = window.textsecure || {};
|
||||
window.textsecure.replay = {
|
||||
|
@ -47,7 +47,7 @@
|
|||
|
||||
function OutgoingIdentityKeyError(number, message, timestamp, identityKey) {
|
||||
ReplayableError.call(this, {
|
||||
functionCode : Type.SEND_MESSAGE,
|
||||
functionCode : Type.ENCRYPT_MESSAGE,
|
||||
args : [number, message, timestamp]
|
||||
});
|
||||
this.name = 'OutgoingIdentityKeyError';
|
||||
|
@ -58,22 +58,39 @@
|
|||
OutgoingIdentityKeyError.prototype = new ReplayableError();
|
||||
OutgoingIdentityKeyError.prototype.constructor = OutgoingIdentityKeyError;
|
||||
|
||||
function NetworkError(number, jsonData, legacy, code) {
|
||||
function OutgoingMessageError(number, message, timestamp, httpError) {
|
||||
ReplayableError.call(this, {
|
||||
functionCode : Type.NETWORK_REQUEST,
|
||||
functionCode : Type.ENCRYPT_MESSAGE,
|
||||
args : [number, message, timestamp]
|
||||
});
|
||||
this.name = 'OutgoingMessageError';
|
||||
if (httpError) {
|
||||
this.code = httpError.code;
|
||||
this.message = httpError.message;
|
||||
this.stack = httpError.stack;
|
||||
}
|
||||
}
|
||||
OutgoingMessageError.prototype = new ReplayableError();
|
||||
OutgoingMessageError.prototype.constructor = OutgoingMessageError;
|
||||
|
||||
function SendMessageNetworkError(number, jsonData, legacy, httpError) {
|
||||
ReplayableError.call(this, {
|
||||
functionCode : Type.TRANSMIT_MESSAGE,
|
||||
args : [number, jsonData, legacy]
|
||||
});
|
||||
this.name = 'NetworkError';
|
||||
this.message = 'Network request failed'
|
||||
this.code = code;
|
||||
this.name = 'SendMessageNetworkError';
|
||||
this.number = number;
|
||||
this.code = httpError.code;
|
||||
this.message = httpError.message;
|
||||
this.stack = httpError.stack;
|
||||
}
|
||||
NetworkError.prototype = new ReplayableError();
|
||||
NetworkError.prototype.constructor = NetworkError;
|
||||
SendMessageNetworkError.prototype = new ReplayableError();
|
||||
SendMessageNetworkError.prototype.constructor = SendMessageNetworkError;
|
||||
|
||||
window.textsecure.NetworkError = NetworkError;
|
||||
window.textsecure.SendMessageNetworkError = SendMessageNetworkError;
|
||||
window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError;
|
||||
window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError;
|
||||
window.textsecure.ReplayableError = ReplayableError;
|
||||
window.textsecure.OutgoingMessageError = OutgoingMessageError;
|
||||
|
||||
})();
|
||||
|
|
|
@ -37,14 +37,14 @@ MessageSender.prototype = {
|
|||
});
|
||||
})).then(function(jsonData) {
|
||||
var legacy = (message instanceof textsecure.protobuf.DataMessage);
|
||||
return this.sendRequest(number, jsonData, legacy);
|
||||
return this.sendMessageRequest(number, jsonData, legacy);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
sendRequest: function(number, jsonData, legacy) {
|
||||
sendMessageRequest: function(number, jsonData, legacy) {
|
||||
return this.server.sendMessages(number, jsonData, legacy).catch(function(e) {
|
||||
if (e.name === 'HTTPError' && e.code === -1) {
|
||||
throw new NetworkError(number, jsonData, legacy);
|
||||
if (e.name === 'HTTPError' && (e.code !== 409 && e.code !== 410)) {
|
||||
throw new textsecure.SendMessageNetworkError(number, jsonData, legacy, e);
|
||||
}
|
||||
throw e;
|
||||
});
|
||||
|
@ -84,9 +84,10 @@ MessageSender.prototype = {
|
|||
};
|
||||
|
||||
var registerError = function(number, reason, error) {
|
||||
if (!error) {
|
||||
error = new Error(reason);
|
||||
if (!error || error.name === 'HTTPError') {
|
||||
error = new textsecure.OutgoingMessageError(number, message.toArrayBuffer(), timestamp, error);
|
||||
}
|
||||
|
||||
error.number = number;
|
||||
error.reason = reason;
|
||||
errors[errors.length] = error;
|
||||
|
@ -425,8 +426,8 @@ window.textsecure = window.textsecure || {};
|
|||
|
||||
textsecure.MessageSender = function(url, username, password) {
|
||||
var sender = new MessageSender(url, username, password);
|
||||
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.SEND_MESSAGE);
|
||||
textsecure.replay.registerFunction(sender.sendRequest.bind(sender), textsecure.replay.Type.NETWORK_REQUEST);
|
||||
textsecure.replay.registerFunction(sender.tryMessageAgain.bind(sender), textsecure.replay.Type.ENCRYPT_MESSAGE);
|
||||
textsecure.replay.registerFunction(sender.sendMessageRequest.bind(sender), textsecure.replay.Type.TRANSMIT_MESSAGE);
|
||||
|
||||
this.sendRequestGroupSyncMessage = sender.sendRequestGroupSyncMessage .bind(sender);
|
||||
this.sendRequestContactSyncMessage = sender.sendRequestContactSyncMessage.bind(sender);
|
||||
|
|
|
@ -61,13 +61,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
.conflict {
|
||||
.contact-detail button {
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
padding: 0.5em;
|
||||
font-weight: bold;
|
||||
background: #d00;
|
||||
background: $blue;
|
||||
|
||||
span {
|
||||
vertical-align: middle;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
|
@ -75,13 +80,15 @@
|
|||
vertical-align: middle;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: url('/images/error.png') no-repeat center center;
|
||||
background: url('/images/refresh.png') no-repeat center center;
|
||||
background-size: 100%;
|
||||
}
|
||||
}
|
||||
.conflict {
|
||||
background: #d00;
|
||||
|
||||
span {
|
||||
vertical-align: middle;
|
||||
padding-left: 5px;
|
||||
&:before {
|
||||
background: url('/images/error.png') no-repeat center center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -550,24 +550,28 @@ input.search {
|
|||
font-weight: bold;
|
||||
padding-right: 1em;
|
||||
vertical-align: top; }
|
||||
.message-detail .conflict {
|
||||
.message-detail .contact-detail button {
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
color: white;
|
||||
padding: 0.5em;
|
||||
font-weight: bold;
|
||||
background: #d00; }
|
||||
.message-detail .conflict:before {
|
||||
background: #2090ea; }
|
||||
.message-detail .contact-detail button span {
|
||||
vertical-align: middle;
|
||||
padding-left: 5px; }
|
||||
.message-detail .contact-detail button:before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
background: url("/images/error.png") no-repeat center center;
|
||||
background: url("/images/refresh.png") no-repeat center center;
|
||||
background-size: 100%; }
|
||||
.message-detail .conflict span {
|
||||
vertical-align: middle;
|
||||
padding-left: 5px; }
|
||||
.message-detail .conflict {
|
||||
background: #d00; }
|
||||
.message-detail .conflict:before {
|
||||
background: url("/images/error.png") no-repeat center center; }
|
||||
|
||||
.group-update {
|
||||
font-size: smaller; }
|
||||
|
|
Loading…
Reference in a new issue