Nest key verification inside conflict dialogs

// FREEBIE
This commit is contained in:
lilia 2016-03-23 12:33:50 -07:00
parent c4fcbd8cbe
commit 6fe9c3f964
8 changed files with 123 additions and 122 deletions

View file

@ -22,16 +22,18 @@
} }
}, },
"acceptNewKey": { "acceptNewKey": {
"message": "Accept new key" "message": "Accept",
"description": "Label for a button to accept a new identity key"
}, },
"verify": { "verify": {
"message": "Verify" "message": "Verify"
}, },
"newIdentity": { "newIdentity": {
"message": "New Identity" "message": "New Identity",
"description": "Header for a key change dialog"
}, },
"identityChanged": { "identityChanged": {
"message": "This contact's identity key has changed. This could either mean that someone is trying to intercept your communication, or this contact simply re-installed Signal and now has a new identity key." "message": "This contact is using a new Signal identity. This could either mean that someone is trying to intercept your communication, or this contact simply re-installed Signal. You may wish to verify their new identity."
}, },
"outgoingKeyConflict": { "outgoingKeyConflict": {
"message": "This contact's identity key has changed. Click to process and display." "message": "This contact's identity key has changed. Click to process and display."
@ -242,5 +244,13 @@
"messageNotSent": { "messageNotSent": {
"message": "Message not sent.", "message": "Message not sent.",
"description": "Informational label, appears on messages that failed to send" "description": "Informational label, appears on messages that failed to send"
},
"showMore": {
"message": "Details",
"description": "Displays the details of a key change"
},
"showLess": {
"message": "Hide details",
"description": "Hides the details of a key change"
} }
} }

View file

@ -235,8 +235,12 @@
<script type='text/x-tmpl-mustache' id='group-member-list'> <script type='text/x-tmpl-mustache' id='group-member-list'>
<div class='container'></div> <div class='container'></div>
</script> </script>
<script type='text/x-tmpl-mustache' id='key-verification'> <script type='text/x-tmpl-mustache' id='key_verification_panel'>
<div class='container'> <div class='container'>
{{> key_verification }}
</div>
</script>
<script type='text/x-tmpl-mustache' id='key_verification'>
<p> {{theirIdentity}} </p> <p> {{theirIdentity}} </p>
{{ ^their_key }} {{ ^their_key }}
<div class='placeholder'>{{ their_key_unknown }}</div> <div class='placeholder'>{{ their_key_unknown }}</div>
@ -250,7 +254,6 @@
<div class='key'> <div class='key'>
{{ #your_key }} <span>{{ . }}</span> {{ /your_key }} {{ #your_key }} <span>{{ . }}</span> {{ /your_key }}
</div> </div>
</div>
</script> </script>
<!-- index --> <!-- index -->
<script type='text/x-tmpl-mustache' id='group_info_input'> <script type='text/x-tmpl-mustache' id='group_info_input'>
@ -305,15 +308,13 @@
<div class='clearfix'> <div class='clearfix'>
<h3>{{ newIdentity }}</h3> <h3>{{ newIdentity }}</h3>
{{> avatar }} {{> avatar }}
<span class='name'>{{ name }} <span class='name'>{{ name }}</span>
<button class='conflict'><span>{{ verify }}</span></button> <button class='resolve'>{{ resolve }}</button>
<button class='cancel hide'><span>{{ cancel }}</span></button> <span class='hideKeys hide'> {{ hideKeys }} </span>
</span> <span class='showKeys'> {{ showKeys }} </span>
</div> </div>
<div class='content hide'> <div class='keys hide'>
<p> {{ message }} </p> <p> {{ message }} </p>
<p> {{{ verifyContact }}} </p>
<p><button class='resolve'>{{ resolve }}</button></p>
</div> </div>
</script> </script>
<script type='text/x-tmpl-mustache' id='window-controls'> <script type='text/x-tmpl-mustache' id='window-controls'>

View file

@ -162,7 +162,7 @@
var our_number = textsecure.storage.user.getNumber(); var our_number = textsecure.storage.user.getNumber();
textsecure.storage.axolotl.getIdentityKey(their_number).then(function(their_key) { textsecure.storage.axolotl.getIdentityKey(their_number).then(function(their_key) {
textsecure.storage.axolotl.getIdentityKey(our_number).then(function(our_key) { textsecure.storage.axolotl.getIdentityKey(our_number).then(function(our_key) {
var view = new Whisper.KeyVerificationView({ var view = new Whisper.KeyVerificationPanelView({
model: { their_key: their_key, your_key: our_key } model: { their_key: their_key, your_key: our_key }
}).render(); }).render();
this.listenBack(view); this.listenBack(view);

View file

@ -11,42 +11,48 @@
className: 'key-conflict-dialogue clearfix', className: 'key-conflict-dialogue clearfix',
initialize: function(options) { initialize: function(options) {
this.contact = options.contact; this.contact = options.contact;
this.conflict = options.conflict;
this.conversation = options.conversation; this.conversation = options.conversation;
textsecure.storage.axolotl.getIdentityKey(textsecure.storage.user.getNumber()).then(function(our_key) {
this.your_key = our_key;
this.render();
}.bind(this));
textsecure.storage.axolotl.getIdentityKey(textsecure.storage.user.getNumber()).then(function(our_key) {
var view = new Whisper.KeyVerificationView({
model: {
their_key : this.model.identityKey,
your_key : our_key
}
});
view.render().$el.appendTo(this.$('.keys'));
}.bind(this));
}, },
events: { events: {
'click .conflict': 'showDialog', 'click .showKeys': 'showKeys',
'click .cancel' : 'cancel', 'click .hideKeys': 'hideKeys',
'click .verify' : 'triggerVerify',
'click .resolve' : 'resolve' 'click .resolve' : 'resolve'
}, },
triggerVerify: function() { hideKeys: function() {
this.trigger('verify', {identityKey: this.model.identityKey}); this.$('.keys, .hideKeys').hide();
this.$('.showKeys').show();
},
showKeys: function() {
this.$('.keys, .hideKeys').show();
this.$('.showKeys').hide();
}, },
resolve: function() { resolve: function() {
this.trigger('resolve');
this.remove(); this.remove();
this.conversation.resolveConflicts(this.model); this.conversation.resolveConflicts(this.model);
}, },
showDialog: function() {
this.$('.conflict').hide();
this.$('.cancel, .content').show();
},
cancel: function() {
this.$('.cancel, .content').hide();
this.$('.conflict').show();
},
render_attributes: function() { render_attributes: function() {
return { return {
name : this.contact.getTitle(), name : this.contact.getTitle(),
avatar : this.contact.getAvatar(), avatar : this.contact.getAvatar(),
conflict : this.conflict, conflict : this.model,
verify : i18n('verify'),
cancel : i18n('cancel'),
newIdentity : i18n('newIdentity'), newIdentity : i18n('newIdentity'),
message : i18n('identityChanged'), message : i18n('identityChanged'),
resolve : i18n('acceptNewKey'), resolve : i18n('acceptNewKey'),
verifyContact: i18n('verifyContact') showKeys : i18n('showMore'),
hideKeys : i18n('showLess')
}; };
} }
}); });

View file

@ -6,8 +6,8 @@
window.Whisper = window.Whisper || {}; window.Whisper = window.Whisper || {};
Whisper.KeyVerificationView = Whisper.View.extend({ Whisper.KeyVerificationView = Whisper.View.extend({
className: 'key-verification panel', className: 'key-verification',
templateName: 'key-verification', templateName: 'key_verification',
events: { events: {
'click .back': 'goBack' 'click .back': 'goBack'
}, },
@ -36,4 +36,8 @@
}; };
} }
}); });
Whisper.KeyVerificationPanelView = Whisper.KeyVerificationView.extend({
className: 'key-verification panel',
templateName: 'key_verification_panel',
});
})(); })();

View file

@ -43,19 +43,6 @@
goBack: function() { goBack: function() {
this.trigger('back'); this.trigger('back');
}, },
verify: function(their_key) {
textsecure.storage.axolotl.getIdentityKey(textsecure.storage.user.getNumber()).then(function(our_key) {
var view = new Whisper.KeyVerificationView({
model: { their_key: their_key, your_key: our_key }
});
this.$el.hide();
view.render().$el.insertAfter(this.el);
this.listenTo(view, 'back', function() {
view.remove();
this.$el.show();
}.bind(this));
}.bind(this));
},
contacts: function() { contacts: function() {
if (this.model.isIncoming()) { if (this.model.isIncoming()) {
var number = this.model.get('source'); var number = this.model.get('source');
@ -83,14 +70,6 @@
conversation: this.conversation conversation: this.conversation
}).render(); }).render();
this.$('.conflicts').append(view.el); this.$('.conflicts').append(view.el);
this.listenTo(view, 'verify', function(data) {
this.verify(conflict.identityKey);
});
/*
this.listenTo(view, 'resolve', function() {
this.render();
});
*/
}, },
render: function() { render: function() {
this.errors = _.groupBy(this.model.get('errors'), 'number'); this.errors = _.groupBy(this.model.get('errors'), 'number');

View file

@ -47,17 +47,16 @@
} }
.key-verification { .key-verification {
background: white; &.panel {
padding: 20px 10px; padding: 20px 10px;
p {
padding: 1em;
} }
.key, .placeholder { .key, .placeholder {
padding: 0 1em; padding: 0 1em;
-webkit-user-select: text; -webkit-user-select: text;
} }
.key { .key {
display: inline-block;
font-family: monospace; font-family: monospace;
padding: 10px; padding: 10px;
margin: 10px; margin: 10px;
@ -71,39 +70,36 @@
} }
.message-detail { .message-detail {
& > .container > * {
max-width: 800px;
margin: 0 auto;
}
.key-conflict-dialogue { .key-conflict-dialogue {
background: #F3F3A7; background: #F3F3A7;
border-radius: 5px; border-radius: 5px;
padding: 1em; padding: 20px;
margin: 1em; margin: 20px;
button { button.resolve {
outline: none; outline: none;
border: none; border: none;
border-radius: 5px; border-radius: 5px;
color: white; color: white;
padding: 0.5em 1em;
font-weight: bold; font-weight: bold;
line-height: 18px; line-height: 36px;
padding: 0 20px;
span { float: right;
vertical-align: middle; background: $blue;
} margin-left: 20px;
} }
}
.key-conflict-dialogue { .hideKeys, .showKeys {
.content p {
max-width: 40em;
margin: 1em auto;
}
.verify {
color: $blue; color: $blue;
text-decoration: underline; text-decoration: underline;
cursor: pointer; cursor: pointer;
} float: right;
.resolve { line-height: 36px;
background: $blue;
} }
} }
@ -446,12 +442,6 @@
display: none; display: none;
} }
.avatar {
height: 36px;
width: 36px;
line-height: 36px;
}
.end-session { .end-session {
font: small; font: small;
font-style: italic; font-style: italic;
@ -471,6 +461,16 @@
} }
} }
.message-list,
.message-container,
.key-conflict-dialogue {
.avatar {
height: 36px;
width: 36px;
line-height: 36px;
}
}
.bottom-bar { .bottom-bar {
box-sizing: content-box; box-sizing: content-box;
$button-width: 36px; $button-width: 36px;

View file

@ -657,48 +657,47 @@ input.search {
padding: 2em 20px 0; padding: 2em 20px 0;
overflow-y: auto; } overflow-y: auto; }
.key-verification { .key-verification.panel {
background: white;
padding: 20px 10px; } padding: 20px 10px; }
.key-verification p { .key-verification .key, .key-verification .placeholder {
padding: 1em; } padding: 0 1em;
.key-verification .key, .key-verification .placeholder { -webkit-user-select: text; }
padding: 0 1em; .key-verification .key {
-webkit-user-select: text; } display: inline-block;
.key-verification .key { font-family: monospace;
font-family: monospace; padding: 10px;
padding: 10px; margin: 10px;
margin: 10px; background: #f3f3f3;
background: #f3f3f3; border: solid 1px #d9d9d9;
border: solid 1px #d9d9d9; border-radius: 5px; }
border-radius: 5px; } .key-verification .placeholder {
.key-verification .placeholder { font-weight: bold; }
font-weight: bold; }
.message-detail > .container > * {
max-width: 800px;
margin: 0 auto; }
.message-detail .key-conflict-dialogue { .message-detail .key-conflict-dialogue {
background: #F3F3A7; background: #F3F3A7;
border-radius: 5px; border-radius: 5px;
padding: 1em; padding: 20px;
margin: 1em; } margin: 20px; }
.message-detail .key-conflict-dialogue button { .message-detail .key-conflict-dialogue button.resolve {
outline: none; outline: none;
border: none; border: none;
border-radius: 5px; border-radius: 5px;
color: white; color: white;
padding: 0.5em 1em;
font-weight: bold; font-weight: bold;
line-height: 18px; } line-height: 36px;
.message-detail .key-conflict-dialogue button span { padding: 0 20px;
vertical-align: middle; } float: right;
.message-detail .key-conflict-dialogue .content p { background: #2090ea;
max-width: 40em; margin-left: 20px; }
margin: 1em auto; } .message-detail .key-conflict-dialogue .hideKeys, .message-detail .key-conflict-dialogue .showKeys {
.message-detail .key-conflict-dialogue .verify { color: #2090ea;
color: #2090ea; text-decoration: underline;
text-decoration: underline; cursor: pointer;
cursor: pointer; } float: right;
.message-detail .key-conflict-dialogue .resolve { line-height: 36px; }
background: #2090ea; }
.message-detail .message-container { .message-detail .message-container {
background: white; background: white;
padding: 20px; } padding: 20px; }
@ -972,11 +971,6 @@ input.search {
.message-container .outgoing .avatar, .message-container .outgoing .avatar,
.message-list .outgoing .avatar { .message-list .outgoing .avatar {
display: none; } display: none; }
.message-container .avatar,
.message-list .avatar {
height: 36px;
width: 36px;
line-height: 36px; }
.message-container .end-session, .message-container .end-session,
.message-list .end-session { .message-list .end-session {
font: small; font: small;
@ -992,6 +986,13 @@ input.search {
.message-list .key-conflict button { .message-list .key-conflict button {
margin-top: 5px; } margin-top: 5px; }
.message-list .avatar,
.message-container .avatar,
.key-conflict-dialogue .avatar {
height: 36px;
width: 36px;
line-height: 36px; }
.bottom-bar { .bottom-bar {
box-sizing: content-box; box-sizing: content-box;
padding: 5px 5px 5px 0; padding: 5px 5px 5px 0;