Add resize functionality to occupants-list in MUC.

This adds the ability to resize the MUC-Member-List in all MUCs. The
MUC-Member-List can be scaled between 20% width of the MUC and 75% of
the MUC.
This commit is contained in:
ndoell 2019-09-25 08:15:36 +02:00
parent 1f673b7aae
commit b94e5653a9
8 changed files with 194 additions and 58 deletions

View File

@ -2,6 +2,7 @@
## 6.0.0 (Unreleased)
- Add: Resizing of the occupants-list in Multi-User-Chats
- #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
- #1089: When filtering the roster for `online` users, show all non-offline users.

View File

@ -386,7 +386,8 @@
height: 5px;
width: 100%;
}
&-left {
&-left,
&-occupants-left {
cursor: w-resize;
width: 5px;
height: 100%;

View File

@ -155,6 +155,8 @@
display: flex;
flex-direction: column;
word-wrap: break-word;
flex: 0 1 100%;
min-width: 25%;
.new-msgs-indicator {
background-color: var(--chatroom-head-color);
}
@ -173,7 +175,9 @@
border-left: var(--occupants-border-left);
border-bottom-right-radius: var(--chatbox-border-radius);
padding: 0.5em;
max-width: var(--occupants-max-width);
max-width: 75%;
min-width: 20%;
flex: 0 0 25%;
.occupants-header {
display: flex;

View File

@ -36,7 +36,7 @@ converse.plugins.add('converse-dragresize', {
*
* NB: These plugins need to have already been loaded via require.js.
*/
dependencies: ["converse-chatview", "converse-headline", "converse-muc-views"],
dependencies: ["converse-chatview", "converse-headline", "converse-muc-views", "converse-mouse-events"],
enabled (_converse) {
return _converse.view_mode == 'overlayed';
@ -146,7 +146,6 @@ converse.plugins.add('converse-dragresize', {
'allow_dragresize': true,
});
const dragResizable = {
initDragResize () {
@ -182,7 +181,7 @@ converse.plugins.add('converse-dragresize', {
return this;
},
resizeChatBox (ev) {
resize (ev) {
let diff;
if (_converse.resizing.direction.indexOf('top') === 0) {
diff = ev.pageY - this.prev_pageY;
@ -314,59 +313,7 @@ converse.plugins.add('converse-dragresize', {
};
Object.assign(_converse.ChatBoxView.prototype, dragResizable);
_converse.applyDragResistance = function (value, default_value) {
/* This method applies some resistance around the
* default_value. If value is close enough to
* default_value, then default_value is returned instead.
*/
if (value === undefined) {
return undefined;
} else if (default_value === undefined) {
return value;
}
const resistance = 10;
if ((value !== default_value) &&
(Math.abs(value- default_value) < resistance)) {
return default_value;
}
return value;
};
/************************ BEGIN Event Handlers ************************/
function registerGlobalEventHandlers () {
document.addEventListener('mousemove', function (ev) {
if (!_converse.resizing || !_converse.allow_dragresize) { return true; }
ev.preventDefault();
_converse.resizing.chatbox.resizeChatBox(ev);
});
document.addEventListener('mouseup', function (ev) {
if (!_converse.resizing || !_converse.allow_dragresize) { return true; }
ev.preventDefault();
const height = _converse.applyDragResistance(
_converse.resizing.chatbox.height,
_converse.resizing.chatbox.model.get('default_height')
);
const width = _converse.applyDragResistance(
_converse.resizing.chatbox.width,
_converse.resizing.chatbox.model.get('default_width')
);
if (_converse.api.connection.connected()) {
_converse.resizing.chatbox.model.save({'height': height});
_converse.resizing.chatbox.model.save({'width': width});
} else {
_converse.resizing.chatbox.model.set({'height': height});
_converse.resizing.chatbox.model.set({'width': width});
}
_converse.resizing = null;
});
}
_converse.api.listen.on('registeredGlobalEventHandlers', registerGlobalEventHandlers);
_converse.api.listen.on('beforeShowingChatView', view => view.initDragResize().setDimensions());
/************************ END Event Handlers ************************/
}
});

View File

@ -0,0 +1,91 @@
// Converse.js (A browser based XMPP chat client)
// https://conversejs.org
//
// Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
// Licensed under the Mozilla Public License (MPLv2)
//
import "converse-chatview";
import "converse-controlbox";
import converse from "@converse/headless/converse-core";
const { _ } = converse.env;
converse.plugins.add('converse-mouse-events', {
dependencies: ["converse-chatview", "converse-headline", "converse-muc-views"],
enabled (_converse) {
return _converse.view_mode == 'overlayed' ||
_converse.allow_occupants_view_resizing;
},
initialize () {
const { _converse } = this;
_converse.applyDragResistance = function (value, default_value) {
if (_.isUndefined(value)) {
return undefined;
} else if (_.isUndefined(default_value)) {
return value;
}
const resistance = 10;
if ((value !== default_value) &&
(Math.abs(value - default_value) < resistance)) {
return default_value;
}
return value;
};
function registerGlobalEventHandlers () {
document.addEventListener('mousemove', function (ev) {
if (!_converse.resizing ||
(!_converse.allow_dragresize && !_converse.allow_occupants_view_resizing)) {
return true;
}
ev.preventDefault();
_converse.resizing.chatbox.resize(ev);
});
document.addEventListener('mouseup', function (ev) {
if (!_converse.resizing ||
(!_converse.allow_dragresize && !_converse.allow_occupants_view_resizing)) {
return true;
}
ev.preventDefault();
const height = _converse.applyDragResistance(
_converse.resizing.chatbox.height,
_converse.resizing.chatbox.model.get('default_height')
);
const width = _converse.applyDragResistance(
_converse.resizing.chatbox.width,
_converse.resizing.chatbox.model.get('default_width')
);
if (_converse.resizing.width_occupants) {
if (_converse.connection.connected) {
_converse.resizing.chatbox.chatroomview.model.save({'width_occupants': _converse.resizing.width_occupants});
} else {
_converse.resizing.chatbox.chatroomview.model.set({'width_occupants': _converse.resizing.width_occupants});
}
} else {
if (_converse.api.connection.connected()) {
_converse.resizing.chatbox.model.save({'height': height});
_converse.resizing.chatbox.model.save({'width': width});
} else {
if (_converse.connection.connected) {
_converse.resizing.chatbox.model.save({'height': height});
_converse.resizing.chatbox.model.save({'width': width});
} else {
_converse.resizing.chatbox.model.set({'height': height});
_converse.resizing.chatbox.model.set({'width': width});
}
}
}
_converse.resizing = null;
});
}
_converse.api.listen.on('registeredGlobalEventHandlers', registerGlobalEventHandlers);
}
});

View File

@ -1942,6 +1942,9 @@ converse.plugins.add('converse-muc-views', {
listItems: 'model',
sortEvent: 'change:role',
listSelector: '.occupant-list',
events: {
'mousedown .dragresize-occupants-left': 'onStartHorizontalResizeOccupants',
},
ItemView: _converse.ChatRoomOccupantView,
@ -1971,6 +1974,12 @@ converse.plugins.add('converse-muc-views', {
_converse.api.waitUntil('rosterContactsFetched').then(() => this.renderInviteWidget());
}
this.setVisibility();
this.renderDragResizeHandles();
this.is_maximum = false;
this.is_minimum = false;
return this.renderRoomFeatures();
},
@ -2097,7 +2106,78 @@ converse.plugins.add('converse-muc-views', {
this.invite_auto_complete.on('suggestion-box-open', () => {
this.invite_auto_complete.ul.setAttribute('style', `max-height: calc(${this.el.offsetHeight}px - 80px);`);
});
},
renderDragResizeHandles () {
const flyout = this.el;
const div = document.createElement('div');
div.innerHTML = '<div class="dragresize dragresize-occupants-left"></div>';
flyout.insertBefore(
div,
flyout.firstChild
);
},
onStartHorizontalResizeOccupants (ev) {
const flyout = this.el,
style = window.getComputedStyle(flyout);
this.width = parseInt(style.width.replace(/px$/, ''), 10);
_converse.resizing = {
'chatbox': this,
'direction': 'left'
};
this.prev_pageX = ev.pageX;
},
resize (ev) {
if (_.includes(_converse.resizing.direction, 'left')) {
this.change_in_pixel = (this.prev_pageX - ev.pageX);
this.resizeOccupantsView(this.change_in_pixel, ev.pageX);
this.prev_pageX = ev.pageX;
}
},
resizeOccupantsView (change_in_pixel, current_mouse_position) {
const element_position = this.el.getBoundingClientRect();
// has mouse reached the minimum to the right
if (this.is_minimum) {
this.is_minimum = element_position.left < current_mouse_position;
} // has mouse reached the maximum to the left
else if (this.is_maximum) {
this.is_maximum = element_position.left > current_mouse_position;
} // Scale is within the boundaries
else {
const occupants_width_pixel = this.calculateOccupantsWithInPixel(element_position, change_in_pixel);
this.el.style.flex = "0 0 " + occupants_width_pixel + "px";
_converse.resizing.width_occupants = occupants_width_pixel;
}
},
calculateOccupantsWithInPixel (element_position, change_in_pixel) {
let occupants_width_pixel = element_position.width + change_in_pixel;
const chatroom_width_pixel = this.el.parentElement.clientWidth;
// keeping display in boundaries
if (occupants_width_pixel < (chatroom_width_pixel * 0.20)) {
// set pixel to 20% width
occupants_width_pixel = (chatroom_width_pixel * 0.20);
this.is_minimum = true;
} else if (occupants_width_pixel > (chatroom_width_pixel * 0.75)) {
// set pixel to 75% width
occupants_width_pixel = (chatroom_width_pixel * 0.75);
this.is_maximum = true;
} else if ((chatroom_width_pixel - occupants_width_pixel) < 250) {
// resize occupants if chat-area becomes smaller than 250px (min-width property set in css)
occupants_width_pixel = chatroom_width_pixel - 250;
this.is_maximum = true;
} else {
this.is_maximum = false;
this.is_minimum = false;
}
return occupants_width_pixel;
},
});
@ -2178,6 +2258,15 @@ converse.plugins.add('converse-muc-views', {
fetchAndSetMUCDomain(view);
view.model.on('change:connected', () => fetchAndSetMUCDomain(view));
});
_converse.api.listen.on('beforeShowingChatView', (chatroomview) => {
const occupants_width_pixel = chatroomview.model.get('width_occupants');
const occupants_view = chatroomview.el.querySelector('.occupants');
if (occupants_view && occupants_width_pixel !== undefined) {
occupants_view.style.flex = "0 0 " + occupants_width_pixel + "px";
}
});
/************************ END Event Handlers ************************/

View File

@ -20,6 +20,7 @@ import "converse-fullscreen";
import "converse-mam-views";
import "converse-minimize"; // Allows chat boxes to be minimized
import "converse-muc-views"; // Views related to MUC
import "converse-mouse-events";
import "converse-headlines-view";
import "converse-notification"; // HTML5 Notifications
import "converse-omemo";
@ -51,6 +52,7 @@ const WHITELISTED_PLUGINS = [
'converse-minimize',
'converse-modal',
'converse-muc-views',
'converse-mouse-events',
'converse-headlines-view',
'converse-notification',
'converse-omemo',

View File

@ -234,6 +234,7 @@ _converse.default_connection_options = {'explicitResourceBinding': true};
// ----------------------------
_converse.default_settings = {
allow_non_roster_messaging: false,
allow_occupants_view_resizing: false,
authentication: 'login', // Available values are "login", "prebind", "anonymous" and "external".
auto_away: 0, // Seconds after which user status is set to 'away'
auto_login: false, // Currently only used in connection with anonymous login