Updating Converse upstream (with bootstrap5):

* bootstrap 5 compatibility
* other Converse updates integration
* hack to get the sidebar work as with Converse v10.
* modal onHide was renamed close.
* fix slow mode infobox margin.
* fix margin
* shorter action label, for better dropdown UX.
This commit is contained in:
John Livingston 2024-08-05 15:54:03 +02:00
parent 33da4314af
commit 003cb24dd8
No known key found for this signature in database
GPG Key ID: B17B5640CE66CDBC
18 changed files with 99 additions and 73 deletions

View File

@ -18,10 +18,8 @@ set -x
CONVERSE_VERSION="v11.0.0" CONVERSE_VERSION="v11.0.0"
CONVERSE_REPO="https://github.com/conversejs/converse.js.git" 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. # You can eventually set CONVERSE_COMMIT to a specific commit ID, if you want to apply some patches.
# 2024-07-31: using Converse upstream (v11 WIP). # 2024-08-05: using Converse upstream (v11 WIP).
CONVERSE_COMMIT="2f8cfc02d04bb6191b3b9facb706e475836279f5" CONVERSE_COMMIT="5017efb780973d704f237c478ba52b23d901e1bf"
# # 2024-07-31: testing the jcbrand/bootstrap5 branch
# CONVERSE_COMMIT="e5edeec997d53a8720470a49685be123e8688e1c"
# It is possible to use another repository, if we want some customization that are not upstream (yet): # It is possible to use another repository, if we want some customization that are not upstream (yet):
# CONVERSE_VERSION="livechat" # CONVERSE_VERSION="livechat"
@ -29,6 +27,10 @@ CONVERSE_COMMIT="2f8cfc02d04bb6191b3b9facb706e475836279f5"
# CONVERSE_REPO="https://github.com/JohnXLivingston/converse.js" # CONVERSE_REPO="https://github.com/JohnXLivingston/converse.js"
# CONVERSE_COMMIT="xxxx" # CONVERSE_COMMIT="xxxx"
# 2024-08-06: including fix waiting for merge:
CONVERSE_VERSION="livechat_converse_11"
CONVERSE_COMMIT="f69b96439ac15d0fc9c138319e2d635ab28be071"
rootdir="$(pwd)" rootdir="$(pwd)"
src_dir="$rootdir/conversejs" src_dir="$rootdir/conversejs"
converse_src_dir="$rootdir/vendor/conversejs-$CONVERSE_VERSION" converse_src_dir="$rootdir/vendor/conversejs-$CONVERSE_VERSION"

View File

@ -8,14 +8,14 @@
* @description This files will override the original ConverseJS index.js file. * @description This files will override the original ConverseJS index.js file.
*/ */
import 'shared/styles/index.scss'
import './i18n/index.js' import './i18n/index.js'
import 'shared/registry.js' import 'shared/registry.js'
import { CustomElement } from 'shared/components/element' import { CustomElement } from 'shared/components/element'
import { VIEW_PLUGINS } from './shared/constants.js' import { VIEW_PLUGINS } from './shared/constants.js'
import { _converse, converse } from '@converse/headless' import { _converse, converse } from '@converse/headless'
import 'shared/styles/index.scss'
/* START: Removable plugins /* START: Removable plugins
* ------------------------ * ------------------------
* Any of the following plugin imports may be removed if the plugin is not needed * Any of the following plugin imports may be removed if the plugin is not needed

View File

@ -67,7 +67,7 @@ export function tplMucNote (el, note) {
: '' : ''
} }
${_tplNoteForm(note)} ${_tplNoteForm(note)}
<fieldset class="form-group"> <fieldset>
<input type="submit" class="btn btn-primary" value="${__('Ok')}" /> <input type="submit" class="btn btn-primary" value="${__('Ok')}" />
<input type="button" class="btn btn-secondary button-cancel" <input type="button" class="btn btn-secondary button-cancel"
value="${__('Cancel')}" @click=${el.toggleEdit} value="${__('Cancel')}" @click=${el.toggleEdit}
@ -81,7 +81,7 @@ function _tplNoteForm (note) {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
const i18nNoteDesc = __(LOC_moderator_note_description) const i18nNoteDesc = __(LOC_moderator_note_description)
return html`<fieldset class="form-group"> return html`<fieldset>
<textarea <textarea
class="form-control" name="description" class="form-control" name="description"
placeholder="${i18nNoteDesc}" placeholder="${i18nNoteDesc}"
@ -116,7 +116,7 @@ export function tplMucCreateNoteForm (notesEl, occupant) {
: '' : ''
} }
${_tplNoteForm(undefined)} ${_tplNoteForm(undefined)}
<fieldset class="form-group"> <fieldset>
<input type="submit" class="btn btn-primary" value="${i18nOk}" /> <input type="submit" class="btn btn-primary" value="${i18nOk}" />
<input type="button" class="btn btn-secondary button-cancel" <input type="button" class="btn btn-secondary button-cancel"
value="${i18nCancel}" @click=${notesEl.closeCreateNoteForm} value="${i18nCancel}" @click=${notesEl.closeCreateNoteForm}

View File

@ -113,7 +113,7 @@ export default class MUCPollFormView extends CustomElement {
await api.sendIQ(iq) await api.sendIQ(iq)
if (this.modal) { if (this.modal) {
this.modal.onHide() this.modal.close()
} }
} catch (err) { } catch (err) {
if (u.isErrorStanza(err)) { if (u.isErrorStanza(err)) {

View File

@ -13,8 +13,8 @@ class PollFormModal extends BaseModal {
super.initialize() super.initialize()
} }
onHide () { close () {
super.onHide() super.close()
api.modal.remove('livechat-converse-poll-form-modal') api.modal.remove('livechat-converse-poll-form-modal')
} }

View File

@ -44,7 +44,7 @@ export function tplPollForm (el) {
${formFieldTemplates} ${formFieldTemplates}
<fieldset class="buttons form-group"> <fieldset class="buttons">
<input type="submit" class="btn btn-primary" value="${i18nOk}" /> <input type="submit" class="btn btn-primary" value="${i18nOk}" />
</fieldset> </fieldset>
</form>` </form>`

View File

@ -19,22 +19,22 @@ export default function (el) {
return html` return html`
<form class="converse-form converse-form--modal confirm" action="#" @submit=${ev => el.onPick(ev)}> <form class="converse-form converse-form--modal confirm" action="#" @submit=${ev => el.onPick(ev)}>
<div class="form-group"> <fieldset>
<select class="form-control" name="tasklist"> <select class="form-control" name="tasklist">
${ ${
repeat(muc.tasklists, (tasklist) => tasklist.get('id'), (tasklist) => { repeat(muc.tasklists, (tasklist) => tasklist.get('id'), (tasklist) => {
return html`<option value="${tasklist.get('id')}">${tasklist.get('name')}</option>` return html`<option value="${tasklist.get('id')}">${tasklist.get('name')}</option>`
}) })
} }
</select> </select>
<small class="form-text text-muted"> <small class="form-text text-muted">
${i18nMessage} ${i18nMessage}
</small> </small>
</div> </fieldset>
<div class="form-group"> <fieldset>
<button type="submit" class="btn btn-primary">${__('OK')}</button> <button type="submit" class="btn btn-primary">${__('OK')}</button>
<input type="button" class="btn btn-secondary" data-dismiss="modal" value="${__('Cancel')}"/> <input type="button" class="btn btn-secondary" data-dismiss="modal" value="${__('Cancel')}"/>
</div> </fieldset>
</form>` </form>`
} }

View File

@ -24,7 +24,7 @@ export default function tplMucTaskLists (el, tasklists) {
}) })
} }
<form class="converse-form" @submit=${el.submitCreateTaskList}> <form class="converse-form" @submit=${el.submitCreateTaskList}>
<div class="form-group"> <fieldset>
<label> <label>
${i18nCreateTaskList} ${i18nCreateTaskList}
<input type="text" value="" class="form-control" name="name" placeholder="${i18nTaskListName}" /> <input type="text" value="" class="form-control" name="name" placeholder="${i18nTaskListName}" />
@ -34,6 +34,6 @@ export default function tplMucTaskLists (el, tasklists) {
? '' ? ''
: html`<div class="invalid-feedback d-block">${el.create_tasklist_error_message}</div>` : html`<div class="invalid-feedback d-block">${el.create_tasklist_error_message}</div>`
} }
</div> </fieldset>
</form>` </form>`
} }

View File

@ -45,7 +45,7 @@ export function tplMucTask (el, task) {
<div class="task-line draggables-line"> <div class="task-line draggables-line">
<form class="converse-form" @submit=${el.saveTask}> <form class="converse-form" @submit=${el.saveTask}>
${_tplTaskForm(task)} ${_tplTaskForm(task)}
<fieldset class="form-group"> <fieldset>
<input type="submit" class="btn btn-primary" value="${__('Ok')}" /> <input type="submit" class="btn btn-primary" value="${__('Ok')}" />
<input type="button" class="btn btn-secondary button-cancel" <input type="button" class="btn btn-secondary button-cancel"
value="${__('Cancel')}" @click=${el.toggleEdit} value="${__('Cancel')}" @click=${el.toggleEdit}
@ -61,7 +61,7 @@ function _tplTaskForm (task) {
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
const i18nTaskDesc = __(LOC_task_description) const i18nTaskDesc = __(LOC_task_description)
return html`<fieldset class="form-group"> return html`<fieldset>
<input type="text" name="name" <input type="text" name="name"
class="form-control" value="${task ? task.get('name') : ''}" class="form-control" value="${task ? task.get('name') : ''}"
placeholder="${i18nTaskName}" placeholder="${i18nTaskName}"
@ -80,7 +80,7 @@ export function tplMucAddTaskForm (tasklistEl, _tasklist) {
return html` return html`
<form class="task-list-add-task converse-form" @submit=${tasklistEl.submitAddTask}> <form class="task-list-add-task converse-form" @submit=${tasklistEl.submitAddTask}>
${_tplTaskForm(undefined)} ${_tplTaskForm(undefined)}
<fieldset class="form-group"> <fieldset>
<input type="submit" class="btn btn-primary" value="${i18nOk}" /> <input type="submit" class="btn btn-primary" value="${i18nOk}" />
<input type="button" class="btn btn-secondary button-cancel" <input type="button" class="btn btn-secondary button-cancel"
value="${i18nCancel}" @click=${tasklistEl.closeAddTaskForm} value="${i18nCancel}" @click=${tasklistEl.closeAddTaskForm}

View File

@ -20,8 +20,8 @@ class ExternalLoginModal extends BaseModal {
return __(LOC_login_using_external_account) return __(LOC_login_using_external_account)
} }
onHide () { close () {
super.onHide() super.close()
// kill the externalAuthGetResult handler if still there // kill the externalAuthGetResult handler if still there
try { try {
if (window.externalAuthGetResult) { window.externalAuthGetResult() } if (window.externalAuthGetResult) { window.externalAuthGetResult() }

View File

@ -8,7 +8,7 @@
.dropdown-menu { .dropdown-menu {
// Fixing all dropdown colors // Fixing all dropdown colors
--text-color: #212529; // default bootstrap color for dropdown-items --text-color: #212529; // default bootstrap color for dropdown-items
--text-color-lighten-15-percent: #8c8c8c; // default ConverseJS theme color --inverse-link-color: #8c8c8c; // default ConverseJS theme color
background-color: #fff; // this is the default bootstrap color, used by ConverseJS background-color: #fff; // this is the default bootstrap color, used by ConverseJS
@ -27,6 +27,7 @@
border: 1px dashed var(--peertube-menu-background); border: 1px dashed var(--peertube-menu-background);
color: var(--peertube-main-foreground); color: var(--peertube-main-foreground);
background-color: var(--peertube-main-background); background-color: var(--peertube-main-background);
margin: 0 5px;
.livechat-hide-slow-mode-info-box { .livechat-hide-slow-mode-info-box {
cursor: pointer; cursor: pointer;

View File

@ -35,6 +35,7 @@ body.converse-embedded converse-root.theme-peertube {
--foreground: var(--peertube-main-foreground); --foreground: var(--peertube-main-foreground);
--background: var(--peertube-main-background); --background: var(--peertube-main-background);
--subdued-color: #a8aba1; --subdued-color: #a8aba1;
--muc-color: var(--peertube-button-background);
--green: #3aa569; // only in this file --green: #3aa569; // only in this file
--redder-orange: #e77051; // only in this file --redder-orange: #e77051; // only in this file
--orange: #e7a151; // only in this file --orange: #e7a151; // only in this file
@ -55,7 +56,6 @@ body.converse-embedded converse-root.theme-peertube {
--text-shadow-color: var(--peertube-main-background); // FIXME: should be a little different from background --text-shadow-color: var(--peertube-main-background); // FIXME: should be a little different from background
--text-color: var(--peertube-input-foreground); --text-color: var(--peertube-input-foreground);
--controlbox-text-color: var(--peertube-input-foreground); // Note: controlbox is not used --controlbox-text-color: var(--peertube-input-foreground); // Note: controlbox is not used
--text-color-lighten-15-percent: var(--peertube-input-foreground);
--message-text-color: var(--peertube-input-foreground); --message-text-color: var(--peertube-input-foreground);
--message-receipt-color: var(--green); --message-receipt-color: var(--green);
--save-button-color: var(--green); --save-button-color: var(--green);
@ -73,7 +73,6 @@ body.converse-embedded converse-root.theme-peertube {
--chat-correcting-color: var(--peertube-grey-background); --chat-correcting-color: var(--peertube-grey-background);
--chat-head-color-dark: #1e9652; // should not be used in this plugin --chat-head-color-dark: #1e9652; // should not be used in this plugin
--chat-head-color-darker: #0e763b; // should not be used in this plugin --chat-head-color-darker: #0e763b; // should not be used in this plugin
--chat-head-color-lighten-50-percent: #e7f7ee; // should not be used in this plugin
--chat-head-color: var(--green); --chat-head-color: var(--green);
--chat-head-text-color: var(--peertube-input-foreground); --chat-head-text-color: var(--peertube-input-foreground);
--chat-toolbar-btn-color: var(--peertube-button-background); --chat-toolbar-btn-color: var(--peertube-button-background);
@ -106,7 +105,6 @@ body.converse-embedded converse-root.theme-peertube {
--controlbox-pane-background-color: #333; --controlbox-pane-background-color: #333;
--controlbox-pane-bg-hover-color: #464646; --controlbox-pane-bg-hover-color: #464646;
--panel-divider-color: #333; --panel-divider-color: #333;
--chat-gutter: 0.5em;
--minimized-chats-width: 130px; --minimized-chats-width: 130px;
--mobile-chat-width: 100%; --mobile-chat-width: 100%;
--mobile-chat-height: 400px; --mobile-chat-height: 400px;
@ -119,9 +117,10 @@ body.converse-embedded converse-root.theme-peertube {
--chatroom-badge-color: var(--peertube-button-background); --chatroom-badge-color: var(--peertube-button-background);
--chatroom-badge-hover-color: var(--peertube-button-background); --chatroom-badge-hover-color: var(--peertube-button-background);
--chatroom-correcting-color: var(--peertube-grey-background); --chatroom-correcting-color: var(--peertube-grey-background);
--chatroom-head-bg-color-dark: #d24e2b; --chatroom-head-bg-color-dark: var(--peertube-button-background);
--chatroom-head-bg-color: var(--peertube-menu-background); --chatroom-head-bg-color: var(--peertube-menu-background);
--chatroom-head-border-bottom: 1px solid var(--peertube-grey-foreground); --chatroom-head-border-bottom: 0.15em solid var(--peertube-grey-foreground);
--chatroom-head-fg-color: var(--subdued-color);
--chatroom-head-button-color: #999; --chatroom-head-button-color: #999;
--chatroom-head-color: var(--peertube-menu-foreground); --chatroom-head-color: var(--peertube-menu-foreground);
--chatroom-head-description-border-left: 1px solid #ddd; --chatroom-head-description-border-left: 1px solid #ddd;
@ -163,6 +162,7 @@ body.converse-embedded converse-root.theme-peertube {
--fullpage-chat-width: 100%; --fullpage-chat-width: 100%;
--fullpage-emoji-picker-height: 300px; --fullpage-emoji-picker-height: 300px;
--fullpage-max-chat-textarea-height: 15em; --fullpage-max-chat-textarea-height: 15em;
--overlayed-chat-gutter: 1em;
--overlayed-chat-head-height: 55px; --overlayed-chat-head-height: 55px;
--overlayed-chat-height: 450px; --overlayed-chat-height: 450px;
--overlayed-chat-width: 300px; --overlayed-chat-width: 300px;

View File

@ -60,7 +60,7 @@ body.livechat-readonly.livechat-noscroll {
} }
} }
// Viewer mode // Viewer mode (before the user has chosen its nickname)
.livechat-viewer-mode-content { .livechat-viewer-mode-content {
display: none; display: none;
@ -73,7 +73,7 @@ body.livechat-readonly.livechat-noscroll {
gap: 0.5em 10px; gap: 0.5em 10px;
align-items: baseline; align-items: baseline;
.form-group, fieldset,
label { label {
margin-bottom: 0 !important; // replaced by the gap on .livechat-viewer-mode-content margin-bottom: 0 !important; // replaced by the gap on .livechat-viewer-mode-content
} }
@ -171,7 +171,8 @@ body.converse-embedded {
#peertube-plugin-livechat-container { #peertube-plugin-livechat-container {
converse-muc-message-form { converse-muc-message-form {
// For an unknown reason, message field in truncated... so adding a bottom margin. // For an unknown reason, message field in truncated... so adding a bottom margin.
margin-bottom: 6px; // We also add left and right margin, as Converse v11 adds a g-0 class on converse-muc-chatarea
margin: 0 1px 6px 5px;
} }
} }
@ -187,4 +188,38 @@ body.converse-embedded {
// So we must revert appearance: // So we must revert appearance:
appearance: revert !important; appearance: revert !important;
} }
.toolbar-buttons {
// Converse v11 removed the toggle_occupant button on the right.
// To add it back, we must ensure that this toolbar takes all the width, and
// that the toggle-occupants button is on the right.
flex-grow: 2;
.toggle-occupants {
// Cancelling the flex-grow from btn-group
flex-grow: 0 !important;
// This margin-left trick is to align the button on the right.
margin-left: auto !important;
order: 99;
}
}
// These CSS are tricks: Converse v11 tries to hide the MUC when screen width is under 768px.
// We don't want that, so we cancel the d-none.
// FIXME: these hacks should be temporary, waiting for some improvement on Converse.
converse-muc-chatarea {
.chat-area.d-none {
display: flex !important;
}
/* stylelint-disable-next-line no-descending-specificity */
converse-muc-sidebar {
width: auto !important;
.occupants {
width: 100%;
}
}
}
} }

View File

@ -97,7 +97,7 @@ const tplViewerMode = (o) => {
<div class="livechat-viewer-mode-content chatroom-form-container"> <div class="livechat-viewer-mode-content chatroom-form-container">
<form class="converse-form chatroom-form" @submit=${ev => setNickname(ev, model)}> <form class="converse-form chatroom-form" @submit=${ev => setNickname(ev, model)}>
<label>${i18nHeading}</label> <label>${i18nHeading}</label>
<fieldset class="form-group"> <fieldset>
<input type="text" <input type="text"
required required
name="nick" name="nick"
@ -105,7 +105,7 @@ const tplViewerMode = (o) => {
class="form-control" class="form-control"
placeholder="${i18nNickname}"/> placeholder="${i18nNickname}"/>
</fieldset> </fieldset>
<fieldset class="form-group"> <fieldset>
<input type="submit" class="btn btn-primary" name="join" value="${i18nJoin}"/> <input type="submit" class="btn btn-primary" name="join" value="${i18nJoin}"/>
</fieldset> </fieldset>
</form> </form>

View File

@ -17,12 +17,12 @@ export default (o) => {
${ ${
o.model o.model
? html` ? html`
<converse-muc-heading jid="${o.model.get('jid')}" class="chat-head chat-head-chatroom row no-gutters"> <converse-muc-heading jid="${o.model.get('jid')}" class="chat-head chat-head-chatroom row g-0">
</converse-muc-heading> </converse-muc-heading>
<livechat-converse-muc-terms .model=${o.model} termstype="global"></livechat-converse-muc-terms> <livechat-converse-muc-terms .model=${o.model} termstype="global"></livechat-converse-muc-terms>
<livechat-converse-muc-terms .model=${o.model} termstype="muc"></livechat-converse-muc-terms> <livechat-converse-muc-terms .model=${o.model} termstype="muc"></livechat-converse-muc-terms>
<livechat-converse-muc-poll .model=${o.model}></livechat-converse-muc-poll> <livechat-converse-muc-poll .model=${o.model}></livechat-converse-muc-poll>
<div class="chat-body chatroom-body row no-gutters">${getChatRoomBodyTemplate(o)}</div>` <div class="chat-body chatroom-body row g-0">${getChatRoomBodyTemplate(o)}</div>`
: ''} : ''}
</div>` </div>`
} }

View File

@ -71,8 +71,7 @@ function defaultConverseParams (
visible_toolbar_buttons: { visible_toolbar_buttons: {
call: false, call: false,
spoiler: false, spoiler: false,
emoji: true, emoji: true
toggle_occupants: true
}, },
theme: theme || 'peertube', theme: theme || 'peertube',
dark_theme: theme || 'peertube', // dark theme should be the same as theme dark_theme: theme || 'peertube', // dark theme should be the same as theme

View File

@ -16,23 +16,7 @@ export function customizeToolbar (plugin: any): void {
function getToolbarButtons (this: any, toolbarEl: any, buttons: any[]): any { function getToolbarButtons (this: any, toolbarEl: any, buttons: any[]): any {
const _converse = this._converse const _converse = this._converse
// We will replace the toggle occupant button, to change its appearance. // Adding a toggle_occupants button.
// 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. // Note: we don't need to test conditions, we know the button was here.
const i18nHideOccupants = _converse.__('Hide participants') const i18nHideOccupants = _converse.__('Hide participants')
const i18nShowOccupants = _converse.__('Show participants') const i18nShowOccupants = _converse.__('Show participants')
@ -59,9 +43,14 @@ function getToolbarButtons (this: any, toolbarEl: any, buttons: any[]): any {
size="1em"> size="1em">
</converse-icon>` </converse-icon>`
buttons.push(html` buttons.push(html`
<button class="toggle_occupants right" <button class="toggle-occupants btn"
title="${toolbarEl.hidden_occupants ? i18nShowOccupants : i18nHideOccupants}" title="${toolbarEl.hidden_occupants ? i18nShowOccupants : i18nHideOccupants}"
@click=${toolbarEl.toggleOccupants}> @click=${(ev?: Event) => {
ev?.preventDefault()
toolbarEl.model.save({
hidden_occupants: !toolbarEl.model.get('hidden_occupants')
})
}}>
${icon} ${icon}
</button>` </button>`
) )

View File

@ -605,11 +605,11 @@ moderator_note_create: 'Create a new note'
moderator_note_description: 'Description' moderator_note_description: 'Description'
moderator_note_delete: 'Delete note' moderator_note_delete: 'Delete note'
moderator_note_delete_confirm: 'Are you sure you want to delete this note?' moderator_note_delete_confirm: 'Are you sure you want to delete this note?'
moderator_note_create_for_participant: 'Create a new note about this participant' moderator_note_create_for_participant: 'Create a new note'
moderator_note_search_for_participant: 'Search notes about this participant' moderator_note_search_for_participant: 'Search notes'
moderator_note_filters: 'Search filters' moderator_note_filters: 'Search filters'
moderator_note_original_nick: 'Nickname of the participant at the time of the note moderator_note_original_nick: 'Nickname of the participant at the time of the note
creation' creation'
search_occupant_message: 'Search all messages from this participant' search_occupant_message: 'Search all messages'
message_search: 'Message search' message_search: 'Message search'