Style resend button as an inline link

For messages that failed to send due to network errors, this change
allows retrying them directly from the main conversation view rather
than only from the message detail view.

// FREEBIE
pull/749/head
lilia 9 years ago
parent c48484e04f
commit 3901bcb8df

@ -238,5 +238,9 @@
"restartSignal": {
"message": "Restart Signal",
"description": "Menu item for restarting the program."
},
"messageNotSent": {
"message": "Message not sent.",
"description": "Informational label, appears on messages that failed to send"
}
}

@ -110,6 +110,10 @@
<img src='{{ source }}' class='preview' />
<div class='close'>x</div>
</script>
<script type='text/x-tmpl-mustache' id='hasRetry'>
{{ messageNotSent }}
<span href='#' class='retry'>{{ resend }}</span>
</script>
<script type='text/x-tmpl-mustache' id='message'>
{{> avatar }}
<div class='bubble'>
@ -196,12 +200,6 @@
</script>
<script type='text/x-tmpl-mustache' id='message-detail'>
<div class='container'>
{{ #hasRetry }}
<div class='hasRetry clearfix'>
<h3 class='retryMessage'>{{ failedToSend }}</h3>
<button class='retry'>{{ resend }}</button>
</div>
{{ /hasRetry }}
{{ #hasConflict }}
<div class='hasConflict clearfix'>
<div class='conflicts'>

@ -211,6 +211,14 @@
this.set({errors: errors});
},
hasNetworkError: function(number) {
var error = _.find(this.get('errors'), function(e) {
return (e.name === 'MessageError' ||
e.name === 'OutgoingMessageError' ||
e.name === 'SendMessageNetworkError');
});
return !!error;
},
removeOutgoingErrors: function(number) {
var errors = _.partition(this.get('errors'), function(e) {
return e.number === number &&

@ -38,8 +38,7 @@
this.listenTo(this.model, 'change', this.render);
},
events: {
'click .back': 'goBack',
'click .retry': 'retryMessage',
'click .back': 'goBack'
},
goBack: function() {
this.trigger('back');
@ -65,16 +64,6 @@
return this.conversation.contactCollection.models;
}
},
retryMessage: function() {
var retrys = _.filter(this.model.get('errors'), function(e) {
return (e.name === 'MessageError' ||
e.name === 'OutgoingMessageError' ||
e.name === 'SendMessageNetworkError');
});
_.map(retrys, 'number').forEach(function(number) {
this.model.resend(number);
}.bind(this));
},
renderContact: function(contact) {
var view = new ContactView({
model: contact,
@ -105,11 +94,6 @@
},
render: function() {
this.errors = _.groupBy(this.model.get('errors'), 'number');
var hasRetry = _.find(this.model.get('errors'), function(e) {
return (e.name === 'MessageError' ||
e.name === 'OutgoingMessageError' ||
e.name === 'SendMessageNetworkError');
});
var unknownErrors = this.errors['undefined'];
if (unknownErrors) {
unknownErrors = unknownErrors.filter(function(e) {
@ -124,10 +108,7 @@
title : i18n('messageDetail'),
sent : i18n('sent'),
received : i18n('received'),
resend : i18n('resend'),
failedToSend: i18n('failedToSend'),
errorLabel : i18n('error'),
hasRetry : hasRetry,
hasConflict : this.model.hasKeyConflicts()
}));
this.view.$el.prependTo(this.$('.message-container'));

@ -7,6 +7,16 @@
var URL_REGEX = /(^|[\s\n]|<br\/?>)((?:https?|ftp):\/\/[\-A-Z0-9\u00A0-\uD7FF\uE000-\uFDCF\uFDF0-\uFFFD+\u0026\u2019@#\/%?=()~_|!:,.;]*[\-A-Z0-9+\u0026@#\/%=~()_|])/gi;
var NetworkErrorView = Whisper.View.extend({
tagName: 'span',
className: 'hasRetry',
templateName: 'hasRetry',
render_attributes: {
messageNotSent: i18n('messageNotSent'),
resend: i18n('resend')
}
});
Whisper.MessageView = Whisper.View.extend({
tagName: 'li',
templateName: 'message',
@ -22,9 +32,21 @@
this.timeStampView = new Whisper.ExtendedTimestampView();
},
events: {
'click .meta': 'select',
'click .retry': 'retryMessage',
'click .timestamp': 'select',
'click .status': 'select',
'click .error': 'select'
},
retryMessage: function() {
var retrys = _.filter(this.model.get('errors'), function(e) {
return (e.name === 'MessageError' ||
e.name === 'OutgoingMessageError' ||
e.name === 'SendMessageNetworkError');
});
_.map(retrys, 'number').forEach(function(number) {
this.model.resend(number);
}.bind(this));
},
select: function(e) {
this.$el.trigger('select', {message: this.model});
e.stopPropagation();
@ -63,6 +85,11 @@
} else {
this.$el.removeClass('error');
}
if (this.model.hasNetworkError()) {
this.$('.meta').prepend(new NetworkErrorView().render().el);
} else {
this.$('.meta .hasRetry').remove();
}
},
renderControl: function() {
if (this.model.isEndSession() || this.model.isGroupUpdate()) {
@ -79,7 +106,7 @@
message: this.model.get('body'),
timestamp: this.model.get('sent_at'),
sender: (contact && contact.getTitle()) || '',
avatar: (contact && contact.getAvatar())
avatar: (contact && contact.getAvatar()),
}, this.render_partials())
);
this.timeStampView.setElement(this.$('.timestamp'));

@ -70,8 +70,7 @@
}
.message-detail {
.key-conflict-dialogue,
.hasRetry {
.key-conflict-dialogue {
background: #F3F3A7;
border-radius: 5px;
padding: 1em;
@ -92,24 +91,6 @@
}
}
.hasRetry {
padding: 10px 20px;
button {
margin: 5px;
background: $blue;
&:before {
content: '';
display: inline-block;
vertical-align: middle;
width: 18px;
height: 18px;
background: url('/images/refresh.png') no-repeat center center;
background-size: 100%;
}
}
}
.key-conflict-dialogue {
.content p {
max-width: 40em;
@ -247,7 +228,6 @@
}
.timestamp {
font-size: smaller;
margin-right: 3px;
}
@ -300,28 +280,43 @@
}
.meta {
font-size: smaller;
margin-top: 3px;
float: right;
cursor: pointer;
.hasRetry + .timestamp {
&:before {
content:"\00b7"; // &middot
font-weight: bold;
padding: 0 5px 0 4px;
text-decoration: none;
opacity: 0.5;
}
}
.retry {
text-decoration: underline;
cursor: pointer;
}
.hasRetry, .timestamp, .status {
float: left;
}
.timestamp, .status {
cursor: pointer;
opacity: 0.5;
}
&:hover {
.timestamp, .status {
&:hover {
opacity: 1.0;
}
.timestamp {
text-decoration: underline;
}
}
}
.status {
float: right;
width: 18px;
height: 1em;
height: 14px;
line-height: 1em;
}
.sent .status {
display: inline-block;

@ -675,14 +675,12 @@ input.search {
.key-verification .placeholder {
font-weight: bold; }
.message-detail .key-conflict-dialogue,
.message-detail .hasRetry {
.message-detail .key-conflict-dialogue {
background: #F3F3A7;
border-radius: 5px;
padding: 1em;
margin: 1em; }
.message-detail .key-conflict-dialogue button,
.message-detail .hasRetry button {
.message-detail .key-conflict-dialogue button {
outline: none;
border: none;
border-radius: 5px;
@ -690,22 +688,8 @@ input.search {
padding: 0.5em 1em;
font-weight: bold;
line-height: 18px; }
.message-detail .key-conflict-dialogue button span,
.message-detail .hasRetry button span {
.message-detail .key-conflict-dialogue button span {
vertical-align: middle; }
.message-detail .hasRetry {
padding: 10px 20px; }
.message-detail .hasRetry button {
margin: 5px;
background: #2090ea; }
.message-detail .hasRetry button:before {
content: '';
display: inline-block;
vertical-align: middle;
width: 18px;
height: 18px;
background: url("/images/refresh.png") no-repeat center center;
background-size: 100%; }
.message-detail .key-conflict-dialogue .content p {
max-width: 40em;
margin: 1em auto; }
@ -807,7 +791,6 @@ input.search {
font-weight: bold; }
.timestamp {
font-size: smaller;
margin-right: 3px; }
.message-container,
@ -853,25 +836,39 @@ input.search {
margin: 0; }
.message-container .meta,
.message-list .meta {
font-size: smaller;
margin-top: 3px;
float: right;
cursor: pointer; }
float: right; }
.message-container .meta .hasRetry + .timestamp:before,
.message-list .meta .hasRetry + .timestamp:before {
content: "\00b7";
font-weight: bold;
padding: 0 5px 0 4px;
text-decoration: none;
opacity: 0.5; }
.message-container .meta .retry,
.message-list .meta .retry {
text-decoration: underline;
cursor: pointer; }
.message-container .meta .hasRetry, .message-container .meta .timestamp, .message-container .meta .status,
.message-list .meta .hasRetry,
.message-list .meta .timestamp,
.message-list .meta .status {
float: left; }
.message-container .meta .timestamp, .message-container .meta .status,
.message-list .meta .timestamp,
.message-list .meta .status {
cursor: pointer;
opacity: 0.5; }
.message-container .meta:hover .timestamp, .message-container .meta:hover .status,
.message-list .meta:hover .timestamp,
.message-list .meta:hover .status {
opacity: 1.0; }
.message-container .meta:hover .timestamp,
.message-list .meta:hover .timestamp {
text-decoration: underline; }
.message-container .meta .timestamp:hover, .message-container .meta .status:hover,
.message-list .meta .timestamp:hover,
.message-list .meta .status:hover {
opacity: 1.0; }
.message-container .status,
.message-list .status {
float: right;
width: 18px;
height: 1em; }
height: 14px;
line-height: 1em; }
.message-container .sent .status,
.message-list .sent .status {
display: inline-block;

Loading…
Cancel
Save