Improve support for opening multiple clients at once

- Synchornize unread counter with the server
- Fix unread marker on no attached clients
- Increase unread counter for server messages
This commit is contained in:
Pavel Djundik 2016-09-25 09:41:10 +03:00 committed by Jérémie Astori
parent b2a0cae626
commit a1f56c7395
10 changed files with 81 additions and 49 deletions

View file

@ -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");
}
});

View file

@ -1,6 +1,6 @@
{{#each channels}}
<div data-id="{{id}}" data-target="#chan-{{id}}" data-title="{{name}}" class="chan {{type}}">
<span class="badge{{#if highlight}} highlight{{/if}}" data-count="{{unread}}">{{#if unread}}{{roundBadgeNumber unread}}{{/if}}</span>
<span class="badge{{#if highlight}} highlight{{/if}}">{{#if unread}}{{roundBadgeNumber unread}}{{/if}}</span>
<button class="close" aria-label="Close"></button>
<span class="name" title="{{name}}">{{name}}</span>
</div>

View file

@ -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;

View file

@ -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;
}

View file

@ -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) {

View file

@ -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

View file

@ -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);
}
};

View file

@ -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", {

View file

@ -15,6 +15,6 @@ module.exports = function(irc, network) {
type: Msg.Type.UNHANDLED,
command: command.command,
params: command.params
}));
}), true);
});
};

View file

@ -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
});