Turn bookmarks list into a Lit component
This commit is contained in:
parent
230b72139a
commit
ce22508344
@ -13,7 +13,7 @@ const Bookmarks = {
|
||||
model: Bookmark,
|
||||
comparator: (item) => item.get('name').toLowerCase(),
|
||||
|
||||
initialize () {
|
||||
async initialize () {
|
||||
this.on('add', bm => this.openBookmarkedRoom(bm)
|
||||
.then(bm => this.markRoomAsBookmarked(bm))
|
||||
.catch(e => log.fatal(e))
|
||||
@ -25,6 +25,17 @@ const Bookmarks = {
|
||||
const cache_key = `converse.room-bookmarks${_converse.bare_jid}`;
|
||||
this.fetched_flag = cache_key+'fetched';
|
||||
initStorage(this, cache_key);
|
||||
|
||||
await this.fetchBookmarks();
|
||||
|
||||
/**
|
||||
* Triggered once the _converse.Bookmarks collection
|
||||
* has been created and cached bookmarks have been fetched.
|
||||
* @event _converse#bookmarksInitialized
|
||||
* @type { _converse.Bookmarks }
|
||||
* @example _converse.api.listen.on('bookmarksInitialized', (bookmarks) => { ... });
|
||||
*/
|
||||
api.trigger('bookmarksInitialized', this);
|
||||
},
|
||||
|
||||
async openBookmarkedRoom (bookmark) {
|
||||
@ -108,16 +119,12 @@ const Bookmarks = {
|
||||
|
||||
markRoomAsBookmarked (bookmark) {
|
||||
const groupchat = _converse.chatboxes.get(bookmark.get('jid'));
|
||||
if (groupchat !== undefined) {
|
||||
groupchat.save('bookmarked', true);
|
||||
}
|
||||
groupchat?.save('bookmarked', true);
|
||||
},
|
||||
|
||||
markRoomAsUnbookmarked (bookmark) {
|
||||
const groupchat = _converse.chatboxes.get(bookmark.get('jid'));
|
||||
if (groupchat !== undefined) {
|
||||
groupchat.save('bookmarked', false);
|
||||
}
|
||||
groupchat?.save('bookmarked', false);
|
||||
},
|
||||
|
||||
createBookmarksFromStanza (stanza) {
|
||||
|
@ -7,58 +7,31 @@
|
||||
import "@converse/headless/plugins/muc/index.js";
|
||||
import Bookmark from './model.js';
|
||||
import Bookmarks from './collection.js';
|
||||
import log from "@converse/headless/log.js";
|
||||
import { Collection } from "@converse/skeletor/src/collection";
|
||||
import { Collection } from "@converse/skeletor/src/collection.js";
|
||||
import { Model } from '@converse/skeletor/src/model.js';
|
||||
import { _converse, api, converse } from "@converse/headless/core";
|
||||
import { initBookmarks, getNicknameFromBookmark } from './utils.js';
|
||||
import { _converse, api, converse } from "@converse/headless/core.js";
|
||||
import { initBookmarks, getNicknameFromBookmark, handleBookmarksPush } from './utils.js';
|
||||
|
||||
const { Strophe, sizzle } = converse.env;
|
||||
const { Strophe } = converse.env;
|
||||
|
||||
Strophe.addNamespace('BOOKMARKS', 'storage:bookmarks');
|
||||
|
||||
|
||||
function handleBookmarksPush (message) {
|
||||
if (sizzle(`event[xmlns="${Strophe.NS.PUBSUB}#event"] items[node="${Strophe.NS.BOOKMARKS}"]`, message).length) {
|
||||
api.waitUntil('bookmarksInitialized')
|
||||
.then(() => _converse.bookmarks.createBookmarksFromStanza(message))
|
||||
.catch(e => log.fatal(e));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
converse.plugins.add('converse-bookmarks', {
|
||||
|
||||
/* Plugin dependencies are other plugins which might be
|
||||
* overridden or relied upon, and therefore need to be loaded before
|
||||
* this plugin.
|
||||
*
|
||||
* If the setting "strict_plugin_dependencies" is set to true,
|
||||
* an error will be raised if the plugin is not found. By default it's
|
||||
* false, which means these plugins are only loaded opportunistically.
|
||||
*
|
||||
* NB: These plugins need to have already been loaded via require.js.
|
||||
*/
|
||||
dependencies: ["converse-chatboxes", "converse-muc"],
|
||||
|
||||
overrides: {
|
||||
// Overrides mentioned here will be picked up by converse.js's
|
||||
// plugin architecture they will replace existing methods on the
|
||||
// relevant objects or classes.
|
||||
//
|
||||
// New functions which don't exist yet can also be added.
|
||||
|
||||
ChatRoom: {
|
||||
getDisplayName () {
|
||||
const { _converse } = this.__super__;
|
||||
if (this.get('bookmarked') && _converse.bookmarks) {
|
||||
const bookmark = _converse.bookmarks.get(this.get('jid'));
|
||||
if (bookmark) {
|
||||
return bookmark.get('name');
|
||||
}
|
||||
}
|
||||
return this.__super__.getDisplayName.apply(this, arguments);
|
||||
const { _converse, getDisplayName } = this.__super__;
|
||||
const bookmark = this.get('bookmarked') ? _converse.bookmarks?.get(this.get('jid')) : null;
|
||||
return bookmark?.get('name') || getDisplayName.apply(this, arguments);
|
||||
},
|
||||
|
||||
getAndPersistNickname (nick) {
|
||||
@ -69,10 +42,6 @@ converse.plugins.add('converse-bookmarks', {
|
||||
},
|
||||
|
||||
initialize () {
|
||||
/* The initialize function gets called as soon as the plugin is
|
||||
* loaded by converse.js's plugin machinery.
|
||||
*/
|
||||
|
||||
// Configuration values for this plugin
|
||||
// ====================================
|
||||
// Refer to docs/source/configuration.rst for explanations of these
|
||||
@ -101,7 +70,7 @@ converse.plugins.add('converse-bookmarks', {
|
||||
})
|
||||
|
||||
api.listen.on('clearSession', () => {
|
||||
if (_converse.bookmarks !== undefined) {
|
||||
if (_converse.bookmarks) {
|
||||
_converse.bookmarks.clearStore({'silent': true});
|
||||
window.sessionStorage.removeItem(_converse.bookmarks.fetched_flag);
|
||||
delete _converse.bookmarks;
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { _converse, api, converse } from '@converse/headless/core';
|
||||
const { Strophe } = converse.env;
|
||||
import log from "@converse/headless/log.js";
|
||||
import { _converse, api, converse } from '@converse/headless/core.js';
|
||||
|
||||
const { Strophe, sizzle } = converse.env;
|
||||
|
||||
export async function checkBookmarksSupport () {
|
||||
const identity = await api.disco.getIdentity('pubsub', 'pep', _converse.bare_jid);
|
||||
@ -16,27 +18,21 @@ export async function initBookmarks () {
|
||||
}
|
||||
if (await checkBookmarksSupport()) {
|
||||
_converse.bookmarks = new _converse.Bookmarks();
|
||||
await _converse.bookmarks.fetchBookmarks();
|
||||
/**
|
||||
* Triggered once the _converse.Bookmarks collection
|
||||
* has been created and cached bookmarks have been fetched.
|
||||
* @event _converse#bookmarksInitialized
|
||||
* @example _converse.api.listen.on('bookmarksInitialized', () => { ... });
|
||||
*/
|
||||
api.trigger('bookmarksInitialized');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user has a bookmark with a saved nickanme
|
||||
* for this groupchat and return it.
|
||||
*/
|
||||
export function getNicknameFromBookmark (jid) {
|
||||
if (!_converse.bookmarks || !api.settings.get('allow_bookmarks')) {
|
||||
if (!api.settings.get('allow_bookmarks')) {
|
||||
return null;
|
||||
}
|
||||
const bookmark = _converse.bookmarks.get(jid);
|
||||
if (bookmark) {
|
||||
return bookmark.get('nick');
|
||||
}
|
||||
return _converse.bookmarks?.get(jid)?.get('nick');
|
||||
}
|
||||
|
||||
export function handleBookmarksPush (message) {
|
||||
if (sizzle(`event[xmlns="${Strophe.NS.PUBSUB}#event"] items[node="${Strophe.NS.BOOKMARKS}"]`, message).length) {
|
||||
api.waitUntil('bookmarksInitialized')
|
||||
.then(() => _converse.bookmarks.createBookmarksFromStanza(message))
|
||||
.catch(e => log.fatal(e));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ const UserDetailsModal = BootstrapModal.extend({
|
||||
* Triggered once the UserDetailsModal has been initialized
|
||||
* @event _converse#userDetailsModalInitialized
|
||||
* @type { _converse.ChatBox }
|
||||
* @example _converse.api.listen.on('userDetailsModalInitialized', chatbox => { ... });
|
||||
* @example _converse.api.listen.on('userDetailsModalInitialized', (chatbox) => { ... });
|
||||
*/
|
||||
api.trigger('userDetailsModalInitialized', this.model);
|
||||
},
|
||||
|
@ -1,57 +1,47 @@
|
||||
import log from '@converse/headless/log';
|
||||
import log from '@converse/headless/log.js';
|
||||
import tpl_bookmarks_list from './templates/list.js';
|
||||
import { ElementView } from '@converse/skeletor/src/element.js';
|
||||
import { _converse, api, converse } from '@converse/headless/core';
|
||||
import { CustomElement } from 'shared/components/element.js';
|
||||
import { _converse, api } from '@converse/headless/core.js';
|
||||
import { initStorage } from '@converse/headless/utils/storage.js';
|
||||
import { render } from 'lit';
|
||||
|
||||
const u = converse.env.utils;
|
||||
|
||||
export default class BookmarksView extends ElementView {
|
||||
export default class BookmarksView extends CustomElement {
|
||||
|
||||
async initialize () {
|
||||
await api.waitUntil('bookmarksInitialized');
|
||||
const { bookmarks, chatboxes } = _converse;
|
||||
|
||||
this.listenTo(_converse.bookmarks, 'add', this.render);
|
||||
this.listenTo(_converse.bookmarks, 'remove', this.render);
|
||||
this.listenTo(bookmarks, 'add', () => this.requestUpdate());
|
||||
this.listenTo(bookmarks, 'remove', () => this.requestUpdate());
|
||||
|
||||
this.listenTo(_converse.chatboxes, 'add', this.render);
|
||||
this.listenTo(_converse.chatboxes, 'remove', this.render);
|
||||
this.listenTo(chatboxes, 'add', () => this.requestUpdate());
|
||||
this.listenTo(chatboxes, 'remove', () => this.requestUpdate());
|
||||
|
||||
const id = `converse.bookmarks-list-model-${_converse.bare_jid}`;
|
||||
this.model = new _converse.BookmarksList({ id });
|
||||
initStorage(this.model, id);
|
||||
|
||||
this.listenTo(this.model, 'change', () => this.requestUpdate());
|
||||
|
||||
this.model.fetch({
|
||||
'success': () => this.render(),
|
||||
'error': (model, err) => {
|
||||
'success': () => this.requestUpdate(),
|
||||
'error': (_m, err) => {
|
||||
log.error(err);
|
||||
this.render();
|
||||
this.requestUpdate();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render () {
|
||||
render(tpl_bookmarks_list({
|
||||
'toggleBookmarksList': ev => this.toggleBookmarksList(ev),
|
||||
'toggle_state': this.model.get('toggle-state')
|
||||
}), this);
|
||||
return _converse.bookmarks ? tpl_bookmarks_list(this) : '';
|
||||
}
|
||||
|
||||
toggleBookmarksList (ev) {
|
||||
ev?.preventDefault?.();
|
||||
const icon_el = ev.target.matches('.fa') ? ev.target : ev.target.querySelector('.fa');
|
||||
if (u.hasClass('fa-caret-down', icon_el)) {
|
||||
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.querySelector('.bookmarks'));
|
||||
this.model.save({ 'toggle-state': _converse.OPENED });
|
||||
}
|
||||
const { CLOSED, OPENED } = _converse;
|
||||
this.model.save({
|
||||
'toggle-state': this.model.get('toggle-state') === CLOSED ? OPENED : CLOSED
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,8 +3,8 @@ import { _converse, api } from '@converse/headless/core.js';
|
||||
import { html } from "lit";
|
||||
import { openRoomViaEvent, removeBookmarkViaEvent } from '../utils.js';
|
||||
|
||||
export default (o) => {
|
||||
const jid = o.bm.get('jid');
|
||||
export default (bm) => {
|
||||
const jid = bm.get('jid');
|
||||
const is_hidden = !!(api.settings.get('hide_open_bookmarks') && _converse.chatboxes.get(jid));
|
||||
const info_remove_bookmark = __('Unbookmark this groupchat');
|
||||
const open_title = __('Click to open this groupchat');
|
||||
@ -12,11 +12,11 @@ export default (o) => {
|
||||
<div class="list-item controlbox-padded room-item available-chatroom d-flex flex-row ${ is_hidden ? 'hidden' : ''}" data-room-jid="${jid}">
|
||||
<a class="list-item-link open-room w-100" data-room-jid="${jid}"
|
||||
title="${open_title}"
|
||||
@click=${openRoomViaEvent}>${o.bm.getDisplayName()}</a>
|
||||
@click=${openRoomViaEvent}>${bm.getDisplayName()}</a>
|
||||
|
||||
<a class="list-item-action remove-bookmark fa fa-bookmark align-self-center ${ o.bm.get('bookmarked') ? 'button-on' : '' }"
|
||||
<a class="list-item-action remove-bookmark fa fa-bookmark align-self-center ${ bm.get('bookmarked') ? 'button-on' : '' }"
|
||||
data-room-jid="${jid}"
|
||||
data-bookmark-name="${o.bm.getDisplayName()}"
|
||||
data-bookmark-name="${bm.getDisplayName()}"
|
||||
title="${info_remove_bookmark}"
|
||||
@click=${removeBookmarkViaEvent}></a>
|
||||
</div>
|
||||
|
@ -3,20 +3,21 @@ import { __ } from 'i18n';
|
||||
import { _converse } from '@converse/headless/core.js';
|
||||
import { html } from "lit";
|
||||
|
||||
export default (o) => {
|
||||
const is_collapsed = _converse.bookmarks.getUnopenedBookmarks().length ? true : false;
|
||||
export default (el) => {
|
||||
const should_show = !!_converse.bookmarks.getUnopenedBookmarks().length;
|
||||
const desc_bookmarks = __('Click to toggle the bookmarks list');
|
||||
const label_bookmarks = __('Bookmarks');
|
||||
const toggle_state = el.model.get('toggle-state');
|
||||
return html`
|
||||
<div class="list-container list-container--bookmarks ${ !is_collapsed && 'hidden' || '' }">
|
||||
<div class="list-container list-container--bookmarks ${ should_show ? 'fade-in' : 'hidden' }">
|
||||
<a class="list-toggle bookmarks-toggle controlbox-padded"
|
||||
title="${desc_bookmarks}"
|
||||
@click=${o.toggleBookmarksList}>
|
||||
@click=${() => el.toggleBookmarksList()}>
|
||||
|
||||
<span class="fa ${(o.toggle_state === _converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }">
|
||||
<span class="fa ${(toggle_state === _converse.OPENED) ? 'fa-caret-down' : 'fa-caret-right' }">
|
||||
</span> ${label_bookmarks}</a>
|
||||
<div class="items-list bookmarks rooms-list ${ (o.toggle_state !== _converse.OPENED) ? 'hidden' : '' }">
|
||||
${ _converse.bookmarks.map(bm => bookmark_item(Object.assign({bm}, o))) }
|
||||
<div class="items-list bookmarks rooms-list ${ (toggle_state === _converse.OPENED) ? 'fade-in' : 'hidden fade-out' }">
|
||||
${ _converse.bookmarks.map(bm => bookmark_item(bm)) }
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -662,11 +662,15 @@ describe("Bookmarks", function () {
|
||||
|
||||
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();
|
||||
|
||||
await u.waitUntil(() => u.hasClass('hidden', sizzle('#chatrooms .bookmarks.rooms-list', chats_el).pop()));
|
||||
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();
|
||||
|
||||
await u.waitUntil(() => !u.hasClass('hidden', sizzle('#chatrooms .bookmarks.rooms-list', chats_el).pop()));
|
||||
expect(sizzle(selector, chats_el).filter(u.isVisible).length).toBe(1);
|
||||
expect(bookmarks_el.model.get('toggle-state')).toBe(_converse.OPENED);
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user