Commit 26e93658 authored by JC Brand's avatar JC Brand

Add devices section to own profile modal

Allow for devices to be removed.
parent 8cc69ee5
This diff is collapsed.
This diff is collapsed.
......@@ -60,15 +60,6 @@
width: 100%;
}
#converse-modals {
.set-xmpp-status {
margin: 1em;
.custom-control-label {
margin-top: 0.25em;
}
}
}
#controlbox {
.box-flyout {
background-color: white;
......
......@@ -61,6 +61,10 @@ body.reset {
direction: ltr;
z-index: 1031; // One more than bootstrap navbar
.nopadding {
padding: 0 !important;
}
&.converse-overlayed {
> .row {
flex-direction: row-reverse;
......
......@@ -5,10 +5,6 @@
}
form {
.form-group {
margin-bottom: 2em;
}
.form-check-label {
margin-top: $form-check-input-margin-y;
}
......@@ -108,6 +104,11 @@
}
}
}
&.converse-form--modal {
padding-bottom: 0;
}
&.converse-centered-form {
text-align: center;
}
......
#conversejs {
#converse-modals {
.set-xmpp-status {
margin: 1em;
.custom-control-label {
margin-top: 0.25em;
}
}
#omemo-tabpanel {
margin-top: 1em;
}
.btn {
font-weight: normal;
}
#user-profile-modal {
label {
font-weight: bold;
}
.list-group-item {
display: flex;
justify-content: left;
font-size: 95%;
input[type="checkbox"] {
margin-right: 1em;
}
}
}
.fingerprints {
width: 100%;
margin-bottom: 1em;
}
.fingerprint-trust {
display: flex;
justify-content: space-between;
font-size: 95%;
}
}
}
#conversejs {
#user-profile-modal {
label {
font-weight: bold;
}
}
.fingerprint-trust {
display: flex;
justify-content: space-between;
font-size: 95%;
}
}
......@@ -26,6 +26,8 @@
@import "bootstrap/scss/button-group";
@import "bootstrap/scss/input-group";
@import "bootstrap/scss/custom-forms";
@import "bootstrap/scss/nav";
@import "bootstrap/scss/navbar";
@import "bootstrap/scss/card";
@import "bootstrap/scss/breadcrumb";
@import "bootstrap/scss/badge";
......@@ -40,9 +42,9 @@
}
@import "core";
@import "forms";
@import "profile";
@import "chatbox";
@import "controlbox";
@import "modal";
@import "roster";
@import "lists";
@import "chatrooms";
......
......@@ -70,6 +70,41 @@
overrides: {
ProfileModal: {
events: {
'change input.select-all': 'selectAll',
'submit .fingerprint-removal': 'removeSelectedFingerprints'
},
initialize () {
const { _converse } = this.__super__,
device_id = _converse.omemo_store.get('device_id');
this.devicelist = _converse.devicelists.get(_converse.bare_jid);
this.current_device = this.devicelist.devices.get(device_id);
this.other_devices = this.devicelist.devices.filter(d => (d.get('id') !== device_id));
this.devicelist.devices.on('change:bundle', this.render, this);
return this.__super__.initialize.apply(this, arguments);
},
selectAll (ev) {
let sibling = ev.target.parentElement.nextElementSibling;
while (sibling) {
sibling.firstElementChild.checked = ev.target.checked;
sibling = sibling.nextElementSibling;
}
},
removeSelectedFingerprints (ev) {
ev.preventDefault();
ev.stopPropagation();
const checkboxes = ev.target.querySelectorAll('.fingerprint-removal-item input[type="checkbox"]:checked'),
device_ids = _.map(checkboxes, 'value');
this.devicelist.removeOwnDevices(device_ids);
},
},
UserDetailsModal: {
events: {
'click .fingerprint-trust .btn input': 'toggleDeviceTrust'
......@@ -415,7 +450,7 @@
});
}
_converse.getFingerprintsForContact = function (jid) {
_converse.generateFingerprints= function (jid) {
return _converse.getDevicesForContact(jid)
.then(devices => Promise.all(devices.map(d => generateFingerprint(d))))
}
......@@ -734,6 +769,10 @@
});
_converse.connection.sendIQ(stanza, resolve, reject, _converse.IQ_TIMEOUT);
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
},
removeOwnDevices (device_ids) {
// TODO
}
});
......@@ -893,7 +932,11 @@
_converse.api.listen.on('userDetailsModalInitialized', (contact) => {
const jid = contact.get('jid');
_converse.getFingerprintsForContact(jid).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
_converse.generateFingerprints(jid).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
});
_converse.api.listen.on('profileModalInitialized', (contact) => {
_converse.generateFingerprints(_converse.bare_jid).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
});
}
});
......
......@@ -48,32 +48,40 @@
events: {
'click .change-avatar': "openFileSelection",
'change input[type="file"': "updateFilePreview",
'submit form': 'onFormSubmitted'
'submit .profile-form': 'onFormSubmitted'
},
initialize () {
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
this.model.on('change', this.render, this);
_converse.emit('profileModalInitialized', this.model);
},
toHTML () {
return tpl_profile_modal(_.extend(
this.model.toJSON(),
this.model.vcard.toJSON(), {
'_': _,
'__': __,
'_converse': _converse,
'alt_avatar': __('Your avatar image'),
'heading_profile': __('Your Profile'),
'label_close': __('Close'),
'label_email': __('Email'),
'label_fullname': __('Full Name'),
'label_nickname': __('Nickname'),
'label_jid': __('XMPP Address (JID)'),
'label_nickname': __('Nickname'),
'label_role': __('Role'),
'label_role_help': __('Use commas to separate multiple roles. Your roles are shown next to your name on your chat messages.'),
'label_save': __('Save'),
'label_url': __('URL'),
'alt_avatar': __('Your avatar image')
'view': this
}));
},
afterRender () {
this.tabs = _.map(this.el.querySelectorAll('.nav-item'), (tab) => new bootstrap.Tab(tab));
},
openFileSelection (ev) {
ev.preventDefault();
this.el.querySelector('input[type="file"]').click();
......
......@@ -5,8 +5,18 @@
<h5 class="modal-title" id="user-profile-modal-label">{{{o.heading_profile}}}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="{{{o.label_close}}}"><span aria-hidden="true">&times;</span></button>
</div>
<form class="converse-form">
<div class="modal-body">
<ul class="nav nav-pills justify-content-center">
<li role="presentation" class="nav-item">
<a class="nav-link active" id="profile-tab" href="#profile-tabpanel" aria-controls="profile-tabpanel" role="tab" data-toggle="tab">Profile</a>
</li>
<li role="presentation" class="nav-item">
<a class="nav-link" id="omemo-tab" href="#omemo-tabpanel" aria-controls="omemo-tabpanel" role="tab" data-toggle="tab">OMEMO</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade show active" id="profile-tabpanel" role="tabpanel" aria-labelledby="profile-tab">
<form class="converse-form converse-form--modal profile-form" action="#">
<div class="row">
<div class="col-auto">
<a class="change-avatar" href="#">
......@@ -47,12 +57,53 @@
<input id="vcard-role" type="text" class="form-control" name="role" value="{{{o.role}}}" aria-describedby="vcard-role-help">
<small id="vcard-role-help" class="form-text text-muted">{{{o.label_role_help}}}</small>
</div>
<hr/>
<div class="form-group">
<button type="submit" class="save-form btn btn-primary">{{{o.__('Save and close')}}}</button>
</div>
<div class="modal-footer">
<button type="submit" class="save-form btn btn-primary">{{{o.label_save}}}</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{{o.label_close}}}</button>
</form>
</div>
{[ if (o._converse.pluggable.plugins['converse-omemo'].enabled()) { ]}
<div class="tab-pane fade" id="omemo-tabpanel" role="tabpanel" aria-labelledby="omemo-tab">
<form class="converse-form fingerprint-removal">
<ul class="list-group fingerprints">
<li class="list-group-item active">{{{o.__("This device's OMEMO fingerprint")}}}</li>
<li class="fingerprint-removal-item list-group-item">
{[ if (o.view.current_device.get('bundle') && o.view.current_device.get('bundle').fingerprint) { ]}
<input type="checkbox" value="{{{o.view.current_device.get('id')}}}"
aria-label="{{{o.__('Checkbox for removing the following fingerprint')}}}">
<span class="fingerprint">{{{o.view.current_device.get('bundle').fingerprint}}}</span>
{[ } else {]}
<span class="spinner fa fa-spinner centered"/>
{[ } ]}
</li>
</ul>
{[ if (o.view.other_devices) { ]}
<ul class="list-group fingerprints">
<li class="list-group-item active">
<input type="checkbox" class="select-all" title="{{{o.__('Select all')}}}"
aria-label="{{{o.__('Checkbox to select fingerprints of all other OMEMO devices')}}}">
{{{o.__('Other OMEMO-enabled devices')}}}
</li>
{[ o._.forEach(o.view.other_devices, function (device) { ]}
{[ if (device.get('bundle') && device.get('bundle').fingerprint) { ]}
<li class="fingerprint-removal-item list-group-item">
<input type="checkbox" value="{{{device.get('id')}}}"
aria-label="{{{o.__('Checkbox for selecting the following fingerprint')}}}">
<span class="fingerprint">{{{device.get('bundle').fingerprint}}}</span>
</li>
{[ } ]}
{[ }); ]}
</ul>
{[ } ]}
<div class="form-group">
<button type="submit" class="save-form btn btn-primary">{{{o.__('Remove checked devices and close')}}}</button>
</div>
</form>
</div>
{[ } ]}
</div>
</div>
</div>
</div>
</div>
......@@ -40,7 +40,6 @@
{[ if (device.get('bundle') && device.get('bundle').fingerprint) { ]}
<li class="list-group-item">
<form class="fingerprint-trust">
<span class="fingerprint">{{{device.get('bundle').fingerprint}}}</span>
<div class="btn-group btn-group-toggle">
<label class="btn btn--small {[ if (device.get('trusted') !== -1) { ]} btn-primary active {[ } else { ]} btn-secondary {[ } ]}">
<input type="radio" name="{{{device.get('id')}}}" value="1"
......@@ -51,6 +50,7 @@
{[ if (device.get('trusted') === -1) { ]} checked="checked" {[ } ]}>{{{o.__('Untrusted')}}}
</label>
</div>
<span class="fingerprint">{{{device.get('bundle').fingerprint}}}</span>
</form>
</li>
{[ } ]}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment