2017-05-18 20:08:54 +00:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const $ = require("jquery");
|
|
|
|
const templates = require("../views");
|
|
|
|
const options = require("./options");
|
2017-07-06 06:16:01 +00:00
|
|
|
const renderPreview = require("./renderPreview");
|
2017-05-18 20:08:54 +00:00
|
|
|
const utils = require("./utils");
|
2017-06-22 20:08:36 +00:00
|
|
|
const constants = require("./constants");
|
2017-08-19 18:47:23 +00:00
|
|
|
const condensed = require("./condensed");
|
2017-12-21 20:40:50 +00:00
|
|
|
const JoinChannel = require("./join-channel");
|
2018-07-08 09:09:33 +00:00
|
|
|
const {vueApp} = require("./vue");
|
2017-05-18 20:08:54 +00:00
|
|
|
|
|
|
|
module.exports = {
|
2017-07-06 06:16:01 +00:00
|
|
|
renderNetworks,
|
2017-11-23 14:23:32 +00:00
|
|
|
trimMessageInChannel,
|
2017-05-18 20:08:54 +00:00
|
|
|
};
|
|
|
|
|
2017-08-24 13:50:47 +00:00
|
|
|
function appendMessage(container, chanId, chanType, msg) {
|
2017-08-28 15:03:27 +00:00
|
|
|
if (utils.lastMessageId < msg.id) {
|
|
|
|
utils.lastMessageId = msg.id;
|
|
|
|
}
|
|
|
|
|
2018-07-08 12:18:17 +00:00
|
|
|
return;
|
|
|
|
|
2017-09-01 11:43:24 +00:00
|
|
|
let lastChild = container.children(".msg, .date-marker-container").last();
|
2017-09-04 16:52:02 +00:00
|
|
|
const renderedMessage = buildChatMessage(msg);
|
2017-08-24 13:50:47 +00:00
|
|
|
|
|
|
|
// Check if date changed
|
|
|
|
const msgTime = new Date(msg.time);
|
2017-09-01 11:43:24 +00:00
|
|
|
const prevMsgTime = new Date(lastChild.data("time"));
|
2017-08-24 13:50:47 +00:00
|
|
|
|
|
|
|
// Insert date marker if date changed compared to previous message
|
|
|
|
if (prevMsgTime.toDateString() !== msgTime.toDateString()) {
|
2017-09-04 16:52:02 +00:00
|
|
|
lastChild = $(templates.date_marker({time: msg.time}));
|
2017-09-01 11:43:24 +00:00
|
|
|
container.append(lastChild);
|
2017-08-24 13:50:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If current window is not a channel or this message is not condensable,
|
|
|
|
// then just append the message to container and be done with it
|
2018-03-21 12:48:07 +00:00
|
|
|
if (msg.self || msg.highlight || constants.condensedTypes.indexOf(msg.type) === -1 || chanType !== "channel") {
|
2017-08-24 13:50:47 +00:00
|
|
|
container.append(renderedMessage);
|
2017-08-19 18:47:23 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-06 12:07:43 +00:00
|
|
|
const obj = {};
|
|
|
|
obj[msg.type] = 1;
|
|
|
|
|
2017-08-24 13:50:47 +00:00
|
|
|
// If the previous message is already condensed,
|
|
|
|
// we just append to it and update text
|
|
|
|
if (lastChild.hasClass("condensed")) {
|
|
|
|
lastChild.append(renderedMessage);
|
2017-12-06 12:07:43 +00:00
|
|
|
condensed.updateText(lastChild, obj);
|
2017-08-30 12:43:31 +00:00
|
|
|
return;
|
2017-06-22 20:08:36 +00:00
|
|
|
}
|
2017-08-30 12:43:31 +00:00
|
|
|
|
2017-09-01 11:43:24 +00:00
|
|
|
// Always create a condensed container
|
2017-09-04 16:52:02 +00:00
|
|
|
const newCondensed = $(templates.msg_condensed({time: msg.time}));
|
2017-08-30 12:43:31 +00:00
|
|
|
|
2017-12-06 12:07:43 +00:00
|
|
|
condensed.updateText(newCondensed, obj);
|
2017-08-30 12:43:31 +00:00
|
|
|
newCondensed.append(renderedMessage);
|
|
|
|
container.append(newCondensed);
|
2017-06-22 20:08:36 +00:00
|
|
|
}
|
|
|
|
|
2017-09-04 16:52:02 +00:00
|
|
|
function buildChatMessage(msg) {
|
2017-08-24 13:50:47 +00:00
|
|
|
const type = msg.type;
|
2017-05-18 20:08:54 +00:00
|
|
|
let template = "msg";
|
|
|
|
|
2017-07-21 08:35:05 +00:00
|
|
|
// See if any of the custom highlight regexes match
|
2017-08-24 13:50:47 +00:00
|
|
|
if (!msg.highlight && !msg.self
|
2017-07-21 08:35:05 +00:00
|
|
|
&& options.highlightsRE
|
|
|
|
&& (type === "message" || type === "notice")
|
2017-08-24 13:50:47 +00:00
|
|
|
&& options.highlightsRE.exec(msg.text)) {
|
|
|
|
msg.highlight = true;
|
2017-05-18 20:08:54 +00:00
|
|
|
}
|
|
|
|
|
2018-02-13 11:05:33 +00:00
|
|
|
if (typeof templates.actions[type] !== "undefined") {
|
2017-05-18 20:08:54 +00:00
|
|
|
template = "msg_action";
|
|
|
|
} else if (type === "unhandled") {
|
|
|
|
template = "msg_unhandled";
|
|
|
|
}
|
|
|
|
|
2018-07-09 05:30:51 +00:00
|
|
|
// Make the MOTDs a little nicer if possible
|
|
|
|
if (msg.type === "motd") {
|
|
|
|
let lines = msg.text.split("\n");
|
|
|
|
|
|
|
|
// If all non-empty lines of the MOTD start with a hyphen (which is common
|
|
|
|
// across MOTDs), remove all the leading hyphens.
|
|
|
|
if (lines.every((line) => line === "" || line[0] === "-")) {
|
|
|
|
lines = lines.map((line) => line.substr(2));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove empty lines around the MOTD (but not within it)
|
2018-07-16 17:54:47 +00:00
|
|
|
msg.text = lines
|
2018-07-17 13:25:30 +00:00
|
|
|
.map((line) => line.replace(/\s*$/, ""))
|
2018-07-16 17:54:47 +00:00
|
|
|
.join("\n")
|
|
|
|
.replace(/^[\r\n]+|[\r\n]+$/g, "");
|
2018-07-09 05:30:51 +00:00
|
|
|
}
|
|
|
|
|
2017-08-24 13:50:47 +00:00
|
|
|
const renderedMessage = $(templates[template](msg));
|
|
|
|
const content = renderedMessage.find(".content");
|
2017-05-18 20:08:54 +00:00
|
|
|
|
|
|
|
if (template === "msg_action") {
|
2017-08-24 13:50:47 +00:00
|
|
|
content.html(templates.actions[type](msg));
|
2017-05-18 20:08:54 +00:00
|
|
|
}
|
|
|
|
|
2017-08-24 13:50:47 +00:00
|
|
|
msg.previews.forEach((preview) => {
|
|
|
|
renderPreview(preview, renderedMessage);
|
2017-07-18 05:27:18 +00:00
|
|
|
});
|
|
|
|
|
2017-08-24 13:50:47 +00:00
|
|
|
return renderedMessage;
|
2017-05-18 20:08:54 +00:00
|
|
|
}
|
|
|
|
|
2017-08-28 20:06:28 +00:00
|
|
|
function renderNetworks(data, singleNetwork) {
|
2017-12-21 20:40:50 +00:00
|
|
|
// Add keyboard handlers to the "Join a channel…" form inputs/button
|
2018-05-02 13:57:19 +00:00
|
|
|
JoinChannel.handleKeybinds(data.networks);
|
2017-12-21 20:40:50 +00:00
|
|
|
|
2017-08-28 20:06:28 +00:00
|
|
|
let newChannels;
|
2017-05-18 20:08:54 +00:00
|
|
|
const channels = $.map(data.networks, function(n) {
|
|
|
|
return n.channels;
|
|
|
|
});
|
2017-08-28 20:06:28 +00:00
|
|
|
|
|
|
|
if (!singleNetwork && utils.lastMessageId > -1) {
|
|
|
|
newChannels = [];
|
|
|
|
|
|
|
|
channels.forEach((channel) => {
|
|
|
|
const chan = $("#chan-" + channel.id);
|
|
|
|
|
|
|
|
if (chan.length > 0) {
|
2018-07-08 12:18:17 +00:00
|
|
|
if (channel.type === "channel") {
|
|
|
|
channel.usersOutdated = true;
|
2017-08-28 20:06:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (channel.messages.length > 0) {
|
|
|
|
const container = chan.find(".messages");
|
2017-10-01 09:00:59 +00:00
|
|
|
|
2017-08-28 20:06:28 +00:00
|
|
|
if (container.find(".msg").length >= 100) {
|
|
|
|
container.find(".show-more").addClass("show");
|
|
|
|
}
|
|
|
|
|
2018-02-23 16:21:42 +00:00
|
|
|
container.parent().trigger("keepToBottom");
|
2017-08-28 20:06:28 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
newChannels.push(channel);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
newChannels = channels;
|
|
|
|
}
|
|
|
|
|
2018-02-06 08:57:16 +00:00
|
|
|
if (newChannels.length > 0) {
|
|
|
|
newChannels.forEach((channel) => {
|
|
|
|
if (channel.type === "channel") {
|
2018-07-08 12:18:17 +00:00
|
|
|
channel.usersOutdated = true;
|
2018-02-06 08:57:16 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2017-05-18 20:08:54 +00:00
|
|
|
|
|
|
|
utils.confirmExit();
|
|
|
|
|
2018-07-08 09:09:33 +00:00
|
|
|
for (const network of vueApp.networks) {
|
|
|
|
for (const channel of network.channels) {
|
|
|
|
if (channel.highlight > 0) {
|
|
|
|
utils.updateTitle();
|
|
|
|
utils.toggleNotificationMarkers(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2017-05-18 20:08:54 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-29 09:19:37 +00:00
|
|
|
|
2017-11-23 14:23:32 +00:00
|
|
|
function trimMessageInChannel(channel, messageLimit) {
|
|
|
|
const messages = channel.find(".messages .msg").slice(0, -messageLimit);
|
|
|
|
|
|
|
|
if (messages.length === 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
messages.remove();
|
|
|
|
|
|
|
|
channel.find(".show-more").addClass("show");
|
|
|
|
|
|
|
|
// Remove date-separators that would otherwise be "stuck" at the top of the channel
|
|
|
|
channel.find(".date-marker-container").each(function() {
|
|
|
|
if ($(this).next().hasClass("date-marker-container")) {
|
|
|
|
$(this).remove();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|