mirror of
https://github.com/thelounge/thelounge
synced 2024-11-10 22:54:15 +00:00
Condense Joins
This commit is contained in:
parent
d87662482b
commit
499dfdfe92
12 changed files with 209 additions and 82 deletions
|
@ -197,6 +197,7 @@ kbd {
|
|||
#settings #play:before,
|
||||
#form #submit:before,
|
||||
#chat .invite .from:before,
|
||||
#chat .condensed .expander:before,
|
||||
#chat .join .from:before,
|
||||
#chat .kick .from:before,
|
||||
#chat .part .from:before,
|
||||
|
@ -284,6 +285,22 @@ kbd {
|
|||
color: #2ecc40;
|
||||
}
|
||||
|
||||
#chat .condensed {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#chat .condensed div {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#chat .condensed .expander:before {
|
||||
content: "\f0d7"; /* http://fontawesome.io/icon/caret-down/ */
|
||||
}
|
||||
|
||||
#chat .condensed.closed .expander:before {
|
||||
content: "\f0da"; /* http://fontawesome.io/icon/caret-right/ */
|
||||
}
|
||||
|
||||
#chat .join .from:before {
|
||||
content: "\f090"; /* http://fontawesome.io/icon/sign-in/ */
|
||||
color: #2ecc40;
|
||||
|
@ -801,6 +818,18 @@ kbd {
|
|||
display: block;
|
||||
}
|
||||
|
||||
#chat .condensed {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#chat .condensed .msg {
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
#chat .condensed.closed .msg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#windows .header .topic,
|
||||
.messages .msg,
|
||||
.sidebar {
|
||||
|
@ -1092,15 +1121,17 @@ kbd {
|
|||
color: #555;
|
||||
}
|
||||
|
||||
#chat.hide-join .join,
|
||||
#chat.hide-mode .mode,
|
||||
#chat.hide-motd .motd,
|
||||
#chat.hide-nick .nick,
|
||||
#chat.hide-part .part,
|
||||
#chat.hide-quit .quit {
|
||||
#chat.hide-optional .join,
|
||||
#chat.hide-optional .mode,
|
||||
#chat.hide-optional .nick,
|
||||
#chat.hide-optional .part,
|
||||
#chat.hide-optional .quit,
|
||||
#chat.hide-optional .condensed,
|
||||
#chat.hide-motd .motd {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#chat .condensed .content,
|
||||
#chat .join .content,
|
||||
#chat .kick .content,
|
||||
#chat .mode .content,
|
||||
|
@ -2130,3 +2161,7 @@ part/quit messages where we don't load previews (adds a blank line otherwise) */
|
|||
#chat table.channel-list .topic {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.hide-text {
|
||||
color: transparent !important;
|
||||
}
|
||||
|
|
|
@ -218,8 +218,14 @@
|
|||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="opt">
|
||||
<input type="checkbox" name="join">
|
||||
Show joins
|
||||
<input type="checkbox" name="optional">
|
||||
Show <abbr title="Joins, parts, kicks, nick changes, and mode changes">status messages</abbr>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="opt">
|
||||
<input type="checkbox" name="condense">
|
||||
Condense <abbr title="Joins, parts, kicks, nick changes, and mode changes">status messages</abbr>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
|
@ -228,30 +234,6 @@
|
|||
Show <abbr title="Message Of The Day">MOTD</abbr>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="opt">
|
||||
<input type="checkbox" name="part">
|
||||
Show parts
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="opt">
|
||||
<input type="checkbox" name="nick">
|
||||
Show nick changes
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="opt">
|
||||
<input type="checkbox" name="mode">
|
||||
Show mode
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="opt">
|
||||
<input type="checkbox" name="quit">
|
||||
Show quits
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<label class="opt">
|
||||
<input type="checkbox" name="showSeconds">
|
||||
|
|
37
client/js/condensed.js
Normal file
37
client/js/condensed.js
Normal file
|
@ -0,0 +1,37 @@
|
|||
"use strict";
|
||||
|
||||
const constants = require("./constants");
|
||||
|
||||
module.exports = {
|
||||
updateText
|
||||
};
|
||||
|
||||
function updateText(condensed, addedTypes) {
|
||||
var obj = {};
|
||||
|
||||
for (var i in constants.condensedTypes) {
|
||||
var msgType = constants.condensedTypes[i];
|
||||
obj[msgType] = condensed.data(msgType) || 0;
|
||||
}
|
||||
|
||||
for (var k in addedTypes) {
|
||||
var added = addedTypes[k];
|
||||
obj[added]++;
|
||||
condensed.data(added, obj[added]);
|
||||
}
|
||||
|
||||
var text = "";
|
||||
|
||||
for (var j in constants.condensedTypes) {
|
||||
var messageType = constants.condensedTypes[j];
|
||||
if (obj[messageType]) {
|
||||
text += text === "" ? "" : ", ";
|
||||
text += obj[messageType] + " " + messageType;
|
||||
if (messageType === "nick" || messageType === "mode") {
|
||||
text += " change";
|
||||
}
|
||||
text += obj[messageType] > 1 ? "s" : "";
|
||||
}
|
||||
}
|
||||
condensed.find(".condensed-msg").text(text);
|
||||
}
|
|
@ -56,6 +56,32 @@ const commands = [
|
|||
"/whois"
|
||||
];
|
||||
|
||||
const actionTypes = [
|
||||
"ban_list",
|
||||
"invite",
|
||||
"join",
|
||||
"mode",
|
||||
"kick",
|
||||
"nick",
|
||||
"part",
|
||||
"quit",
|
||||
"topic",
|
||||
"topic_set_by",
|
||||
"action",
|
||||
"whois",
|
||||
"ctcp",
|
||||
"channel_list",
|
||||
];
|
||||
|
||||
const condensedTypes = [
|
||||
"join",
|
||||
"kick",
|
||||
"mode",
|
||||
"nick",
|
||||
"part",
|
||||
"quit",
|
||||
];
|
||||
|
||||
const timeFormats = {
|
||||
msgDefault: "HH:mm",
|
||||
msgWithSeconds: "HH:mm:ss"
|
||||
|
@ -63,6 +89,8 @@ const timeFormats = {
|
|||
|
||||
module.exports = {
|
||||
colorCodeMap: colorCodeMap,
|
||||
timeFormats: timeFormats,
|
||||
commands: commands
|
||||
commands: commands,
|
||||
condensedTypes: condensedTypes,
|
||||
actionTypes: actionTypes,
|
||||
timeFormats: timeFormats
|
||||
};
|
||||
|
|
|
@ -439,6 +439,14 @@ $(function() {
|
|||
}
|
||||
});
|
||||
|
||||
chat.on("click", ".condensed", function() {
|
||||
$(this).toggleClass("closed");
|
||||
});
|
||||
|
||||
chat.on("click", ".condensed div", function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
chat.on("click", ".user", function() {
|
||||
var name = $(this).data("name");
|
||||
var chan = findCurrentNetworkChan(name);
|
||||
|
@ -707,6 +715,9 @@ $(function() {
|
|||
chat.on("click", ".show-more-button", function() {
|
||||
var self = $(this);
|
||||
var lastMessage = self.parent().next(".messages").children(".msg").first();
|
||||
if (lastMessage.is(".condensed")) {
|
||||
lastMessage = lastMessage.children(".msg").first();
|
||||
}
|
||||
var lastMessageId = parseInt(lastMessage[0].id.replace("msg-", ""), 10);
|
||||
|
||||
self
|
||||
|
|
|
@ -11,16 +11,13 @@ const chat = $("#chat");
|
|||
|
||||
const options = $.extend({
|
||||
coloredNicks: true,
|
||||
condense: true,
|
||||
desktopNotifications: false,
|
||||
join: true,
|
||||
links: true,
|
||||
mode: true,
|
||||
motd: true,
|
||||
nick: true,
|
||||
notification: true,
|
||||
notifyAllMessages: false,
|
||||
part: true,
|
||||
quit: true,
|
||||
optional: true,
|
||||
showSeconds: false,
|
||||
theme: $("#theme").attr("href").replace(/^themes\/(.*).css$/, "$1"), // Extracts default theme name, set on the server configuration
|
||||
thumbnails: true,
|
||||
|
@ -66,15 +63,7 @@ settings.on("change", "input, select, textarea", function() {
|
|||
|
||||
storage.set("settings", JSON.stringify(options));
|
||||
|
||||
if ([
|
||||
"join",
|
||||
"mode",
|
||||
"motd",
|
||||
"nick",
|
||||
"part",
|
||||
"quit",
|
||||
"notifyAllMessages",
|
||||
].indexOf(name) !== -1) {
|
||||
if (name === "optional" || name === "motd") {
|
||||
chat.toggleClass("hide-" + name, !self.prop("checked"));
|
||||
} else if (name === "coloredNicks") {
|
||||
chat.toggleClass("colored-nicks", self.prop("checked"));
|
||||
|
|
|
@ -6,11 +6,14 @@ const options = require("./options");
|
|||
const renderPreview = require("./renderPreview");
|
||||
const utils = require("./utils");
|
||||
const sorting = require("./sorting");
|
||||
const constants = require("./constants");
|
||||
const condense = require("./condensed");
|
||||
|
||||
const chat = $("#chat");
|
||||
const sidebar = $("#sidebar");
|
||||
|
||||
module.exports = {
|
||||
appendMessage,
|
||||
buildChannelMessages,
|
||||
buildChatMessage,
|
||||
renderChannel,
|
||||
|
@ -19,16 +22,39 @@ module.exports = {
|
|||
renderNetworks,
|
||||
};
|
||||
|
||||
function buildChannelMessages(channel, messages) {
|
||||
return messages.reduce(function(docFragment, message) {
|
||||
docFragment.append(buildChatMessage({
|
||||
chan: channel,
|
||||
function buildChannelMessages(data) {
|
||||
return data.messages.reduce(function(docFragment, message) {
|
||||
appendMessage(docFragment, data.id, data.type, message.type, buildChatMessage({
|
||||
chan: data.id,
|
||||
msg: message
|
||||
}));
|
||||
return docFragment;
|
||||
}, $(document.createDocumentFragment()));
|
||||
}
|
||||
|
||||
function appendMessage(container, chan, chanType, messageType, msg) {
|
||||
if (constants.condensedTypes.indexOf(messageType) !== -1 && chanType !== "lobby") {
|
||||
var condensedTypesClasses = "." + constants.condensedTypes.join(", .");
|
||||
var lastChild = container.children("div.msg").last();
|
||||
var lastDate = (new Date(lastChild.attr("data-time"))).toDateString();
|
||||
var msgDate = (new Date(msg.attr("data-time"))).toDateString();
|
||||
if (lastChild && $(lastChild).hasClass("condensed") && !$(msg).hasClass("message") && lastDate === msgDate) {
|
||||
lastChild.append(msg);
|
||||
condense.updateText(lastChild, [messageType]);
|
||||
} else if (lastChild && $(lastChild).is(condensedTypesClasses) && options.condense) {
|
||||
var condensed = buildChatMessage({msg: {type: "condensed", time: msg.attr("data-time"), previews: []}, chan: chan});
|
||||
condensed.append(lastChild);
|
||||
condensed.append(msg);
|
||||
container.append(condensed);
|
||||
condense.updateText(condensed, [messageType, lastChild.attr("data-type")]);
|
||||
} else {
|
||||
container.append(msg);
|
||||
}
|
||||
} else {
|
||||
container.append(msg);
|
||||
}
|
||||
}
|
||||
|
||||
function buildChatMessage(data) {
|
||||
const type = data.msg.type;
|
||||
let target = "#chan-" + data.chan;
|
||||
|
@ -45,25 +71,13 @@ function buildChatMessage(data) {
|
|||
data.msg.highlight = true;
|
||||
}
|
||||
|
||||
if ([
|
||||
"invite",
|
||||
"join",
|
||||
"mode",
|
||||
"kick",
|
||||
"nick",
|
||||
"part",
|
||||
"quit",
|
||||
"topic",
|
||||
"topic_set_by",
|
||||
"action",
|
||||
"whois",
|
||||
"ctcp",
|
||||
"channel_list",
|
||||
"ban_list",
|
||||
].indexOf(type) !== -1) {
|
||||
if (constants.actionTypes.indexOf(type) !== -1) {
|
||||
data.msg.template = "actions/" + type;
|
||||
template = "msg_action";
|
||||
} else if (type === "unhandled") {
|
||||
template = "msg_unhandled";
|
||||
} else if (type === "condensed") {
|
||||
template = "msg_condensed";
|
||||
}
|
||||
|
||||
const msg = $(templates[template](data.msg));
|
||||
|
@ -100,7 +114,7 @@ function renderChannel(data) {
|
|||
}
|
||||
|
||||
function renderChannelMessages(data) {
|
||||
const documentFragment = buildChannelMessages(data.id, data.messages);
|
||||
const documentFragment = buildChannelMessages(data);
|
||||
const channel = chat.find("#chan-" + data.id + " .messages").append(documentFragment);
|
||||
|
||||
if (data.firstUnread > 0) {
|
||||
|
@ -109,6 +123,8 @@ function renderChannelMessages(data) {
|
|||
// TODO: If the message is far off in the history, we still need to append the marker into DOM
|
||||
if (!first.length) {
|
||||
channel.prepend(templates.unread_marker());
|
||||
} else if (first.parent().hasClass("condensed")) {
|
||||
first.parent().before(templates.unread_marker());
|
||||
} else {
|
||||
first.before(templates.unread_marker());
|
||||
}
|
||||
|
@ -129,6 +145,10 @@ function renderChannelMessages(data) {
|
|||
}
|
||||
|
||||
if (lastDate.toDateString() !== msgDate.toDateString()) {
|
||||
var parent = msg.parent();
|
||||
if (parent.hasClass("condensed")) {
|
||||
msg.insertAfter(parent);
|
||||
}
|
||||
msg.before(templates.date_marker({msgDate: msgDate}));
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ const chat = $("#chat");
|
|||
const templates = require("../../views");
|
||||
|
||||
socket.on("more", function(data) {
|
||||
const documentFragment = render.buildChannelMessages(data.chan, data.messages);
|
||||
const documentFragment = render.buildChannelMessages(data);
|
||||
const chan = chat
|
||||
.find("#chan-" + data.chan)
|
||||
.find(".messages");
|
||||
|
@ -24,6 +24,8 @@ socket.on("more", function(data) {
|
|||
} else if (children.eq(1).hasClass("date-marker-container")) {
|
||||
// The unread-marker could be at index 0, which will cause the date-marker to become "stuck"
|
||||
children.eq(1).remove();
|
||||
} else if (children.eq(0).hasClass("condensed") && children.eq(0).children(".date-marker-container").eq(0).hasClass("date-marker-container")) {
|
||||
children.eq(0).children(".date-marker-container").eq(0).remove();
|
||||
}
|
||||
|
||||
// Add the older messages
|
||||
|
@ -52,6 +54,10 @@ socket.on("more", function(data) {
|
|||
}
|
||||
|
||||
if (lastDate.toDateString() !== msgDate.toDateString()) {
|
||||
var parent = msg.parent();
|
||||
if (parent.hasClass("condensed")) {
|
||||
msg.insertAfter(parent);
|
||||
}
|
||||
msg.before(templates.date_marker({msgDate: msgDate}));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,9 @@ const templates = require("../../views");
|
|||
|
||||
socket.on("msg", function(data) {
|
||||
const msg = render.buildChatMessage(data);
|
||||
const target = data.chan;
|
||||
const channel = chat.find("#chan-" + target);
|
||||
const targetId = data.chan;
|
||||
const target = "#chan-" + targetId;
|
||||
const channel = chat.find(target);
|
||||
const container = channel.find(".messages");
|
||||
|
||||
const activeChannelId = chat.find(".chan.active").data("id");
|
||||
|
@ -19,7 +20,7 @@ socket.on("msg", function(data) {
|
|||
}
|
||||
|
||||
// Check if date changed
|
||||
const prevMsg = $(container.find(".msg")).last();
|
||||
let prevMsg = $(container.find(".msg")).last();
|
||||
const prevMsgTime = new Date(prevMsg.attr("data-time"));
|
||||
const msgTime = new Date(msg.attr("data-time"));
|
||||
|
||||
|
@ -29,17 +30,26 @@ socket.on("msg", function(data) {
|
|||
}
|
||||
|
||||
if (prevMsgTime.toDateString() !== msgTime.toDateString()) {
|
||||
var parent = prevMsg.parent();
|
||||
if (parent.hasClass("condensed")) {
|
||||
prevMsg = parent;
|
||||
}
|
||||
prevMsg.after(templates.date_marker({msgDate: msgTime}));
|
||||
}
|
||||
|
||||
// Add message to the container
|
||||
container
|
||||
.append(msg)
|
||||
.trigger("msg", [
|
||||
"#chan-" + target,
|
||||
data
|
||||
])
|
||||
.trigger("keepToBottom");
|
||||
render.appendMessage(
|
||||
container,
|
||||
data.chan,
|
||||
$(target).attr("data-type"),
|
||||
data.msg.type,
|
||||
msg
|
||||
);
|
||||
|
||||
container.trigger("msg", [
|
||||
target,
|
||||
data
|
||||
]).trigger("keepToBottom");
|
||||
|
||||
var lastVisible = container.find("div:visible").last();
|
||||
if (data.msg.self
|
||||
|
@ -52,7 +62,7 @@ socket.on("msg", function(data) {
|
|||
}
|
||||
|
||||
// Message arrived in a non active channel, trim it to 100 messages
|
||||
if (activeChannelId !== target && container.find(".msg").slice(0, -100).remove().length) {
|
||||
if (activeChannelId !== targetId && container.find(".msg").slice(0, -100).remove().length) {
|
||||
channel.find(".show-more").addClass("show");
|
||||
|
||||
// Remove date-seperators that would otherwise
|
||||
|
|
|
@ -25,6 +25,7 @@ module.exports = {
|
|||
date_marker: require("./date-marker.tpl"),
|
||||
msg: require("./msg.tpl"),
|
||||
msg_action: require("./msg_action.tpl"),
|
||||
msg_condensed: require("./msg_condensed.tpl"),
|
||||
msg_preview: require("./msg_preview.tpl"),
|
||||
msg_preview_toggle: require("./msg_preview_toggle.tpl"),
|
||||
msg_unhandled: require("./msg_unhandled.tpl"),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<div class="msg {{type}}{{#if self}} self{{/if}}{{#if highlight}} highlight{{/if}}" id="msg-{{id}}" data-time="{{time}}">
|
||||
<div class="msg {{type}}{{#if self}} self{{/if}}{{#if highlight}} highlight{{/if}}"
|
||||
data-type="{{type}}" id="msg-{{id}}" data-time="{{time}}">
|
||||
<span class="time tooltipped tooltipped-e" aria-label="{{localetime time}}">
|
||||
{{tz time}}
|
||||
</span>
|
||||
|
|
7
client/views/msg_condensed.tpl
Normal file
7
client/views/msg_condensed.tpl
Normal file
|
@ -0,0 +1,7 @@
|
|||
<div class="msg {{type}} closed" data-time="{{time}}">
|
||||
<span class="time hide-text">{{tz time}}</span>
|
||||
<span class="from"><span class="expander"></span></span>
|
||||
<span class="content">
|
||||
<span class="text condensed-msg"></span>
|
||||
</span>
|
||||
</div>
|
Loading…
Reference in a new issue