diff --git a/CHANGELOG.md b/CHANGELOG.md index bc064151..9dfb1747 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## 11.0.0 (Not Released Yet) + +### New features + +* Updating ConverseJS, to use upstream (v11 WIP). This comes with many improvments and new features. + +## 10.3.1 + +### Minor changes and fixes + +* Moderation delay: fix accessibility on the timer shown to moderators. +* Fix «create new poll» icon. + ## 10.3.0 ### New features diff --git a/conversejs/build-conversejs.sh b/conversejs/build-conversejs.sh index 239c2918..010ab156 100644 --- a/conversejs/build-conversejs.sh +++ b/conversejs/build-conversejs.sh @@ -15,32 +15,21 @@ 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" +CONVERSE_COMMIT="bbee0e4e8d2dc43636385cf4cca34f3604f59520" 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..4dbe4e52 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 } @@ -32,7 +32,7 @@ export function getHeadingButtons (view, buttons) { api.modal.show('livechat-converse-poll-form-modal', { model: muc }) }, a_class: '', - icon_class: 'fa-list-check', // FIXME + icon_class: 'fa-square-poll-horizontal', name: 'muc-create-poll' }) 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..2713ea23 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 @@ -23,6 +23,11 @@ export default () => { + + + + + ` } 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) diff --git a/conversejs/lib/plugins/moderation-delay.ts b/conversejs/lib/plugins/moderation-delay.ts index 70945adc..d8c6bfc7 100644 --- a/conversejs/lib/plugins/moderation-delay.ts +++ b/conversejs/lib/plugins/moderation-delay.ts @@ -42,7 +42,7 @@ export const moderationDelayPlugin = { // Ok... We will add some info about how many remains... r.pretty_time = window.converse.env.html` - ${r.pretty_time} - ${Math.round(remains)}⏱ + ${r.pretty_time} ` // and we must update in 1 second... setTimeout(() => this.requestUpdate(), 1000) diff --git a/package-lock.json b/package-lock.json index 165ec12c..0788ce80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "peertube-plugin-livechat", - "version": "10.3.0", + "version": "10.3.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "peertube-plugin-livechat", - "version": "10.3.0", + "version": "10.3.1", "license": "AGPL-3.0", "dependencies": { "@xmpp/jid": "^0.13.1", diff --git a/package.json b/package.json index ad699854..745d3d85 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "peertube-plugin-livechat", "description": "NCTV fork of the peertube-plugin-livechat plugin, containing styling and other shit. This will be maintained with upstream.", - "version": "10.3.0", + "version": "10.3.1", "license": "AGPL-3.0", "author": { "name": "Matty Boombalatty", diff --git a/support/documentation/po/livechat.de.po b/support/documentation/po/livechat.de.po index b14f8ae4..b316785f 100644 --- a/support/documentation/po/livechat.de.po +++ b/support/documentation/po/livechat.de.po @@ -8,9 +8,11 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "POT-Creation-Date: 2024-07-10 16:54+0200\n" -"PO-Revision-Date: 2024-07-05 19:12+0000\n" -"Last-Translator: Victor Hampel \n" -"Language-Team: German \n" +"PO-Revision-Date: 2024-07-12 09:10+0000\n" +"Last-Translator: Victor Hampel " +"\n" +"Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -3272,25 +3274,30 @@ msgstr "Um den Wert für einen bereits bestehenden Raum zu ändern, öffnen Sie #: support/documentation/content/en/documentation/user/streamers/moderation_delay.md msgid "Currently, this feature has one known bug: users that join the chat will get all messages, even messages that are still pending for other participants. However, messages sent after they joined will be delayed correctly." msgstr "" +"Derzeit gibt es bei dieser Funktion einen bekannten Fehler: Benutzer, die " +"dem Chat beitreten, erhalten alle Nachrichten, auch solche, die noch für " +"andere Teilnehmer ausstehen. Allerdings werden Nachrichten, die nach dem " +"Beitritt gesendet werden, korrekt verzögert." #. type: Title ## #: support/documentation/content/en/documentation/user/streamers/moderation_delay.md -#, fuzzy, no-wrap -#| msgid "Share the chat" +#, no-wrap msgid "In the chat" -msgstr "Teilen Sie den Chat" +msgstr "Im Chat" #. type: Plain text #: support/documentation/content/en/documentation/user/streamers/moderation_delay.md msgid "As a moderator, you will see the remaining time (in seconds) before the message is broadcasted, just besides the message datetime." msgstr "" +"Als Moderator sehen Sie neben dem Datum der Nachricht auch die verbleibende " +"Zeit (in Sekunden), bevor die Nachricht veröffentlicht wird." #. type: Plain text #: support/documentation/content/en/documentation/user/streamers/moderation_delay.md -#, fuzzy -#| msgid "![Channel configuration / Moderation delay](/peertube-plugin-livechat/images/moderation_delay_channel_option.png?classes=shadow,border&height=400px)" msgid "![Moderation delay timer](/peertube-plugin-livechat/images/moderation_delay_timer.png?classes=shadow,border)" -msgstr "![Kanalkonfiguration / Moderationsverzögerung](/peertube-plugin-livechat/images/moderation_delay_channel_option.png?classes=shadow,border&height=400px)" +msgstr "" +"![Moderationsverzögerungstimer](/peertube-plugin-livechat/images/" +"moderation_delay_timer.png?classes=shadow,border)" #. type: Yaml Front Matter Hash Value: description #: build/documentation/pot_in/documentation/user/streamers/moderation.md @@ -3337,10 +3344,11 @@ msgstr "Über das [Chat Dropdown Menü](/peertube-plugin-livechat/de/documentati #. type: Plain text #: build/documentation/pot_in/documentation/user/streamers/moderation.md -#, fuzzy -#| msgid "The video owner will be owner of the chat room. This means he can configure the room, delete it, promote other users as admins, ..." msgid "The video owner will be owner of the chat room. This means they can configure the room, delete it, promote other users as admins, ..." -msgstr "Der Videobesitzer ist der Besitzer des Chatraums. Das bedeutet, er kann den Raum konfigurieren, löschen, andere Benutzer als Administratoren befördern, ..." +msgstr "" +"Der Videobesitzer ist der Besitzer des Chatraums. Das bedeutet, er kann den " +"Raum konfigurieren, löschen, andere Benutzer als Administratoren befördern, " +"..." #. type: Plain text #: build/documentation/pot_in/documentation/user/streamers/moderation.md