Commit ede21e7c authored by JC Brand's avatar JC Brand

Remove controlbox tabs and show rooms and contacts panels together

parent b6501bcf
......@@ -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; }
......
......@@ -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; }
......
......@@ -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">
......
This diff is collapsed.
......@@ -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;
......
......@@ -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;
},
......
This diff is collapsed.
......@@ -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;
}
......
......@@ -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;
},
......
......@@ -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
}
});
}
......
......@@ -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);
}
}
},
......
......@@ -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
......
<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>
<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>
<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>
<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>
{[ } ]}
......
<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>
<!-- <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> -->
<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>
<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>
......@@ -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;
};
......
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