diff --git a/spec/bookmarks.js b/spec/bookmarks.js index e03b29452..3299c252c 100644 --- a/spec/bookmarks.js +++ b/spec/bookmarks.js @@ -410,7 +410,7 @@ describe("Bookmarks", function () { it("can be retrieved from the XMPP server", mock.initConverse( - ['chatBoxesFetched', 'roomsPanelRendered', 'rosterGroupsFetched'], {}, + ['chatBoxesFetched', 'rosterGroupsFetched'], {}, async function (done, _converse) { const { Strophe, sizzle, u, $iq } = converse.env; @@ -420,14 +420,14 @@ describe("Bookmarks", function () { ['http://jabber.org/protocol/pubsub#publish-options'] ); /* Client requests all items - * ------------------------- - * - * - * - * - * - * - */ + * ------------------------- + * + * + * + * + * + * + */ const IQ_stanzas = _converse.connection.IQ_stanzas; const sent_stanza = await u.waitUntil( () => IQ_stanzas.filter(s => sizzle('items[node="storage:bookmarks"]', s).length).pop()); @@ -487,7 +487,7 @@ describe("Bookmarks", function () { done(); })); - describe("The rooms panel", function () { + describe("The bookmarks list", function () { it("shows a list of bookmarks", mock.initConverse( ['rosterGroupsFetched'], {}, @@ -649,19 +649,21 @@ describe("Bookmarks", function () { 'name': 'The Play', 'nick': '' }); - const el = _converse.chatboxviews.el + const chats_el = document.querySelector('converse-chats'); const selector = '#chatrooms .bookmarks.rooms-list .room-item'; - await u.waitUntil(() => sizzle(selector, el).filter(u.isVisible).length); - expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', el).pop())).toBeFalsy(); - expect(sizzle(selector, el).filter(u.isVisible).length).toBe(1); - expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); - sizzle('#chatrooms .bookmarks-toggle', el).pop().click(); - expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', el).pop())).toBeTruthy(); - expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.CLOSED); - sizzle('#chatrooms .bookmarks-toggle', el).pop().click(); - expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', el).pop())).toBeFalsy(); - expect(sizzle(selector, el).filter(u.isVisible).length).toBe(1); - expect(_converse.bookmarksview.list_model.get('toggle-state')).toBe(_converse.OPENED); + await u.waitUntil(() => sizzle(selector, chats_el).filter(u.isVisible).length); + expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', chats_el).pop())).toBeFalsy(); + expect(sizzle(selector, chats_el).filter(u.isVisible).length).toBe(1); + + const bookmarks_el = chats_el.querySelector('converse-bookmarks'); + expect(bookmarks_el.model.get('toggle-state')).toBe(_converse.OPENED); + sizzle('#chatrooms .bookmarks-toggle', chats_el).pop().click(); + expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', chats_el).pop())).toBeTruthy(); + expect(bookmarks_el.model.get('toggle-state')).toBe(_converse.CLOSED); + sizzle('#chatrooms .bookmarks-toggle', chats_el).pop().click(); + expect(u.hasClass('collapsed', sizzle('#chatrooms .bookmarks.rooms-list', chats_el).pop())).toBeFalsy(); + expect(sizzle(selector, chats_el).filter(u.isVisible).length).toBe(1); + expect(bookmarks_el.model.get('toggle-state')).toBe(_converse.OPENED); done(); })); }); @@ -688,20 +690,20 @@ describe("When hide_open_bookmarks is true and a bookmarked room is opened", fun expect(_converse.bookmarks.length).toBe(1); const u = converse.env.utils; - const bmarks_view = _converse.bookmarksview; - await u.waitUntil(() => bmarks_view.querySelectorAll(".open-room").length, 500); - const room_els = bmarks_view.querySelectorAll(".open-room"); + const bookmarks_el = document.querySelector('converse-bookmarks'); + await u.waitUntil(() => bookmarks_el.querySelectorAll(".open-room").length, 500); + const room_els = bookmarks_el.querySelectorAll(".open-room"); expect(room_els.length).toBe(1); - const bookmark = _converse.bookmarksview.querySelector(".open-room"); + const bookmark = bookmarks_el.querySelector(".open-room"); bookmark.click(); await u.waitUntil(() => _converse.chatboxviews.get(jid)); - expect(u.hasClass('hidden', _converse.bookmarksview.querySelector(".available-chatroom"))).toBeTruthy(); + expect(u.hasClass('hidden', bookmarks_el.querySelector(".available-chatroom"))).toBeTruthy(); // Check that it reappears once the room is closed const view = _converse.chatboxviews.get(jid); view.close(); - await u.waitUntil(() => !u.hasClass('hidden', _converse.bookmarksview.querySelector(".available-chatroom"))); + await u.waitUntil(() => !u.hasClass('hidden', bookmarks_el.querySelector(".available-chatroom"))); done(); })); }); diff --git a/spec/muclist.js b/spec/muclist.js index b37c9d42c..b9bd7064d 100644 --- a/spec/muclist.js +++ b/spec/muclist.js @@ -126,7 +126,7 @@ describe("A groupchat shown in the groupchats list", function () { expect(room_els.length).toBe(1); let item = room_els[0]; - await u.waitUntil(() => lview.model.get(muc_jid).get('hidden') === false); + await u.waitUntil(() => _converse.chatboxes.get(muc_jid).get('hidden') === false); await u.waitUntil(() => u.hasClass('open', item), 1000); expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit'); await _converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'}, true); diff --git a/src/headless/core.js b/src/headless/core.js index 8d0aacd41..ac2f3d42c 100644 --- a/src/headless/core.js +++ b/src/headless/core.js @@ -742,7 +742,6 @@ export const api = _converse.api = { * * [rosterContactsFetched](/docs/html/events.html#rosterContactsFetched) * * [rosterGroupsFetched](/docs/html/events.html#rosterGroupsFetched) * * [rosterInitialized](/docs/html/events.html#rosterInitialized) - * * [roomsPanelRendered](/docs/html/events.html#roomsPanelRendered) * * The various plugins might also provide promises, and they do this by using the * `promises.add` api method. diff --git a/src/headless/plugins/muc/index.js b/src/headless/plugins/muc/index.js index c7df737fd..ecc25350e 100644 --- a/src/headless/plugins/muc/index.js +++ b/src/headless/plugins/muc/index.js @@ -16,7 +16,6 @@ import muc_api from './api.js'; import muc_utils from './utils.js'; import u from '../../utils/form'; import { Collection } from '@converse/skeletor/src/collection'; -import { Model } from '@converse/skeletor/src/model.js'; import { _converse, api, converse } from '../../core.js'; import { isObject } from 'lodash-es'; @@ -369,21 +368,6 @@ converse.plugins.add('converse-muc', { }); - _converse.RoomsPanelModel = Model.extend({ - defaults: function () { - return { - 'muc_domain': api.settings.get('muc_domain'), - 'nick': _converse.getDefaultMUCNickname() - }; - }, - - setDomain (jid) { - if (!api.settings.get('locked_muc_domain')) { - this.save('muc_domain', Strophe.getDomainFromJid(jid)); - } - } - }); - /** * A direct MUC invitation to join a groupchat has been received * See XEP-0249: Direct MUC invitations. diff --git a/src/plugins/bookmark-views/bookmarks-list.js b/src/plugins/bookmark-views/bookmarks-list.js index 7bc81d588..656a8fa10 100644 --- a/src/plugins/bookmark-views/bookmarks-list.js +++ b/src/plugins/bookmark-views/bookmarks-list.js @@ -10,31 +10,30 @@ export default class BookmarksView extends ElementView { async initialize () { await api.waitUntil('bookmarksInitialized'); - this.model = _converse.bookmarks; - this.listenTo(this.model, 'add', this.render); - this.listenTo(this.model, 'remove', this.render); + this.listenTo(_converse.bookmarks, 'add', this.render); + this.listenTo(_converse.bookmarks, 'remove', this.render); this.listenTo(_converse.chatboxes, 'add', this.render); this.listenTo(_converse.chatboxes, 'remove', this.render); const id = `converse.room-bookmarks${_converse.bare_jid}-list-model`; - this.list_model = new _converse.BookmarksList({ id }); - this.list_model.browserStorage = _converse.createStore(id); - this.list_model.fetch({ 'success': () => this.render(), 'error': () => this.render() }); + this.model = new _converse.BookmarksList({ id }); + this.model.browserStorage = _converse.createStore(id); + this.model.fetch({ 'success': () => this.render(), 'error': () => this.render() }); } render () { const is_hidden = b => !!(api.settings.get('hide_open_bookmarks') && _converse.chatboxes.get(b.get('jid'))); render(tpl_bookmarks_list({ '_converse': _converse, - 'bookmarks': this.model, - 'hidden': this.model.getUnopenedBookmarks().length && true, + 'bookmarks': _converse.bookmarks, + 'hidden': _converse.bookmarks.getUnopenedBookmarks().length && true, 'is_hidden': is_hidden, 'openRoom': ev => this.openRoom(ev), 'removeBookmark': ev => this.removeBookmark(ev), 'toggleBookmarksList': ev => this.toggleBookmarksList(ev), - 'toggle_state': this.list_model.get('toggle-state') + 'toggle_state': this.model.get('toggle-state') }), this); } @@ -58,15 +57,15 @@ export default class BookmarksView extends ElementView { } const icon_el = ev.target.matches('.fa') ? ev.target : ev.target.querySelector('.fa'); if (u.hasClass('fa-caret-down', icon_el)) { - u.slideIn(this.el.querySelector('.bookmarks')); - this.list_model.save({ 'toggle-state': _converse.CLOSED }); + u.slideIn(this.querySelector('.bookmarks')); + this.model.save({ 'toggle-state': _converse.CLOSED }); icon_el.classList.remove('fa-caret-down'); icon_el.classList.add('fa-caret-right'); } else { icon_el.classList.remove('fa-caret-right'); icon_el.classList.add('fa-caret-down'); - u.slideOut(this.el.querySelector('.bookmarks')); - this.list_model.save({ 'toggle-state': _converse.OPENED }); + u.slideOut(this.querySelector('.bookmarks')); + this.model.save({ 'toggle-state': _converse.OPENED }); } } } diff --git a/src/plugins/controlbox/templates/controlbox.js b/src/plugins/controlbox/templates/controlbox.js index 12b139412..035d394f2 100644 --- a/src/plugins/controlbox/templates/controlbox.js +++ b/src/plugins/controlbox/templates/controlbox.js @@ -15,9 +15,11 @@ export default o => html` ${o.connected ? html` - - - ` + +
+ + +
` : o['active-form'] === 'register' ? html`` : html`` diff --git a/src/plugins/muc-views/index.js b/src/plugins/muc-views/index.js index c8d527b2e..4f19dcb49 100644 --- a/src/plugins/muc-views/index.js +++ b/src/plugins/muc-views/index.js @@ -94,8 +94,6 @@ converse.plugins.add('converse-muc-views', { initialize () { const { _converse } = this; - api.promises.add(['roomsPanelRendered']); - // Configuration values for this plugin // ==================================== // Refer to docs/source/configuration.rst for explanations of these diff --git a/src/plugins/muc-views/rooms-panel.js b/src/plugins/muc-views/rooms-panel.js index dbbc7e145..676bcb5a8 100644 --- a/src/plugins/muc-views/rooms-panel.js +++ b/src/plugins/muc-views/rooms-panel.js @@ -1,74 +1,12 @@ -import AddMUCModal from 'modals/add-muc.js'; -import tpl_room_panel from 'templates/room_panel.js'; -import { View } from '@converse/skeletor/src/view.js'; -import MUCListModal from 'modals/muc-list.js'; -import { _converse, api, converse } from '@converse/headless/core'; -import { __ } from 'i18n'; +import { converse } from '@converse/headless/core'; const u = converse.env.utils; -/** - * View which renders MUC section of the control box. - * @class - * @namespace _converse.RoomsPanel - * @memberOf _converse - */ -export const RoomsPanel = View.extend({ - tagName: 'div', - className: 'controlbox-section', - id: 'chatrooms', - events: { - 'click a.controlbox-heading__btn.show-add-muc-modal': 'showAddRoomModal', - 'click a.controlbox-heading__btn.show-list-muc-modal': 'showMUCListModal' - }, - - toHTML () { - return tpl_room_panel({ - 'heading_chatrooms': __('Groupchats'), - 'title_new_room': __('Add a new groupchat'), - 'title_list_rooms': __('Query for groupchats') - }); - }, - - showAddRoomModal (ev) { - api.modal.show(AddMUCModal, { 'model': this.model }, ev); - }, - - showMUCListModal (ev) { - api.modal.show(MUCListModal, { 'model': this.model }, ev); - } -}); - /** * Mixin which adds the ability to a ControlBox to render a list of open groupchats * @mixin */ export const RoomsPanelViewMixin = { - renderRoomsPanel () { - if (this.roomspanel && u.isInDOM(this.roomspanel.el)) { - return this.roomspanel; - } - const id = `converse.roomspanel${_converse.bare_jid}`; - - this.roomspanel = new _converse.RoomsPanel({ - 'model': new (_converse.RoomsPanelModel.extend({ - id, - 'browserStorage': _converse.createStore(id) - }))() - }); - this.roomspanel.model.fetch(); - this.querySelector('.controlbox-pane').insertAdjacentElement('beforeEnd', this.roomspanel.render().el); - - /** - * Triggered once the section of the { @link _converse.ControlBoxView } - * which shows gropuchats has been rendered. - * @event _converse#roomsPanelRendered - * @example _converse.api.listen.on('roomsPanelRendered', () => { ... }); - */ - api.trigger('roomsPanelRendered'); - return this.roomspanel; - }, - getRoomsPanel () { if (this.roomspanel && u.isInDOM(this.roomspanel.el)) { return this.roomspanel; diff --git a/src/plugins/roomslist/index.js b/src/plugins/roomslist/index.js index 0b478901d..d58126031 100644 --- a/src/plugins/roomslist/index.js +++ b/src/plugins/roomslist/index.js @@ -7,28 +7,14 @@ */ import "@converse/headless/plugins/muc/index.js"; import './view.js'; -import RoomsList from './model.js'; import { _converse, api, converse } from "@converse/headless/core"; converse.plugins.add('converse-roomslist', { - /* Dependencies are other plugins which might be - * overridden or relied upon, and therefore need to be loaded before - * this plugin. They are called "optional" because they might not be - * available, in which case any overrides applicable to them will be - * ignored. - * - * It's possible however to make optional dependencies non-optional. - * If the setting "strict_plugin_dependencies" is set to true, - * an error will be raised if the plugin is not found. - * - * NB: These plugins need to have already been loaded via require.js. - */ + dependencies: ["converse-singleton", "converse-controlbox", "converse-muc", "converse-bookmarks"], initialize () { - _converse.RoomsList= RoomsList; - // Event handlers api.listen.on('connected', async () => { if (_converse.allow_bookmarks) { @@ -36,7 +22,6 @@ converse.plugins.add('converse-roomslist', { } else { await Promise.all([ api.waitUntil('chatBoxesFetched'), - api.waitUntil('roomsPanelRendered') ]); } }); diff --git a/src/plugins/roomslist/model.js b/src/plugins/roomslist/model.js deleted file mode 100644 index 1b7664257..000000000 --- a/src/plugins/roomslist/model.js +++ /dev/null @@ -1,9 +0,0 @@ -import { _converse } from "@converse/headless/core"; -import { Model } from '@converse/skeletor/src/model.js'; - - -export default Model.extend({ - defaults: { - "toggle-state": _converse.OPENED - } -}); diff --git a/src/plugins/roomslist/templates/roomslist.js b/src/plugins/roomslist/templates/roomslist.js index 7c22bd392..785e1a779 100644 --- a/src/plugins/roomslist/templates/roomslist.js +++ b/src/plugins/roomslist/templates/roomslist.js @@ -1,5 +1,8 @@ -import { html } from "lit-html"; +import AddMUCModal from 'modals/add-muc.js'; +import MUCListModal from 'modals/muc-list.js'; import { __ } from 'i18n'; +import { _converse, api } from "@converse/headless/core"; +import { html } from "lit-html"; const bookmark = (o) => { @@ -58,10 +61,23 @@ const room_item = (o) => { export default (o) => { const i18n_desc_rooms = __('Click to toggle the list of open groupchats'); + const i18n_heading_chatrooms = __('Groupchats'); + const i18n_title_list_rooms = __('Query for groupchats'); + const i18n_title_new_room = __('Add a new groupchat'); return html` +
+ ${i18n_heading_chatrooms} + api.modal.show(MUCListModal, { 'model': o.model }, ev)} + title="${i18n_title_list_rooms}" data-toggle="modal" data-target="#muc-list-modal"> + api.modal.show(AddMUCModal, { 'model': o.model }, ev)} + title="${i18n_title_new_room}" data-toggle="modal" data-target="#add-chatrooms-modal"> +
+
- ${__('Open Groupchats')} + ${__('Open Groupchats')}
${ o.rooms.map(room => room_item(Object.assign({room}, o))) }
diff --git a/src/plugins/roomslist/view.js b/src/plugins/roomslist/view.js index 3711b29b1..3603149cf 100644 --- a/src/plugins/roomslist/view.js +++ b/src/plugins/roomslist/view.js @@ -1,26 +1,47 @@ import RoomDetailsModal from 'modals/muc-details.js'; import tpl_rooms_list from "./templates/roomslist.js"; import { ElementView } from '@converse/skeletor/src/element.js'; +import { Model } from '@converse/skeletor/src/model.js'; import { __ } from 'i18n'; import { _converse, api, converse } from "@converse/headless/core"; +import { render } from 'lit-html'; const { Strophe } = converse.env; const u = converse.env.utils; +const RoomsListModel = Model.extend({ + defaults: function () { + return { + 'muc_domain': api.settings.get('muc_domain'), + 'nick': _converse.getDefaultMUCNickname(), + 'toggle-state': _converse.OPENED, + }; + }, + + setDomain (jid) { + if (!api.settings.get('locked_muc_domain')) { + this.save('muc_domain', Strophe.getDomainFromJid(jid)); + } + } +}); + + export class RoomsList extends ElementView { initialize () { - this.model = _converse.chatboxes; - 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.roomspanel${_converse.bare_jid}`; + this.model = new (RoomsListModel.extend({ + id, + 'browserStorage': _converse.createStore(id) + }))(); + this.model.fetch(); + + this.listenTo(_converse.chatboxes, 'add', this.renderIfChatRoom) + this.listenTo(_converse.chatboxes, 'remove', this.renderIfChatRoom) + this.listenTo(_converse.chatboxes, 'destroy', this.renderIfChatRoom) + this.listenTo(_converse.chatboxes, '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(); } @@ -36,21 +57,21 @@ export class RoomsList extends ElementView { } } - toHTML () { - return tpl_rooms_list({ - '_converse': _converse, + render () { + render(tpl_rooms_list({ 'addBookmark': ev => this.addBookmark(ev), 'allow_bookmarks': _converse.allow_bookmarks && _converse.bookmarks, 'closeRoom': ev => this.closeRoom(ev), - 'collapsed': this.list_model.get('toggle-state') !== _converse.OPENED, + 'collapsed': this.model.get('toggle-state') !== _converse.OPENED, 'currently_open': room => _converse.isUniView() && !room.get('hidden'), + 'model': this.model, 'openRoom': ev => this.openRoom(ev), 'removeBookmark': ev => this.removeBookmark(ev), - 'rooms': this.model.filter(m => m.get('type') === _converse.CHATROOMS_TYPE), + 'rooms': _converse.chatboxes.filter(m => m.get('type') === _converse.CHATROOMS_TYPE), 'showRoomDetailsModal': ev => this.showRoomDetailsModal(ev), 'toggleRoomsList': ev => this.toggleRoomsList(ev), - 'toggle_state': this.list_model.get('toggle-state') - }); + 'toggle_state': this.model.get('toggle-state') + }), this); } showRoomDetailsModal (ev) { // eslint-disable-line class-methods-use-this @@ -94,13 +115,13 @@ export class RoomsList extends ElementView { const icon_el = ev.target.matches('.fa') ? ev.target : ev.target.querySelector('.fa'); if (icon_el.classList.contains("fa-caret-down")) { u.slideIn(this.el.querySelector('.open-rooms-list')).then(() => { - this.list_model.save({'toggle-state': _converse.CLOSED}); + this.model.save({'toggle-state': _converse.CLOSED}); icon_el.classList.remove("fa-caret-down"); icon_el.classList.add("fa-caret-right"); }); } else { u.slideOut(this.el.querySelector('.open-rooms-list')).then(() => { - this.list_model.save({'toggle-state': _converse.OPENED}); + this.model.save({'toggle-state': _converse.OPENED}); icon_el.classList.remove("fa-caret-right"); icon_el.classList.add("fa-caret-down"); }); diff --git a/src/templates/room_panel.js b/src/templates/room_panel.js deleted file mode 100644 index b8b95abdf..000000000 --- a/src/templates/room_panel.js +++ /dev/null @@ -1,10 +0,0 @@ -import { html } from "lit-html"; - -export default (o) => html` -
- ${o.heading_chatrooms} - - -
- - `;