Frontend for timer updates and timer indicator

This commit is contained in:
lilia 2016-09-28 16:47:57 -07:00
parent 448835e4d5
commit 2b2c6ab040
10 changed files with 242 additions and 26 deletions

View File

@ -360,5 +360,77 @@
"example": "10m"
}
}
},
"timerOption_0_seconds": {
"message": "off",
"description": "Label for option to turn off message expiration in the timer menu"
},
"timerOption_5_seconds": {
"message": "5 seconds",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_10_seconds": {
"message": "10 seconds",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_30_seconds": {
"message": "30 seconds",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_1_day": {
"message": "1 day",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_1_week": {
"message": "1 week",
"description": "Label for a selectable option in the message expiration timer menu"
},
"disappearingMessages": {
"message": "Disappearing messages",
"description": "Conversation menu option to enable disappearing messages"
},
"timerOption_5_seconds_abbreviated": {
"message": "5s",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_10_seconds_abbreviated": {
"message": "10s",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_30_seconds_abbreviated": {
"message": "30s",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_1_minute_abbreviated": {
"message": "1m",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_5_minutes_abbreviated": {
"message": "5m",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_30_minutes_abbreviated": {
"message": "30m",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_1_hour_abbreviated": {
"message": "1h",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_6_hours_abbreviated": {
"message": "6h",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_12_hours_abbreviated": {
"message": "12h",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_1_day_abbreviated": {
"message": "1d",
"description": "Label for a selectable option in the message expiration timer menu"
},
"timerOption_1_week_abbreviated": {
"message": "1w",
"description": "Label for a selectable option in the message expiration timer menu"
}
}

View File

@ -75,9 +75,18 @@
<li class='end-session'>{{ end-session }}</li>
<li class='verify-identity'>{{ verify-identity }}</li>
{{/group}}
<li class='disappearing-messages'>{{ disappearing-messages }}</li>
<li class='destroy'>{{ destroy }}</li>
</ul>
</div>
<div class='timer-menu menu'>
<button class='clock' alt='timer menu'></button>
<ul class='menu-list'>
{{ #timer_options }}
<li data-seconds={{ attributes.seconds }}>{{ getName }}</li>
{{ /timer_options }}
</ul>
</div>
</div>
</div>
<span class='conversation-title'>

View File

@ -11,4 +11,55 @@
this.fetchExpiring();
}
}))();
var TimerOption = Backbone.Model.extend({
getName: function() {
return i18n([
'timerOption', this.get('time'), this.get('unit'),
].join('_')) || moment.duration(this.get('time'), this.get('unit')).humanize();
},
getAbbreviated: function() {
return i18n([
'timerOption', this.get('time'), this.get('unit'), 'abbreviated'
].join('_'));
}
});
Whisper.ExpirationTimerOptions = new (Backbone.Collection.extend({
model: TimerOption,
getName: function(seconds) {
if (!seconds) {
seconds = 0;
}
var o = this.findWhere({seconds: seconds});
if (o) { return o.getName(); }
},
getAbbreviated: function(seconds) {
if (!seconds) {
seconds = 0;
}
var o = this.findWhere({seconds: seconds});
if (o) { return o.getAbbreviated(); }
}
}))([
[ 0, 'seconds' ],
[ 5, 'seconds' ],
[ 10, 'seconds' ],
[ 30, 'seconds' ],
[ 1, 'minute' ],
[ 5, 'minutes' ],
[ 30, 'minutes' ],
[ 1, 'hour' ],
[ 6, 'hours' ],
[ 12, 'hours' ],
[ 1, 'day' ],
[ 1, 'week' ],
].map(function(o) {
var duration = moment.duration(o[0], o[1]); // 5, 'seconds'
return {
time: o[0],
unit: o[1],
seconds: duration.asSeconds()
};
}));
})();

View File

@ -166,20 +166,26 @@
}.bind(this));
},
addExpirationTimerUpdate: function(source, time) {
addExpirationTimerUpdate: function(time, source) {
var now = Date.now();
this.save({ expireTimer: time });
var message = this.messageCollection.add({
conversationId : this.id,
type : 'expirationTimerUpdate',
sent_at : now,
received_at : now,
timerUpdate : {
conversationId : this.id,
type : 'outgoing',
sent_at : now,
received_at : now,
flags : textsecure.protobuf.DataMessage.Flags.EXPIRATION_TIMER_UPDATE,
expirationTimerUpdate : {
expireTimer : time,
source : source
}
});
message.save();
},
sendExpirationTimerUpdate: function(time) {
this.addExpirationTimerUpdate(time, textsecure.storage.user.getNumber());
// todo: send.
},
isSearchable: function() {
return !this.get('left') || !!this.get('lastMessage');

View File

@ -71,7 +71,6 @@
if (this.isIncoming() && this.hasErrors()) {
return i18n('incomingError');
}
return this.get('body');
},
getNotificationText: function() {
@ -126,15 +125,6 @@
}
return c;
},
getModelForExpirationTimerUpdate: function() {
var id = this.get('timerUpdate').source;
var c = ConversationController.get(id);
if (!c) {
c = ConversationController.create({ id: id, type: 'private' });
c.fetch();
}
return c;
},
isOutgoing: function() {
return this.get('type') === 'outgoing';
},
@ -364,9 +354,18 @@
flags : dataMessage.flags,
errors : []
});
if (dataMessage.expireTimer) {
if (message.isExpirationTimerUpdate()) {
message.set({
expirationTimerUpdate: {
source : source,
expireTimer : dataMessage.expireTimer
}
});
conversation.set({expireTimer: dataMessage.expireTimer});
} else if (dataMessage.expireTimer) {
message.set({expireTimer: dataMessage.expireTimer});
// todo: insert an update if needed
conversation.set({expireTimer: dataMessage.expireTimer});
}
var conversation_timestamp = conversation.get('timestamp');

View File

@ -16,6 +16,39 @@
}
});
var MenuView = Whisper.View.extend({
toggleMenu: function() {
this.$('.menu-list').toggle();
}
});
var TimerMenuView = MenuView.extend({
initialize: function() {
this.render();
this.listenTo(this.model, 'change:expireTimer', this.render);
},
events: {
'click button': 'toggleMenu',
'click li': 'setTimer'
},
setTimer: function(e) {
var seconds = this.$(e.target).data().seconds;
if (seconds >= 0) {
this.model.sendExpirationTimerUpdate(seconds);
}
},
render: function() {
var seconds = this.model.get('expireTimer');
if (seconds) {
var s = Whisper.ExpirationTimerOptions.getAbbreviated(seconds);
this.$el.attr('data-time', s);
this.$el.show();
} else {
this.$el.attr('data-time', null);
this.$el.hide();
}
}
});
Whisper.ConversationView = Whisper.View.extend({
className: function() {
return [ 'conversation', this.model.get('type') ].join(' ');
@ -30,11 +63,14 @@
name: this.model.getName(),
number: this.model.getNumber(),
avatar: this.model.getAvatar(),
expireTimer: this.model.get('expireTimer'),
'view-members' : i18n('members'),
'end-session' : i18n('resetSession'),
'verify-identity' : i18n('verifyIdentity'),
'destroy' : i18n('deleteMessages'),
'send-message' : i18n('sendMessage')
'send-message' : i18n('sendMessage'),
'disappearing-messages': i18n('disappearingMessages'),
timer_options : Whisper.ExpirationTimerOptions.models
};
},
initialize: function(options) {
@ -47,6 +83,7 @@
this.listenTo(this.model.messageCollection, 'expired', this.onExpiredCollection);
this.render();
new TimerMenuView({ el: this.$('.timer-menu'), model: this.model });
emoji_util.parse(this.$('.conversation-name'));
@ -105,6 +142,7 @@
'click .bottom-bar': 'focusMessageField',
'click .back': 'resetPanel',
'click .microphone': 'captureAudio',
'click .disappearing-messages': 'enableDisappearingMessages',
'focus .send-message': 'focusBottomBar',
'change .file-input': 'toggleMicrophone',
'blur .send-message': 'unfocusBottomBar',
@ -113,6 +151,13 @@
'select .message-list .entry': 'messageDetail',
'force-resize': 'forceUpdateMessageFieldSize'
},
enableDisappearingMessages: function() {
if (!this.model.get('expireTimer')) {
this.model.sendExpirationTimerUpdate(
moment.duration(1, 'day').asSeconds()
);
}
},
toggleMicrophone: function() {
if (this.$('.send-message').val().length > 0 || this.fileInput.hasFiles()) {
this.$('.capture-audio').hide();
@ -240,7 +285,10 @@
closeMenu: function(e) {
if (e && !$(e.target).hasClass('hamburger')) {
this.$('.menu-list').hide();
this.$('.conversation-menu .menu-list').hide();
}
if (e && !$(e.target).hasClass('clock')) {
this.$('.timer-menu .menu-list').hide();
}
},
@ -255,7 +303,7 @@
},
toggleMenu: function() {
this.$('.menu-list').toggle();
this.$('.conversation-menu .menu-list').toggle();
},
newGroupUpdate: function() {

View File

@ -44,7 +44,7 @@
},
addOne: function(model) {
var view;
if (model.get('type') === 'expirationTimerUpdate') {
if (model.isExpirationTimerUpdate()) {
view = new Whisper.ExpirationTimerUpdateView({model: model}).render();
} else {
view = new this.itemView({model: model}).render();

View File

@ -48,14 +48,16 @@
className: 'expirationTimerUpdate advisory',
templateName: 'expirationTimerUpdate',
initialize: function() {
this.conversation = this.model.getModelForExpirationTimerUpdate();
this.conversation = this.model.getContact();
this.listenTo(this.conversation, 'change', this.render);
},
render_attributes: function() {
var seconds = this.model.get('expirationTimerUpdate').expireTimer;
return {
content: i18n('changedTheTimer',
this.conversation.getTitle(),
this.model.get('timerUpdate').time)
content: i18n('changedTheTimer', [
this.conversation.getTitle(),
Whisper.ExpirationTimerOptions.getName(seconds)
])
};
}
});

View File

@ -123,6 +123,22 @@ button.hamburger {
}
}
.conversation-header .timer-menu {
margin-right: 10px;
&:before {
content: attr(data-time);
display: inline-block;
position: absolute;
bottom: -10px;
height: 10px;
width: 100%;
text-align: center;
font-size: 8px;
font-weight: bold;
}
}
.menu {
position: relative;
float: right;

View File

@ -126,6 +126,19 @@ button.hamburger {
vertical-align: middle;
display: table-cell; }
.conversation-header .timer-menu {
margin-right: 10px; }
.conversation-header .timer-menu:before {
content: attr(data-time);
display: inline-block;
position: absolute;
bottom: -10px;
height: 10px;
width: 100%;
text-align: center;
font-size: 8px;
font-weight: bold; }
.menu {
position: relative;
float: right; }