Commit 91397125 authored by JC Brand's avatar JC Brand

roomslist: Refactor to use VDOMView instead of OrderedListView

parent 28d0e885
......@@ -15,11 +15,9 @@
test_utils.openControlBox();
const controlbox = _converse.chatboxviews.get('controlbox');
let list = controlbox.el.querySelector('div.rooms-list-container');
let list = controlbox.el.querySelector('.list-container--openrooms');
expect(_.includes(list.classList, 'hidden')).toBeTruthy();
await test_utils.openChatRoom(_converse, 'room', 'conference.shakespeare.lit', 'JC');
expect(_converse.rooms_list_view === undefined).toBeFalsy();
const lview = _converse.rooms_list_view
await u.waitUntil(() => lview.el.querySelectorAll(".open-room").length);
......@@ -37,7 +35,7 @@
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(1);
expect(room_els[0].innerText).toBe('lounge@montague.lit');
list = controlbox.el.querySelector('div.rooms-list-container');
list = controlbox.el.querySelector('.list-container--openrooms');
u.waitUntil(() => _.includes(list.classList, 'hidden'));
view = _converse.chatboxviews.get('lounge@montague.lit');
......@@ -45,11 +43,10 @@
room_els = _converse.rooms_list_view.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(0);
list = controlbox.el.querySelector('div.rooms-list-container');
list = controlbox.el.querySelector('.list-container--openrooms');
expect(_.includes(list.classList, 'hidden')).toBeTruthy();
done();
}
));
}));
it("uses bookmarks to determine groupchat names",
mock.initConverse(
......@@ -100,7 +97,7 @@
await _converse.api.waitUntil('roomsListInitialized');
const controlbox = _converse.chatboxviews.get('controlbox');
const list = controlbox.el.querySelector('div.rooms-list-container');
const list = controlbox.el.querySelector('.list-container--openrooms');
expect(_.includes(list.classList, 'hidden')).toBeFalsy();
const items = list.querySelectorAll('.list-item');
expect(items.length).toBe(1);
......
......@@ -10,10 +10,8 @@
* rooms in the "Rooms Panel" of the ControlBox.
*/
import "@converse/headless/converse-muc";
import { OrderedListView } from "backbone.overview";
import converse from "@converse/headless/converse-core";
import tpl_rooms_list from "templates/rooms_list.html";
import tpl_rooms_list_item from "templates/rooms_list_item.html"
const { Backbone, Strophe, } = converse.env;
const u = converse.env.utils;
......@@ -39,118 +37,21 @@ converse.plugins.add('converse-roomslist', {
/* The initialize function gets called as soon as the plugin is
* loaded by converse.js's plugin machinery.
*/
const { _converse } = this,
{ __ } = _converse;
const { _converse } = this;
const { __ } = _converse;
// Promises exposed by this plugin
_converse.api.promises.add('roomsListInitialized');
_converse.OpenRooms = _converse.Collection.extend({
comparator (room) {
if (_converse.bookmarks && room.get('bookmarked')) {
const bookmark = _converse.bookmarks.findWhere({'jid': room.get('jid')});
return bookmark.get('name');
} else {
return room.get('name');
}
},
initialize () {
_converse.chatboxes.on('add', this.onChatBoxAdded, this);
_converse.chatboxes.on('change:hidden', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:bookmarked', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:name', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:num_unread', this.onChatBoxChanged, this);
_converse.chatboxes.on('change:num_unread_general', this.onChatBoxChanged, this);
_converse.chatboxes.on('remove', this.onChatBoxRemoved, this);
this.reset(_converse.chatboxes.where({'type': _converse.CHATROOMS_TYPE}).map(cb => cb.attributes));
},
onChatBoxAdded (item) {
if (item.get('type') === _converse.CHATROOMS_TYPE) {
this.create(item.attributes);
}
},
onChatBoxChanged (item) {
if (item.get('type') === _converse.CHATROOMS_TYPE) {
const room = this.get(item.get('jid'));
room && room.set(item.attributes);
}
},
onChatBoxRemoved (item) {
if (item.get('type') === _converse.CHATROOMS_TYPE) {
const room = this.get(item.get('jid'))
this.remove(room);
}
}
});
_converse.RoomsList = Backbone.Model.extend({
defaults: {
"toggle-state": _converse.OPENED
}
});
_converse.RoomsListElementView = Backbone.VDOMView.extend({
events: {
'click .room-info': 'showRoomDetailsModal'
},
initialize () {
this.listenTo(this.model, 'destroy', this.remove)
this.listenTo(this.model, 'remove', this.remove)
this.listenTo(this.model, 'change:bookmarked', this.render)
this.listenTo(this.model, 'change:hidden', this.render)
this.listenTo(this.model, 'change:name', this.render)
this.listenTo(this.model, 'change:num_unread', this.render)
this.listenTo(this.model, 'change:num_unread_general', this.render)
},
toHTML () {
return tpl_rooms_list_item(
Object.assign(this.model.toJSON(), {
// XXX: By the time this renders, the _converse.bookmarks
// collection should already exist if bookmarks are
// supported by the XMPP server. So we can use it
// as a check for support (other ways of checking are async).
'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
'currently_open': _converse.isUniView() && !this.model.get('hidden'),
'info_leave_room': __('Leave this groupchat'),
'info_remove_bookmark': __('Unbookmark this groupchat'),
'info_add_bookmark': __('Bookmark this groupchat'),
'info_title': __('Show more information on this groupchat'),
'name': this.getRoomsListElementName(),
'open_title': __('Click to open this groupchat')
}));
},
showRoomDetailsModal (ev) {
const room = _converse.chatboxes.get(this.model.get('jid'));
ev.preventDefault();
if (room.room_details_modal === undefined) {
room.room_details_modal = new _converse.RoomDetailsModal({'model': room});
}
room.room_details_modal.show(ev);
},
getRoomsListElementName () {
if (this.model.get('bookmarked') && _converse.bookmarks) {
const bookmark = _converse.bookmarks.findWhere({'jid': this.model.get('jid')});
if (bookmark) {
return bookmark.get('name');
}
}
return this.model.get('name');
}
});
_converse.RoomsListView = OrderedListView.extend({
_converse.RoomsListView = Backbone.VDOMView.extend({
tagName: 'div',
className: 'open-rooms-list list-container rooms-list-container',
events: {
......@@ -159,41 +60,52 @@ converse.plugins.add('converse-roomslist', {
'click .list-toggle': 'toggleRoomsList',
'click .remove-bookmark': 'removeBookmark',
'click .open-room': 'openRoom',
'click .room-info': 'showRoomDetailsModal'
},
listSelector: '.rooms-list',
ItemView: _converse.RoomsListElementView,
subviewIndex: 'jid',
initialize () {
OrderedListView.prototype.initialize.apply(this, arguments);
this.listenTo(this.model, 'add', this.showOrHide)
this.listenTo(this.model, 'remove', this.showOrHide)
const storage = _converse.config.get('storage'),
id = `converse.roomslist${_converse.bare_jid}`;
this.list_model = new _converse.RoomsList({'id': id});
this.list_model.browserStorage = _converse.createStore(id, storage);
this.listenTo(this.model, 'add', this.renderIfChatRoom)
this.listenTo(this.model, 'remove', this.renderIfChatRoom)
this.listenTo(this.model, 'destroy', this.renderIfChatRoom)
this.listenTo(this.model, 'change', this.renderIfRelevantChange)
const id = `converse.roomslist${_converse.bare_jid}`;
this.list_model = new _converse.RoomsList({id});
this.list_model.browserStorage = _converse.createStore(id);
this.list_model.fetch();
this.render();
this.sortAndPositionAllItems();
this.insertIntoControlBox();
},
render () {
this.el.innerHTML = tpl_rooms_list({
'toggle_state': this.list_model.get('toggle-state'),
renderIfChatRoom (model) {
u.isChatRoom(model) && this.render();
},
renderIfRelevantChange (model) {
const attrs = ['bookmarked', 'hidden', 'name', 'num_unread', 'num_unread_general'];
const changed = model.changed || {};
if (u.isChatRoom(model) && Object.keys(changed).filter(m => attrs.includes(m)).length) {
this.render();
}
},
toHTML () {
return tpl_rooms_list({
'rooms': _converse.api.rooms.get(),
'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks,
'collapsed': this.list_model.get('toggle-state') !== _converse.OPENED,
'desc_rooms': __('Click to toggle the list of open groupchats'),
'info_add_bookmark': __('Bookmark this groupchat'),
'info_leave_room': __('Leave this groupchat'),
'info_remove_bookmark': __('Unbookmark this groupchat'),
'info_title': __('Show more information on this groupchat'),
'open_title': __('Click to open this groupchat'),
'currently_open': room => _converse.isUniView() && !room.get('hidden'),
'toggle_state': this.list_model.get('toggle-state'),
// Note to translators, "Open Groupchats" refers to groupchats that are open, NOT a command.
'label_rooms': __('Open Groupchats'),
'_converse': _converse
'_converse': _converse,
});
if (this.list_model.get('toggle-state') !== _converse.OPENED) {
this.el.querySelector('.open-rooms-list').classList.add('collapsed');
}
this.showOrHide();
this.insertIntoControlBox();
return this;
},
insertIntoControlBox () {
......@@ -206,12 +118,14 @@ converse.plugins.add('converse-roomslist', {
}
},
hide () {
u.hideElement(this.el);
},
show () {
u.showElement(this.el);
showRoomDetailsModal (ev) {
const jid = ev.target.getAttribute('data-room-jid');
const room = _converse.chatboxes.get(jid);
ev.preventDefault();
if (room.room_details_modal === undefined) {
room.room_details_modal = new _converse.RoomDetailsModal({'model': room});
}
room.room_details_modal.show(ev);
},
async openRoom (ev) {
......@@ -235,14 +149,6 @@ converse.plugins.add('converse-roomslist', {
}
},
showOrHide () {
if (!this.model.models.length) {
u.hideElement(this.el);
} else {
u.showElement(this.el);
}
},
removeBookmark: _converse.removeBookmarkViaEvent,
addBookmark: _converse.addBookmarkViaEvent,
......@@ -266,12 +172,7 @@ converse.plugins.add('converse-roomslist', {
});
const initRoomsListView = function () {
const storage = _converse.config.get('storage'),
id = `converse.open-rooms-{_converse.bare_jid}`,
model = new _converse.OpenRooms();
model.browserStorage = _converse.createStore(id, storage);
_converse.rooms_list_view = new _converse.RoomsListView({'model': model});
_converse.rooms_list_view = new _converse.RoomsListView({'model': _converse.chatboxes});
/**
* Triggered once the _converse.RoomsListView has been created and initialized.
* @event _converse#roomsListInitialized
......
......@@ -355,7 +355,7 @@ _converse.isUniView = function () {
};
_converse.createStore = function (id, storage) {
const s = storage ? storage : _converse.storage[_converse.config.get('storage')];
const s = storage ? storage : _converse.config.get('storage');
return new BrowserStorage[s](id);
}
......
......@@ -169,13 +169,17 @@ u.isOnlyMessageDeliveryReceipt = function (msg) {
return msg['received'] && u.isEmptyMessage(msg);
};
u.isChatRoom = function (model) {
return model && (model.get('type') === 'chatroom');
}
u.isHeadlineMessage = function (_converse, message) {
const from_jid = message.getAttribute('from');
if (message.getAttribute('type') === 'headline') {
return true;
}
const chatbox = _converse.chatboxes.get(Strophe.getBareJidFromJid(from_jid));
if (chatbox && chatbox.get('type') === _converse.CHATROOMS_TYPE) {
if (u.isChatRoom(chatbox)) {
return false;
}
if (message.getAttribute('type') !== 'error' && from_jid && !_.includes(from_jid, '@')) {
......
<div class="list-container list-container--openrooms {{{ !o.rooms.length && 'hidden' || '' }}}">
<a href="#" class="list-toggle open-rooms-toggle controlbox-padded" title="{{{o.desc_rooms}}}">
<span class="fa {[ if (o.toggle_state === o._converse.OPENED) { ]} fa-caret-down {[ } else { ]} fa-caret-right {[ } ]}">
</span> {{{o.label_rooms}}}</a>
<div class="items-list rooms-list open-rooms-list"></div>
<span class="fa {[ if (o.toggle_state === o._converse.OPENED) { ]} fa-caret-down {[ } else { ]} fa-caret-right {[ } ]}">
</span> {{{o.label_rooms}}}</a>
<div class="items-list rooms-list open-rooms-list {{{ o.collapsed && 'collapsed' }}}">
{[o.rooms.forEach(function (room) { ]}
<div class="list-item controlbox-padded available-chatroom d-flex flex-row
{[ if (o.currently_open(room)) { ]} open {[ } ]}
{[ if (room.get('num_unread_general')) { ]} unread-msgs {[ } ]}"
data-room-jid="{{{room.get('jid')}}}">
{[ if (room.get('num_unread')) { ]}
<span class="list-item-badge badge badge-room-color msgs-indicator">{{{ room.get('num_unread') }}}</span>
{[ } ]}
<a class="list-item-link open-room available-room w-100"
data-room-jid="{{{room.get('jid')}}}"
title="{{{o.open_title}}}" href="#">{{{room.getDisplayName()}}}</a>
{[ if (o.allow_bookmarks) { ]}
<a class="list-item-action fa {[ if (o.bookmarked) { ]} fa-bookmark remove-bookmark button-on {[ } else { ]} add-bookmark fa-bookmark {[ } ]}"
data-room-jid="{{{room.get('jid')}}}"
data-bookmark-name="{{{room.getDisplayName()}}}"
title="{[ if (o.bookmarked) { ]} {{{o.info_remove_bookmark}}} {[ } else { ]} {{{o.info_add_bookmark}}} {[ } ]}"
href="#"></a>
{[ } ]}
<a class="list-item-action room-info fa fa-info-circle"
data-room-jid="{{{room.get('jid')}}}"
title="{{{o.info_title}}}" href="#"></a>
<a class="list-item-action fa fa-sign-out-alt close-room"
data-room-jid="{{{room.get('jid')}}}"
data-room-name="{{{room.getDisplayName()}}}"
title="{{{o.info_leave_room}}}" href="#"></a>
</div>
{[ }) ]}
</div>
</div>
<div class="list-item controlbox-padded available-chatroom d-flex flex-row
{[ if (o.currently_open) { ]} open {[ } ]}
{[ if (o.num_unread_general) { ]} unread-msgs {[ } ]}"
data-room-jid="{{{o.jid}}}">
{[ if (o.num_unread) { ]}
<span class="list-item-badge badge badge-room-color msgs-indicator">{{{ o.num_unread }}}</span>
{[ } ]}
<a class="list-item-link open-room available-room w-100"
data-room-jid="{{{o.jid}}}"
title="{{{o.open_title}}}" href="#">{{{o.name || o.jid}}}</a>
{[ if (o.allow_bookmarks) { ]}
<a class="list-item-action fa {[ if (o.bookmarked) { ]} fa-bookmark remove-bookmark button-on {[ } else { ]} add-bookmark fa-bookmark {[ } ]}"
data-room-jid="{{{o.jid}}}" data-bookmark-name="{{{o.name}}}"
title="{[ if (o.bookmarked) { ]} {{{o.info_remove_bookmark}}} {[ } else { ]} {{{o.info_add_bookmark}}} {[ } ]}"
href="#"></a>
{[ } ]}
<a class="list-item-action room-info fa fa-info-circle" data-room-jid="{{{o.jid}}}"
title="{{{o.info_title}}}" href="#"></a>
<a class="list-item-action fa fa-sign-out-alt close-room"
data-room-jid="{{{o.jid}}}"
data-room-name="{{{o.name || o.jid}}}"
title="{{{o.info_leave_room}}}" href="#"></a>
</div>
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