diff --git a/CHANGELOG.md b/CHANGELOG.md index ac5241e6..869a1a41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Changelog -## ??? (Not Released Yet) +## 11.0.0 (Not Released Yet) + +### New features + +* Updating ConverseJS, to use upstream (v11 WIP). This comes with many improvments and new features. ### Minor changes and fixes diff --git a/conversejs/build-conversejs.sh b/conversejs/build-conversejs.sh index 239c2918..3f384cc5 100644 --- a/conversejs/build-conversejs.sh +++ b/conversejs/build-conversejs.sh @@ -15,32 +15,20 @@ set -x # Set CONVERSE_VERSION and CONVERSE_REPO to select which repo and tag/commit/branch use. # Defaults values: -CONVERSE_VERSION="v10.1.6" +CONVERSE_VERSION="v11.0.0" CONVERSE_REPO="https://github.com/conversejs/converse.js.git" # You can eventually set CONVERSE_COMMIT to a specific commit ID, if you want to apply some patches. -CONVERSE_COMMIT="" +# 2024-07-15: using Converse upstream (v11 WIP). +CONVERSE_COMMIT="46313ad92c1a861bcb50b9653859cfa9a960ae4a" +# 2024-07-15, FIXME: the following commit includes a quick fix for Converse/#3443, waiting for upstream to be fixed. +CONVERSE_COMMIT="7d65ef8d30a1f3949dbc590b6d27a9d786bf819f" -# 2014-01-16: we are using a custom version, to wait for some PR to be apply upstream. -# This version includes following changes: -# - #converse.js/3300: Adding the maxWait option for `debouncedPruneHistory` -# - #converse.js/3302: debounce MUC sidebar rendering -# - Fix: refresh the MUC sidebar when participants collection is sorted -# - Fix: MUC occupant list does not sort itself on nicknames or roles changes -# - Fix inconsistency between browsers on textarea outlines -# - Fix: room information not correctly refreshed when modifications are made by other users -# This version already includes following changes that will not be merged in ConverseJS upstream: -# - Don't load vCards for all room occupants when the right menu is closed -# - Changing the default avatar, for something very light (to mitigate blinking effect when vCards are loaded) -# - Custom settings livechat_load_all_vcards for the readonly mode -# - Adding "users" icon in the menu toggle button -# - Removing unecessary plugins: headless/pubsub, minimize, notifications, profile, omemo, push, roomlist, dragresize. -# - Destroy room: remove the challenge, and the new JID -# - New config option [colorize_username](https://conversejs.org/docs/html/configuration.html#colorize_username) -# - New loadEmojis hook, to customize emojis at runtime. -# - Fix custom emojis path when assets_path is not the default path. -CONVERSE_VERSION="livechat-10.1.0" -# CONVERSE_COMMIT="4402fcc3fc60f6c9334f86528c33a0b463371d12" +# It is possible to use another repository, if we want some customization that are not upstream (yet): +# CONVERSE_VERSION="livechat" +# # CONVERSE_COMMIT="4402fcc3fc60f6c9334f86528c33a0b463371d12" CONVERSE_REPO="https://github.com/JohnXLivingston/converse.js" +# 2024-07-15, fix MUC save. +CONVERSE_COMMIT="58c682b9ba09038beb961e9d8f804c270408ea69" rootdir="$(pwd)" src_dir="$rootdir/conversejs" diff --git a/conversejs/custom/index.js b/conversejs/custom/index.js index 51d352c5..71d2ab6d 100644 --- a/conversejs/custom/index.js +++ b/conversejs/custom/index.js @@ -8,12 +8,11 @@ * @description This files will override the original ConverseJS index.js file. */ -import '@converse/headless' import './i18n/index.js' import 'shared/registry.js' import { CustomElement } from 'shared/components/element' import { VIEW_PLUGINS } from './shared/constants.js' -import { _converse, converse } from '@converse/headless/core' +import { _converse, converse } from '@converse/headless' import 'shared/styles/index.scss' @@ -50,6 +49,9 @@ import '../custom/plugins/terms/index.js' import '../custom/plugins/poll/index.js' /* END: Removable components */ +// Running some specific livechat patches: +import '../custom/livechat-patch-vcard.js' + import { CORE_PLUGINS } from './headless/shared/constants.js' import { ROOM_FEATURES } from './headless/plugins/muc/constants.js' // We must add our custom plugins to CORE_PLUGINS (so it is white listed): @@ -61,7 +63,7 @@ CORE_PLUGINS.push('livechat-converse-poll') // (see headless/plugins/muc, getDiscoInfoFeatures, which loops on this const) ROOM_FEATURES.push('x_peertubelivechat_mute_anonymous') -_converse.CustomElement = CustomElement +_converse.exports.CustomElement = CustomElement const initialize = converse.initialize diff --git a/conversejs/custom/livechat-external-login-content.js b/conversejs/custom/livechat-external-login-content.js index 10f4b099..5bca5b5c 100644 --- a/conversejs/custom/livechat-external-login-content.js +++ b/conversejs/custom/livechat-external-login-content.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { api } from '@converse/headless/core.js' +import { api } from '@converse/headless/index.js' import { CustomElement } from 'shared/components/element.js' import { tplExternalLoginModal } from 'templates/livechat-external-login-modal.js' import { __ } from 'i18n' diff --git a/conversejs/custom/livechat-patch-vcard.js b/conversejs/custom/livechat-patch-vcard.js new file mode 100644 index 00000000..e108f71d --- /dev/null +++ b/conversejs/custom/livechat-patch-vcard.js @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2024 John Livingston +// +// SPDX-License-Identifier: AGPL-3.0-only + +// Here we are patching the vCard plugin, to add some specific optimizations. + +import { _converse, api } from '@converse/headless/index.js' +import { + onOccupantAvatarChanged, + setVCardOnModel, + setVCardOnOccupant +} from '@converse/headless/plugins/vcard/utils.js' + +const pluginDefinition = _converse.pluggable.plugins['converse-vcard'] +const originalInitialize = pluginDefinition.initialize + +pluginDefinition.initialize = function initialize () { + const previousListeners = _converse._events.chatRoomInitialized ?? [] + originalInitialize.apply(this) + + _converse.api.settings.extend({ + livechat_load_all_vcards: false + }) + + // Now we must detect the new chatRoomInitialized listener, and remove it: + const listenersToRemove = [] + for (const def of _converse._events.chatRoomInitialized ?? []) { + if (def.callback && !previousListeners.includes(def.callback)) { + listenersToRemove.push(def.callback) + } + } + for (const callback of listenersToRemove) { + console.debug('Livechat patching vcard: we must remove this listener', callback) + api.listen.not('chatRoomInitialized', callback) + } + + // Adding the new listener: + api.listen.on('chatRoomInitialized', (m) => { + console.debug('Patched version of the vcard chatRoomInitialized event.') + setVCardOnModel(m) + + // loadAll: when in readonly mode (ie: OBS integration), always load all avatars. + const loadAll = api.settings.get('livechat_load_all_vcards') === true + let hiddenOccupants = m.get('hidden_occupants') + if (hiddenOccupants !== true || loadAll) { + m.occupants.forEach(setVCardOnOccupant) + } + m.listenTo(m.occupants, 'add', (occupant) => { + if (hiddenOccupants !== true || loadAll) { + setVCardOnOccupant(occupant) + } + }) + m.on('change:hidden_occupants', () => { + hiddenOccupants = m.get('hidden_occupants') + if (hiddenOccupants !== true || loadAll) { + m.occupants.forEach(setVCardOnOccupant) + } + }) + m.listenTo(m.occupants, 'change:image_hash', o => onOccupantAvatarChanged(o)) + }) +} diff --git a/conversejs/custom/plugins/poll/components/poll-form-view.js b/conversejs/custom/plugins/poll/components/poll-form-view.js index a0fba934..9bbdf9cd 100644 --- a/conversejs/custom/plugins/poll/components/poll-form-view.js +++ b/conversejs/custom/plugins/poll/components/poll-form-view.js @@ -4,7 +4,7 @@ import { XMLNS_POLL } from '../constants.js' import { tplPollForm } from '../templates/poll-form.js' import { CustomElement } from 'shared/components/element.js' -import { converse, api } from '@converse/headless/core' +import { converse, api, parsers } from '@converse/headless' import { webForm2xForm } from '@converse/headless/utils/form' import { __ } from 'i18n' import '../styles/poll-form.scss' @@ -18,7 +18,6 @@ export default class MUCPollFormView extends CustomElement { return { model: { type: Object, attribute: true }, modal: { type: Object, attribute: true }, - form_fields: { type: Object, attribute: false }, alert_message: { type: Object, attribute: false }, title: { type: String, attribute: false }, instructions: { type: String, attribute: false } @@ -27,6 +26,8 @@ export default class MUCPollFormView extends CustomElement { _fieldTranslationMap = new Map() + xform = undefined + async initialize () { this.alert_message = undefined if (!this.model) { @@ -36,20 +37,18 @@ export default class MUCPollFormView extends CustomElement { try { this._initFieldTranslations() const stanza = await this._fetchPollForm() - const query = stanza.querySelector('query') - const xform = sizzle(`x[xmlns="${Strophe.NS.XFORM}"]`, query)[0] + const xform = parsers.parseXForm(stanza) if (!xform) { throw Error('Missing xform in stanza') } + xform.fields?.map(f => this._translateField(f)) + this.xform = xform + // eslint-disable-next-line no-undef this.title = __(LOC_poll_title) // xform.querySelector('title')?.textContent ?? '' // eslint-disable-next-line no-undef this.instructions = __(LOC_poll_instructions) // xform.querySelector('instructions')?.textContent ?? '' - this.form_fields = Array.from(xform.querySelectorAll('field')).map(field => { - this._translateField(field) - return u.xForm2TemplateResult(field, stanza) - }) } catch (err) { console.error(err) this.alert_message = __('Error') @@ -86,10 +85,10 @@ export default class MUCPollFormView extends CustomElement { } _translateField (field) { - const v = field.getAttribute('var') + const v = field.var const label = this._fieldTranslationMap.get(v) if (label) { - field.setAttribute('label', label) + field.label = label } } diff --git a/conversejs/custom/plugins/poll/components/poll-view.js b/conversejs/custom/plugins/poll/components/poll-view.js index 9973aa99..a51c5d02 100644 --- a/conversejs/custom/plugins/poll/components/poll-view.js +++ b/conversejs/custom/plugins/poll/components/poll-view.js @@ -4,7 +4,7 @@ import { tplPoll } from '../templates/poll.js' import { CustomElement } from 'shared/components/element.js' -import { converse, _converse, api } from '@converse/headless/core' +import { converse, _converse, api } from '@converse/headless' import '../styles/poll.scss' export default class MUCPollView extends CustomElement { diff --git a/conversejs/custom/plugins/poll/index.js b/conversejs/custom/plugins/poll/index.js index d7e94b0c..749b4891 100644 --- a/conversejs/custom/plugins/poll/index.js +++ b/conversejs/custom/plugins/poll/index.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { _converse, converse } from '../../../src/headless/core.js' +import { _converse, converse } from '../../../src/headless/index.js' import { getHeadingButtons } from './utils.js' import { POLL_MESSAGE_TAG, POLL_QUESTION_TAG, POLL_CHOICE_TAG } from './constants.js' import { __ } from 'i18n' diff --git a/conversejs/custom/plugins/poll/modals/poll-form.js b/conversejs/custom/plugins/poll/modals/poll-form.js index f56bb9c3..7d51eb05 100644 --- a/conversejs/custom/plugins/poll/modals/poll-form.js +++ b/conversejs/custom/plugins/poll/modals/poll-form.js @@ -4,7 +4,7 @@ import { __ } from 'i18n' import BaseModal from 'plugins/modal/modal.js' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import { modal_close_button as ModalCloseButton } from 'plugins/modal/templates/buttons.js' import { html } from 'lit' diff --git a/conversejs/custom/plugins/poll/templates/poll-form.js b/conversejs/custom/plugins/poll/templates/poll-form.js index 4e831171..2b66983e 100644 --- a/conversejs/custom/plugins/poll/templates/poll-form.js +++ b/conversejs/custom/plugins/poll/templates/poll-form.js @@ -5,6 +5,10 @@ import { converseLocalizedHelpUrl } from '../../../shared/lib/help' import { html } from 'lit' import { __ } from 'i18n' +import { converse } from '@converse/headless' + +const u = converse.env.utils + export function tplPollForm (el) { const i18nOk = __('Ok') // eslint-disable-next-line no-undef @@ -13,10 +17,18 @@ export function tplPollForm (el) { page: 'documentation/user/streamers/polls' }) + let formFieldTemplates + if (el.xform) { + const fields = el.xform.fields + formFieldTemplates = fields.map(field => { + return u.xFormField2TemplateResult(field) + }) + } + return html` ${el.alert_message ? html`
${el.alert_message}
` : ''} ${ - el.form_fields + formFieldTemplates ? html`
el.formSubmit(ev)}>

@@ -30,7 +42,7 @@ export function tplPollForm (el) {

${el.instructions}

- ${el.form_fields} + ${formFieldTemplates}
diff --git a/conversejs/custom/plugins/poll/templates/poll.js b/conversejs/custom/plugins/poll/templates/poll.js index f1b61144..b95b1368 100644 --- a/conversejs/custom/plugins/poll/templates/poll.js +++ b/conversejs/custom/plugins/poll/templates/poll.js @@ -63,7 +63,7 @@ function _tplChoice (el, currentPoll, choice, canVote) {

diff --git a/conversejs/custom/plugins/poll/utils.js b/conversejs/custom/plugins/poll/utils.js index 9a4a3812..f10172b4 100644 --- a/conversejs/custom/plugins/poll/utils.js +++ b/conversejs/custom/plugins/poll/utils.js @@ -3,12 +3,12 @@ // SPDX-License-Identifier: AGPL-3.0-only import { XMLNS_POLL } from './constants.js' -import { _converse, api } from '../../../src/headless/core.js' +import { _converse, api } from '../../../src/headless/index.js' import { __ } from 'i18n' export function getHeadingButtons (view, buttons) { const muc = view.model - if (muc.get('type') !== _converse.CHATROOMS_TYPE) { + if (muc.get('type') !== _converse.constants.CHATROOMS_TYPE) { // only on MUC. return buttons } diff --git a/conversejs/custom/plugins/size/index.js b/conversejs/custom/plugins/size/index.js index 7732002e..d02ce408 100644 --- a/conversejs/custom/plugins/size/index.js +++ b/conversejs/custom/plugins/size/index.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { _converse, converse, api } from '../../../src/headless/core.js' +import { _converse, converse, api } from '../../../src/headless/index.js' /** * This plugin computes the available width of converse-root, and adds classes diff --git a/conversejs/custom/plugins/tasks/components/muc-task-app-view.js b/conversejs/custom/plugins/tasks/components/muc-task-app-view.js index 155b75a2..32e3c7ce 100644 --- a/conversejs/custom/plugins/tasks/components/muc-task-app-view.js +++ b/conversejs/custom/plugins/tasks/components/muc-task-app-view.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import { CustomElement } from 'shared/components/element.js' import { tplMUCTaskApp } from '../templates/muc-task-app.js' diff --git a/conversejs/custom/plugins/tasks/components/muc-task-list-view.js b/conversejs/custom/plugins/tasks/components/muc-task-list-view.js index 3f97abfd..8688468c 100644 --- a/conversejs/custom/plugins/tasks/components/muc-task-list-view.js +++ b/conversejs/custom/plugins/tasks/components/muc-task-list-view.js @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { CustomElement } from 'shared/components/element.js' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import tplMucTaskList from '../templates/muc-task-list' import { __ } from 'i18n' diff --git a/conversejs/custom/plugins/tasks/components/muc-task-lists-view.js b/conversejs/custom/plugins/tasks/components/muc-task-lists-view.js index c4429827..7c0df41c 100644 --- a/conversejs/custom/plugins/tasks/components/muc-task-lists-view.js +++ b/conversejs/custom/plugins/tasks/components/muc-task-lists-view.js @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { CustomElement } from 'shared/components/element.js' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import tplMucTaskLists from '../templates/muc-task-lists' import { __ } from 'i18n' diff --git a/conversejs/custom/plugins/tasks/components/muc-task-view.js b/conversejs/custom/plugins/tasks/components/muc-task-view.js index 1d02af85..db7bfdda 100644 --- a/conversejs/custom/plugins/tasks/components/muc-task-view.js +++ b/conversejs/custom/plugins/tasks/components/muc-task-view.js @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { CustomElement } from 'shared/components/element.js' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import { tplMucTask } from '../templates/muc-task' import { __ } from 'i18n' diff --git a/conversejs/custom/plugins/tasks/index.js b/conversejs/custom/plugins/tasks/index.js index 50b6afd7..8c7b53fb 100644 --- a/conversejs/custom/plugins/tasks/index.js +++ b/conversejs/custom/plugins/tasks/index.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { _converse, converse } from '../../../src/headless/core.js' +import { _converse, converse } from '../../../src/headless/index.js' import { ChatRoomTaskLists } from './task-lists.js' import { ChatRoomTaskList } from './task-list.js' import { ChatRoomTasks } from './tasks.js' @@ -18,9 +18,14 @@ converse.plugins.add('livechat-converse-tasks', { dependencies: ['converse-muc', 'converse-disco', 'converse-pubsub'], initialize () { - _converse.ChatRoomTaskLists = ChatRoomTaskLists - _converse.ChatRoomTaskList = ChatRoomTaskList - _converse.ChatRoomTasks = ChatRoomTasks + Object.assign( + _converse.exports, + { + ChatRoomTaskLists, + ChatRoomTaskList, + ChatRoomTasks + } + ) _converse.api.settings.extend({ livechat_task_app_enabled: false, diff --git a/conversejs/custom/plugins/tasks/modals/pick-task-list.js b/conversejs/custom/plugins/tasks/modals/pick-task-list.js index 7258bd33..1c5e1701 100644 --- a/conversejs/custom/plugins/tasks/modals/pick-task-list.js +++ b/conversejs/custom/plugins/tasks/modals/pick-task-list.js @@ -4,7 +4,7 @@ import BaseModal from 'plugins/modal/modal.js' import tplPickTaskList from './templates/pick-task-list.js' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import { __ } from 'i18n' export default class PickTaskListModal extends BaseModal { diff --git a/conversejs/custom/plugins/tasks/task-list.js b/conversejs/custom/plugins/tasks/task-list.js index e58106de..23a00a0a 100644 --- a/conversejs/custom/plugins/tasks/task-list.js +++ b/conversejs/custom/plugins/tasks/task-list.js @@ -7,7 +7,7 @@ import { Model } from '@converse/skeletor/src/model.js' /** * A chat room task list. * @class - * @namespace _converse.ChatRoomTaskList + * @namespace _converse.exports.ChatRoomTaskList * @memberof _converse */ class ChatRoomTaskList extends Model { diff --git a/conversejs/custom/plugins/tasks/task-lists.js b/conversejs/custom/plugins/tasks/task-lists.js index d74edb81..17130a73 100644 --- a/conversejs/custom/plugins/tasks/task-lists.js +++ b/conversejs/custom/plugins/tasks/task-lists.js @@ -7,9 +7,9 @@ import { ChatRoomTaskList } from './task-list' import { initStorage } from '@converse/headless/utils/storage.js' /** - * A list of {@link _converse.ChatRoomTaskList} instances, representing task lists associated to a MUC. + * A list of {@link _converse.exports.ChatRoomTaskList} instances, representing task lists associated to a MUC. * @class - * @namespace _converse.ChatRoomTaskLists + * @namespace _converse.exports.ChatRoomTaskLists * @memberOf _converse */ class ChatRoomTaskLists extends Collection { diff --git a/conversejs/custom/plugins/tasks/task.js b/conversejs/custom/plugins/tasks/task.js index 7d21b947..9bf9c6f6 100644 --- a/conversejs/custom/plugins/tasks/task.js +++ b/conversejs/custom/plugins/tasks/task.js @@ -7,7 +7,7 @@ import { Model } from '@converse/skeletor/src/model.js' /** * A chat room task. * @class - * @namespace _converse.ChatRoomTask + * @namespace _converse.exports.ChatRoomTask * @memberof _converse */ class ChatRoomTask extends Model { diff --git a/conversejs/custom/plugins/tasks/tasks.js b/conversejs/custom/plugins/tasks/tasks.js index 239a1723..facc16d6 100644 --- a/conversejs/custom/plugins/tasks/tasks.js +++ b/conversejs/custom/plugins/tasks/tasks.js @@ -7,9 +7,9 @@ import { ChatRoomTask } from './task' import { initStorage } from '@converse/headless/utils/storage.js' /** - * A list of {@link _converse.ChatRoomTask} instances, representing all tasks associated to a MUC. + * A list of {@link _converse.exports.ChatRoomTask} instances, representing all tasks associated to a MUC. * @class - * @namespace _converse.ChatRoomTasks + * @namespace _converse.exports.ChatRoomTasks * @memberOf _converse */ class ChatRoomTasks extends Collection { diff --git a/conversejs/custom/plugins/tasks/utils.js b/conversejs/custom/plugins/tasks/utils.js index 8406412d..52e0162b 100644 --- a/conversejs/custom/plugins/tasks/utils.js +++ b/conversejs/custom/plugins/tasks/utils.js @@ -4,12 +4,12 @@ import { XMLNS_TASKLIST, XMLNS_TASK } from './constants.js' import { PubSubManager } from '../../shared/lib/pubsub-manager.js' -import { converse, _converse, api } from '../../../src/headless/core.js' +import { converse, _converse, api } from '../../../src/headless/index.js' import { __ } from 'i18n' export function getHeadingButtons (view, buttons) { const muc = view.model - if (muc.get('type') !== _converse.CHATROOMS_TYPE) { + if (muc.get('type') !== _converse.constants.CHATROOMS_TYPE) { // only on MUC. return buttons } @@ -74,8 +74,8 @@ function _initChatRoomTaskLists (mucModel) { return } - mucModel.tasklists = new _converse.ChatRoomTaskLists(undefined, { chatroom: mucModel }) - mucModel.tasks = new _converse.ChatRoomTasks(undefined, { chatroom: mucModel }) + mucModel.tasklists = new _converse.exports.ChatRoomTaskLists(undefined, { chatroom: mucModel }) + mucModel.tasks = new _converse.exports.ChatRoomTasks(undefined, { chatroom: mucModel }) mucModel.taskManager = new PubSubManager( mucModel.get('jid'), @@ -127,7 +127,7 @@ function _destroyChatRoomTaskLists (mucModel) { } export function initOrDestroyChatRoomTaskLists (mucModel) { - if (mucModel.get('type') !== _converse.CHATROOMS_TYPE) { + if (mucModel.get('type') !== _converse.constants.CHATROOMS_TYPE) { // only on MUC. return _destroyChatRoomTaskLists(mucModel) } diff --git a/conversejs/custom/plugins/terms/components/muc-terms.js b/conversejs/custom/plugins/terms/components/muc-terms.js index ac57d74a..b133e64b 100644 --- a/conversejs/custom/plugins/terms/components/muc-terms.js +++ b/conversejs/custom/plugins/terms/components/muc-terms.js @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { CustomElement } from 'shared/components/element.js' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import { html } from 'lit' import { __ } from 'i18n' diff --git a/conversejs/custom/plugins/terms/index.js b/conversejs/custom/plugins/terms/index.js index 8459cd82..95d25b61 100644 --- a/conversejs/custom/plugins/terms/index.js +++ b/conversejs/custom/plugins/terms/index.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { converse, api } from '../../../src/headless/core.js' +import { converse, api } from '../../../src/headless/index.js' import './components/muc-terms.js' const { sizzle } = converse.env diff --git a/conversejs/custom/shared/components/font-awesome.js b/conversejs/custom/shared/components/font-awesome.js index 8a93dfef..33b8c1b0 100644 --- a/conversejs/custom/shared/components/font-awesome.js +++ b/conversejs/custom/shared/components/font-awesome.js @@ -4,7 +4,7 @@ /* eslint-disable max-len */ import { html } from 'lit' -import tplIcons from '../../../src/shared/templates/icons.js' +import tplIcons from '../../../src/shared/components/templates/icons.js' export default () => { // Here we are adding some additonal icons to ConverseJS defaults diff --git a/conversejs/custom/shared/lib/pubsub-manager.js b/conversejs/custom/shared/lib/pubsub-manager.js index ceabf378..51a4e13b 100644 --- a/conversejs/custom/shared/lib/pubsub-manager.js +++ b/conversejs/custom/shared/lib/pubsub-manager.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { converse, _converse, api } from '../../../src/headless/core.js' +import { converse, _converse, api } from '../../../src/headless/index.js' const { $build, Strophe, $iq, sizzle } = converse.env /** @@ -50,7 +50,7 @@ export class PubSubManager { async start () { // FIXME: handle errors. Find a way to display to user that this failed. - this.stanzaHandler = _converse.connection.addHandler( + this.stanzaHandler = api.connection.get().addHandler( (message) => { try { this._handleMessage(message) @@ -79,7 +79,7 @@ export class PubSubManager { // Note: no need to unsubscribe from the pubsub node, the backend will do when users leave the room. if (this.stanzaHandler) { - _converse.connection.deleteHandler(this.stanzaHandler) + api.connection.get().deleteHandler(this.stanzaHandler) this.stanzaHandler = undefined } } diff --git a/conversejs/custom/shared/modals/livechat-external-login.js b/conversejs/custom/shared/modals/livechat-external-login.js index b0accf00..edbbfa30 100644 --- a/conversejs/custom/shared/modals/livechat-external-login.js +++ b/conversejs/custom/shared/modals/livechat-external-login.js @@ -4,7 +4,7 @@ import { __ } from 'i18n' import BaseModal from 'plugins/modal/modal.js' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import { html } from 'lit' import 'livechat-external-login-content.js' diff --git a/conversejs/custom/templates/background_logo.js b/conversejs/custom/templates/background_logo.js index 585de358..4548f2a5 100644 --- a/conversejs/custom/templates/background_logo.js +++ b/conversejs/custom/templates/background_logo.js @@ -5,7 +5,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { html } from 'lit' -import { api } from '@converse/headless/core.js' +import { api } from '@converse/headless/index.js' export default () => html`

diff --git a/conversejs/custom/templates/livechat-external-login-modal.js b/conversejs/custom/templates/livechat-external-login-modal.js index a8cbca95..52e33027 100644 --- a/conversejs/custom/templates/livechat-external-login-modal.js +++ b/conversejs/custom/templates/livechat-external-login-modal.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { _converse, api } from '@converse/headless/core' +import { _converse, api } from '@converse/headless' import { __ } from 'i18n' import { html } from 'lit' diff --git a/conversejs/custom/templates/muc-bottom-panel.js b/conversejs/custom/templates/muc-bottom-panel.js index cfac6d2c..37ebc48b 100644 --- a/conversejs/custom/templates/muc-bottom-panel.js +++ b/conversejs/custom/templates/muc-bottom-panel.js @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { __ } from 'i18n' -import { _converse, api } from '@converse/headless/core' +import { _converse, api } from '@converse/headless' import { html } from 'lit' import tplMucBottomPanel from '../../src/plugins/muc-views/templates/muc-bottom-panel.js' import { CustomElement } from 'shared/components/element.js' @@ -79,7 +79,7 @@ class SlowMode extends CustomElement { api.elements.define('livechat-slow-mode', SlowMode) const tplSlowMode = (o) => { - if (!o.can_edit) { return html`` } + if (!o.can_post) { return html`` } return html`` } @@ -128,17 +128,9 @@ const tplViewerMode = (o) => { } export default (o) => { - // ConverseJS 10.x does not handle properly the visitor role in unmoderated rooms. - // See https://github.com/conversejs/converse.js/issues/3428 for more info. - // So we will do a dirty hack here to fix this case. - // Note: ConverseJS 11.x has changed the code, and could be fixed more cleanly (or will be fixed if #3428 is fixed). - if (o.can_edit && o.model.getOwnRole() === 'visitor') { - o.can_edit = false - } - let mutedAnonymousMessage if ( - !o.can_edit && + !o.can_post && o.model.features?.get?.('x_peertubelivechat_mute_anonymous') && _converse.api.settings.get('livechat_specific_is_anonymous') === true ) { diff --git a/conversejs/custom/templates/muc-chatarea.js b/conversejs/custom/templates/muc-chatarea.js index 726e8fd5..d709ca56 100644 --- a/conversejs/custom/templates/muc-chatarea.js +++ b/conversejs/custom/templates/muc-chatarea.js @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: AGPL-3.0-only -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import tplMUCChatarea from '../../src/plugins/muc-views/templates/muc-chatarea.js' import { html } from 'lit' diff --git a/conversejs/custom/templates/muc-head.js b/conversejs/custom/templates/muc-head.js index d926ed32..ebd1ef7a 100644 --- a/conversejs/custom/templates/muc-head.js +++ b/conversejs/custom/templates/muc-head.js @@ -3,7 +3,7 @@ // SPDX-License-Identifier: AGPL-3.0-only import { html } from 'lit' -import { api } from '@converse/headless/core' +import { api } from '@converse/headless' import { until } from 'lit/directives/until.js' import { repeat } from 'lit/directives/repeat.js' import { unsafeHTML } from 'lit/directives/unsafe-html.js' diff --git a/conversejs/custom/webpack.livechat.js b/conversejs/custom/webpack.livechat.js index bf6e041c..6825b35b 100644 --- a/conversejs/custom/webpack.livechat.js +++ b/conversejs/custom/webpack.livechat.js @@ -44,7 +44,7 @@ module.exports = merge(prod, { '../../templates/background_logo.js$': path.resolve(__dirname, 'custom/templates/background_logo.js'), './templates/muc-chatarea.js': path.resolve('custom/templates/muc-chatarea.js'), - '../templates/icons.js': path.resolve(__dirname, 'custom/shared/components/font-awesome.js'), + './templates/icons.js': path.resolve(__dirname, 'custom/shared/components/font-awesome.js'), 'shared/styles/index.scss$': path.resolve(__dirname, 'custom/shared/styles/livechat.scss'), diff --git a/conversejs/lib/converse-params.ts b/conversejs/lib/converse-params.ts index e7ef1c06..43040524 100644 --- a/conversejs/lib/converse-params.ts +++ b/conversejs/lib/converse-params.ts @@ -97,6 +97,7 @@ function defaultConverseParams ( pruning_behavior: 'unscrolled', colorize_username: true, send_chat_markers: [], + reuse_scram_keys: false, // for now we don't use this. // This is a specific settings, that is used in ConverseJS customization, to force avatars loading in readonly mode. livechat_load_all_vcards: !!forceReadonly, diff --git a/conversejs/lib/plugins/livechat-mini-muc-head.ts b/conversejs/lib/plugins/livechat-mini-muc-head.ts index 82f71484..49815919 100644 --- a/conversejs/lib/plugins/livechat-mini-muc-head.ts +++ b/conversejs/lib/plugins/livechat-mini-muc-head.ts @@ -16,7 +16,7 @@ export const livechatMiniMucHeadPlugin = { }) _converse.api.listen.on('getHeadingButtons', (view: any, buttons: any[]) => { - if (view.model.get('type') !== _converse.CHATROOMS_TYPE) { + if (view.model.get('type') !== _converse.constants.CHATROOMS_TYPE) { // only on MUC. return buttons } diff --git a/conversejs/lib/plugins/livechat-specific.ts b/conversejs/lib/plugins/livechat-specific.ts index 6c7fdf43..b50d254e 100644 --- a/conversejs/lib/plugins/livechat-specific.ts +++ b/conversejs/lib/plugins/livechat-specific.ts @@ -15,7 +15,7 @@ export const livechatSpecificsPlugin = { }) _converse.api.listen.on('getHeadingButtons', (view: any, buttons: any[]) => { - if (view.model.get('type') !== _converse.CHATROOMS_TYPE) { + if (view.model.get('type') !== _converse.constants.CHATROOMS_TYPE) { // only on MUC. return buttons } @@ -53,6 +53,71 @@ export const livechatSpecificsPlugin = { return buttons }) + _converse.api.listen.on('getToolbarButtons', (toolbarEl: any, buttons: any[]) => { + // We will replace the toggle occupant button, to change its appearance. + // First, we must find it. We search from the end, because usually it is the last one. + let toggleOccupantButton: any + for (const button of buttons.reverse()) { + if (button.strings?.find((s: string) => s.includes('toggle_occupants'))) { // searching the classname + console.debug('[livechatSpecificsPlugin] found the toggle occupants button', button) + toggleOccupantButton = button + break + } + } + if (!toggleOccupantButton) { + console.debug('[livechatSpecificsPlugin] Did not found the toggle occupants button') + return buttons + } + + buttons = buttons.filter(b => b !== toggleOccupantButton) + // Replacing by the new button... + // Note: we don't need to test conditions, we know the button was here. + const i18nHideOccupants = _converse.__('Hide participants') + const i18nShowOccupants = _converse.__('Show participants') + const html = window.converse.env.html + const icon = toolbarEl.hidden_occupants + ? html` + + + ` + : html` + + + ` + buttons.push(html` + ` + ) + return buttons + }) + + // Overriding the MUCHeading custom element, to customize the destroyMUC function: + const MUCHeading = _converse.api.elements.registry['converse-muc-heading'] + if (MUCHeading) { + class MUCHeadingOverloaded extends MUCHeading { + async destroy (ev: Event): Promise { + ev.preventDefault() + await destroyMUC(_converse, this.model) // here we call a custom version of destroyMUC + } + } + _converse.api.elements.define('converse-muc-heading', MUCHeadingOverloaded) + } + _converse.api.listen.on('chatRoomViewInitialized', function (this: any, _model: any): void { // Remove the spinner if present... document.getElementById('livechat-loading-spinner')?.remove() @@ -117,7 +182,7 @@ export const livechatSpecificsPlugin = { }, overrides: { ChatRoom: { - getActionInfoMessage: function (this: any, code: string, nick: string, actor: any): any { + getActionInfoMessage: function getActionInfoMessage (this: any, code: string, nick: string, actor: any): any { if (code === '303') { // When there is numerous anonymous users joining at the same time, // they can all change their nicknames at the same time, generating a log of action messages. @@ -130,6 +195,12 @@ export const livechatSpecificsPlugin = { } } return this.__super__.getActionInfoMessage(code, nick, actor) + }, + canPostMessages: function canPostMessages (this: any) { + // ConverseJS does not handle properly the visitor role in unmoderated rooms. + // See https://github.com/conversejs/converse.js/issues/3428 for more info. + // FIXME: if #3428 is fixed, remove this override. + return this.isEntered() && this.getOwnRole() !== 'visitor' } }, ChatRoomMessage: { @@ -183,3 +254,26 @@ function getOpenPromise (): any { ) return promise } + +async function destroyMUC (_converse: any, model: any): Promise { + const __ = _converse.__ + const messages = [__('Are you sure you want to destroy this groupchat?')] + // Note: challenge and newjid make no sens for peertube-plugin-livechat, + // we remove them comparing to the original function. + let fields = [ + { + name: 'reason', + label: __('Optional reason for destroying this groupchat'), + placeholder: __('Reason'), + value: undefined + } + ] + try { + fields = await _converse.api.confirm(__('Confirm'), messages, fields) + const reason = fields.filter(f => f.name === 'reason').pop()?.value + const newjid = undefined + return model.sendDestroyIQ(reason, newjid).then(() => model.close()) + } catch (e) { + console.error(e) + } +} diff --git a/conversejs/lib/plugins/livechat-viewer-mode.ts b/conversejs/lib/plugins/livechat-viewer-mode.ts index b01fffab..4d889c88 100644 --- a/conversejs/lib/plugins/livechat-viewer-mode.ts +++ b/conversejs/lib/plugins/livechat-viewer-mode.ts @@ -17,11 +17,11 @@ export const livechatViewerModePlugin = { livechat_external_auth_reconnect_mode: undefined }) - const originalGetDefaultMUCNickname = _converse.getDefaultMUCNickname + const originalGetDefaultMUCNickname = _converse.exports.getDefaultMUCNickname if (!originalGetDefaultMUCNickname) { console.error('[livechatViewerModePlugin] getDefaultMUCNickname is not initialized.') } else { - Object.assign(_converse, { + Object.assign(_converse.exports, { getDefaultMUCNickname: function (this: any): any { if (!_converse.api.settings.get('livechat_enable_viewer_mode')) { return originalGetDefaultMUCNickname.apply(this, arguments)