Add new Last Seen Indicator with unread count, scroll to it

This is to ensure that when there are a lot of unread messages, the user
is given the chance to see all of them by being scrolled to the oldest
new message.

When a new message comes in, the indicator will be incremented.

When the user sends a message or switches away from the conversation,
the last seen indicator will be removed.

FREEBIE
This commit is contained in:
Scott Nonnenberg 2017-05-17 14:32:03 -07:00
parent bec69826ae
commit fed26c36ca
8 changed files with 133 additions and 2 deletions

View File

@ -3,6 +3,20 @@
"message": "You left the group",
"description": "Displayed when a user can't send a message because they have left the group"
},
"unreadMessage": {
"message": "1 unread message",
"description": "Text for unread message separator, just one message"
},
"unreadMessages": {
"message": "$count$ unread messages",
"description": "Text for unread message separator, with count",
"placeholders": {
"count": {
"content": "$1",
"example": "5"
}
}
},
"debugLogExplanation": {
"message": "This log will be posted publicly online for contributors to view. You may examine and edit it before submitting."
},

View File

@ -42,6 +42,11 @@
</div>
</div>
</script>
<script type='text/x-tmpl-mustache' id='last-seen-indicator-view'>
<div class='text'>
{{ unreadMessages }}
</div>
</script>
<script type='text/x-tmpl-mustache' id='expired_alert'>
<a target='_blank' href='https://chrome.google.com/webstore/detail/bikioccmkafdpakkkcpdbppfkghcmihk'>
<button class='upgrade'>{{ upgrade }}</button>
@ -630,6 +635,7 @@
<script type='text/javascript' src='js/emoji_util.js'></script>
<script type='text/javascript' src='js/views/whisper_view.js'></script>
<script type='text/javascript' src='js/views/last_seen_indicator_view.js'></script>
<script type='text/javascript' src='js/views/debug_log_view.js'></script>
<script type='text/javascript' src='js/views/toast_view.js'></script>
<script type='text/javascript' src='js/views/attachment_preview_view.js'></script>

View File

@ -201,11 +201,45 @@
this.$('.bottom-bar form').addClass('active');
},
updateUnread: function() {
this.updateLastSeenIndicator();
this.model.markRead();
},
onOpened: function() {
this.view.resetScrollPosition();
this.$el.trigger('force-resize');
this.focusMessageField();
this.model.markRead();
if (this.inProgressFetch) {
this.inProgressFetch.then(this.updateUnread.bind(this));
} else {
this.updateUnread();
}
},
removeLastSeenIndicator: function() {
if (this.lastSeenIndicator) {
this.lastSeenIndicator.remove();
this.lastSeenIndicator = null;
}
},
updateLastSeenIndicator: function() {
this.removeLastSeenIndicator();
var oldestUnread = this.model.messageCollection.find(function(model) {
return model.get('unread');
});
if (oldestUnread) {
var unreadCount = this.model.get('unreadCount');
this.lastSeenIndicator = new Whisper.LastSeenIndicatorView({count: unreadCount});
var unreadEl = this.lastSeenIndicator.render().$el;
unreadEl.insertBefore(this.$('#' + oldestUnread.get('id')));
var position = unreadEl[0].scrollIntoView(true);
}
},
focusMessageField: function() {
@ -215,15 +249,18 @@
fetchMessages: function() {
console.log('fetchMessages');
this.$('.bar-container').show();
return this.model.fetchContacts().then(function() {
this.inProgressFetch = this.model.fetchContacts().then(function() {
return this.model.fetchMessages().then(function() {
this.$('.bar-container').hide();
this.model.messageCollection.where({unread: 1}).forEach(function(m) {
m.fetch();
});
this.inProgressFetch = null;
}.bind(this));
}.bind(this));
// TODO catch?
return this.inProgressFetch;
},
onExpired: function(message) {
@ -241,6 +278,10 @@
this.model.messageCollection.add(message, {merge: true});
message.setToExpire();
if (this.lastSeenIndicator) {
this.lastSeenIndicator.increment(1);
}
if (!this.isHidden() && window.isFocused()) {
this.markRead();
}
@ -345,6 +386,8 @@
},
sendMessage: function(e) {
this.removeLastSeenIndicator();
var toast;
if (extension.expired()) {
toast = new Whisper.ExpiredToast();

View File

@ -0,0 +1,30 @@
/*
* vim: ts=4:sw=4:expandtab
*/
(function () {
'use strict';
window.Whisper = window.Whisper || {};
Whisper.LastSeenIndicatorView = Whisper.View.extend({
className: 'last-seen-indicator-view',
templateName: 'last-seen-indicator-view',
initialize: function(options) {
options = options || {};
this.count = options.count || 0;
},
increment: function(count) {
this.count += count;
this.render();
},
render_attributes: function() {
var unreadMessages = this.count === 1 ? i18n('unreadMessage')
: i18n('unreadMessages', [this.count]);
return {
unreadMessages: unreadMessages
};
}
});
})();

View File

@ -70,4 +70,8 @@
.inactive button.back {
@include header-icon-black('/images/back.svg');
}
.message-list .last-seen-indicator-view .text {
margin-top: 2em;
}
}

View File

@ -682,3 +682,17 @@ li.entry .error-icon-container {
border-radius: $border-radius;
}
}
.message-list .last-seen-indicator-view {
display: flex;
flex-direction: column;
align-items: center;
.text {
border-radius: $border-radius;
padding: 5px 10px;
margin: 1em;
background-color: $grey_l2;
}
}

View File

@ -202,4 +202,9 @@ $text-dark: #CCCCCC;
.recorder {
background: $grey-dark_l2;
}
.message-list .last-seen-indicator-view .text {
margin-top: 2em;
background-color: $grey-dark_l2;
}
}

View File

@ -1496,6 +1496,16 @@ li.entry .error-icon-container {
color: #454545;
border-radius: 5px; }
.message-list .last-seen-indicator-view {
display: flex;
flex-direction: column;
align-items: center; }
.message-list .last-seen-indicator-view .text {
border-radius: 5px;
padding: 5px 10px;
margin: 1em;
background-color: #d9d9d9; }
.ios #header {
height: 64px;
border-bottom: 1px solid rgba(0, 0, 0, 0.05);
@ -1838,6 +1848,8 @@ li.entry .error-icon-container {
-webkit-mask: url("/images/back.svg") no-repeat center;
-webkit-mask-size: 100%;
background-color: black; }
.android .message-list .last-seen-indicator-view .text {
margin-top: 2em; }
.android-dark {
color: #CCCCCC; }
@ -2098,5 +2110,8 @@ li.entry .error-icon-container {
background-color: #292929; }
.android-dark .recorder {
background: #292929; }
.android-dark .message-list .last-seen-indicator-view .text {
margin-top: 2em;
background-color: #292929; }
/*# sourceMappingURL=manifest.css.map */