Frontend for timer updates and timer indicator
This commit is contained in:
parent
448835e4d5
commit
2b2c6ab040
10 changed files with 242 additions and 26 deletions
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'>
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
}));
|
||||
|
||||
})();
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
])
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
Loading…
Reference in a new issue