Some refactoring of the code that collapses leave/join messages

Mostly to match any previous leave/join message from the same user

Fixes #1062
This commit is contained in:
JC Brand 2018-10-13 13:23:55 +02:00
parent 7b9c97dfd3
commit 7270abb08b
5 changed files with 159 additions and 168 deletions

View File

@ -2,9 +2,10 @@
## 4.0.3 (Unreleased)
- Reduce join/leave clutter by removing subsequent ones (without text messages in between)
- Bugfix. Handler not triggered when submitting MUC password form 2nd time
- Bugfix. MUC features weren't being refreshed when saving the config form
- #537 Render `xmpp:` URI as link
- #1062 Collapse multiple join/leave messages into one
- #1063 URLs in the topic / subject are not clickable
- #1140 Add support for destroyed chatrooms
- #1169 Non-joined participants display an unwanted status message

View File

@ -10770,7 +10770,9 @@ body.reset {
font-style: italic; }
#conversejs .message.chat-info.chat-event {
clear: left;
font-style: italic; }
font-style: italic;
font-size: 90%;
padding: 0.17rem 1rem; }
#conversejs .message.chat-info.chat-error {
color: #D24E2B;
font-weight: bold; }

156
dist/converse.js vendored
View File

@ -70015,6 +70015,31 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
}
},
getPreviousJoinOrLeaveNotification(el, nick) {
/* Working backwards, get the first join/leave notification
* from the same user, on the same day and BEFORE any chat
* messages were received.
*/
while (!_.isNil(el)) {
const data = _.get(el, 'dataset', {});
if (!_.includes(_.get(el, 'classList', []), 'chat-info')) {
return;
}
if (!moment(el.getAttribute('data-isodate')).isSame(new Date(), "day")) {
el = el.previousElementSibling;
continue;
}
if (data.join === nick || data.leave === nick || data.leavejoin === nick || data.joinleave === nick) {
return el;
}
el = el.previousElementSibling;
}
},
showJoinNotification(occupant) {
if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
return;
@ -70022,21 +70047,30 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
const nick = occupant.get('nick'),
stat = occupant.get('status'),
last_leave_el = this.getImmediateNotification(this.content.lastElementChild, nick, 'leave');
prev_info_el = this.getPreviousJoinOrLeaveNotification(this.content.lastElementChild, nick),
data = _.get(prev_info_el, 'dataset', {});
if (_.includes(_.get(last_leave_el, 'classList', []), 'chat-info') && _.get(last_leave_el, 'dataset', {}).leave === nick) {
let el = this.content.lastElementChild;
el.insertAdjacentElement('afterend', last_leave_el);
last_leave_el.outerHTML = tpl_info({
if (data.leave === nick) {
let message;
if (_.isNil(stat)) {
message = __('%1$s has left and re-entered the groupchat', nick);
} else {
message = __('%1$s has left and re-entered the groupchat. "%2$s"', nick, stat);
}
const data = {
'data_name': 'leavejoin',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': __('%1$s has left and re-entered the groupchat', nick)
});
el = this.content.lastElementChild;
'message': message
};
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
const el = this.content.lastElementChild;
setTimeout(() => u.addClass('fade-out', el), 5000);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5500);
} else {
let message;
@ -70054,45 +70088,18 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'message': message
};
if (_.includes(_.get(last_leave_el, 'classList', []), 'chat-info') && _.get(last_leave_el, 'dataset', {}).joinleave === nick) {
last_leave_el.outerHTML = tpl_info(data);
if (prev_info_el) {
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
} else {
const el = u.stringToElement(tpl_info(data));
this.content.insertAdjacentElement('beforeend', el);
this.insertDayIndicator(el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
this.insertDayIndicator(this.content.lastElementChild);
}
}
this.scrollDown();
},
getImmediateNotification(el, nick, type = 'join') {
while (!_.isNil(el)) {
const data = _.get(el, 'dataset', {});
if (!_.includes(_.get(el, 'classList', []), 'chat-info')) {
return;
}
if (!moment(el.getAttribute('data-isodate')).isSame(new Date(), "day")) {
el = el.previousElementSibling;
continue;
}
if (type === 'join') {
if (data.join === nick || data.leavejoin === nick) {
return el;
}
} else {
if (data.leave === nick || data.joinleave === nick) {
return el;
}
}
el = el.previousElementSibling;
}
},
showLeaveNotification(occupant) {
if (_.includes(occupant.get('states'), '303') || _.includes(occupant.get('states'), '307')) {
return;
@ -70100,46 +70107,30 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
const nick = occupant.get('nick'),
stat = occupant.get('status'),
last_join_el = this.getImmediateNotification(this.content.lastElementChild, nick, 'join'),
data = _.get(last_join_el, 'dataset', {});
prev_info_el = this.getPreviousJoinOrLeaveNotification(this.content.lastElementChild, nick),
dataset = _.get(prev_info_el, 'dataset', {});
if (last_join_el) {
if (dataset.join === nick) {
let message;
if (data.join === nick) {
if (_.isNil(stat)) {
message = __('%1$s has entered and left the groupchat', nick);
} else {
message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
}
let el = this.content.lastElementChild;
el.insertAdjacentElement('afterend', last_join_el);
last_join_el.outerHTML = tpl_info({
'data_name': 'joinleave',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': message
});
el = this.content.lastElementChild;
setTimeout(() => u.addClass('fade-out', el), 5000);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
} else if (data.leavejoin === nick) {
if (_.isNil(stat)) {
message = __('%1$s has left the groupchat', nick);
} else {
message = __('%1$s has left the groupchat. "%2$s"', nick, stat);
}
last_join_el.outerHTML = tpl_info({
'data_name': 'leave',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': message
});
if (_.isNil(stat)) {
message = __('%1$s has entered and left the groupchat', nick);
} else {
message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
}
const data = {
'data_name': 'joinleave',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': message
};
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
const el = this.content.lastElementChild;
setTimeout(() => u.addClass('fade-out', el), 5000);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5500);
} else {
let message;
@ -70156,9 +70147,14 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
'data_name': 'leave',
'data_value': nick
};
const el = u.stringToElement(tpl_info(data));
this.content.insertAdjacentElement('beforeend', el);
this.insertDayIndicator(el);
if (prev_info_el) {
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
} else {
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
this.insertDayIndicator(this.content.lastElementChild);
}
}
this.scrollDown();

View File

@ -48,6 +48,8 @@
&.chat-event {
clear: left;
font-style: italic;
font-size: 90%;
padding: 0.17rem 1rem
}
&.chat-error {
color: $warning-color;

View File

@ -1498,32 +1498,60 @@
}
},
getPreviousJoinOrLeaveNotification (el, nick) {
/* Working backwards, get the first join/leave notification
* from the same user, on the same day and BEFORE any chat
* messages were received.
*/
while (!_.isNil(el)) {
const data = _.get(el, 'dataset', {});
if (!_.includes(_.get(el, 'classList', []), 'chat-info')) {
return;
}
if (!moment(el.getAttribute('data-isodate')).isSame(new Date(), "day")) {
el = el.previousElementSibling;
continue;
}
if (data.join === nick ||
data.leave === nick ||
data.leavejoin === nick ||
data.joinleave === nick) {
return el;
}
el = el.previousElementSibling;
}
},
showJoinNotification (occupant) {
if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
return;
}
const nick = occupant.get('nick'),
stat = occupant.get('status'),
last_leave_el = this.getImmediateNotification(this.content.lastElementChild, nick, 'leave');
prev_info_el = this.getPreviousJoinOrLeaveNotification(this.content.lastElementChild, nick),
data = _.get(prev_info_el, 'dataset', {});
if (_.includes(_.get(last_leave_el, 'classList', []), 'chat-info') &&
_.get(last_leave_el, 'dataset', {}).leave === nick) {
let el = this.content.lastElementChild;
el.insertAdjacentElement('afterend', last_leave_el);
last_leave_el.outerHTML =
tpl_info({
'data_name': 'leavejoin',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': __('%1$s has left and re-entered the groupchat', nick)
});
el = this.content.lastElementChild;
if (data.leave === nick) {
let message;
if (_.isNil(stat)) {
message = __('%1$s has left and re-entered the groupchat', nick);
} else {
message = __('%1$s has left and re-entered the groupchat. "%2$s"', nick, stat);
}
const data = {
'data_name': 'leavejoin',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': message
};
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
const el = this.content.lastElementChild;
setTimeout(() => u.addClass('fade-out', el), 5000);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5500);
} else {
let message;
let message;
if (_.isNil(stat)) {
message = __('%1$s has entered the groupchat', nick);
} else {
@ -1536,87 +1564,45 @@
'extra_classes': 'chat-event',
'message': message
};
if (_.includes(_.get(last_leave_el, 'classList', []), 'chat-info') &&
_.get(last_leave_el, 'dataset', {}).joinleave === nick) {
last_leave_el.outerHTML = tpl_info(data);
if (prev_info_el) {
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
} else {
const el = u.stringToElement(tpl_info(data));
this.content.insertAdjacentElement('beforeend', el);
this.insertDayIndicator(el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
this.insertDayIndicator(this.content.lastElementChild);
}
}
this.scrollDown();
},
getImmediateNotification (el, nick, type='join') {
while (!_.isNil(el)) {
const data = _.get(el, 'dataset', {});
if (!_.includes(_.get(el, 'classList', []), 'chat-info')) {
return;
}
if (!moment(el.getAttribute('data-isodate')).isSame(new Date(), "day")) {
el = el.previousElementSibling;
continue;
}
if (type === 'join') {
if (data.join === nick || data.leavejoin === nick) {
return el;
}
} else {
if (data.leave === nick || data.joinleave === nick) {
return el;
}
}
el = el.previousElementSibling;
}
},
showLeaveNotification (occupant) {
if (_.includes(occupant.get('states'), '303') || _.includes(occupant.get('states'), '307')) {
return;
}
const nick = occupant.get('nick'),
stat = occupant.get('status'),
last_join_el = this.getImmediateNotification(this.content.lastElementChild, nick, 'join'),
data = _.get(last_join_el, 'dataset', {});
prev_info_el = this.getPreviousJoinOrLeaveNotification(this.content.lastElementChild, nick),
dataset = _.get(prev_info_el, 'dataset', {});
if (last_join_el) {
if (dataset.join === nick) {
let message;
if (data.join === nick) {
if (_.isNil(stat)) {
message = __('%1$s has entered and left the groupchat', nick);
} else {
message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
}
let el = this.content.lastElementChild;
el.insertAdjacentElement('afterend', last_join_el);
last_join_el.outerHTML =
tpl_info({
'data_name': 'joinleave',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': message
});
el = this.content.lastElementChild;
setTimeout(() => u.addClass('fade-out', el), 5000);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5250);
} else if (data.leavejoin === nick) {
if (_.isNil(stat)) {
message = __('%1$s has left the groupchat', nick);
} else {
message = __('%1$s has left the groupchat. "%2$s"', nick, stat);
}
last_join_el.outerHTML =
tpl_info({
'data_name': 'leave',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': message
});
if (_.isNil(stat)) {
message = __('%1$s has entered and left the groupchat', nick);
} else {
message = __('%1$s has entered and left the groupchat. "%2$s"', nick, stat);
}
const data = {
'data_name': 'joinleave',
'data_value': nick,
'isodate': moment().format(),
'extra_classes': 'chat-event',
'message': message
};
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
const el = this.content.lastElementChild;
setTimeout(() => u.addClass('fade-out', el), 5000);
setTimeout(() => el.parentElement && el.parentElement.removeChild(el), 5500);
} else {
let message;
if (_.isNil(stat)) {
@ -1631,9 +1617,13 @@
'data_name': 'leave',
'data_value': nick
}
const el = u.stringToElement(tpl_info(data));
this.content.insertAdjacentElement('beforeend', el);
this.insertDayIndicator(el);
if (prev_info_el) {
this.content.removeChild(prev_info_el);
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
} else {
this.content.insertAdjacentHTML('beforeend', tpl_info(data));
this.insertDayIndicator(this.content.lastElementChild);
}
}
this.scrollDown();
},