Remove controlbox tabs and show rooms and contacts panels together

This commit is contained in:
JC Brand 2018-02-15 15:50:55 +01:00
parent b6501bcf09
commit ede21e7c32
22 changed files with 309 additions and 400 deletions

View File

@ -5722,17 +5722,17 @@ body.reset {
display: block;
font-weight: normal;
margin: 1em 0; }
#conversejs #controlbox #chatrooms, #conversejs #controlbox #contacts {
margin-top: 0.75em;
padding-bottom: 0.75em; }
#conversejs #controlbox .controlbox-pane .userinfo {
padding-bottom: 1em;
border-bottom: 1px solid #818479; }
#conversejs #controlbox .controlbox-pane .userinfo .username {
margin-left: 0.5em; }
margin-left: 0.5em;
overflow: hidden;
text-overflow: ellipsis; }
#conversejs #controlbox .controlbox-pane .userinfo .d-flex {
margin-bottom: 0.2em; }
#conversejs #controlbox #chatrooms {
padding: 0;
border-bottom: 1px solid #818479; }
#conversejs #controlbox #chatrooms form.add-chatroom {
margin: 0;
@ -5827,6 +5827,9 @@ body.reset {
padding: 0.3em 0;
clear: left;
width: 100%; }
#conversejs #controlbox #chatrooms, #conversejs #controlbox #converse-roster {
margin-top: 0.75em;
padding-bottom: 0.75em; }
#conversejs #controlbox .dropdown a {
width: 143px;
display: inline-block; }

View File

@ -5794,17 +5794,17 @@ body {
display: block;
font-weight: normal;
margin: 1em 0; }
#conversejs #controlbox #chatrooms, #conversejs #controlbox #contacts {
margin-top: 0.75em;
padding-bottom: 0.75em; }
#conversejs #controlbox .controlbox-pane .userinfo {
padding-bottom: 1em;
border-bottom: 1px solid #818479; }
#conversejs #controlbox .controlbox-pane .userinfo .username {
margin-left: 0.5em; }
margin-left: 0.5em;
overflow: hidden;
text-overflow: ellipsis; }
#conversejs #controlbox .controlbox-pane .userinfo .d-flex {
margin-bottom: 0.2em; }
#conversejs #controlbox #chatrooms {
padding: 0;
border-bottom: 1px solid #818479; }
#conversejs #controlbox #chatrooms form.add-chatroom {
margin: 0;
@ -5899,6 +5899,9 @@ body {
padding: 0.3em 0;
clear: left;
width: 100%; }
#conversejs #controlbox #chatrooms, #conversejs #controlbox #converse-roster {
margin-top: 0.75em;
padding-bottom: 0.75em; }
#conversejs #controlbox .dropdown a {
width: 143px;
display: inline-block; }

View File

@ -24,7 +24,7 @@
</div>
</div>
<div class="chatbox col col col-lg-2 col-md-3 col-sm-4 col-sx-12 w-100" id="chatbox-37c0c87392010303765fe36b05c0967d62c6b70f">
<div class="chatbox col col-lg-2 col-md-3 col-sm-4 col-sx-12 w-100" id="chatbox-37c0c87392010303765fe36b05c0967d62c6b70f">
<div class="flyout box-flyout">
<div class="chat-head chat-head-chatbox row no-gutters">

View File

@ -16,7 +16,7 @@
<div id="chatrooms">
<div class="d-flex">
<span class="w-100">Chatrooms</span>
<a class="chatbox-btn fa fa-users" title="Click to change rooms" data-toggle="modal" data-target="#chatroomsModal"></a>
<a class="chatbox-btn fa fa-users" title="Click to add a new room" data-toggle="modal" data-target="#chatroomsModal"></a>
</div>
<div class="list-container rooms-list-container">
<div class="rooms-list">
@ -42,123 +42,121 @@
</div>
<div id="converse-roster">
<div id="contacts">
<div class="d-flex">
<span class="w-100">Contacts</span>
<a class="chatbox-btn fa fa-user-plus" title="Click to add new chat contacts" data-toggle="modal" data-target="#addContactModal"></a>
<div class="d-flex">
<span class="w-100">Contacts</span>
<a class="chatbox-btn fa fa-user-plus" title="Click to add new chat contacts" data-toggle="modal" data-target="#addContactModal"></a>
</div>
<form class="pure-form roster-filter-form input-button-group">
<div class="form-group form-inline">
<input value="" class="roster-filter form-control" placeholder="Filter">
<div class="filter-by">
<span class="fa fa-user" title="Filter by contacts"></span>
<span class="fa fa-users" title="Filter by groups"></span>
<span class="fa fa-circle" title="Filter by status"></span>
</div>
</div>
<form class="pure-form roster-filter-form input-button-group">
<div class="form-group form-inline">
<input value="" class="roster-filter form-control" placeholder="Filter">
<div class="filter-by">
<span class="fa fa-user" title="Filter by contacts"></span>
<span class="fa fa-users" title="Filter by groups"></span>
<span class="fa fa-circle" title="Filter by status"></span>
</div>
</div>
</form>
</form>
<div class="roster-contacts">
<div class="roster-group" id="xmpp-contact-requests">
<a href="#" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Contact Requests</a>
<ul>
<li class="offline requesting-xmpp-contact d-flex">
<span class="req-contact-name w-100">Bob Skinstad</span>
<a class="accept-xmpp-request fa fa-check align-self-center" title="Click here to accept this contact's request" href="#"></a>
<a class="decline-xmpp-request fa fa-times align-self-center" title="Click here to decline this contact's request" href="#"></a>
</li>
<li class="offline requesting-xmpp-contact d-flex">
<span class="req-contact-name w-100">André Vos</span>
<a class="accept-xmpp-request fa fa-check align-self-center" title="Click here to accept this contact's request" href="#"></a>
<a class="decline-xmpp-request fa fa-times align-self-center" title="Click here to decline this contact's request" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" data-group="Colleagues">
<a href="#" data-group="Colleagues" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Colleagues</a>
<ul>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> Victor Matfield</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="away current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle-o" title="this contact is away"></span> William Winterbottom</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="dnd current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-minus-circle" title="This contact is busy"></span> Gary Teichmann</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<div class="roster-contacts">
<div class="roster-group" id="xmpp-contact-requests">
<a href="#" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Contact Requests</a>
<ul>
<li class="offline requesting-xmpp-contact d-flex">
<span class="req-contact-name w-100">Bob Skinstad</span>
<a class="accept-xmpp-request fa fa-check align-self-center" title="Click here to accept this contact's request" href="#"></a>
<a class="decline-xmpp-request fa fa-times align-self-center" title="Click here to decline this contact's request" href="#"></a>
</li>
</div>
<li class="offline requesting-xmpp-contact d-flex">
<span class="req-contact-name w-100">André Vos</span>
<a class="accept-xmpp-request fa fa-check align-self-center" title="Click here to accept this contact's request" href="#"></a>
<a class="decline-xmpp-request fa fa-times align-self-center" title="Click here to decline this contact's request" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" data-group="Family">
<a href="#" data-group="Family" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Family</a>
<ul>
<li class="away current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle-o" title="this contact is away"></span> Allan Donald</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="offline current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-times-circle" title="This contact is offline"></span> Corné Krige</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" data-group="Colleagues">
<a href="#" data-group="Colleagues" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Colleagues</a>
<div class="roster-group" data-group="Friends">
<a href="#" data-group="Friends" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Friends</a>
<ul>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> John Smit</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> Bakkies Botha</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
<ul>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> Victor Matfield</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="away current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle-o" title="this contact is away"></span> William Winterbottom</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="dnd current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-minus-circle" title="This contact is busy"></span> Gary Teichmann</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</li>
</div>
<div class="roster-group" data-group="Ungrouped">
<a href="#" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Ungrouped</a>
<ul>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> James Small</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" data-group="Family">
<a href="#" data-group="Family" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Family</a>
<ul>
<li class="away current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle-o" title="this contact is away"></span> Allan Donald</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="offline current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-times-circle" title="This contact is offline"></span> Corné Krige</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" id="pending-xmpp-contacts">
<a href="#" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Pending Contacts</a>
<ul>
<li class="offline pending-xmpp-contact d-flex">
<span class="pending-contact-name w-100">Rassie Erasmus</span>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="offline pending-xmpp-contact d-flex">
<span class="pending-contact-name w-100">Victor Matfield</span>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" data-group="Friends">
<a href="#" data-group="Friends" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Friends</a>
<ul>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> John Smit</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> Bakkies Botha</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" data-group="Ungrouped">
<a href="#" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Ungrouped</a>
<ul>
<li class="online current-xmpp-contact d-flex">
<a class="open-chat w-100" title="Click to chat with this contact" href="#">
<span class="fa fa-circle" title="This contact is online"></span> James Small</a>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
<div class="roster-group" id="pending-xmpp-contacts">
<a href="#" class="group-toggle" title="Click to hide these contacts">
<span class="fa fa-caret-down"></span> Pending Contacts</a>
<ul>
<li class="offline pending-xmpp-contact d-flex">
<span class="pending-contact-name w-100">Rassie Erasmus</span>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
<li class="offline pending-xmpp-contact d-flex">
<span class="pending-contact-name w-100">Victor Matfield</span>
<a class="remove-xmpp-contact fa fa-trash align-self-center" title="Click to remove this contact" href="#"></a>
</li>
</ul>
</div>
</div>
</div>

View File

@ -157,11 +157,6 @@
}
#chatrooms, #contacts {
margin-top: 0.75em;
padding-bottom: 0.75em;
}
.controlbox-pane {
.userinfo {
padding-bottom: 1em;
@ -169,6 +164,8 @@
.username {
margin-left: 0.5em;
overflow: hidden;
text-overflow: ellipsis;
}
.d-flex {
margin-bottom: 0.2em;
@ -177,6 +174,7 @@
}
#chatrooms {
padding: 0;
border-bottom: 1px solid $gray-color;
form.add-chatroom {
@ -284,6 +282,11 @@
}
}
#chatrooms, #converse-roster {
margin-top: 0.75em;
padding-bottom: 0.75em;
}
.dropdown {
a {
width: 143px;

View File

@ -304,6 +304,7 @@
},
render () {
this.setClasses();
this.el.setAttribute('id', this.model.get('box_id'));
this.el.innerHTML = tpl_chatbox(
_.extend(this.model.toJSON(), {
@ -316,6 +317,20 @@
return this;
},
setClasses () {
if (_converse.view_mode === 'fullscreen') {
this.el.classList.add('col-xl-10');
this.el.classList.add('col-md-9');
} else {
this.el.classList.add('col');
this.el.classList.add('col-lg-2');
this.el.classList.add('col-md-3');
this.el.classList.add('col-sm-4');
this.el.classList.add('col-sx-12');
this.el.classList.add('w-100');
}
},
renderToolbar (toolbar, options) {
if (!_converse.show_toolbar) {
return this;
@ -431,10 +446,7 @@
* as well as src/converse-muc.js (if those plugins are
* enabled).
*/
const container = _converse.root.querySelector('#conversejs');
if (this.el.parentNode !== container) {
container.insertBefore(this.el, container.firstChild);
}
_converse.chatboxviews.insertRowColumn(this.el);
return this;
},

View File

@ -12,8 +12,6 @@
"tpl!add_contact_dropdown",
"tpl!add_contact_form",
"tpl!converse_brand_heading",
"tpl!contacts_panel",
"tpl!contacts_tab",
"tpl!controlbox",
"tpl!controlbox_toggle",
"tpl!login_panel",
@ -28,8 +26,6 @@
tpl_add_contact_dropdown,
tpl_add_contact_form,
tpl_brand_heading,
tpl_contacts_panel,
tpl_contacts_tab,
tpl_controlbox,
tpl_controlbox_toggle,
tpl_login_panel,
@ -37,7 +33,6 @@
) {
"use strict";
const USERS_PANEL_ID = 'users';
const CHATBOX_TYPE = 'chatbox';
const { Strophe, Backbone, Promise, _, moment } = converse.env;
const u = converse.env.utils;
@ -91,7 +86,7 @@
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-chatboxes"],
dependencies: ["converse-chatboxes", "converse-rosterview"],
overrides: {
// Overrides mentioned here will be picked up by converse.js's
@ -201,6 +196,7 @@
},
ChatBoxView: {
insertIntoDOM () {
const view = this.__super__._converse.chatboxviews.get("controlbox");
if (view) {
@ -248,15 +244,15 @@
className: 'chatbox',
id: 'controlbox',
events: {
'click a.close-chatbox-button': 'close',
'click ul#controlbox-tabs li a': 'switchTab',
'click a.close-chatbox-button': 'close'
},
initialize () {
if (_.isUndefined(_converse.controlboxtoggle)) {
_converse.controlboxtoggle = new _converse.ControlBoxToggle();
_converse.controlboxtoggle.el.insertAdjacentElement('afterend', this.el);
}
_converse.controlboxtoggle.el.insertAdjacentElement('afterend', this.el);
this.model.on('change:connected', this.onConnected, this);
this.model.on('destroy', this.hide, this);
this.model.on('hide', this.hide, this);
@ -277,23 +273,23 @@
this.model.set('closed', !_converse.show_controlbox_by_default);
}
}
if (!this.model.get('closed')) {
this.show();
} else {
this.hide();
}
this.el.innerHTML = tpl_controlbox(
_.extend(this.model.toJSON(), {
'sticky_controlbox': _converse.sticky_controlbox
}));
if (!this.model.get('closed')) {
this.show();
} else {
this.hide();
}
if (!_converse.connection.connected ||
!_converse.connection.authenticated ||
_converse.connection.disconnecting) {
this.renderLoginPanel();
} else if (this.model.get('connected') &&
(!this.contactspanel || !u.isVisible(this.contactspanel.el))) {
this.renderContactsPanel();
(!this.controlbox_pane || !u.isVisible(this.controlbox_pane.el))) {
this.renderControlBoxPane();
}
return this;
},
@ -310,7 +306,7 @@
insertRoster () {
/* Place the rosterview inside the "Contacts" panel. */
this.contactspanel.el.insertAdjacentElement(
this.controlbox_pane.el.insertAdjacentElement(
'beforeEnd',
_converse.rosterview.el
);
@ -333,6 +329,8 @@
renderLoginPanel () {
this.el.classList.add("logged-out");
this.el.classList.remove("col-xl-2");
this.el.classList.remove("col-md-3");
if (_.isNil(this.loginpanel)) {
this.loginpanel = new _converse.LoginPanel({
'model': new _converse.LoginPanelModel()
@ -347,7 +345,7 @@
return this;
},
renderContactsPanel () {
renderControlBoxPane () {
/* Renders the "Contacts" panel of the controlbox.
*
* This will only be called after the user has already been
@ -358,19 +356,14 @@
delete this.loginpanel;
}
this.el.classList.remove("logged-out");
this.el.classList.add("col-xl-2");
this.el.classList.add("col-md-3");
if (_.isUndefined(this.model.get('active-panel'))) {
this.model.save({'active-panel': USERS_PANEL_ID});
}
this.contactspanel = new _converse.ContactsPanel({
'parent_el': this.el.querySelector('.controlbox-panes')
});
this.contactspanel.insertIntoDOM();
_converse.xmppstatusview = new _converse.XMPPStatusView({
'model': _converse.xmppstatus
});
_converse.xmppstatusview.render();
this.controlbox_pane = new _converse.ControlBoxPane();
this.el.querySelector('.controlbox-panes').insertAdjacentElement(
'afterBegin',
this.controlbox_pane.el
)
},
close (ev) {
@ -421,24 +414,6 @@
return this;
},
switchTab (ev) {
if (ev && ev.preventDefault) { ev.preventDefault(); }
const tab = ev.target,
sibling_li = tab.parentNode.nextElementSibling || tab.parentNode.previousElementSibling,
sibling = sibling_li.firstChild,
sibling_panel = _converse.root.querySelector(sibling.getAttribute('href')),
tab_panel = _converse.root.querySelector(tab.getAttribute('href'));
u.hideElement(sibling_panel);
u.removeClass('current', sibling);
u.addClass('current', tab);
u.removeClass('hidden', tab_panel);
if (!_.isUndefined(_converse.chatboxes.browserStorage)) {
this.model.save({'active-panel': tab.getAttribute('data-id')});
}
return this;
},
showHelpMessages () {
/* Override showHelpMessages in ChatBoxView, for now do nothing.
*
@ -553,10 +528,9 @@
});
_converse.ContactsPanel = Backbone.NativeView.extend({
_converse.ControlBoxPane = Backbone.NativeView.extend({
tagName: 'div',
className: 'controlbox-pane',
id: 'users',
events: {
'click a.toggle-xmpp-contact-form': 'toggleContactForm',
'submit form.add-xmpp-contact': 'addContactFromForm',
@ -564,57 +538,14 @@
'click a.subscribe-to-user': 'addContactFromList'
},
initialize (cfg) {
this.parent_el = cfg.parent_el;
this.tab_el = document.createElement('li');
_converse.chatboxes.on('change:num_unread', this.renderTab, this);
_converse.chatboxes.on('add', _.debounce(this.renderTab, 100), this);
},
render () {
this.renderTab();
let widgets = tpl_contacts_panel({
label_online: __('Online'),
label_busy: __('Busy'),
label_away: __('Away'),
label_offline: __('Offline'),
label_logout: __('Log out'),
include_offline_state: _converse.include_offline_state,
allow_logout: _converse.allow_logout
initialize () {
_converse.xmppstatusview = new _converse.XMPPStatusView({
'model': _converse.xmppstatus
});
if (_converse.allow_contact_requests) {
widgets += tpl_add_contact_dropdown({
label_click_to_chat: __('Click to add new chat contacts'),
label_add_contact: __('Add a contact')
});
}
this.el.innerHTML = widgets;
const controlbox = _converse.chatboxes.get('controlbox');
if (controlbox.get('active-panel') !== USERS_PANEL_ID) {
this.el.classList.add('hidden');
}
return this;
},
renderTab () {
const controlbox = _converse.chatboxes.get('controlbox');
if (_.isNil(controlbox)) {
return;
}
const chats = fp.filter(_.partial(u.isOfType, CHATBOX_TYPE), _converse.chatboxes.models);
this.tab_el.innerHTML = tpl_contacts_tab({
'label_contacts': LABEL_CONTACTS,
'is_current': controlbox.get('active-panel') === USERS_PANEL_ID,
'num_unread': fp.sum(fp.map(fp.curry(u.getAttribute)('num_unread'), chats))
});
},
insertIntoDOM () {
this.parent_el.appendChild(this.render().el);
this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs');
this.tabs.appendChild(this.tab_el);
return this;
this.el.insertAdjacentElement(
'afterBegin',
_converse.xmppstatusview.render().el
);
},
generateAddContactHTML (settings={}) {
@ -728,11 +659,10 @@
},
initialize () {
_converse.chatboxviews.el.insertAdjacentElement('afterBegin', this.render().el);
const that = this;
_converse.api.waitUntil('initialized').then(() => {
this.render();
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
_converse.chatboxviews.insertRowColumn(this.render().el);
_converse.api.waitUntil('initialized')
.then(this.render.bind(this))
.catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
},
render () {
@ -796,7 +726,6 @@
*/
const view = _converse.chatboxviews.get('controlbox');
view.model.set({connected:false});
view.el.querySelector('#controlbox-tabs').innerHTML = '';
view.renderLoginPanel();
};
_converse.on('disconnected', disconnect);

View File

@ -312,8 +312,8 @@
return result;
},
renderContactsPanel () {
const result = this.__super__.renderContactsPanel.apply(this, arguments);
renderControlBoxPane () {
const result = this.__super__.renderControlBoxPane.apply(this, arguments);
this.initDragResize().setDimensions();
return result;
}

View File

@ -26,7 +26,6 @@
"tpl!chatroom_password_form",
"tpl!chatroom_sidebar",
"tpl!chatroom_toolbar",
"tpl!chatrooms_tab",
"tpl!info",
"tpl!occupant",
"tpl!room_description",
@ -57,7 +56,6 @@
tpl_chatroom_password_form,
tpl_chatroom_sidebar,
tpl_chatroom_toolbar,
tpl_chatrooms_tab,
tpl_info,
tpl_occupant,
tpl_room_description,
@ -69,7 +67,6 @@
) {
"use strict";
const ROOMS_PANEL_ID = 'chatrooms';
const CHATROOMS_TYPE = 'chatroom';
const MUC_ROLE_WEIGHTS = {
@ -160,17 +157,21 @@
},
ControlBoxView: {
renderRoomsPanel () {
const { _converse } = this.__super__;
this.roomspanel = new _converse.RoomsPanel({
'parent': this.el.querySelector('.controlbox-panes'),
'model': new (_converse.RoomsPanelModel.extend({
id: b64_sha1(`converse.roomspanel${_converse.bare_jid}`), // Required by sessionStorage
browserStorage: new Backbone.BrowserStorage[_converse.storage](
b64_sha1(`converse.roomspanel${_converse.bare_jid}`))
}))()
});
this.roomspanel.insertIntoDOM().model.fetch();
this.roomspanel.model.fetch();
this.el.querySelector('.controlbox-pane').insertAdjacentElement(
'beforeEnd', this.roomspanel.render().el);
if (!this.roomspanel.model.get('nick')) {
this.roomspanel.model.save({
nick: Strophe.getNodeFromJid(_converse.bare_jid)
@ -179,9 +180,9 @@
_converse.emit('roomsPanelRendered');
},
renderContactsPanel () {
renderControlBoxPane () {
const { _converse } = this.__super__;
this.__super__.renderContactsPanel.apply(this, arguments);
this.__super__.renderControlBoxPane.apply(this, arguments);
if (_converse.allow_muc) {
this.renderRoomsPanel();
}
@ -470,6 +471,7 @@
},
render () {
this.setClasses();
this.el.setAttribute('id', this.model.get('box_id'));
this.el.innerHTML = tpl_chatroom();
this.renderHeading();
@ -480,6 +482,20 @@
return this;
},
setClasses () {
if (_converse.view_mode === 'fullscreen') {
this.el.classList.add('col-xl-10');
this.el.classList.add('col-md-9');
} else {
this.el.classList.add('col');
this.el.classList.add('col-lg-4');
this.el.classList.add('col-md-6');
this.el.classList.add('col-sm-8');
this.el.classList.add('col-sx-12');
this.el.classList.add('w-100');
}
},
renderHeading () {
/* Render the heading UI of the chat room. */
this.el.querySelector('.chat-head-chatroom').innerHTML = this.generateHeadingHTML();
@ -2556,11 +2572,9 @@
});
_converse.RoomsPanel = Backbone.NativeView.extend({
/* Backbone.NativeView which renders the "Rooms" tab and accompanying
* panel in the control box.
/* Backbone.NativeView which renders MUC section of the control box.
*
* In this panel, chat rooms can be listed, joined and new rooms
* can be created.
* Chat rooms can be listed, joined and new rooms can be created.
*/
tagName: 'div',
className: 'controlbox-pane',
@ -2576,46 +2590,16 @@
initialize (cfg) {
this.join_form = new _converse.MUCJoinForm({'model': this.model});
this.parent_el = cfg.parent;
this.tab_el = document.createElement('li');
this.model.on('change:muc_domain', this.onDomainChange, this);
this.model.on('change:nick', this.onNickChange, this);
_converse.chatboxes.on('change:num_unread', this.renderTab, this);
_converse.chatboxes.on('add', _.debounce(this.renderTab, 100), this);
},
render () {
this.el.innerHTML = tpl_room_panel();
this.el.innerHTML = tpl_room_panel({
'title_new_room': __('Click to add a new room')
});
this.join_form.setElement(this.el.querySelector('.add-chatroom'));
this.join_form.render();
this.renderTab();
const controlbox = _converse.chatboxes.get('controlbox');
if (controlbox.get('active-panel') !== ROOMS_PANEL_ID) {
this.el.classList.add('hidden');
} else {
this.el.classList.remove('hidden');
}
return this;
},
renderTab () {
const controlbox = _converse.chatboxes.get('controlbox');
const chatrooms = fp.filter(
_.partial(u.isOfType, CHATROOMS_TYPE),
_converse.chatboxes.models
);
this.tab_el.innerHTML = tpl_chatrooms_tab({
'label_rooms': __('Rooms'),
'is_current': controlbox.get('active-panel') === ROOMS_PANEL_ID,
'num_unread': fp.sum(fp.map(fp.curry(u.getAttribute)('num_unread'), chatrooms))
});
},
insertIntoDOM () {
this.parent_el.appendChild(this.render().el);
this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs');
this.tabs.appendChild(this.tab_el);
return this;
},

View File

@ -9,7 +9,7 @@
(function (root, factory) {
define(["converse-core",
"tpl!change_status_message",
"tpl!chat_status",
"tpl!profile_view",
"tpl!choose_status",
"tpl!status_option",
"converse-vcard"
@ -17,7 +17,7 @@
}(this, function (
converse,
tpl_change_status_message,
tpl_chat_status,
tpl_profile_view,
tpl_choose_status,
tpl_status_option
) {
@ -35,8 +35,9 @@
const { _converse } = this,
{ __ } = _converse;
_converse.XMPPStatusView = Backbone.NativeView.extend({
el: "form#set-xmpp-status",
_converse.XMPPStatusView = Backbone.VDOMView.extend({
tagName: "div",
events: {
"click a.choose-xmpp-status": "toggleOptions",
"click #fancy-xmpp-status-select a.change-xmpp-status-message": "renderStatusChangeForm",
@ -50,30 +51,17 @@
this.model.on("update-status-ui", this.updateStatusUI, this);
},
render () {
// Replace the default dropdown with something nicer
const options = this.el.querySelectorAll('#select-xmpp-status option');
toHTML () {
const chat_status = this.model.get('status') || 'offline';
this.el.innerHTML = tpl_choose_status();
this.el.querySelector('#fancy-xmpp-status-select')
.innerHTML = tpl_chat_status({
'status_message': this.model.get('status_message') ||
__("I am %1$s", this.getPrettyStatus(chat_status)),
'chat_status': chat_status,
'desc_custom_status': __('Click here to write a custom status message'),
'desc_change_status': __('Click to change your chat status')
});
// iterate through all the <option> elements and add option values
const options_list = _.map(
options,
(el) => tpl_status_option({'value': el.value, 'text': el.text })
);
const options_target = this.el.querySelector(".xmpp-status-menu");
options_target.classList.add('collapsed');
options_target.innerHTML = options_list.join('');
return this;
return tpl_profile_view(_.extend(this.model.toJSON(), {
'fullname': this.model.get('fullname') || _converse.bare_jid,
'status_message': this.model.get('status_message') ||
__("I am %1$s", this.getPrettyStatus(chat_status)),
'chat_status': chat_status,
'title_change_settings': __('Change settings'),
'title_change_status': __('Click to change your chat status'),
'title_your_profile': __('Your profile')
}));
},
toggleOptions (ev) {
@ -133,14 +121,7 @@
// For translators: the %1$s part gets replaced with the status
// Example, I am online
const status_message = model.get('status_message') || __("I am %1$s", this.getPrettyStatus(stat));
const fancy_select = this.el.querySelector('#fancy-xmpp-status-select');
fancy_select.classList.remove('no-border');
fancy_select.innerHTML = tpl_chat_status({
'chat_status': stat,
'status_message': status_message,
'desc_custom_status': __('Click here to write a custom status message'),
'desc_change_status': __('Click to change your chat status')
});
// TODO
}
});
}

View File

@ -131,7 +131,7 @@
_converse.RoomsListView = Backbone.OrderedListView.extend({
tagName: 'div',
className: 'open-rooms-list rooms-list-container',
className: 'open-rooms-list list-container rooms-list-container',
events: {
'click .add-bookmark': 'addBookmark',
'click .close-room': 'closeRoom',
@ -177,9 +177,9 @@
const controlboxview = _converse.chatboxviews.get('controlbox');
if (!_.isUndefined(controlboxview) &&
!_converse.root.contains(this.el)) {
const container = controlboxview.el.querySelector('#chatrooms');
if (!_.isNull(container)) {
container.insertBefore(this.el, container.firstChild);
const el = controlboxview.el.querySelector('.open-rooms-list');
if (!_.isNull(el)) {
el.parentNode.replaceChild(this.el, el);
}
}
},

View File

@ -129,7 +129,8 @@
});
_converse.RosterFilterView = Backbone.VDOMView.extend({
tagName: 'span',
tagName: 'form',
className: 'roster-filter-form',
events: {
"keydown .roster-filter": "liveFilter",
"submit form.roster-filter-form": "submitFilter",
@ -149,9 +150,9 @@
_.extend(this.model.toJSON(), {
visible: this.shouldBeVisible(),
placeholder: __('Filter'),
label_contacts: LABEL_CONTACTS,
label_groups: LABEL_GROUPS,
label_state: __('State'),
title_contact_filter: __('Filter by contact name'),
title_group_filter: __('Filter by group name'),
title_status_filter: __('Filter by status'),
label_any: __('Any'),
label_unread_messages: __('Unread'),
label_online: __('Online'),
@ -655,9 +656,14 @@
},
render () {
this.el.innerHTML = "";
this.el.appendChild(this.filter_view.render().el);
this.renderRoster();
this.el.innerHTML = tpl_roster({
'heading_contacts': __('Contacts'),
'title_add_contact': __('Add a contact')
});
const form = this.el.querySelector('.roster-filter-form');
this.el.replaceChild(this.filter_view.render().el, form);
this.roster_el = this.el.querySelector('.roster-contacts');
if (!_converse.allow_contact_requests) {
// XXX: if we ever support live editing of config then
// we'll need to be able to remove this class on the fly.
@ -666,13 +672,6 @@
return this;
},
renderRoster () {
const div = document.createElement('div');
div.insertAdjacentHTML('beforeend', tpl_roster());
this.roster_el = div.firstChild;
this.el.insertAdjacentElement('beforeend', this.roster_el);
},
createRosterFilter () {
// Create a model on which we can store filter properties
const model = new _converse.RosterFilter();
@ -703,16 +702,9 @@
if (!u.isVisible(this.roster_el)) {
u.showElement(this.roster_el);
}
return this.showHideFilter();
}, _converse.animate ? 100 : 0),
showHideFilter () {
if (!u.isVisible(this.el)) {
return;
}
this.filter_view.showOrHide();
return this;
},
}, _converse.animate ? 100 : 0),
filter (query, type) {
// First we make sure the filter is restored to its

View File

@ -1,6 +0,0 @@
<div class="xmpp-status">
<a class="choose-xmpp-status {{{o.chat_status}}} icon-{{{o.chat_status}}}" data-value="{{{o.status_message}}}" href="#" title="{{{o.desc_change_status}}}">
{{{o.status_message}}}
</a>
<a class="change-xmpp-status-message icon-pencil" href="#" title="{{{o.desc_custom_status}}}"></a>
</div>

View File

@ -1,9 +0,0 @@
<a class="s rooms-tab
{[ if (o.is_current) { ]} current {[ } ]}
{[ if (o.num_unread) { ]} unread-msgs {[ } ]}"
data-id="chatrooms" href="#chatrooms">
{{{o.label_rooms}}}
{[ if (o.num_unread) { ]}
<span class="msgs-indicator">{{{o. num_unread }}}</span>
{[ } ]}
</a>

View File

@ -1,9 +0,0 @@
<a class="s contacts-tab
{[ if (o.is_current) { ]} current {[ } ]}
{[ if (o.num_unread) { ]} unread-msgs {[ } ]}"
data-id="users" href="#users">
{{{o.label_contacts}}}
{[ if (o.num_unread) { ]}
<span class="msgs-indicator">{{{ o.num_unread }}}</span>
{[ } ]}
</a>

View File

@ -1,6 +1,5 @@
<div class="flyout box-flyout">
<div class="chat-head controlbox-head">
<ul id="controlbox-tabs"></ul>
{[ if (!o.sticky_controlbox) { ]}
<a class="chatbox-btn close-chatbox-button icon-close"></a>
{[ } ]}

View File

@ -0,0 +1,13 @@
<div class="userinfo">
<div class="d-flex">
<canvas height="20" width="20" class="avatar align-self-center"></canvas>
<span class="username w-100 align-self-center">{{{o.fullname}}}</span>
<a class="chatbox-btn fa fa-vcard align-self-center" title="{{{o.title_your_profile}}}" data-toggle="modal" data-target="#userProfileModal"></a>
<a class="chatbox-btn fa fa-cog align-self-center" title="{{{o.title_change_status}}}" data-toggle="modal" data-target="#settingsModal"></a>
</div>
<div class="d-flex xmpp-status">
<span class="{{{o.chat_status}}} w-100 align-self-center" data-value="{{{o.chat_status}}}">
<span class="fa fa-circle"></span> {{{o.status_message}}}</span>
<a class="chatbox-btn fa fa-pencil" title="{{{o.title_change_status}}}" data-toggle="modal" data-target="#changeStatusModal"></a>
</div>
</div>

View File

@ -1,4 +1,10 @@
<!-- <div id="chatrooms"> -->
<form class="add-chatroom"></form>
<div class="list-container rooms-list-container">
<dl id="available-chatrooms" class="rooms-list"></dl>
<div class="d-flex">
<span class="w-100">Chatrooms</span>
<a class="chatbox-btn fa fa-users" title="{{{o.title_new_room}}}" data-toggle="modal" data-target="#chatroomsModal"></a>
</div>
<div class="list-container open-rooms-list rooms-list-container">
<div id="available-chatrooms" class="rooms-list"></div>
</div>
<!-- </div> -->

View File

@ -1 +1,9 @@
<div class="d-flex">
<span class="w-100">{{{o.heading_contacts}}}</span>
<a class="chatbox-btn fa fa-user-plus" title="{{{o.title_add_contact}}}"
data-toggle="modal" data-target="#addContactModal"></a>
</div>
<form class="roster-filter-form"></form>
<div class="roster-contacts"></div>

View File

@ -1,32 +1,31 @@
<span {[ if (!o.visible) { ]} class="hidden" {[ } ]}>
<form class="pure-form roster-filter-form input-button-group">
<input value="{{{o.filter_text}}}"
class="roster-filter roster-filter-{{{o.filter_type}}}"
placeholder="{{{o.placeholder}}}">
<select class="state-type state-type-{{{o.filter_type}}}">
<option value="">{{{o.label_any}}}</option>
<option {[ if (o.chat_state === 'unread_messages') { ]} selected="selected" {[ } ]}
value="unread_messages">{{{o.label_unread_messages}}}</option>
<option {[ if (o.chat_state === 'online') { ]} selected="selected" {[ } ]}
value="online">{{{o.label_online}}}</option>
<option {[ if (o.chat_state === 'chat') { ]} selected="selected" {[ } ]}
value="chat">{{{o.label_chatty}}}</option>
<option {[ if (o.chat_state === 'dnd') { ]} selected="selected" {[ } ]}
value="dnd">{{{o.label_busy}}}</option>
<option {[ if (o.chat_state === 'away') { ]} selected="selected" {[ } ]}
value="away">{{{o.label_away}}}</option>
<option {[ if (o.chat_state === 'xa') { ]} selected="selected" {[ } ]}
value="xa">{{{o.label_xa}}}</option>
<option {[ if (o.chat_state === 'offline') { ]} selected="selected" {[ } ]}
value="offline">{{{o.label_offline}}}</option>
</select>
<select class="filter-type">
<option {[ if (o.filter_type === 'contacts') { ]} selected="selected" {[ } ]}
value="contacts">{{{o.label_contacts}}}</option>
<option {[ if (o.filter_type === 'groups') { ]} selected="selected" {[ } ]}
value="groups">{{{o.label_groups}}}</option>
<option {[ if (o.filter_type === 'state') { ]} selected="selected" {[ } ]}
value="state">{{{o.label_state}}}</option>
</select>
<form class="roster-filter-form input-button-group {[ if (!o.visible) { ]} hidden {[ } ]}">
<div class="form-group form-inline">
<input value="{{{o.filter_text}}}"
class="roster-filter roster-filter-{{{o.filter_type}}}"
placeholder="{{{o.placeholder}}}">
<select class="state-type state-type-{{{o.filter_type}}}">
<option value="">{{{o.label_any}}}</option>
<option {[ if (o.chat_state === 'unread_messages') { ]} selected="selected" {[ } ]}
value="unread_messages">{{{o.label_unread_messages}}}</option>
<option {[ if (o.chat_state === 'online') { ]} selected="selected" {[ } ]}
value="online">{{{o.label_online}}}</option>
<option {[ if (o.chat_state === 'chat') { ]} selected="selected" {[ } ]}
value="chat">{{{o.label_chatty}}}</option>
<option {[ if (o.chat_state === 'dnd') { ]} selected="selected" {[ } ]}
value="dnd">{{{o.label_busy}}}</option>
<option {[ if (o.chat_state === 'away') { ]} selected="selected" {[ } ]}
value="away">{{{o.label_away}}}</option>
<option {[ if (o.chat_state === 'xa') { ]} selected="selected" {[ } ]}
value="xa">{{{o.label_xa}}}</option>
<option {[ if (o.chat_state === 'offline') { ]} selected="selected" {[ } ]}
value="offline">{{{o.label_offline}}}</option>
</select>
<div class="filter-by">
<span class="fa fa-user" data-type="contact" title="{{{o.title_contact_filter}}}"></span>
<span class="fa fa-users" data-type="group" title="{{{o.title_group_filter}}}"></span>
<span class="fa fa-circle" data-type="status" title="{{{o.title_status_filter}}}"></span>
</div>
</div>
</form>
</span>

View File

@ -655,6 +655,9 @@
}
u.isVisible = function (el) {
if (u.hasClass('hidden', el)) {
return false;
}
// XXX: Taken from jQuery's "visible" implementation
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
};