diff --git a/client/js/lounge.js b/client/js/lounge.js
index 164e6134..21f64fa2 100644
--- a/client/js/lounge.js
+++ b/client/js/lounge.js
@@ -184,6 +184,13 @@ $(function() {
}
});
+ socket.on("open", function(id) {
+ // Another client opened the channel, clear the unread counter
+ sidebar.find("[data-id='" + id + "'] .badge")
+ .removeClass("highlight")
+ .empty();
+ });
+
socket.on("join", function(data) {
var id = data.network;
var network = sidebar.find("#network-" + id);
@@ -359,7 +366,7 @@ $(function() {
.append(msg)
.trigger("msg", [
target,
- data.msg
+ data
]);
if (data.msg.self) {
@@ -846,7 +853,6 @@ $(function() {
self.addClass("active")
.find(".badge")
.removeClass("highlight")
- .data("count", 0)
.empty();
if (sidebar.find(".highlight").length === 0) {
@@ -955,6 +961,9 @@ $(function() {
});
chat.on("msg", ".messages", function(e, target, msg) {
+ var unread = msg.unread;
+ msg = msg.msg;
+
if (msg.self) {
return;
}
@@ -1004,23 +1013,14 @@ $(function() {
return;
}
- var whitelistedActions = [
- "message",
- "notice",
- "action",
- ];
- if (whitelistedActions.indexOf(msg.type) === -1) {
+ if (!unread) {
return;
}
- var badge = button.find(".badge");
- if (badge.length !== 0) {
- var i = (badge.data("count") || 0) + 1;
- badge.data("count", i);
- badge.html(Handlebars.helpers.roundBadgeNumber(i));
- if (msg.highlight) {
- badge.addClass("highlight");
- }
+ var badge = button.find(".badge").html(Handlebars.helpers.roundBadgeNumber(unread));
+
+ if (msg.highlight) {
+ badge.addClass("highlight");
}
});
diff --git a/client/views/chan.tpl b/client/views/chan.tpl
index 22a6c3cc..626eb228 100644
--- a/client/views/chan.tpl
+++ b/client/views/chan.tpl
@@ -1,6 +1,6 @@
{{#each channels}}
- {{#if unread}}{{roundBadgeNumber unread}}{{/if}}
+ {{#if unread}}{{roundBadgeNumber unread}}{{/if}}
{{name}}
diff --git a/src/client.js b/src/client.js
index 6e08d814..77db906b 100644
--- a/src/client.js
+++ b/src/client.js
@@ -63,7 +63,8 @@ function Client(manager, name, config) {
config = {};
}
_.merge(this, {
- activeChannel: -1,
+ lastActiveChannel: -1,
+ attachedClients: {},
config: config,
id: id++,
name: name,
@@ -201,7 +202,7 @@ Client.prototype.connect = function(args) {
network.channels[0].pushMessage(client, new Msg({
type: Msg.Type.ERROR,
text: "Hostname you specified is not allowed."
- }));
+ }), true);
return;
}
@@ -214,7 +215,7 @@ Client.prototype.connect = function(args) {
network.channels[0].pushMessage(client, new Msg({
type: Msg.Type.ERROR,
text: "You must specify a hostname to connect."
- }));
+ }), true);
return;
}
@@ -319,6 +320,13 @@ Client.prototype.inputLine = function(data) {
var client = this;
var text = data.text;
var target = client.find(data.target);
+ if (!target) {
+ return;
+ }
+
+ // Sending a message to a channel is higher priority than merely opening one
+ // so that reloading the page will open this channel
+ this.lastActiveChannel = target.chan.id;
// This is either a normal message or a command escaped with a leading '/'
if (text.charAt(0) !== "/" || text.charAt(1) === "/") {
@@ -366,14 +374,20 @@ Client.prototype.more = function(data) {
});
};
-Client.prototype.open = function(data) {
+Client.prototype.open = function(socketId, data) {
var target = this.find(data);
- if (target) {
- target.chan.firstUnread = 0;
- target.chan.unread = 0;
- target.chan.highlight = false;
- this.activeChannel = target.chan.id;
+ if (!target) {
+ return;
}
+
+ target.chan.firstUnread = 0;
+ target.chan.unread = 0;
+ target.chan.highlight = false;
+
+ this.attachedClients[socketId] = target.chan.id;
+ this.lastActiveChannel = target.chan.id;
+
+ this.emit("open", target.chan.id);
};
Client.prototype.sort = function(data) {
@@ -442,6 +456,14 @@ Client.prototype.quit = function() {
});
};
+Client.prototype.clientAttach = function(socketId) {
+ this.attachedClients[socketId] = this.lastActiveChannel;
+};
+
+Client.prototype.clientDetach = function(socketId) {
+ delete this.attachedClients[socketId];
+};
+
var timer;
Client.prototype.save = function(force) {
var client = this;
diff --git a/src/models/chan.js b/src/models/chan.js
index a8c10474..69e582ab 100644
--- a/src/models/chan.js
+++ b/src/models/chan.js
@@ -28,11 +28,20 @@ function Chan(attr) {
});
}
-Chan.prototype.pushMessage = function(client, msg) {
- client.emit("msg", {
+Chan.prototype.pushMessage = function(client, msg, increasesUnread) {
+ var obj = {
chan: this.id,
msg: msg
- });
+ };
+
+ // If this channel is open in any of the clients, do not increase unread counter
+ var isOpen = _.includes(client.attachedClients, this.id);
+
+ if ((increasesUnread || msg.highlight) && !isOpen) {
+ obj.unread = ++this.unread;
+ }
+
+ client.emit("msg", obj);
// Never store messages in public mode as the session
// is completely destroyed when the page gets closed
@@ -46,7 +55,7 @@ Chan.prototype.pushMessage = function(client, msg) {
this.messages.splice(0, this.messages.length - Helper.config.maxHistory);
}
- if (!msg.self && this.id !== client.activeChannel) {
+ if (!msg.self && !isOpen) {
if (!this.firstUnread) {
this.firstUnread = msg.id;
}
diff --git a/src/plugins/irc-events/connection.js b/src/plugins/irc-events/connection.js
index a5507d93..2d843086 100644
--- a/src/plugins/irc-events/connection.js
+++ b/src/plugins/irc-events/connection.js
@@ -11,13 +11,13 @@ module.exports = function(irc, network) {
network.channels[0].pushMessage(client, new Msg({
text: "Network created, connecting to " + network.host + ":" + network.port + "..."
- }));
+ }), true);
irc.on("registered", function() {
if (network.irc.network.cap.enabled.length > 0) {
network.channels[0].pushMessage(client, new Msg({
text: "Enabled capabilities: " + network.irc.network.cap.enabled.join(", ")
- }));
+ }), true);
}
var delay = 1000;
@@ -54,13 +54,13 @@ module.exports = function(irc, network) {
network.channels[0].pushMessage(client, new Msg({
text: "Connected to the network."
- }));
+ }), true);
});
irc.on("close", function() {
network.channels[0].pushMessage(client, new Msg({
text: "Disconnected from the network, and will not reconnect. Use /connect to reconnect again."
- }));
+ }), true);
});
if (identd.isEnabled()) {
@@ -91,19 +91,19 @@ module.exports = function(irc, network) {
network.channels[0].pushMessage(client, new Msg({
type: Msg.Type.ERROR,
text: "Socket error: " + err
- }));
+ }), true);
});
irc.on("reconnecting", function(data) {
network.channels[0].pushMessage(client, new Msg({
text: "Disconnected from the network. Reconnecting in " + Math.round(data.wait / 1000) + " seconds… (Attempt " + data.attempt + " of " + data.max_retries + ")"
- }));
+ }), true);
});
irc.on("ping timeout", function() {
network.channels[0].pushMessage(client, new Msg({
text: "Ping timeout, disconnecting…"
- }));
+ }), true);
});
irc.on("server options", function(data) {
diff --git a/src/plugins/irc-events/error.js b/src/plugins/irc-events/error.js
index 477645fb..d08e033c 100644
--- a/src/plugins/irc-events/error.js
+++ b/src/plugins/irc-events/error.js
@@ -15,7 +15,7 @@ module.exports = function(irc, network) {
type: Msg.Type.ERROR,
text: text,
});
- lobby.pushMessage(client, msg);
+ lobby.pushMessage(client, msg, true);
});
irc.on("nick in use", function(data) {
@@ -24,7 +24,7 @@ module.exports = function(irc, network) {
type: Msg.Type.ERROR,
text: data.nick + ": " + (data.reason || "Nickname is already in use."),
});
- lobby.pushMessage(client, msg);
+ lobby.pushMessage(client, msg, true);
if (irc.connection.registered === false) {
var random = (data.nick || irc.user.nick) + Math.floor(10 + (Math.random() * 89));
@@ -43,7 +43,7 @@ module.exports = function(irc, network) {
type: Msg.Type.ERROR,
text: data.nick + ": " + (data.reason || "Nickname is invalid."),
});
- lobby.pushMessage(client, msg);
+ lobby.pushMessage(client, msg, true);
if (irc.connection.registered === false) {
var random = "i" + Math.random().toString(36).substr(2, 10); // 'i' so it never begins with a number
diff --git a/src/plugins/irc-events/message.js b/src/plugins/irc-events/message.js
index 558964e6..5eb231fe 100644
--- a/src/plugins/irc-events/message.js
+++ b/src/plugins/irc-events/message.js
@@ -79,10 +79,6 @@ module.exports = function(irc, network) {
highlight = network.highlightRegex.test(data.message);
}
- if (!self && chan.id !== client.activeChannel) {
- chan.unread++;
- }
-
var msg = new Msg({
type: data.type,
time: data.time,
@@ -92,6 +88,6 @@ module.exports = function(irc, network) {
self: self,
highlight: highlight
});
- chan.pushMessage(client, msg);
+ chan.pushMessage(client, msg, !self);
}
};
diff --git a/src/plugins/irc-events/nick.js b/src/plugins/irc-events/nick.js
index 5096c7a2..c8519530 100644
--- a/src/plugins/irc-events/nick.js
+++ b/src/plugins/irc-events/nick.js
@@ -15,7 +15,7 @@ module.exports = function(irc, network) {
msg = new Msg({
text: "You're now known as " + data.new_nick,
});
- lobby.pushMessage(client, msg);
+ lobby.pushMessage(client, msg, true);
self = true;
client.save();
client.emit("nick", {
diff --git a/src/plugins/irc-events/unhandled.js b/src/plugins/irc-events/unhandled.js
index 46b98f22..a07a48ee 100644
--- a/src/plugins/irc-events/unhandled.js
+++ b/src/plugins/irc-events/unhandled.js
@@ -15,6 +15,6 @@ module.exports = function(irc, network) {
type: Msg.Type.UNHANDLED,
command: command.command,
params: command.params
- }));
+ }), true);
});
};
diff --git a/src/server.js b/src/server.js
index 2ce7be08..bea7776b 100644
--- a/src/server.js
+++ b/src/server.js
@@ -147,6 +147,11 @@ function init(socket, client) {
} else {
socket.emit("authorized");
+ socket.on("disconnect", function() {
+ client.clientDetach(socket.id);
+ });
+ client.clientAttach(socket.id);
+
socket.on(
"input",
function(data) {
@@ -215,7 +220,7 @@ function init(socket, client) {
socket.on(
"open",
function(data) {
- client.open(data);
+ client.open(socket.id, data);
}
);
socket.on(
@@ -232,7 +237,7 @@ function init(socket, client) {
);
socket.join(client.id);
socket.emit("init", {
- active: client.activeChannel,
+ active: client.lastActiveChannel,
networks: client.networks,
token: client.config.token || null
});