Commit d7d810ba authored by JC Brand's avatar JC Brand

Improvements to rendering MUC MAM logs before joining

- Add config variable `muc_show_logs_before_join`
- Restore nickname form for the original use-case (when not showing MAM logs before joining).
- Render nickname form in the `.muc-bottom-panel` when showing MAM logs (instead of in a modal)
- Show a message when there aren't any archived messages to show
- Fix converse-mam so that chat logs are properly fetched before entering a MUC

closes #1266
parent a83911d6
...@@ -10,9 +10,10 @@ ...@@ -10,9 +10,10 @@
To add custom emojis, edit the `emojis.json` file. To add custom emojis, edit the `emojis.json` file.
- Refactor some presence and status handling code from `converse-core` into `@converse/headless/converse-status`. - Refactor some presence and status handling code from `converse-core` into `@converse/headless/converse-status`.
- New API [\_converse.api.headlines](https://conversejs.org/docs/html/api/-_converse.api.headlines.html#.get) - New API [\_converse.api.headlines](https://conversejs.org/docs/html/api/-_converse.api.headlines.html#.get)
- New config option [muc-mention-autocomplete-filter](https://conversejs.org/docs/html/configuration.html#muc-mention-autocomplete-filter)
- New config option [muc-mention-autocomplete-show-avatar](https://conversejs.org/docs/html/configuration.html#muc-mention-autocomplete-show-avatar)
- New config option [allow_message_retraction](https://conversejs.org/docs/html/configuration.html#allow-message-retraction) - New config option [allow_message_retraction](https://conversejs.org/docs/html/configuration.html#allow-message-retraction)
- New config option [muc-show-logs-before-join](https://conversejs.org/docs/html/configuration.html#muc-show-logs-before-join)
_ New config option [muc_mention_autocomplete_filter](https://conversejs.org/docs/html/configuration.html#muc_mention_autocomplete_filter)
_ New config option [muc_mention_autocomplete_show_avatar](https://conversejs.org/docs/html/configuration.html#muc_mention_autocomplete_show_avatar)
- #129: Add support for XEP-0156: Disovering Alternative XMPP Connection Methods. Only XML is supported for now. - #129: Add support for XEP-0156: Disovering Alternative XMPP Connection Methods. Only XML is supported for now.
- #1105: Preliminary support for storing persistent data in IndexedDB instead of localStorage - #1105: Preliminary support for storing persistent data in IndexedDB instead of localStorage
......
...@@ -316,6 +316,18 @@ ...@@ -316,6 +316,18 @@
} }
} }
.empty-history-feedback {
position: relative;
height: 100%;
color: var(--text-color-lighten-15-percent);
span {
width: 100%;
text-align: center;
position: absolute;
margin-top: 50%;
}
}
.muc-bottom-panel { .muc-bottom-panel {
border-top: var(--message-input-border-top); border-top: var(--message-input-border-top);
height: 3em; height: 3em;
...@@ -324,6 +336,20 @@ ...@@ -324,6 +336,20 @@
font-size: var(--font-size-small); font-size: var(--font-size-small);
background-color: var(--chatroom-head-color); background-color: var(--chatroom-head-color);
color: white; color: white;
&.muc-bottom-panel--nickname {
padding: 0;
height: 16em;
.chatroom-form-container {
border-radius: 0 !important;
.chatroom-form {
padding-top: 2em;
padding-bottom: 0;
}
}
}
} }
.sendXMPPMessage { .sendXMPPMessage {
......
...@@ -196,7 +196,7 @@ ...@@ -196,7 +196,7 @@
</iq>`); </iq>`);
_converse.connection._dataRecv(test_utils.createRequest(result)); _converse.connection._dataRecv(test_utils.createRequest(result));
await u.waitUntil(() => view.model.messages.length === 5); await u.waitUntil(() => view.model.messages.length === 5);
expect(view.model.fetchArchivedMessages.calls.count()).toBe(3); expect(view.model.fetchArchivedMessages.calls.count()).toBe(5);
const msg_els = view.content.querySelectorAll('.chat-msg__text'); const msg_els = view.content.querySelectorAll('.chat-msg__text');
expect(Array.from(msg_els).map(e => e.textContent).join(' ')).toBe("2nd Message 3rd Message 4th Message 5th Message 6th Message"); expect(Array.from(msg_els).map(e => e.textContent).join(' ')).toBe("2nd Message 3rd Message 4th Message 5th Message 6th Message");
done(); done();
......
...@@ -1547,7 +1547,7 @@ ...@@ -1547,7 +1547,7 @@
expect(presencebroadcast.length).toBe(1); expect(presencebroadcast.length).toBe(1);
presencebroadcast[0].value = ['moderator']; presencebroadcast[0].value = ['moderator'];
view.el.querySelector('input[type="submit"]').click(); view.el.querySelector('.chatroom-form input[type="submit"]').click();
const sent_stanza = sent_IQ.nodeTree; const sent_stanza = sent_IQ.nodeTree;
expect(sent_stanza.querySelector('field[var="muc#roomconfig_membersonly"] value').textContent.trim()).toBe('1'); expect(sent_stanza.querySelector('field[var="muc#roomconfig_membersonly"] value').textContent.trim()).toBe('1');
...@@ -2578,7 +2578,7 @@ ...@@ -2578,7 +2578,7 @@
expect(el.textContent.trim()).toBe("Configuration for room@conference.example.org"); expect(el.textContent.trim()).toBe("Configuration for room@conference.example.org");
sizzle('[name="muc#roomconfig_membersonly"]', chatroomview.el).pop().click(); sizzle('[name="muc#roomconfig_membersonly"]', chatroomview.el).pop().click();
sizzle('[name="muc#roomconfig_roomname"]', chatroomview.el).pop().value = "New room name" sizzle('[name="muc#roomconfig_roomname"]', chatroomview.el).pop().value = "New room name"
chatroomview.el.querySelector('.btn-primary').click(); chatroomview.el.querySelector('.chatroom-form input[type="submit"]').click();
iq = await u.waitUntil(() => _.filter(IQs, iq => u.matchesSelector(iq, `iq[to="${jid}"][type="set"]`)).pop()); iq = await u.waitUntil(() => _.filter(IQs, iq => u.matchesSelector(iq, `iq[to="${jid}"][type="set"]`)).pop());
const result = $iq({ const result = $iq({
......
...@@ -979,7 +979,7 @@ ...@@ -979,7 +979,7 @@
await u.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent === await u.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'hello z3r0 gibson sw0rdf1sh, how are you?', 500); 'hello z3r0 gibson sw0rdf1sh, how are you?', 500);
const correction = _converse.connection.send.calls.all()[2].args[0]; const correction = _converse.connection.send.calls.all()[3].args[0];
expect(correction.toLocaleString()) expect(correction.toLocaleString())
.toBe(`<message from="romeo@montague.lit/orchard" id="${correction.nodeTree.getAttribute("id")}" `+ .toBe(`<message from="romeo@montague.lit/orchard" id="${correction.nodeTree.getAttribute("id")}" `+
`to="lounge@montague.lit" type="groupchat" `+ `to="lounge@montague.lit" type="groupchat" `+
......
This diff is collapsed.
...@@ -58,6 +58,7 @@ converse.plugins.add('converse-mam', { ...@@ -58,6 +58,7 @@ converse.plugins.add('converse-mam', {
/** /**
* Fetches messages that might have been archived *after* * Fetches messages that might have been archived *after*
* the last archived message in our local cache. * the last archived message in our local cache.
* @private
*/ */
fetchNewestMessages () { fetchNewestMessages () {
if (this.disable_mam) { if (this.disable_mam) {
...@@ -165,8 +166,9 @@ converse.plugins.add('converse-mam', { ...@@ -165,8 +166,9 @@ converse.plugins.add('converse-mam', {
Object.assign(_converse.ChatRoom.prototype, { Object.assign(_converse.ChatRoom.prototype, {
fetchArchivedMessagesIfNecessary () { fetchArchivedMessagesIfNecessary () {
if (this.get('connection_status') !== converse.ROOMSTATUS.ENTERED || const conn_status = this.get('connection_status');
!this.get('mam_enabled') || if ((!_converse.muc_show_logs_before_join && conn_status !== converse.ROOMSTATUS.ENTERED) ||
!this.features.get('mam_enabled') ||
this.get('mam_initialized')) { this.get('mam_initialized')) {
return; return;
} }
...@@ -177,7 +179,7 @@ converse.plugins.add('converse-mam', { ...@@ -177,7 +179,7 @@ converse.plugins.add('converse-mam', {
_converse.onMAMError = function (iq) { _converse.onMAMError = function (iq) {
if (iq.querySelectorAll('feature-not-implemented').length) { if (iq && iq.querySelectorAll('feature-not-implemented').length) {
log.warn("Message Archive Management (XEP-0313) not supported by this server"); log.warn("Message Archive Management (XEP-0313) not supported by this server");
} else { } else {
log.error("An error occured while trying to set archiving preferences."); log.error("An error occured while trying to set archiving preferences.");
...@@ -232,7 +234,11 @@ converse.plugins.add('converse-mam', { ...@@ -232,7 +234,11 @@ converse.plugins.add('converse-mam', {
_converse.api.listen.on('addClientFeatures', () => _converse.api.disco.own.features.add(Strophe.NS.MAM)); _converse.api.listen.on('addClientFeatures', () => _converse.api.disco.own.features.add(Strophe.NS.MAM));
_converse.api.listen.on('serviceDiscovered', getMAMPrefsFromFeature); _converse.api.listen.on('serviceDiscovered', getMAMPrefsFromFeature);
_converse.api.listen.on('enteredNewRoom', chat => chat.fetchNewestMessages()); _converse.api.listen.on('enteredNewRoom', room => room.features.get('mam_enabled') && room.fetchNewestMessages());
_converse.api.listen.on('chatRoomOpened', (view) => {
view.listenTo(view.model, 'change:connection_status', () => view.model.fetchArchivedMessagesIfNecessary());
});
_converse.api.listen.on('chatReconnected', chat => { _converse.api.listen.on('chatReconnected', chat => {
// XXX: For MUCs, we listen to enteredNewRoom instead // XXX: For MUCs, we listen to enteredNewRoom instead
if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE) { if (chat.get('type') === _converse.PRIVATE_CHAT_TYPE) {
...@@ -250,11 +256,6 @@ converse.plugins.add('converse-mam', { ...@@ -250,11 +256,6 @@ converse.plugins.add('converse-mam', {
chat.fetchNewestMessages(); chat.fetchNewestMessages();
} }
}); });
_converse.api.listen.on('chatRoomOpened', (room) => {
room.on('change:mam_enabled', room.fetchArchivedMessagesIfNecessary, room);
room.on('change:connection_status', room.fetchArchivedMessagesIfNecessary, room);
});
/************************ END Event Handlers **************************/ /************************ END Event Handlers **************************/
......
...@@ -129,7 +129,8 @@ converse.plugins.add('converse-muc', { ...@@ -129,7 +129,8 @@ converse.plugins.add('converse-muc', {
'muc_fetch_members': true, 'muc_fetch_members': true,
'muc_history_max_stanzas': undefined, 'muc_history_max_stanzas': undefined,
'muc_instant_rooms': true, 'muc_instant_rooms': true,
'muc_nickname_from_jid': false 'muc_nickname_from_jid': false,
'muc_show_logs_before_join': false
}); });
_converse.api.promises.add(['roomsAutoJoined']); _converse.api.promises.add(['roomsAutoJoined']);
......
<div class="chat-area col"> <div class="chat-area col">
<div class="chat-content {[ if (o.show_send_button) { ]}chat-content-sendbutton{[ } ]}" aria-live="polite"></div> <div class="chat-content {[ if (o.show_send_button) { ]}chat-content-sendbutton{[ } ]}" aria-live="polite">
{[ if (o.muc_show_logs_before_join) { ]}
<div class="empty-history-feedback"><span>{{{o.__('No message history available.')}}}</span></div>
{[ } ]}
</div>
<div class="bottom-panel"></div> <div class="bottom-panel"></div>
</div> </div>
{[ if (o.can_edit) { ]} {[ if (o.entered) { ]}
<div class="emoji-picker__container dropup"></div> {[ if (o.can_edit) { ]}
<div class="message-form-container"> <div class="emoji-picker__container dropup"></div>
<div class="message-form-container">
{[ } else { ]}
<div class="muc-bottom-panel">{{{o.__("You're not allowed to send messages in this room")}}}</div>
{[ } ]}
{[ } else { ]} {[ } else { ]}
<div class="muc-bottom-panel">{{{o.__("You're not allowed to send messages in this room")}}}</div> <div class="muc-bottom-panel"></div>
{[ } ]} {[ } ]}
<div class="chatroom-form-container muc-nickname-form">
<form class="converse-form chatroom-form converse-centered-form">
<fieldset class="form-group">
<label>{{{o.heading}}}</label>
<p class="validation-message">{{{o.validation_message}}}</p>
<input type="text" required="required" name="nick" value="{{{o.nickname}}}"
class="form-control {{o.error_class}}" placeholder="{{{o.label_nickname}}}"/>
</fieldset>
<fieldset class="form-group">
<input type="submit" class="btn btn-primary" name="join" value="{{{o.label_join}}}"/>
</fieldset>
</form>
</div>
<div class="modal" id="ask-nickname-modal" tabindex="-1" role="dialog" aria-labelledby="ask-nickname-modal-label" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"
id="ask-nickname-modal-label">{{{o.heading}}}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form class="converse-form chatroom-form converse-centered-form">
<fieldset class="form-group">
<label>{{{o.__('Nickname:')}}}</label>
<p class="validation-message">{{{o.validation_message}}}</p>
<input type="text" required="required" name="nick" value="{{{o.nickname}}}"
class="form-control {{o.error_class}}" placeholder="{{{o.label_nickname}}}"/>
</fieldset>
<fieldset class="form-group">
<input type="submit" class="btn btn-primary" name="join" value="{{{o.label_join}}}"/>
</fieldset>
</form>
</div>
</div>
</div>
</div>
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
converse.initialize({ converse.initialize({
auto_away: 300, auto_away: 300,
auto_register_muc_nickname: true, auto_register_muc_nickname: true,
debug: true, loglevel: 'debug',
enable_smacks: true, enable_smacks: true,
i18n: 'en', i18n: 'en',
message_archiving: 'always', message_archiving: 'always',
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
muc_respect_autojoin: true, muc_respect_autojoin: true,
view_mode: 'fullscreen', view_mode: 'fullscreen',
websocket_url: 'ws://chat.example.org:5380/xmpp-websocket', websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
muc_show_logs_before_join: true,
whitelisted_plugins: ['converse-debug'], whitelisted_plugins: ['converse-debug'],
}); });
</script> </script>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment