Commit 38d1e4e3 authored by JC Brand's avatar JC Brand

Bugfix. Sometimes when trimming chats, minimized chats go off screen

parent 2849adf8
...@@ -273,14 +273,14 @@ ...@@ -273,14 +273,14 @@
it("can be saved to, and retrieved from, browserStorage", it("can be saved to, and retrieved from, browserStorage",
mock.initConverse( mock.initConverse(
null, ['rosterGroupsFetched', 'chatBoxesFetched',], {}, null, ['rosterGroupsFetched'], {},
async function (done, _converse) { async function (done, _converse) {
spyOn(_converse.ChatBoxViews.prototype, 'trimChats');
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
spyOn(_converse.api, "trigger"); spyOn(_converse.api, "trigger");
spyOn(_converse.chatboxviews, 'trimChats');
test_utils.openControlBox(); test_utils.openControlBox();
test_utils.openChatBoxes(_converse, 6); test_utils.openChatBoxes(_converse, 6);
...@@ -386,11 +386,11 @@ ...@@ -386,11 +386,11 @@
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
async function (done, _converse) { async function (done, _converse) {
spyOn(_converse.ChatBoxViews.prototype, 'trimChats');
await test_utils.waitForRoster(_converse, 'current'); await test_utils.waitForRoster(_converse, 'current');
test_utils.openControlBox(); test_utils.openControlBox();
await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length); await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length);
spyOn(_converse.api, "trigger"); spyOn(_converse.api, "trigger");
spyOn(_converse.chatboxviews, 'trimChats');
_converse.chatboxes.browserStorage._clear(); _converse.chatboxes.browserStorage._clear();
test_utils.closeControlBox(); test_utils.closeControlBox();
......
...@@ -555,11 +555,14 @@ converse.plugins.add('converse-chatview', { ...@@ -555,11 +555,14 @@ converse.plugins.add('converse-chatview', {
}, },
insertIntoDOM () { insertIntoDOM () {
/* This method gets overridden in src/converse-controlbox.js
* as well as src/converse-muc.js (if those plugins are
* enabled).
*/
_converse.chatboxviews.insertRowColumn(this.el); _converse.chatboxviews.insertRowColumn(this.el);
/**
* Triggered once the _converse.ChatBoxView has been inserted into the DOM
* @event _converse#chatBoxInsertedIntoDOM
* @type { _converse.ChatBoxView | _converse.HeadlinesBoxView }
* @example _converse.api.listen.on('chatBoxInsertedIntoDOM', view => { ... });
*/
_converse.api.trigger('chatBoxInsertedIntoDOM', this);
return this; return this;
}, },
......
...@@ -344,6 +344,11 @@ converse.plugins.add('converse-controlbox', { ...@@ -344,6 +344,11 @@ converse.plugins.add('converse-controlbox', {
onControlBoxToggleHidden () { onControlBoxToggleHidden () {
this.model.set('closed', false); this.model.set('closed', false);
this.el.classList.remove('hidden'); this.el.classList.remove('hidden');
/**
* Triggered once the controlbox has been opened
* @event _converse#controlBoxOpened
* @type {_converse.ControlBox}
*/
_converse.api.trigger('controlBoxOpened', this); _converse.api.trigger('controlBoxOpened', this);
}, },
......
...@@ -88,12 +88,6 @@ converse.plugins.add('converse-minimize', { ...@@ -88,12 +88,6 @@ converse.plugins.add('converse-minimize', {
} }
}, },
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);
...@@ -301,23 +295,37 @@ converse.plugins.add('converse-minimize', { ...@@ -301,23 +295,37 @@ converse.plugins.add('converse-minimize', {
); );
}, },
trimChats: _.debounce(async function (newchat) { getMinimizedWidth () {
/* This method is called when a newly created chat box will const minimized_el = _.get(_converse.minimized_chats, 'el');
* be shown. return _.includes(this.model.pluck('minimized'), true) ?
* u.getOuterWidth(minimized_el, true) : 0;
* It checks whether there is enough space on the page to show },
* another chat box. Otherwise it minimizes the oldest chat box
* to create space. getBoxesWidth (newchat) {
*/ const new_id = newchat ? newchat.model.get('id') : null;
if (!_converse.connection.connected || _converse.view_mode !== 'overlayed') { const newchat_width = newchat ? u.getOuterWidth(newchat.el, true) : 0;
return Object.values(this.xget(new_id))
.reduce((memo, view) => memo + this.getChatBoxWidth(view), newchat_width);
},
/**
* This method is called when a newly created chat box will be shown.
* It checks whether there is enough space on the page to show
* another chat box. Otherwise it minimizes the oldest chat box
* to create space.
* @private
* @method _converse.ChatBoxViews#trimChats
* @param { [ChatBoxView|ChatRoomView|ControlBoxView|HeadlinesBoxView] } newchat
*/
async trimChats (newchat) {
if (_converse.no_trimming || !_converse.connection.connected || _converse.view_mode !== 'overlayed') {
return; return;
} }
const shown_chats = this.getShownChats(); const shown_chats = this.getShownChats();
const body_width = u.getOuterWidth(document.querySelector('body'), true); if (shown_chats.length <= 1) {
if (_converse.no_trimming || shown_chats.length <= 1) {
return; return;
} }
const body_width = u.getOuterWidth(document.querySelector('body'), true);
if (this.getChatBoxWidth(shown_chats[0]) === body_width) { if (this.getChatBoxWidth(shown_chats[0]) === body_width) {
// If the chats shown are the same width as the body, // If the chats shown are the same width as the body,
// then we're in responsive mode and the chats are // then we're in responsive mode and the chats are
...@@ -325,19 +333,10 @@ converse.plugins.add('converse-minimize', { ...@@ -325,19 +333,10 @@ converse.plugins.add('converse-minimize', {
return; return;
} }
await _converse.api.waitUntil('minimizedChatsInitialized'); await _converse.api.waitUntil('minimizedChatsInitialized');
const minimized_el = _.get(_converse.minimized_chats, 'el'), const minimized_el = _.get(_converse.minimized_chats, 'el');
new_id = newchat ? newchat.model.get('id') : null;
if (minimized_el) { if (minimized_el) {
const minimized_width = _.includes(this.model.pluck('minimized'), true) ? while ((this.getMinimizedWidth() + this.getBoxesWidth(newchat)) > body_width) {
u.getOuterWidth(minimized_el, true) : 0; const new_id = newchat ? newchat.model.get('id') : null;
const boxes_width = _.reduce(
this.xget(new_id),
(memo, view) => memo + this.getChatBoxWidth(view),
newchat ? u.getOuterWidth(newchat.el, true) : 0
);
if ((minimized_width + boxes_width) > body_width) {
const oldest_chat = this.getOldestMaximizedChat([new_id]); const oldest_chat = this.getOldestMaximizedChat([new_id]);
if (oldest_chat) { if (oldest_chat) {
// We hide the chat immediately, because waiting // We hide the chat immediately, because waiting
...@@ -349,10 +348,12 @@ converse.plugins.add('converse-minimize', { ...@@ -349,10 +348,12 @@ converse.plugins.add('converse-minimize', {
view.hide(); view.hide();
} }
oldest_chat.minimize(); oldest_chat.minimize();
} else {
break;
} }
} }
} }
}, 100), },
getOldestMaximizedChat (exclude_ids) { getOldestMaximizedChat (exclude_ids) {
// Get oldest view (if its id is not excluded) // Get oldest view (if its id is not excluded)
...@@ -452,7 +453,6 @@ converse.plugins.add('converse-minimize', { ...@@ -452,7 +453,6 @@ converse.plugins.add('converse-minimize', {
this.el.classList.add('hidden'); this.el.classList.add('hidden');
} else if (this.keys().length > 0 && !u.isVisible(this.el)) { } else if (this.keys().length > 0 && !u.isVisible(this.el)) {
this.el.classList.remove('hidden'); this.el.classList.remove('hidden');
_converse.chatboxviews.trimChats();
} }
return this.el; return this.el;
}, },
...@@ -570,10 +570,11 @@ converse.plugins.add('converse-minimize', { ...@@ -570,10 +570,11 @@ converse.plugins.add('converse-minimize', {
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL)); }).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
const trimChats = () => _converse.chatboxviews.trimChats(); const debouncedTrimChats = _.debounce(() => _converse.chatboxviews.trimChats(), 250);
_converse.api.listen.on('controlBoxOpened', trimChats); _converse.api.listen.on('chatBoxInsertedIntoDOM', view => _converse.chatboxviews.trimChats(view));
_converse.api.listen.on('registeredGlobalEventHandlers', () => window.addEventListener("resize", trimChats)); _converse.api.listen.on('controlBoxOpened', view => _converse.chatboxviews.trimChats(view));
_converse.api.listen.on('unregisteredGlobalEventHandlers', () => window.removeEventListener("resize", trimChats)); _converse.api.listen.on('registeredGlobalEventHandlers', () => window.addEventListener("resize", debouncedTrimChats));
_converse.api.listen.on('unregisteredGlobalEventHandlers', () => window.removeEventListener("resize", debouncedTrimChats));
/************************ END Event Handlers ************************/ /************************ END Event Handlers ************************/
} }
}); });
...@@ -199,12 +199,13 @@ u.stringToNode = function (s) { ...@@ -199,12 +199,13 @@ u.stringToNode = function (s) {
}; };
u.getOuterWidth = function (el, include_margin=false) { u.getOuterWidth = function (el, include_margin=false) {
var width = el.offsetWidth; let width = el.offsetWidth;
if (!include_margin) { if (!include_margin) {
return width; return width;
} }
var style = window.getComputedStyle(el); const style = window.getComputedStyle(el);
width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10); width += parseInt(style.marginLeft ? style.marginLeft : 0, 10) +
parseInt(style.marginRight ? style.marginRight : 0, 10);
return width; return width;
}; };
......
...@@ -108,10 +108,10 @@ ...@@ -108,10 +108,10 @@
}; };
utils.openChatBoxes = function (converse, amount) { utils.openChatBoxes = function (converse, amount) {
var i = 0, jid, views = []; const views = [];
for (i; i<amount; i++) { for (let i=0; i<amount; i++) {
jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@montague.lit'; const jid = mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@montague.lit';
views[i] = converse.roster.get(jid).trigger("open"); views.push(converse.roster.get(jid).trigger("open"));
} }
return views; return views;
}; };
......
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