Render the roster container and filter with lit-html
This is the first commit that makes use of the `ElementView` from Skeletor, which lets us turn views into custom elements.
This commit is contained in:
parent
794a709690
commit
bb3ac36098
6
package-lock.json
generated
6
package-lock.json
generated
@ -13380,9 +13380,9 @@
|
|||||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||||
},
|
},
|
||||||
"lodash-es": {
|
"lodash-es": {
|
||||||
"version": "4.17.15",
|
"version": "4.17.20",
|
||||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
|
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.20.tgz",
|
||||||
"integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
|
"integrity": "sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA=="
|
||||||
},
|
},
|
||||||
"lodash-template-webpack-loader": {
|
"lodash-template-webpack-loader": {
|
||||||
"version": "github:jcbrand/lodash-template-webpack-loader#258c095ab22130dfde454fa59ee0986f302bb733",
|
"version": "github:jcbrand/lodash-template-webpack-loader#258c095ab22130dfde454fa59ee0986f302bb733",
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.10.3",
|
"@babel/cli": "^7.10.3",
|
||||||
"@babel/core": "^7.10.5",
|
"@babel/core": "^7.10.5",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||||
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.12.1",
|
"@babel/plugin-proposal-optional-chaining": "^7.12.1",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import tpl_roster_filter from "./templates/roster_filter.js";
|
import tpl_roster_filter from "./templates/roster_filter.js";
|
||||||
|
import { ElementView } from '@converse/skeletor/src/element.js';
|
||||||
import { Model } from '@converse/skeletor/src/model.js';
|
import { Model } from '@converse/skeletor/src/model.js';
|
||||||
import { View } from '@converse/skeletor/src/view.js';
|
import { _converse, api } from "@converse/headless/core";
|
||||||
import { __ } from 'i18n';
|
|
||||||
import { _converse } from "@converse/headless/core";
|
|
||||||
import { debounce } from "lodash-es";
|
import { debounce } from "lodash-es";
|
||||||
|
import { render } from 'lit-html';
|
||||||
|
|
||||||
|
|
||||||
export const RosterFilter = Model.extend({
|
export const RosterFilter = Model.extend({
|
||||||
@ -17,42 +17,49 @@ export const RosterFilter = Model.extend({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export const RosterFilterView = View.extend({
|
export class RosterFilterView extends ElementView {
|
||||||
tagName: 'span',
|
tagName = 'span';
|
||||||
|
|
||||||
initialize () {
|
initialize () {
|
||||||
|
const model = new _converse.RosterFilter();
|
||||||
|
model.id = `_converse.rosterfilter-${_converse.bare_jid}`;
|
||||||
|
model.browserStorage = _converse.createStore(model.id);
|
||||||
|
this.model = model;
|
||||||
|
|
||||||
|
this.liveFilter = debounce(() => {
|
||||||
|
this.model.save({'filter_text': this.querySelector('.roster-filter').value});
|
||||||
|
}, 250);
|
||||||
|
|
||||||
this.listenTo(this.model, 'change:filter_type', this.render);
|
this.listenTo(this.model, 'change:filter_type', this.render);
|
||||||
this.listenTo(this.model, 'change:filter_text', this.render);
|
this.listenTo(this.model, 'change:filter_text', this.render);
|
||||||
},
|
|
||||||
|
|
||||||
toHTML () {
|
this.listenTo(_converse.roster, "add", this.render);
|
||||||
return tpl_roster_filter(
|
this.listenTo(_converse.roster, "destroy", this.render);
|
||||||
|
this.listenTo(_converse.roster, "remove", this.render);
|
||||||
|
_converse.presences.on('change:show', this.render, this);
|
||||||
|
api.listen.on('rosterContactsFetchedAndProcessed', () => this.render());
|
||||||
|
|
||||||
|
this.model.fetch();
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
render(tpl_roster_filter(
|
||||||
Object.assign(this.model.toJSON(), {
|
Object.assign(this.model.toJSON(), {
|
||||||
visible: this.shouldBeVisible(),
|
visible: this.shouldBeVisible(),
|
||||||
placeholder: __('Filter'),
|
|
||||||
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'),
|
|
||||||
label_chatty: __('Chatty'),
|
|
||||||
label_busy: __('Busy'),
|
|
||||||
label_away: __('Away'),
|
|
||||||
label_xa: __('Extended Away'),
|
|
||||||
label_offline: __('Offline'),
|
|
||||||
changeChatStateFilter: ev => this.changeChatStateFilter(ev),
|
changeChatStateFilter: ev => this.changeChatStateFilter(ev),
|
||||||
changeTypeFilter: ev => this.changeTypeFilter(ev),
|
changeTypeFilter: ev => this.changeTypeFilter(ev),
|
||||||
clearFilter: ev => this.clearFilter(ev),
|
clearFilter: ev => this.clearFilter(ev),
|
||||||
liveFilter: ev => this.liveFilter(ev),
|
liveFilter: ev => this.liveFilter(ev),
|
||||||
submitFilter: ev => this.submitFilter(ev),
|
submitFilter: ev => this.submitFilter(ev),
|
||||||
}));
|
})), this);
|
||||||
},
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
changeChatStateFilter (ev) {
|
changeChatStateFilter (ev) {
|
||||||
ev && ev.preventDefault();
|
ev && ev.preventDefault();
|
||||||
this.model.save({'chat_state': this.el.querySelector('.state-type').value});
|
this.model.save({'chat_state': this.querySelector('.state-type').value});
|
||||||
},
|
}
|
||||||
|
|
||||||
changeTypeFilter (ev) {
|
changeTypeFilter (ev) {
|
||||||
ev && ev.preventDefault();
|
ev && ev.preventDefault();
|
||||||
@ -60,24 +67,20 @@ export const RosterFilterView = View.extend({
|
|||||||
if (type === 'state') {
|
if (type === 'state') {
|
||||||
this.model.save({
|
this.model.save({
|
||||||
'filter_type': type,
|
'filter_type': type,
|
||||||
'chat_state': this.el.querySelector('.state-type').value
|
'chat_state': this.querySelector('.state-type').value
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.model.save({
|
this.model.save({
|
||||||
'filter_type': type,
|
'filter_type': type,
|
||||||
'filter_text': this.el.querySelector('.roster-filter').value
|
'filter_text': this.querySelector('.roster-filter').value
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
liveFilter: debounce(function () {
|
|
||||||
this.model.save({'filter_text': this.el.querySelector('.roster-filter').value});
|
|
||||||
}, 250),
|
|
||||||
|
|
||||||
submitFilter (ev) {
|
submitFilter (ev) {
|
||||||
ev && ev.preventDefault();
|
ev && ev.preventDefault();
|
||||||
this.liveFilter();
|
this.liveFilter();
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the filter is enabled (i.e. if the user
|
* Returns true if the filter is enabled (i.e. if the user
|
||||||
@ -87,14 +90,17 @@ export const RosterFilterView = View.extend({
|
|||||||
*/
|
*/
|
||||||
isActive () {
|
isActive () {
|
||||||
return (this.model.get('filter_type') === 'state' || this.model.get('filter_text'));
|
return (this.model.get('filter_type') === 'state' || this.model.get('filter_text'));
|
||||||
},
|
}
|
||||||
|
|
||||||
shouldBeVisible () {
|
shouldBeVisible () {
|
||||||
return _converse.roster && _converse.roster.length >= 5 || this.isActive();
|
return _converse.roster && _converse.roster.length >= 5 || this.isActive();
|
||||||
},
|
}
|
||||||
|
|
||||||
clearFilter (ev) {
|
clearFilter (ev) {
|
||||||
ev && ev.preventDefault();
|
ev && ev.preventDefault();
|
||||||
this.model.save({'filter_text': ''});
|
this.model.save({'filter_text': ''});
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
|
||||||
|
api.elements.define('converse-roster-filter', RosterFilterView);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import RosterContactView from './contactview.js';
|
import RosterContactView from './contactview.js';
|
||||||
import tpl_group_header from "./templates/group_header.html";
|
import tpl_group_header from "./templates/group_header.html";
|
||||||
import { OrderedListView } from "@converse/skeletor/src/overview";
|
import { OrderedListView } from "@converse/skeletor/src/overview";
|
||||||
import { _converse, converse } from "@converse/headless/core";
|
import { _converse, api, converse } from "@converse/headless/core";
|
||||||
|
|
||||||
const u = converse.env.utils;
|
const u = converse.env.utils;
|
||||||
|
|
||||||
@ -49,10 +49,7 @@ const RosterGroupView = OrderedListView.extend({
|
|||||||
// just this group's) have been fetched from browser
|
// just this group's) have been fetched from browser
|
||||||
// storage or the XMPP server and once they've been
|
// storage or the XMPP server and once they've been
|
||||||
// assigned to their various groups.
|
// assigned to their various groups.
|
||||||
_converse.rosterview.on(
|
api.listen.on('rosterContactsFetchedAndProcessed', () => this.sortAndPositionAllItems());
|
||||||
'rosterContactsFetchedAndProcessed',
|
|
||||||
() => this.sortAndPositionAllItems()
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
@ -10,7 +10,7 @@ import "modals/add-contact.js";
|
|||||||
import RosterContactView from './contactview.js';
|
import RosterContactView from './contactview.js';
|
||||||
import RosterGroupView from './groupview.js';
|
import RosterGroupView from './groupview.js';
|
||||||
import RosterView from './rosterview.js';
|
import RosterView from './rosterview.js';
|
||||||
import log from "@converse/headless/log";
|
import { initRosterView, highlightRosterItem, insertRoster } from './utils.js';
|
||||||
import { RosterFilter, RosterFilterView } from './filterview.js';
|
import { RosterFilter, RosterFilterView } from './filterview.js';
|
||||||
import { _converse, api, converse } from "@converse/headless/core";
|
import { _converse, api, converse } from "@converse/headless/core";
|
||||||
|
|
||||||
@ -20,10 +20,6 @@ converse.plugins.add('converse-rosterview', {
|
|||||||
dependencies: ["converse-roster", "converse-modal", "converse-chatboxviews"],
|
dependencies: ["converse-roster", "converse-modal", "converse-chatboxviews"],
|
||||||
|
|
||||||
initialize () {
|
initialize () {
|
||||||
/* The initialize function gets called as soon as the plugin is
|
|
||||||
* loaded by converse.js's plugin machinery.
|
|
||||||
*/
|
|
||||||
|
|
||||||
api.settings.extend({
|
api.settings.extend({
|
||||||
'autocomplete_add_contact': true,
|
'autocomplete_add_contact': true,
|
||||||
'allow_chat_pending_contacts': true,
|
'allow_chat_pending_contacts': true,
|
||||||
@ -42,50 +38,15 @@ converse.plugins.add('converse-rosterview', {
|
|||||||
|
|
||||||
/* -------- Event Handlers ----------- */
|
/* -------- Event Handlers ----------- */
|
||||||
api.listen.on('chatBoxesInitialized', () => {
|
api.listen.on('chatBoxesInitialized', () => {
|
||||||
function highlightRosterItem (chatbox) {
|
|
||||||
const contact = _converse.roster && _converse.roster.findWhere({'jid': chatbox.get('jid')});
|
|
||||||
if (contact !== undefined) {
|
|
||||||
contact.trigger('highlight');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_converse.chatboxes.on('destroy', chatbox => highlightRosterItem(chatbox));
|
_converse.chatboxes.on('destroy', chatbox => highlightRosterItem(chatbox));
|
||||||
_converse.chatboxes.on('change:hidden', chatbox => highlightRosterItem(chatbox));
|
_converse.chatboxes.on('change:hidden', chatbox => highlightRosterItem(chatbox));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
api.listen.on('controlBoxInitialized', (view) => {
|
api.listen.on('controlBoxInitialized', (view) => {
|
||||||
function insertRoster () {
|
insertRoster(view);
|
||||||
if (!view.model.get('connected') || api.settings.get("authentication") === _converse.ANONYMOUS) {
|
view.model.on('change:connected', () => insertRoster(view));
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Place the rosterview inside the "Contacts" panel. */
|
|
||||||
api.waitUntil('rosterViewInitialized')
|
|
||||||
.then(() => view.controlbox_pane.el.insertAdjacentElement('beforeEnd', _converse.rosterview.el))
|
|
||||||
.catch(e => log.fatal(e));
|
|
||||||
}
|
|
||||||
insertRoster();
|
|
||||||
view.model.on('change:connected', insertRoster);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function initRosterView () {
|
|
||||||
/* Create an instance of RosterView once the RosterGroups
|
|
||||||
* collection has been created (in @converse/headless/core.js)
|
|
||||||
*/
|
|
||||||
if (api.settings.get("authentication") === _converse.ANONYMOUS) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_converse.rosterview = new _converse.RosterView({
|
|
||||||
'model': _converse.rostergroups
|
|
||||||
});
|
|
||||||
_converse.rosterview.render();
|
|
||||||
/**
|
|
||||||
* Triggered once the _converse.RosterView instance has been created and initialized.
|
|
||||||
* @event _converse#rosterViewInitialized
|
|
||||||
* @example _converse.api.listen.on('rosterViewInitialized', () => { ... });
|
|
||||||
*/
|
|
||||||
api.trigger('rosterViewInitialized');
|
|
||||||
}
|
|
||||||
api.listen.on('rosterInitialized', initRosterView);
|
api.listen.on('rosterInitialized', initRosterView);
|
||||||
api.listen.on('rosterReadyAfterReconnection', initRosterView);
|
api.listen.on('rosterReadyAfterReconnection', initRosterView);
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import RosterGroupView from './groupview.js';
|
import RosterGroupView from './groupview.js';
|
||||||
import log from "@converse/headless/log";
|
import log from "@converse/headless/log";
|
||||||
import tpl_roster from "./templates/roster.html";
|
import tpl_roster from "./templates/roster.js";
|
||||||
import { Model } from '@converse/skeletor/src/model.js';
|
import { Model } from '@converse/skeletor/src/model.js';
|
||||||
import { OrderedListView } from "@converse/skeletor/src/overview";
|
import { OrderedListView } from "@converse/skeletor/src/overview";
|
||||||
import { __ } from 'i18n';
|
import { __ } from 'i18n';
|
||||||
import { _converse, api, converse } from "@converse/headless/core";
|
import { _converse, api, converse } from "@converse/headless/core";
|
||||||
import { debounce, has } from "lodash-es";
|
import { debounce, has } from "lodash-es";
|
||||||
|
import { render } from 'lit-html';
|
||||||
|
|
||||||
const u = converse.env.utils;
|
const u = converse.env.utils;
|
||||||
|
|
||||||
@ -57,20 +58,18 @@ const RosterView = OrderedListView.extend({
|
|||||||
_converse.roster.each(contact => this.addRosterContact(contact, {'silent': true}));
|
_converse.roster.each(contact => this.addRosterContact(contact, {'silent': true}));
|
||||||
this.update();
|
this.update();
|
||||||
this.updateFilter();
|
this.updateFilter();
|
||||||
this.trigger('rosterContactsFetchedAndProcessed');
|
api.trigger('rosterContactsFetchedAndProcessed');
|
||||||
});
|
});
|
||||||
this.createRosterFilter();
|
this.render();
|
||||||
|
this.listenToRosterFilter();
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
this.el.innerHTML = tpl_roster({
|
render(tpl_roster({
|
||||||
'allow_contact_requests': _converse.allow_contact_requests,
|
|
||||||
'heading_contacts': __('Contacts'),
|
'heading_contacts': __('Contacts'),
|
||||||
'title_add_contact': __('Add a contact'),
|
'title_add_contact': __('Add a contact'),
|
||||||
'title_sync_contacts': __('Re-sync your contacts')
|
'title_sync_contacts': __('Re-sync your contacts')
|
||||||
});
|
}), this.el);
|
||||||
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');
|
this.roster_el = this.el.querySelector('.roster-contacts');
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
@ -79,14 +78,9 @@ const RosterView = OrderedListView.extend({
|
|||||||
api.modal.show(_converse.AddContactModal, {'model': new Model()}, ev);
|
api.modal.show(_converse.AddContactModal, {'model': new Model()}, ev);
|
||||||
},
|
},
|
||||||
|
|
||||||
createRosterFilter () {
|
listenToRosterFilter () {
|
||||||
// Create a model on which we can store filter properties
|
this.filter_view = this.el.querySelector('converse-roster-filter');
|
||||||
const model = new _converse.RosterFilter();
|
|
||||||
model.id = `_converse.rosterfilter-${_converse.bare_jid}`;
|
|
||||||
model.browserStorage = _converse.createStore(model.id);
|
|
||||||
this.filter_view = new _converse.RosterFilterView({model});
|
|
||||||
this.listenTo(this.filter_view.model, 'change', this.updateFilter);
|
this.listenTo(this.filter_view.model, 'change', this.updateFilter);
|
||||||
this.filter_view.model.fetch();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,7 +103,7 @@ const RosterView = OrderedListView.extend({
|
|||||||
if (!u.isVisible(this.roster_el)) {
|
if (!u.isVisible(this.roster_el)) {
|
||||||
u.showElement(this.roster_el);
|
u.showElement(this.roster_el);
|
||||||
}
|
}
|
||||||
this.filter_view.render();
|
// this.filter_view.render();
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -217,7 +211,7 @@ const RosterView = OrderedListView.extend({
|
|||||||
if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to' || this.isSelf(jid)) {
|
if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to' || this.isSelf(jid)) {
|
||||||
this.addExistingContact(contact, options);
|
this.addExistingContact(contact, options);
|
||||||
} else {
|
} else {
|
||||||
if (!_converse.allow_contact_requests) {
|
if (!api.settings.get('allow_contact_requests')) {
|
||||||
log.debug(
|
log.debug(
|
||||||
`Not adding requesting or pending contact ${jid} `+
|
`Not adding requesting or pending contact ${jid} `+
|
||||||
`because allow_contact_requests is false`
|
`because allow_contact_requests is false`
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
<div class="d-flex controlbox-padded">
|
|
||||||
<span class="w-100 controlbox-heading controlbox-heading--contacts">{{{o.heading_contacts}}}</span>
|
|
||||||
<a class="controlbox-heading__btn sync-contacts fa fa-sync" title="{{{o.title_sync_contacts}}}"></a>
|
|
||||||
{[ if (o.allow_contact_requests) { ]}
|
|
||||||
<a class="controlbox-heading__btn add-contact fa fa-user-plus"
|
|
||||||
title="{{{o.title_add_contact}}}"
|
|
||||||
data-toggle="modal"
|
|
||||||
data-target="#add-contact-modal"></a>
|
|
||||||
{[ } ]}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form class="roster-filter-form"></form>
|
|
||||||
|
|
||||||
<div class="list-container roster-contacts"></div>
|
|
16
src/plugins/rosterview/templates/roster.js
Normal file
16
src/plugins/rosterview/templates/roster.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { html } from "lit-html";
|
||||||
|
import { api } from "@converse/headless/core";
|
||||||
|
|
||||||
|
export default (o) => html`
|
||||||
|
<div class="d-flex controlbox-padded">
|
||||||
|
<span class="w-100 controlbox-heading controlbox-heading--contacts">${o.heading_contacts}</span>
|
||||||
|
<a class="controlbox-heading__btn sync-contacts fa fa-sync" title="${o.title_sync_contacts}"></a>
|
||||||
|
${ api.settings.get('allow_contact_requests') ? html`
|
||||||
|
<a class="controlbox-heading__btn add-contact fa fa-user-plus"
|
||||||
|
title="${o.title_add_contact}"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#add-contact-modal"></a>` : '' }
|
||||||
|
</div>
|
||||||
|
<converse-roster-filter></converse-roster-filter>
|
||||||
|
<div class="list-container roster-contacts"></div>
|
||||||
|
`;
|
@ -1,35 +1,50 @@
|
|||||||
import { html } from "lit-html";
|
import { html } from "lit-html";
|
||||||
|
import { __ } from 'i18n';
|
||||||
|
|
||||||
|
|
||||||
export default (o) => html`
|
export default (o) => {
|
||||||
|
const i18n_placeholder = __('Filter');
|
||||||
|
const title_contact_filter = __('Filter by contact name');
|
||||||
|
const title_group_filter = __('Filter by group name');
|
||||||
|
const title_status_filter = __('Filter by status');
|
||||||
|
const label_any = __('Any');
|
||||||
|
const label_unread_messages = __('Unread');
|
||||||
|
const label_online = __('Online');
|
||||||
|
const label_chatty = __('Chatty');
|
||||||
|
const label_busy = __('Busy');
|
||||||
|
const label_away = __('Away');
|
||||||
|
const label_xa = __('Extended Away');
|
||||||
|
const label_offline = __('Offline');
|
||||||
|
|
||||||
|
return html`
|
||||||
<form class="controlbox-padded roster-filter-form input-button-group ${ (!o.visible) ? 'hidden' : 'fade-in' }"
|
<form class="controlbox-padded roster-filter-form input-button-group ${ (!o.visible) ? 'hidden' : 'fade-in' }"
|
||||||
@submit=${o.submitFilter}>
|
@submit=${o.submitFilter}>
|
||||||
<div class="form-inline flex-nowrap">
|
<div class="form-inline flex-nowrap">
|
||||||
<div class="filter-by d-flex flex-nowrap">
|
<div class="filter-by d-flex flex-nowrap">
|
||||||
<span @click=${o.changeTypeFilter} class="fa fa-user ${ (o.filter_type === 'contacts') ? 'selected' : '' }" data-type="contacts" title="${o.title_contact_filter}"></span>
|
<span @click=${o.changeTypeFilter} class="fa fa-user ${ (o.filter_type === 'contacts') ? 'selected' : '' }" data-type="contacts" title="${title_contact_filter}"></span>
|
||||||
<span @click=${o.changeTypeFilter} class="fa fa-users ${ (o.filter_type === 'groups') ? 'selected' : '' }" data-type="groups" title="${o.title_group_filter}"></span>
|
<span @click=${o.changeTypeFilter} class="fa fa-users ${ (o.filter_type === 'groups') ? 'selected' : '' }" data-type="groups" title="${title_group_filter}"></span>
|
||||||
<span @click=${o.changeTypeFilter} class="fa fa-circle ${ (o.filter_type === 'state') ? 'selected' : '' }" data-type="state" title="${o.title_status_filter}"></span>
|
<span @click=${o.changeTypeFilter} class="fa fa-circle ${ (o.filter_type === 'state') ? 'selected' : '' }" data-type="state" title="${title_status_filter}"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group">
|
<div class="btn-group">
|
||||||
<input .value="${o.filter_text || ''}"
|
<input .value="${o.filter_text || ''}"
|
||||||
@keydown=${o.liveFilter}
|
@keydown=${o.liveFilter}
|
||||||
class="roster-filter form-control ${ (o.filter_type === 'state') ? 'hidden' : '' }"
|
class="roster-filter form-control ${ (o.filter_type === 'state') ? 'hidden' : '' }"
|
||||||
placeholder="${o.placeholder}"/>
|
placeholder="${i18n_placeholder}"/>
|
||||||
<span class="clear-input fa fa-times ${ (!o.filter_text || o.filter_type === 'state') ? 'hidden' : '' }"
|
<span class="clear-input fa fa-times ${ (!o.filter_text || o.filter_type === 'state') ? 'hidden' : '' }"
|
||||||
@click=${o.clearFilter}>
|
@click=${o.clearFilter}>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<select class="form-control state-type ${ (o.filter_type !== 'state') ? 'hidden' : '' }"
|
<select class="form-control state-type ${ (o.filter_type !== 'state') ? 'hidden' : '' }"
|
||||||
@change=${o.changeChatStateFilter}>
|
@change=${o.changeChatStateFilter}>
|
||||||
<option value="">${o.label_any}</option>
|
<option value="">${label_any}</option>
|
||||||
<option ?selected=${o.chat_state === 'unread_messages'} value="unread_messages">${o.label_unread_messages}</option>
|
<option ?selected=${o.chat_state === 'unread_messages'} value="unread_messages">${label_unread_messages}</option>
|
||||||
<option ?selected=${o.chat_state === 'online'} value="online">${o.label_online}</option>
|
<option ?selected=${o.chat_state === 'online'} value="online">${label_online}</option>
|
||||||
<option ?selected=${o.chat_state === 'chat'} value="chat">${o.label_chatty}</option>
|
<option ?selected=${o.chat_state === 'chat'} value="chat">${label_chatty}</option>
|
||||||
<option ?selected=${o.chat_state === 'dnd'} value="dnd">${o.label_busy}</option>
|
<option ?selected=${o.chat_state === 'dnd'} value="dnd">${label_busy}</option>
|
||||||
<option ?selected=${o.chat_state === 'away'} value="away">${o.label_away}</option>
|
<option ?selected=${o.chat_state === 'away'} value="away">${label_away}</option>
|
||||||
<option ?selected=${o.chat_state === 'xa'} value="xa">${o.label_xa}</option>
|
<option ?selected=${o.chat_state === 'xa'} value="xa">${label_xa}</option>
|
||||||
<option ?selected=${o.chat_state === 'offline'} value="offline">${o.label_offline}</option>
|
<option ?selected=${o.chat_state === 'offline'} value="offline">${label_offline}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>`
|
||||||
`;
|
};
|
||||||
|
33
src/plugins/rosterview/utils.js
Normal file
33
src/plugins/rosterview/utils.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import log from "@converse/headless/log";
|
||||||
|
import { _converse, api } from "@converse/headless/core";
|
||||||
|
|
||||||
|
|
||||||
|
export function initRosterView () {
|
||||||
|
if (api.settings.get("authentication") === _converse.ANONYMOUS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_converse.rosterview = new _converse.RosterView({'model': _converse.rostergroups });
|
||||||
|
_converse.rosterview.render();
|
||||||
|
/**
|
||||||
|
* Triggered once the _converse.RosterView instance has been created and initialized.
|
||||||
|
* @event _converse#rosterViewInitialized
|
||||||
|
* @example _converse.api.listen.on('rosterViewInitialized', () => { ... });
|
||||||
|
*/
|
||||||
|
api.trigger('rosterViewInitialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function highlightRosterItem (chatbox) {
|
||||||
|
_converse.roster?.findWhere({'jid': chatbox.get('jid')})?.trigger('highlight');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function insertRoster (view) {
|
||||||
|
if (!view.model.get('connected') || api.settings.get("authentication") === _converse.ANONYMOUS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Place the rosterview inside the "Contacts" panel. */
|
||||||
|
api.waitUntil('rosterViewInitialized')
|
||||||
|
.then(() => view.controlbox_pane.el.insertAdjacentElement('beforeEnd', _converse.rosterview.el))
|
||||||
|
.catch(e => log.fatal(e));
|
||||||
|
}
|
@ -101,6 +101,7 @@ module.exports = {
|
|||||||
}]
|
}]
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
'@babel/plugin-proposal-class-properties',
|
||||||
'@babel/plugin-proposal-nullish-coalescing-operator',
|
'@babel/plugin-proposal-nullish-coalescing-operator',
|
||||||
'@babel/plugin-proposal-optional-chaining',
|
'@babel/plugin-proposal-optional-chaining',
|
||||||
'@babel/plugin-syntax-dynamic-import'
|
'@babel/plugin-syntax-dynamic-import'
|
||||||
|
Loading…
Reference in New Issue
Block a user