Add modal for changing your nickname...
once you're already in a MUC.
This commit is contained in:
parent
ba52defdae
commit
f4fdc36d31
@ -5,8 +5,8 @@
|
||||
- Updated translations: lt
|
||||
- Increased stanza timeout from 10 to 20 seconds
|
||||
- Replace various font icons with SVG icons
|
||||
- Fix OMEMO race condition related to automatic reconnection
|
||||
- #1761: Add a new dark theme based on the [Dracula](https://draculatheme.com/) theme
|
||||
- #2733: Fix OMEMO race condition related to automatic reconnection
|
||||
- #2751: Media not rendered when Converse runs in a browser extension
|
||||
- #2786: Fix webpack configuration not working on Windows OS
|
||||
- #2788: `TypeError` when trying to use `@converse/headless`
|
||||
|
@ -124,6 +124,10 @@ const ChatRoomMixin = {
|
||||
this.initialized.resolve();
|
||||
},
|
||||
|
||||
isEntered () {
|
||||
return this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED;
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks whether we're still joined and if so, restores the MUC state from cache.
|
||||
* @private
|
||||
@ -131,7 +135,7 @@ const ChatRoomMixin = {
|
||||
* @returns { Boolean } Returns `true` if we're still joined, otherwise returns `false`.
|
||||
*/
|
||||
async restoreFromCache () {
|
||||
if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED && (await this.isJoined())) {
|
||||
if (this.isEntered() && (await this.isJoined())) {
|
||||
// We've restored the room from cache and we're still joined.
|
||||
await new Promise(resolve => this.features.fetch({ 'success': resolve, 'error': resolve }));
|
||||
await this.fetchOccupants().catch(e => log.error(e));
|
||||
@ -154,7 +158,7 @@ const ChatRoomMixin = {
|
||||
* model (if available).
|
||||
*/
|
||||
async join (nick, password) {
|
||||
if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
|
||||
if (this.isEntered()) {
|
||||
// We have restored a groupchat from session storage,
|
||||
// so we don't send out a presence stanza again.
|
||||
return this;
|
||||
@ -293,7 +297,7 @@ const ChatRoomMixin = {
|
||||
onOccupantRemoved (occupant) {
|
||||
if (
|
||||
_converse.isInfoVisible(converse.MUC_TRAFFIC_STATES.EXITED) &&
|
||||
this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED &&
|
||||
this.isEntered() &&
|
||||
occupant.get('show') === 'online'
|
||||
) {
|
||||
this.updateNotifications(occupant.get('nick'), converse.MUC_TRAFFIC_STATES.EXITED);
|
||||
@ -339,7 +343,7 @@ const ChatRoomMixin = {
|
||||
},
|
||||
|
||||
async onConnectionStatusChanged () {
|
||||
if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
|
||||
if (this.isEntered()) {
|
||||
if (this.get('hidden') && api.settings.get('muc_subscribe_to_rai') && this.getOwnAffiliation() !== 'none') {
|
||||
try {
|
||||
await this.leave();
|
||||
@ -491,8 +495,7 @@ const ChatRoomMixin = {
|
||||
* @param { XMLElement } stanza
|
||||
*/
|
||||
handleMessageFromMUCHost (stanza) {
|
||||
const conn_status = this.session.get('connection_status');
|
||||
if (conn_status === converse.ROOMSTATUS.ENTERED) {
|
||||
if (this.isEntered()) {
|
||||
// We're not interested in activity indicators when already joined to the room
|
||||
return;
|
||||
}
|
||||
@ -513,7 +516,7 @@ const ChatRoomMixin = {
|
||||
* @param { XMLElement } stanza
|
||||
*/
|
||||
handleForwardedMentions (stanza) {
|
||||
if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
|
||||
if (this.isEntered()) {
|
||||
// Avoid counting mentions twice
|
||||
return;
|
||||
}
|
||||
@ -1023,7 +1026,7 @@ const ChatRoomMixin = {
|
||||
if (
|
||||
!api.settings.get('send_chat_state_notifications') ||
|
||||
!this.get('chat_state') ||
|
||||
this.session.get('connection_status') !== converse.ROOMSTATUS.ENTERED ||
|
||||
!this.isEntered() ||
|
||||
(this.features.get('moderated') && this.getOwnRole() === 'visitor')
|
||||
) {
|
||||
return;
|
||||
@ -1404,6 +1407,10 @@ const ChatRoomMixin = {
|
||||
return this.occupants.getOwnOccupant();
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a presence stanza to update the user's nickname in this MUC.
|
||||
* @param { String } nick
|
||||
*/
|
||||
async setNickname (nick) {
|
||||
if (
|
||||
api.settings.get('auto_register_muc_nickname') &&
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ElementView } from '@converse/skeletor/src/element.js';
|
||||
import MUCInviteModal from 'modals/muc-invite.js';
|
||||
import NicknameModal from './modals/nickname.js';
|
||||
import RoomDetailsModal from 'modals/muc-details.js';
|
||||
import debounce from 'lodash-es/debounce';
|
||||
import tpl_muc_head from './templates/muc-head.js';
|
||||
@ -107,6 +108,15 @@ export default class MUCHeading extends ElementView {
|
||||
});
|
||||
}
|
||||
|
||||
buttons.push({
|
||||
'i18n_text': __('Nickname'),
|
||||
'i18n_title': __("Change the nickname you're using in this groupchat"),
|
||||
'handler': ev => api.modal.show(NicknameModal, { 'model': this.model }, ev),
|
||||
'a_class': 'open-nickname-modal',
|
||||
'icon_class': 'fa-smile',
|
||||
'name': 'nickname'
|
||||
});
|
||||
|
||||
if (this.model.invitesAllowed()) {
|
||||
buttons.push({
|
||||
'i18n_text': __('Invite'),
|
||||
|
15
src/plugins/muc-views/modals/nickname.js
Normal file
15
src/plugins/muc-views/modals/nickname.js
Normal file
@ -0,0 +1,15 @@
|
||||
import tpl_nickname from "./templates/nickname.js";
|
||||
import BaseModal from "plugins/modal/base.js";
|
||||
|
||||
export default BaseModal.extend({
|
||||
id: 'change-nickname-modal',
|
||||
|
||||
initialize (attrs) {
|
||||
this.model = attrs.model;
|
||||
BaseModal.prototype.initialize.apply(this, arguments);
|
||||
},
|
||||
|
||||
toHTML () {
|
||||
return tpl_nickname(this);
|
||||
},
|
||||
});
|
21
src/plugins/muc-views/modals/templates/nickname.js
Normal file
21
src/plugins/muc-views/modals/templates/nickname.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { __ } from 'i18n';
|
||||
import { html } from "lit";
|
||||
import { modal_header_close_button } from "plugins/modal/templates/buttons.js"
|
||||
|
||||
export default (modal) => {
|
||||
const jid = modal.model.get('jid');
|
||||
const i18n_heading = __('Change your nickname');
|
||||
return html`
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="converse-modtools-modal-label">
|
||||
${i18n_heading}</h5>
|
||||
${modal_header_close_button}
|
||||
</div>
|
||||
<div class="modal-body d-flex flex-column">
|
||||
<converse-muc-nickname-form jid="${jid}"></converse-muc-nickname-form>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
@ -19,7 +19,27 @@ class MUCNicknameForm extends CustomElement {
|
||||
}
|
||||
|
||||
render () {
|
||||
return tpl_muc_nickname_form(this.model);
|
||||
return tpl_muc_nickname_form(this);
|
||||
}
|
||||
|
||||
submitNickname (ev) {
|
||||
ev.preventDefault();
|
||||
const nick = ev.target.nick.value.trim();
|
||||
if (!nick) {
|
||||
return;
|
||||
}
|
||||
if (this.model.isEntered()) {
|
||||
this.model.setNickname(nick);
|
||||
this.closeModal();
|
||||
} else {
|
||||
this.model.join(nick);
|
||||
}
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
const evt = document.createEvent('Event');
|
||||
evt.initEvent('hide.bs.modal', true, true);
|
||||
this.dispatchEvent(evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import '../message-form.js';
|
||||
import '../nickname-form.js';
|
||||
import 'shared/chat/toolbar.js';
|
||||
import tpl_muc_nickname_form from './muc-nickname-form.js';
|
||||
import { __ } from 'i18n';
|
||||
import { api, converse } from "@converse/headless/core";
|
||||
import { html } from "lit";
|
||||
@ -45,7 +45,9 @@ export default (o) => {
|
||||
${(o.can_edit) ? tpl_can_edit(o) : html`<span class="muc-bottom-panel muc-bottom-panel--muted">${i18n_not_allowed}</span>`}`;
|
||||
} else if (conn_status == converse.ROOMSTATUS.NICKNAME_REQUIRED) {
|
||||
if (api.settings.get('muc_show_logs_before_join')) {
|
||||
return html`<span class="muc-bottom-panel muc-bottom-panel--nickname">${tpl_muc_nickname_form(o.model)}</span>`;
|
||||
return html`<span class="muc-bottom-panel muc-bottom-panel--nickname">
|
||||
<converse-muc-nickname-form jid="${o.model.get('jid')}"></converse-muc-nickname-form>
|
||||
</span>`;
|
||||
}
|
||||
} else {
|
||||
return '';
|
||||
|
@ -2,24 +2,18 @@ import { __ } from 'i18n';
|
||||
import { api } from "@converse/headless/core";
|
||||
import { html } from "lit";
|
||||
|
||||
function submitNickname (ev, model) {
|
||||
ev.preventDefault();
|
||||
const nick = ev.target.nick.value.trim();
|
||||
nick && model.join(nick);
|
||||
}
|
||||
|
||||
export default (model) => {
|
||||
export default (el) => {
|
||||
const i18n_nickname = __('Nickname');
|
||||
const i18n_join = __('Enter groupchat');
|
||||
const i18n_join = el.model?.isEntered() ? __('Change nickname') : __('Enter groupchat');
|
||||
const i18n_heading = api.settings.get('muc_show_logs_before_join') ?
|
||||
__('Choose a nickname to enter') :
|
||||
__('Please choose your nickname');
|
||||
|
||||
const validation_message = model.get('nickname_validation_message');
|
||||
const validation_message = el.model?.get('nickname_validation_message');
|
||||
|
||||
return html`
|
||||
<div class="chatroom-form-container muc-nickname-form"
|
||||
@submit=${ev => submitNickname(ev, model)}>
|
||||
@submit=${ev => el.submitNickname(ev)}>
|
||||
<form class="converse-form chatroom-form converse-centered-form">
|
||||
<fieldset class="form-group">
|
||||
<label>${i18n_heading}</label>
|
||||
@ -27,7 +21,7 @@ export default (model) => {
|
||||
<input type="text"
|
||||
required="required"
|
||||
name="nick"
|
||||
value="${model.get('nick') || ''}"
|
||||
value="${el.model?.get('nick') || ''}"
|
||||
class="form-control ${validation_message ? 'error': ''}"
|
||||
placeholder="${i18n_nickname}"/>
|
||||
</fieldset>
|
||||
|
@ -2,7 +2,36 @@
|
||||
|
||||
const { $pres, $iq, Strophe, sizzle, u } = converse.env;
|
||||
|
||||
fdescribe("A MUC", function () {
|
||||
describe("A MUC", function () {
|
||||
|
||||
it("allows you to change your nickname via a modal",
|
||||
mock.initConverse([], {'view_mode': 'fullscreen'}, async function (_converse) {
|
||||
|
||||
const muc_jid = 'lounge@montague.lit';
|
||||
const nick = 'romeo';
|
||||
await mock.openAndEnterChatRoom(_converse, muc_jid, nick);
|
||||
|
||||
const view = _converse.chatboxviews.get(muc_jid);
|
||||
const dropdown_item = view.querySelector(".open-nickname-modal");
|
||||
dropdown_item.click();
|
||||
|
||||
const modal = _converse.api.modal.get('change-nickname-modal');
|
||||
await u.waitUntil(() => u.isVisible(modal.el));
|
||||
|
||||
const input = modal.el.querySelector('input[name="nick"]');
|
||||
expect(input.value).toBe(nick);
|
||||
|
||||
const newnick = 'loverboy';
|
||||
input.value = newnick;
|
||||
modal.el.querySelector('input[type="submit"]')?.click();
|
||||
|
||||
await u.waitUntil(() => !u.isVisible(modal.el));
|
||||
|
||||
const { sent_stanzas } = _converse.connection;
|
||||
const sent_stanza = sent_stanzas.pop()
|
||||
expect(Strophe.serialize(sent_stanza).toLocaleString()).toBe(
|
||||
`<presence from="${_converse.jid}" id="${sent_stanza.getAttribute('id')}" to="${muc_jid}/${newnick}" xmlns="jabber:client"/>`);
|
||||
}));
|
||||
|
||||
it("informs users if their nicknames have been changed.",
|
||||
mock.initConverse([], {}, async function (_converse) {
|
||||
@ -44,9 +73,8 @@ fdescribe("A MUC", function () {
|
||||
*/
|
||||
const __ = _converse.__;
|
||||
await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'oldnick');
|
||||
const view = _converse.chatboxviews.get('lounge@montague.lit');
|
||||
expect(view.model.session.get('connection_status')).toBe(converse.ROOMSTATUS.ENTERED);
|
||||
|
||||
const view = _converse.chatboxviews.get('lounge@montague.lit');
|
||||
await u.waitUntil(() => view.querySelectorAll('li .occupant-nick').length, 500);
|
||||
let occupants = view.querySelector('.occupant-list');
|
||||
expect(occupants.childElementCount).toBe(1);
|
||||
|
@ -38,8 +38,8 @@
|
||||
muc_domain: 'conference.chat.example.org',
|
||||
muc_respect_autojoin: true,
|
||||
view_mode: 'fullscreen',
|
||||
// websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
|
||||
websocket_url: 'wss://conversejs.org/xmpp-websocket',
|
||||
websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
|
||||
// websocket_url: 'wss://conversejs.org/xmpp-websocket',
|
||||
// bosh_service_url: 'http://chat.example.org:5280/http-bind',
|
||||
allow_user_defined_connection_url: true,
|
||||
muc_show_logs_before_join: true,
|
||||
|
@ -9,7 +9,7 @@ module.exports = merge(common, {
|
||||
devtool: "inline-source-map",
|
||||
devServer: {
|
||||
static: [ path.resolve(__dirname, '../') ],
|
||||
port: 3004
|
||||
port: 3003
|
||||
},
|
||||
plugins: [
|
||||
new HTMLWebpackPlugin({
|
||||
|
Loading…
Reference in New Issue
Block a user