Commit 2849adf8 authored by JC Brand's avatar JC Brand

Stop debouncing `show`

Instead optimize in other ways.

Also:
- Don't fade in when `animate` is false.
- `trimChats` now gets called in `afterShown`.
- Add now event `beforeShowingChatView`
parent 3a2bf766
...@@ -939,9 +939,10 @@ ...@@ -939,9 +939,10 @@
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) { async function (done, _converse) {
const sent_stanzas = _converse.connection.sent_stanzas;
// Make the timeouts shorter so that we can test // Make the timeouts shorter so that we can test
_converse.TIMEOUTS.PAUSED = 200; _converse.TIMEOUTS.PAUSED = 100;
_converse.TIMEOUTS.INACTIVE = 200; _converse.TIMEOUTS.INACTIVE = 100;
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
...@@ -949,38 +950,50 @@ ...@@ -949,38 +950,50 @@
await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 1000); await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length, 1000);
await test_utils.openChatBoxFor(_converse, contact_jid); await test_utils.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
await u.waitUntil(() => view.model.get('chat_state') === 'active', 1000); await u.waitUntil(() => view.model.get('chat_state') === 'active');
console.log('chat_state set to active'); let messages = await u.waitUntil(() => sent_stanzas.filter(s => s.matches('message')));
expect(messages.length).toBe(1);
expect(view.model.get('chat_state')).toBe('active'); expect(view.model.get('chat_state')).toBe('active');
view.onKeyDown({ view.onKeyDown({
target: view.el.querySelector('textarea.chat-textarea'), target: view.el.querySelector('textarea.chat-textarea'),
keyCode: 1 keyCode: 1
}); });
await u.waitUntil(() => view.model.get('chat_state') === 'composing', 500); await u.waitUntil(() => view.model.get('chat_state') === 'composing', 600);
console.log('chat_state set to composing'); messages = sent_stanzas.filter(s => s.matches('message'));
expect(view.model.get('chat_state')).toBe('composing'); expect(messages.length).toBe(2);
spyOn(_converse.connection, 'send');
await u.waitUntil(() => view.model.get('chat_state') === 'paused', 1000); await u.waitUntil(() => view.model.get('chat_state') === 'paused', 600);
await u.waitUntil(() => view.model.get('chat_state') === 'inactive', 1000); messages = sent_stanzas.filter(s => s.matches('message'));
console.log('chat_state set to inactive'); expect(messages.length).toBe(3);
expect(_converse.connection.send).toHaveBeenCalled();
var calls = _.filter(_converse.connection.send.calls.all(), function (call) { await u.waitUntil(() => view.model.get('chat_state') === 'inactive', 600);
return call.args[0] instanceof Strophe.Builder; messages = sent_stanzas.filter(s => s.matches('message'));
}); expect(messages.length).toBe(4);
expect(calls.length).toBe(2);
var stanza = calls[0].args[0].tree(); expect(Strophe.serialize(messages[0])).toBe(
expect(stanza.getAttribute('to')).toBe(contact_jid); `<message id="${messages[0].getAttribute('id')}" to="mercutio@montague.lit" type="chat" xmlns="jabber:client">`+
expect(stanza.children.length).toBe(3); `<active xmlns="http://jabber.org/protocol/chatstates"/>`+
expect(stanza.children[0].tagName).toBe('paused'); `<no-store xmlns="urn:xmpp:hints"/>`+
expect(stanza.children[1].tagName).toBe('no-store'); `<no-permanent-store xmlns="urn:xmpp:hints"/>`+
expect(stanza.children[2].tagName).toBe('no-permanent-store'); `</message>`);
expect(Strophe.serialize(messages[1])).toBe(
stanza = _converse.connection.send.calls.mostRecent().args[0].tree(); `<message id="${messages[1].getAttribute('id')}" to="mercutio@montague.lit" type="chat" xmlns="jabber:client">`+
expect(stanza.getAttribute('to')).toBe(contact_jid); `<composing xmlns="http://jabber.org/protocol/chatstates"/>`+
expect(stanza.children.length).toBe(3); `<no-store xmlns="urn:xmpp:hints"/>`+
expect(stanza.children[0].tagName).toBe('inactive'); `<no-permanent-store xmlns="urn:xmpp:hints"/>`+
expect(stanza.children[1].tagName).toBe('no-store'); `</message>`);
expect(stanza.children[2].tagName).toBe('no-permanent-store'); expect(Strophe.serialize(messages[2])).toBe(
`<message id="${messages[2].getAttribute('id')}" to="mercutio@montague.lit" type="chat" xmlns="jabber:client">`+
`<paused xmlns="http://jabber.org/protocol/chatstates"/>`+
`<no-store xmlns="urn:xmpp:hints"/>`+
`<no-permanent-store xmlns="urn:xmpp:hints"/>`+
`</message>`);
expect(Strophe.serialize(messages[3])).toBe(
`<message id="${messages[3].getAttribute('id')}" to="mercutio@montague.lit" type="chat" xmlns="jabber:client">`+
`<inactive xmlns="http://jabber.org/protocol/chatstates"/>`+
`<no-store xmlns="urn:xmpp:hints"/>`+
`<no-permanent-store xmlns="urn:xmpp:hints"/>`+
`</message>`);
done(); done();
})); }));
......
...@@ -374,7 +374,6 @@ converse.plugins.add('converse-chatview', { ...@@ -374,7 +374,6 @@ converse.plugins.add('converse-chatview', {
initDebounced () { initDebounced () {
this.scrollDown = _.debounce(this._scrollDown, 100); this.scrollDown = _.debounce(this._scrollDown, 100);
this.markScrolled = _.debounce(this._markScrolled, 100); this.markScrolled = _.debounce(this._markScrolled, 100);
this.show = _.debounce(this._show, 500, {'leading': true});
}, },
render () { render () {
...@@ -1280,7 +1279,7 @@ converse.plugins.add('converse-chatview', { ...@@ -1280,7 +1279,7 @@ converse.plugins.add('converse-chatview', {
} }
}, },
emitFocused: _.debounce(() => { emitFocused () {
/** /**
* Triggered when the focus has been moved to a particular chat. * Triggered when the focus has been moved to a particular chat.
* @event _converse#chatBoxFocused * @event _converse#chatBoxFocused
...@@ -1288,11 +1287,11 @@ converse.plugins.add('converse-chatview', { ...@@ -1288,11 +1287,11 @@ converse.plugins.add('converse-chatview', {
* @example _converse.api.listen.on('chatBoxFocused', view => { ... }); * @example _converse.api.listen.on('chatBoxFocused', view => { ... });
*/ */
_converse.api.trigger('chatBoxFocused', this); _converse.api.trigger('chatBoxFocused', this);
}, 25, {'leading': true}), },
focus () { focus () {
const textarea_el = this.el.querySelector('.chat-textarea'); const textarea_el = this.el.getElementsByClassName('chat-textarea')[0];
if (!_.isNull(textarea_el)) { if (textarea_el && document.activeElement !== textarea_el) {
textarea_el.focus(); textarea_el.focus();
this.emitFocused(); this.emitFocused();
} }
...@@ -1311,18 +1310,30 @@ converse.plugins.add('converse-chatview', { ...@@ -1311,18 +1310,30 @@ converse.plugins.add('converse-chatview', {
if (_converse.auto_focus) { if (_converse.auto_focus) {
this.focus(); this.focus();
} }
this.focus();
}, },
_show () { show () {
/* Inner show method that gets debounced */
if (u.isVisible(this.el)) { if (u.isVisible(this.el)) {
if (_converse.auto_focus) { if (_converse.auto_focus) {
this.focus(); this.focus();
} }
return; return;
} }
u.fadeIn(this.el, _.bind(this.afterShown, this)); /**
* Triggered just before a {@link _converse.ChatBoxView} or {@link _converse.ChatRoomView}
* will be shown.
* @event _converse#beforeShowingChatView
* @type {object}
* @property { _converse.ChatBoxView | _converse.ChatRoomView } view
*/
_converse.api.trigger('beforeShowingChatView', this);
if (_converse.animate) {
u.fadeIn(this.el, () => this.afterShown());
} else {
u.showElement(this.el);
this.afterShown();
}
}, },
showNewMessagesIndicator () { showNewMessagesIndicator () {
...@@ -1395,7 +1406,7 @@ converse.plugins.add('converse-chatview', { ...@@ -1395,7 +1406,7 @@ converse.plugins.add('converse-chatview', {
onWindowStateChanged (state) { onWindowStateChanged (state) {
if (state === 'visible') { if (state === 'visible') {
if (!this.model.isHidden()) { if (!this.model.isHidden()) {
this.model.setChatState(_converse.ACTIVE); // this.model.setChatState(_converse.ACTIVE);
if (this.model.get('num_unread', 0)) { if (this.model.get('num_unread', 0)) {
this.model.clearUnreadMsgCounter(); this.model.clearUnreadMsgCounter();
} }
......
...@@ -72,11 +72,6 @@ converse.plugins.add('converse-dragresize', { ...@@ -72,11 +72,6 @@ converse.plugins.add('converse-dragresize', {
renderDragResizeHandles(this.__super__._converse, this); renderDragResizeHandles(this.__super__._converse, this);
this.setWidth(); this.setWidth();
return result; return result;
},
_show () {
this.initDragResize().setDimensions();
this.__super__._show.apply(this, arguments);
} }
}, },
...@@ -155,12 +150,12 @@ converse.plugins.add('converse-dragresize', { ...@@ -155,12 +150,12 @@ converse.plugins.add('converse-dragresize', {
/* Determine and store the default box size. /* Determine and store the default box size.
* We need this information for the drag-resizing feature. * We need this information for the drag-resizing feature.
*/ */
const flyout = this.el.querySelector('.box-flyout'), const flyout = this.el.querySelector('.box-flyout');
style = window.getComputedStyle(flyout); const style = window.getComputedStyle(flyout);
if (_.isUndefined(this.model.get('height'))) { if (_.isUndefined(this.model.get('height'))) {
const height = parseInt(style.height.replace(/px$/, ''), 10), const height = parseInt(style.height.replace(/px$/, ''), 10);
width = parseInt(style.width.replace(/px$/, ''), 10); const width = parseInt(style.width.replace(/px$/, ''), 10);
this.model.set('height', height); this.model.set('height', height);
this.model.set('default_height', height); this.model.set('default_height', height);
this.model.set('width', width); this.model.set('width', width);
...@@ -341,6 +336,7 @@ converse.plugins.add('converse-dragresize', { ...@@ -341,6 +336,7 @@ converse.plugins.add('converse-dragresize', {
} }
_converse.api.listen.on('registeredGlobalEventHandlers', registerGlobalEventHandlers); _converse.api.listen.on('registeredGlobalEventHandlers', registerGlobalEventHandlers);
_converse.api.listen.on('beforeShowingChatView', view => view.initDragResize().setDimensions());
_converse.api.listen.on('chatBoxInitialized', view => { _converse.api.listen.on('chatBoxInitialized', view => {
window.addEventListener('resize', _.debounce(() => view.setDimensions(), 100)); window.addEventListener('resize', _.debounce(() => view.setDimensions(), 100));
......
...@@ -78,18 +78,22 @@ converse.plugins.add('converse-minimize', { ...@@ -78,18 +78,22 @@ converse.plugins.add('converse-minimize', {
return this.__super__.initialize.apply(this, arguments); return this.__super__.initialize.apply(this, arguments);
}, },
_show () { show () {
const { _converse } = this.__super__; const { _converse } = this.__super__;
if (_converse.view_mode !== 'overlayed') { if (_converse.view_mode === 'overlayed' && this.model.get('minimized')) {
return this.__super__._show.apply(this, arguments);
} else if (!this.model.get('minimized')) {
this.__super__._show.apply(this, arguments);
_converse.chatboxviews.trimChats(this);
} else {
this.model.minimize(); this.model.minimize();
return this;
} else {
return this.__super__.show.apply(this, arguments);
} }
}, },
afterShown () {
const { _converse } = this.__super__;
this.__super__.afterShown.apply(this, arguments);
_converse.chatboxviews.trimChats(this);
},
isNewMessageHidden () { isNewMessageHidden () {
return this.model.get('minimized') || return this.model.get('minimized') ||
this.__super__.isNewMessageHidden.apply(this, arguments); this.__super__.isNewMessageHidden.apply(this, arguments);
......
...@@ -701,19 +701,6 @@ converse.plugins.add('converse-muc-views', { ...@@ -701,19 +701,6 @@ converse.plugins.add('converse-muc-views', {
this.renderEmojiPicker(); this.renderEmojiPicker();
}, },
show () {
if (u.isVisible(this.el)) {
if (_converse.auto_focus) {
this.focus();
}
return;
}
// Override from converse-chatview in order to not use
// "fadeIn", which causes flashing.
u.showElement(this.el);
this.afterShown();
},
onConnectionStatusChanged () { onConnectionStatusChanged () {
const conn_status = this.model.get('connection_status'); const conn_status = this.model.get('connection_status');
if (conn_status === converse.ROOMSTATUS.NICKNAME_REQUIRED) { if (conn_status === converse.ROOMSTATUS.NICKNAME_REQUIRED) {
......
...@@ -75,31 +75,32 @@ converse.plugins.add('converse-uniview', { ...@@ -75,31 +75,32 @@ converse.plugins.add('converse-uniview', {
} else { } else {
return this.__super__.shouldShowOnTextMessage.apply(this, arguments); return this.__super__.shouldShowOnTextMessage.apply(this, arguments);
} }
},
_show (focus) {
/* We only have one chat visible at any one
* time. So before opening a chat, we make sure all other
* chats are hidden.
*/
const { _converse } = this.__super__;
if (_converse.isUniView()) {
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat);
u.safeSave(this.model, {'hidden': false});
}
return this.__super__._show.apply(this, arguments);
} }
}, }
},
ChatRoomView: { initialize () {
show (focus) { /* The initialize function gets called as soon as the plugin is
const { _converse } = this.__super__; * loaded by converse.js's plugin machinery.
if (_converse.isUniView()) { */
_.each(this.__super__._converse.chatboxviews.xget(this.model.get('id')), hideChat); const { _converse } = this;
u.safeSave(this.model, {'hidden': false});
/************************ BEGIN Event Handlers ************************/
_converse.api.listen.on('beforeShowingChatView', (view) => {
/* We only have one chat visible at any one
* time. So before opening a chat, we make sure all other
* chats are hidden.
*/
if (_converse.isUniView()) {
Object.values(_converse.chatboxviews.xget(view.model.get('id')))
.filter(v => !v.model.get('hidden'))
.forEach(hideChat);
if (view.model.get('hidden')) {
u.safeSave(view.model, {'hidden': false});
} }
return this.__super__.show.apply(this, arguments);
} }
} });
/************************ END Event Handlers ************************/
} }
}); });
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