Don't render hidden chats

This commit is contained in:
JC Brand 2021-03-11 12:33:50 +01:00
parent 2dbe50fc97
commit 4646956922
12 changed files with 88 additions and 72 deletions

View File

@ -32,6 +32,9 @@ Removed events:
* `bookmarkViewsInitialized` * `bookmarkViewsInitialized`
* `rosterGroupsFetched` * `rosterGroupsFetched`
The `chatBoxMaximized` and `chatBoxMinimized` events now have the `model` as
payload and not the `view` since it might not be exist at that time.
## 7.0.5 (Unreleased) ## 7.0.5 (Unreleased)
- #2377: The @converse/headless NPM package is missing the dist directory, causing import errors - #2377: The @converse/headless NPM package is missing the dist directory, causing import errors

View File

@ -119,6 +119,7 @@ describe("Chatboxes", function () {
await new Promise(resolve => _converse.api.listen.once('chatBoxViewInitialized', resolve)); await new Promise(resolve => _converse.api.listen.once('chatBoxViewInitialized', resolve));
await u.waitUntil(() => message_promise); await u.waitUntil(() => message_promise);
expect(_converse.chatboxviews.keys().length).toBe(2); expect(_converse.chatboxviews.keys().length).toBe(2);
expect(_converse.chatboxviews.keys().pop()).toBe(sender_jid);
done(); done();
})); }));
@ -198,6 +199,7 @@ describe("Chatboxes", function () {
mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) { mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse);
const contact_jid = mock.cur_names[7].replace(/ /g,'.').toLowerCase() + '@montague.lit'; const contact_jid = mock.cur_names[7].replace(/ /g,'.').toLowerCase() + '@montague.lit';
const rosterview = document.querySelector('converse-roster'); const rosterview = document.querySelector('converse-roster');
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length);
@ -372,8 +374,8 @@ describe("Chatboxes", function () {
u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length); u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length);
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
await mock.openChatBoxFor(_converse, contact_jid); await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid); const model = _converse.chatboxes.get(contact_jid);
expect(view.model.get('chat_state')).toBe('active'); expect(model.get('chat_state')).toBe('active');
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
const stanza = _converse.connection.send.calls.argsFor(0)[0].tree(); const stanza = _converse.connection.send.calls.argsFor(0)[0].tree();
expect(stanza.getAttribute('to')).toBe(contact_jid); expect(stanza.getAttribute('to')).toBe(contact_jid);
@ -394,12 +396,12 @@ describe("Chatboxes", function () {
const rosterview = document.querySelector('converse-roster'); const rosterview = document.querySelector('converse-roster');
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length);
await mock.openChatBoxFor(_converse, contact_jid); await mock.openChatBoxFor(_converse, contact_jid);
const view = _converse.chatboxviews.get(contact_jid); const model = _converse.chatboxes.get(contact_jid);
_converse.minimize.minimize(view.model); _converse.minimize.minimize(model);
expect(view.model.get('chat_state')).toBe('inactive'); expect(model.get('chat_state')).toBe('inactive');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
_converse.minimize.maximize(view.model); _converse.minimize.maximize(model);
await u.waitUntil(() => view.model.get('chat_state') === 'active', 1000); await u.waitUntil(() => model.get('chat_state') === 'active', 1000);
expect(_converse.connection.send).toHaveBeenCalled(); expect(_converse.connection.send).toHaveBeenCalled();
const calls = _.filter(_converse.connection.send.calls.all(), function (call) { const calls = _.filter(_converse.connection.send.calls.all(), function (call) {
return call.args[0] instanceof Strophe.Builder; return call.args[0] instanceof Strophe.Builder;
@ -427,7 +429,7 @@ describe("Chatboxes", function () {
const rosterview = document.querySelector('converse-roster'); const rosterview = document.querySelector('converse-roster');
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length);
await mock.openChatBoxFor(_converse, contact_jid); await mock.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
expect(view.model.get('chat_state')).toBe('active'); expect(view.model.get('chat_state')).toBe('active');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
spyOn(_converse.api, "trigger").and.callThrough(); spyOn(_converse.api, "trigger").and.callThrough();
@ -468,7 +470,7 @@ describe("Chatboxes", function () {
const rosterview = document.querySelector('converse-roster'); const rosterview = document.querySelector('converse-roster');
await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length);
await mock.openChatBoxFor(_converse, contact_jid); await mock.openChatBoxFor(_converse, contact_jid);
var view = _converse.chatboxviews.get(contact_jid); const view = _converse.chatboxviews.get(contact_jid);
expect(view.model.get('chat_state')).toBe('active'); expect(view.model.get('chat_state')).toBe('active');
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
spyOn(_converse.api, "trigger").and.callThrough(); spyOn(_converse.api, "trigger").and.callThrough();
@ -1162,7 +1164,7 @@ describe("Chatboxes", function () {
_converse.handleMessageStanza(msgFactory()); _converse.handleMessageStanza(msgFactory());
await u.waitUntil(() => chatbox.messages.length > 1); await u.waitUntil(() => chatbox.messages.length > 1);
expect(select_msgs_indicator().textContent).toBe('2'); expect(select_msgs_indicator().textContent).toBe('2');
_converse.minimize.minimize(view.model); _converse.minimize.maximize(view.model);
u.waitUntil(() => typeof select_msgs_indicator() === 'undefined'); u.waitUntil(() => typeof select_msgs_indicator() === 'undefined');
done(); done();
})); }));

View File

@ -227,7 +227,7 @@ describe("The 'Add Contact' widget", function () {
mock.initConverse([], {'autocomplete_add_contact': false}, async function (done, _converse) { mock.initConverse([], {'autocomplete_add_contact': false}, async function (done, _converse) {
await mock.waitForRoster(_converse, 'all', 0); await mock.waitForRoster(_converse, 'all', 0);
mock.openControlBox(_converse); await mock.openControlBox(_converse);
const cbview = _converse.chatboxviews.get('controlbox'); const cbview = _converse.chatboxviews.get('controlbox');
cbview.querySelector('.add-contact').click() cbview.querySelector('.add-contact').click()
const modal = _converse.api.modal.get('add-contact-modal'); const modal = _converse.api.modal.get('add-contact-modal');
@ -274,6 +274,7 @@ describe("The 'Add Contact' widget", function () {
const XMLHttpRequestBackup = window.XMLHttpRequest; const XMLHttpRequestBackup = window.XMLHttpRequest;
window.XMLHttpRequest = MockXHR; window.XMLHttpRequest = MockXHR;
await mock.openControlBox(_converse);
const cbview = _converse.chatboxviews.get('controlbox'); const cbview = _converse.chatboxviews.get('controlbox');
cbview.querySelector('.add-contact').click() cbview.querySelector('.add-contact').click()
const modal = _converse.api.modal.get('add-contact-modal'); const modal = _converse.api.modal.get('add-contact-modal');

View File

@ -70,7 +70,7 @@ describe("A chat message", function () {
}); });
describe("A Groupcaht", function () { describe("A Groupchat", function () {
it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'", it("can be minimized by clicking a DOM element with class 'toggle-chatbox-button'",
mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) { mock.initConverse(['chatBoxesFetched'], {}, async function (done, _converse) {
@ -117,7 +117,7 @@ describe("A Chatbox", function () {
expect(_converse.api.trigger.calls.count(), 2); expect(_converse.api.trigger.calls.count(), 2);
expect(u.isVisible(chatview)).toBeFalsy(); expect(u.isVisible(chatview)).toBeFalsy();
expect(chatview.model.get('minimized')).toBeTruthy(); expect(chatview.model.get('minimized')).toBeTruthy();
chatview.querySelector('.toggle-chatbox-button').click(); document.querySelector('converse-minimized-chat').click();
await u.waitUntil(() => _converse.chatboxviews.keys().length); await u.waitUntil(() => _converse.chatboxviews.keys().length);
const minimized_chats = document.querySelector("converse-minimized-chat") const minimized_chats = document.querySelector("converse-minimized-chat")
@ -135,8 +135,7 @@ describe("A Chatbox", function () {
expect(u.isVisible(minimized_chats.firstElementChild)).toBe(false); expect(u.isVisible(minimized_chats.firstElementChild)).toBe(false);
await _converse.api.chats.create(sender_jid, {'minimized': true}); await _converse.api.chats.create(sender_jid, {'minimized': true});
await u.waitUntil(() => _converse.chatboxes.length > 1); await u.waitUntil(() => _converse.chatboxes.length > 1);
const view = _converse.chatboxviews.get(sender_jid); expect(_converse.chatboxviews.get(sender_jid)).toBe(undefined);
expect(u.isVisible(view)).toBeFalsy();
expect(u.isVisible(minimized_chats.firstElementChild)).toBe(true); expect(u.isVisible(minimized_chats.firstElementChild)).toBe(true);
expect(minimized_chats.firstElementChild.querySelectorAll('converse-minimized-chat').length).toBe(1); expect(minimized_chats.firstElementChild.querySelectorAll('converse-minimized-chat').length).toBe(1);
expect(_converse.chatboxes.filter('minimized').length).toBe(1); expect(_converse.chatboxes.filter('minimized').length).toBe(1);
@ -149,7 +148,6 @@ describe("A Chatbox", function () {
await mock.waitForRoster(_converse, 'current'); await mock.waitForRoster(_converse, 'current');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
let jid, chatboxview;
// openControlBox was called earlier, so the controlbox is // openControlBox was called earlier, so the controlbox is
// visible, but no other chat boxes have been created. // visible, but no other chat boxes have been created.
expect(_converse.chatboxes.length).toEqual(1); expect(_converse.chatboxes.length).toEqual(1);
@ -170,12 +168,11 @@ describe("A Chatbox", function () {
for (i=0; i<online_contacts.length; i++) { for (i=0; i<online_contacts.length; i++) {
const el = online_contacts[i]; const el = online_contacts[i];
jid = el.textContent.trim().replace(/ /g,'.').toLowerCase() + '@montague.lit'; const jid = el.textContent.trim().replace(/ /g,'.').toLowerCase() + '@montague.lit';
chatboxview = _converse.chatboxviews.get(jid); const model = _converse.chatboxes.get(jid);
chatboxview.model.set({'minimized': true}); model.set({'minimized': true});
} }
await u.waitUntil(() => _converse.chatboxviews.keys().length); await u.waitUntil(() => _converse.chatboxviews.keys().length === 1);
spyOn(_converse.minimize, 'maximize').and.callThrough();
const minimized_chats = document.querySelector("converse-minimized-chats") const minimized_chats = document.querySelector("converse-minimized-chats")
minimized_chats.querySelector("a.restore-chat").click(); minimized_chats.querySelector("a.restore-chat").click();
expect(_converse.minimize.trimChats.calls.count()).toBe(17); expect(_converse.minimize.trimChats.calls.count()).toBe(17);

View File

@ -25,10 +25,10 @@ describe("MUC Mention Notfications", function () {
await mock.receiveOwnMUCPresence(_converse, muc_jid, nick); await mock.receiveOwnMUCPresence(_converse, muc_jid, nick);
await muc_creation_promise; await muc_creation_promise;
const view = api.chatviews.get(muc_jid); const model = _converse.chatboxes.get(muc_jid);
await u.waitUntil(() => (view.model.session.get('connection_status') === converse.ROOMSTATUS.ENTERED)); await u.waitUntil(() => (model.session.get('connection_status') === converse.ROOMSTATUS.ENTERED));
expect(view.model.get('hidden')).toBe(true); expect(model.get('hidden')).toBe(true);
await u.waitUntil(() => view.model.session.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED); await u.waitUntil(() => model.session.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED);
const room_el = await u.waitUntil(() => document.querySelector("converse-rooms-list .available-chatroom")); const room_el = await u.waitUntil(() => document.querySelector("converse-rooms-list .available-chatroom"));
expect(Array.from(room_el.classList).includes('unread-msgs')).toBeFalsy(); expect(Array.from(room_el.classList).includes('unread-msgs')).toBeFalsy();

View File

@ -267,6 +267,7 @@ describe("A groupchat shown in the groupchats list", function () {
await mock.openChatRoom(_converse, 'lounge', 'conference.shakespeare.lit', 'JC'); await mock.openChatRoom(_converse, 'lounge', 'conference.shakespeare.lit', 'JC');
expect(_converse.chatboxes.length).toBe(2); expect(_converse.chatboxes.length).toBe(2);
await mock.openControlBox(_converse);
const controlbox = _converse.chatboxviews.get('controlbox'); const controlbox = _converse.chatboxviews.get('controlbox');
const lview = controlbox.querySelector('converse-rooms-list'); const lview = controlbox.querySelector('converse-rooms-list');
await u.waitUntil(() => lview.querySelectorAll(".open-room").length); await u.waitUntil(() => lview.querySelectorAll(".open-room").length);

View File

@ -133,9 +133,9 @@ describe("XEP-0437 Room Activity Indicators", function () {
await mock.receiveOwnMUCPresence(_converse, muc_jid, nick); await mock.receiveOwnMUCPresence(_converse, muc_jid, nick);
await muc_creation_promise; await muc_creation_promise;
const view = api.chatviews.get(muc_jid); const model = _converse.chatboxes.get(muc_jid);
await u.waitUntil(() => (view.model.session.get('connection_status') === converse.ROOMSTATUS.ENTERED)); await u.waitUntil(() => (model.session.get('connection_status') === converse.ROOMSTATUS.ENTERED));
expect(view.model.get('hidden')).toBe(true); expect(model.get('hidden')).toBe(true);
const getSentPresences = () => sent_stanzas.filter(s => s.nodeName === 'presence'); const getSentPresences = () => sent_stanzas.filter(s => s.nodeName === 'presence');
@ -156,8 +156,8 @@ describe("XEP-0437 Room Activity Indicators", function () {
`</presence>` `</presence>`
); );
await u.waitUntil(() => view.model.session.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED); await u.waitUntil(() => model.session.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED);
expect(view.model.get('has_activity')).toBe(false); expect(model.get('has_activity')).toBe(false);
const room_el = await u.waitUntil(() => document.querySelector("converse-rooms-list .available-chatroom")); const room_el = await u.waitUntil(() => document.querySelector("converse-rooms-list .available-chatroom"));
expect(Array.from(room_el.classList).includes('unread-msgs')).toBeFalsy(); expect(Array.from(room_el.classList).includes('unread-msgs')).toBeFalsy();
@ -171,7 +171,7 @@ describe("XEP-0437 Room Activity Indicators", function () {
`); `);
_converse.connection._dataRecv(mock.createRequest(activity_stanza)); _converse.connection._dataRecv(mock.createRequest(activity_stanza));
await u.waitUntil(() => view.model.get('has_activity')); await u.waitUntil(() => model.get('has_activity'));
expect(Array.from(room_el.classList).includes('unread-msgs')).toBeTruthy(); expect(Array.from(room_el.classList).includes('unread-msgs')).toBeTruthy();
done(); done();
})); }));

View File

@ -322,7 +322,7 @@ describe("The Contacts Roster", function () {
_converse.roster.get(jid).presence.set('show', 'online'); _converse.roster.get(jid).presence.set('show', 'online');
jid = mock.cur_names[4].replace(/ /g,'.').toLowerCase() + '@montague.lit'; jid = mock.cur_names[4].replace(/ /g,'.').toLowerCase() + '@montague.lit';
_converse.roster.get(jid).presence.set('show', 'dnd'); _converse.roster.get(jid).presence.set('show', 'dnd');
mock.openControlBox(_converse); await mock.openControlBox(_converse);
const rosterview = document.querySelector('converse-roster'); const rosterview = document.querySelector('converse-roster');
const button = rosterview.querySelector('span[data-type="state"]'); const button = rosterview.querySelector('span[data-type="state"]');
button.click(); button.click();
@ -488,7 +488,7 @@ describe("The Contacts Roster", function () {
await mock.waitForRoster(_converse, 'current', 0); await mock.waitForRoster(_converse, 'current', 0);
const groups = ['Colleagues', 'friends']; const groups = ['Colleagues', 'friends'];
mock.openControlBox(_converse); await mock.openControlBox(_converse);
for (let i=0; i<mock.cur_names.length; i++) { for (let i=0; i<mock.cur_names.length; i++) {
_converse.roster.create({ _converse.roster.create({
jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@montague.lit', jid: mock.cur_names[i].replace(/ /g,'.').toLowerCase() + '@montague.lit',
@ -514,7 +514,7 @@ describe("The Contacts Roster", function () {
mock.initConverse([], {}, async function (done, _converse) { mock.initConverse([], {}, async function (done, _converse) {
await mock.waitForRoster(_converse, 'current', 0); await mock.waitForRoster(_converse, 'current', 0);
mock.openControlBox(_converse); await mock.openControlBox(_converse);
let i=0, j=0; let i=0, j=0;
const groups = { const groups = {
@ -568,8 +568,8 @@ describe("The Contacts Roster", function () {
async function (done, _converse) { async function (done, _converse) {
await mock.waitForRoster(_converse, 'all', 0); await mock.waitForRoster(_converse, 'all', 0);
const rosterview = document.querySelector('converse-roster');
await mock.openControlBox(_converse); await mock.openControlBox(_converse);
const rosterview = document.querySelector('converse-roster');
_converse.roster.create({ _converse.roster.create({
jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit', jid: mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit',
subscription: 'none', subscription: 'none',
@ -1072,7 +1072,7 @@ describe("The Contacts Roster", function () {
async function (done, _converse) { async function (done, _converse) {
await mock.waitForRoster(_converse, "current", 0); await mock.waitForRoster(_converse, "current", 0);
mock.openControlBox(_converse); await mock.openControlBox(_converse);
let names = []; let names = [];
const addName = function (item) { const addName = function (item) {
if (!u.hasClass('request-actions', item)) { if (!u.hasClass('request-actions', item)) {

View File

@ -2,6 +2,13 @@ import { html } from 'lit-html';
import { repeat } from 'lit-html/directives/repeat.js'; import { repeat } from 'lit-html/directives/repeat.js';
import { _converse, api } from '@converse/headless/core'; import { _converse, api } from '@converse/headless/core';
function shouldShowChat (c) {
const { CONTROLBOX_TYPE } = _converse;
return c.get('type') === CONTROLBOX_TYPE || !(c.get('hidden') || c.get('minimized'));
}
export default () => { export default () => {
const { chatboxes, CONTROLBOX_TYPE, CHATROOMS_TYPE, HEADLINES_TYPE } = _converse; const { chatboxes, CONTROLBOX_TYPE, CHATROOMS_TYPE, HEADLINES_TYPE } = _converse;
const view_mode = api.settings.get('view_mode'); const view_mode = api.settings.get('view_mode');
@ -9,7 +16,7 @@ export default () => {
const logged_out = !connection?.connected || !connection?.authenticated || connection?.disconnecting; const logged_out = !connection?.connected || !connection?.authenticated || connection?.disconnecting;
return html` return html`
${view_mode === 'overlayed' ? html`<converse-minimized-chats></converse-minimized-chats>` : ''} ${view_mode === 'overlayed' ? html`<converse-minimized-chats></converse-minimized-chats>` : ''}
${repeat(chatboxes, m => m.get('jid'), m => { ${repeat(chatboxes.filter(shouldShowChat), m => m.get('jid'), m => {
if (m.get('type') === CONTROLBOX_TYPE) { if (m.get('type') === CONTROLBOX_TYPE) {
return html` return html`
${view_mode === 'overlayed' ? html`<converse-controlbox-toggle class="${!m.get('closed') ? 'hidden' : ''}"></converse-controlbox-toggle>` : ''} ${view_mode === 'overlayed' ? html`<converse-controlbox-toggle class="${!m.get('closed') ? 'hidden' : ''}"></converse-controlbox-toggle>` : ''}
@ -20,15 +27,15 @@ export default () => {
`; `;
} else if (m.get('type') === CHATROOMS_TYPE) { } else if (m.get('type') === CHATROOMS_TYPE) {
return html` return html`
<converse-muc jid="${m.get('jid')}" class="chatbox chatroom ${(m.get('hidden') || m.get('minimized')) ? 'hidden' : ''}"></converse-muc> <converse-muc jid="${m.get('jid')}" class="chatbox chatroom"></converse-muc>
`; `;
} else if (m.get('type') === HEADLINES_TYPE) { } else if (m.get('type') === HEADLINES_TYPE) {
return html` return html`
<converse-headlines jid="${m.get('jid')}" class="chatbox headlines ${(m.get('hidden') || m.get('minimized')) ? 'hidden' : ''}"></converse-headlines> <converse-headlines jid="${m.get('jid')}" class="chatbox headlines"></converse-headlines>
`; `;
} else { } else {
return html` return html`
<converse-chat jid="${m.get('jid')}" class="chatbox ${(m.get('hidden') || m.get('minimized')) ? 'hidden' : ''}"></converse-chat> <converse-chat jid="${m.get('jid')}" class="chatbox"></converse-chat>
`; `;
} }
})} })}

View File

@ -118,17 +118,17 @@ converse.plugins.add('converse-minimize', {
_converse.minimize.minimize = minimize; _converse.minimize.minimize = minimize;
_converse.minimize.maximize = maximize; _converse.minimize.maximize = maximize;
function onChatInitialized (model) {
model.on( 'change:minimized', () => onMinimizedChanged(model));
}
/************************ BEGIN Event Handlers ************************/ /************************ BEGIN Event Handlers ************************/
api.listen.on('chatBoxViewInitialized', view => _converse.minimize.trimChats(view)); api.listen.on('chatBoxViewInitialized', view => _converse.minimize.trimChats(view));
api.listen.on('chatRoomViewInitialized', view => _converse.minimize.trimChats(view)); api.listen.on('chatRoomViewInitialized', view => _converse.minimize.trimChats(view));
api.listen.on('chatBoxMaximized', view => _converse.minimize.trimChats(view)); api.listen.on('chatBoxMaximized', view => _converse.minimize.trimChats(view));
api.listen.on('controlBoxOpened', view => _converse.minimize.trimChats(view)); api.listen.on('controlBoxOpened', view => _converse.minimize.trimChats(view));
api.listen.on('chatBoxViewInitialized', v => v.listenTo(v.model, 'change:minimized', () => onMinimizedChanged(v))); api.listen.on('chatBoxInitialized', onChatInitialized);
api.listen.on('chatRoomInitialized', onChatInitialized);
api.listen.on('chatRoomViewInitialized', view => {
view.listenTo(view.model, 'change:minimized', () => onMinimizedChanged(view));
view.model.get('minimized') && view.hide();
});
api.listen.on('getHeadingButtons', (view, buttons) => { api.listen.on('getHeadingButtons', (view, buttons) => {
if (view.model.get('type') === _converse.CHATROOMS_TYPE) { if (view.model.get('type') === _converse.CHATROOMS_TYPE) {

View File

@ -145,13 +145,23 @@ export function maximize (ev, chatbox) {
}); });
} }
export function minimize (ev, chatbox) { export function minimize (ev, model) {
if (ev?.preventDefault) { if (ev?.preventDefault) {
ev.preventDefault(); ev.preventDefault();
} else { } else {
chatbox = ev; model = ev;
} }
u.safeSave(chatbox, { // save the scroll position to restore it on maximize
const view = _converse.chatboxviews.get(model.get('jid'));
const content = view.querySelector('.chat-content__messages');
const scroll = content.scrollTop;
if (model.collection && model.collection.browserStorage) {
model.save({ scroll });
} else {
model.set({ scroll });
}
model.setChatState(_converse.INACTIVE);
u.safeSave(model, {
'hidden': true, 'hidden': true,
'minimized': true, 'minimized': true,
'time_minimized': new Date().toISOString() 'time_minimized': new Date().toISOString()
@ -165,20 +175,18 @@ export function minimize (ev, chatbox) {
* Will trigger {@link _converse#chatBoxMaximized} * Will trigger {@link _converse#chatBoxMaximized}
* @returns {_converse.ChatBoxView|_converse.ChatRoomView} * @returns {_converse.ChatBoxView|_converse.ChatRoomView}
*/ */
function onMaximized (view) { function onMaximized (model) {
if (!view.model.isScrolledUp()) { if (!model.isScrolledUp()) {
view.model.clearUnreadMsgCounter(); model.clearUnreadMsgCounter();
} }
view.model.setChatState(_converse.ACTIVE); model.setChatState(_converse.ACTIVE);
view.show();
/** /**
* Triggered when a previously minimized chat gets maximized * Triggered when a previously minimized chat gets maximized
* @event _converse#chatBoxMaximized * @event _converse#chatBoxMaximized
* @type { _converse.ChatBoxView } * @type { _converse.ChatBoxView }
* @example _converse.api.listen.on('chatBoxMaximized', view => { ... }); * @example _converse.api.listen.on('chatBoxMaximized', view => { ... });
*/ */
api.trigger('chatBoxMaximized', view); api.trigger('chatBoxMaximized', model);
return view;
} }
/** /**
@ -188,29 +196,20 @@ function onMaximized (view) {
* Will trigger {@link _converse#chatBoxMinimized} * Will trigger {@link _converse#chatBoxMinimized}
* @returns {_converse.ChatBoxView|_converse.ChatRoomView} * @returns {_converse.ChatBoxView|_converse.ChatRoomView}
*/ */
function onMinimized (view) { function onMinimized (model) {
// save the scroll position to restore it on maximize
const content = view.querySelector('.chat-content__messages');
if (view.model.collection && view.model.collection.browserStorage) {
view.model.save({ 'scroll': content.scrollTop });
} else {
view.model.set({ 'scroll': content.scrollTop });
}
view.model.setChatState(_converse.INACTIVE);
/** /**
* Triggered when a previously maximized chat gets Minimized * Triggered when a previously maximized chat gets Minimized
* @event _converse#chatBoxMinimized * @event _converse#chatBoxMinimized
* @type { _converse.ChatBoxView } * @type { _converse.ChatBoxView }
* @example _converse.api.listen.on('chatBoxMinimized', view => { ... }); * @example _converse.api.listen.on('chatBoxMinimized', view => { ... });
*/ */
api.trigger('chatBoxMinimized', view); api.trigger('chatBoxMinimized', model);
return view;
} }
export function onMinimizedChanged (view) { export function onMinimizedChanged (model) {
if (view.model.get('minimized')) { if (model.get('minimized')) {
onMinimized(view); onMinimized(model);
} else { } else {
onMaximized(view); onMaximized(model);
} }
} }

View File

@ -13,6 +13,12 @@ export default class BaseChatView extends ElementView {
this.debouncedScrollDown = debounce(this.scrollDown, 100); this.debouncedScrollDown = debounce(this.scrollDown, 100);
} }
disconnectedCallback () {
super.disconnectedCallback();
const jid = this.getAttribute('jid');
_converse.chatboxviews.remove(jid, this);
}
hideNewMessagesIndicator () { hideNewMessagesIndicator () {
const new_msgs_indicator = this.querySelector('.new-msgs-indicator'); const new_msgs_indicator = this.querySelector('.new-msgs-indicator');
if (new_msgs_indicator !== null) { if (new_msgs_indicator !== null) {
@ -195,7 +201,7 @@ export default class BaseChatView extends ElementView {
'scrollTop': null 'scrollTop': null
}); });
} }
this.querySelector('.chat-content__messages').scrollDown(); this.querySelector('.chat-content__messages')?.scrollDown();
this.onScrolledDown(); this.onScrolledDown();
} }