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:
parent
b2a0cae626
commit
a1f56c7395
@ -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) {
|
socket.on("join", function(data) {
|
||||||
var id = data.network;
|
var id = data.network;
|
||||||
var network = sidebar.find("#network-" + id);
|
var network = sidebar.find("#network-" + id);
|
||||||
@ -359,7 +366,7 @@ $(function() {
|
|||||||
.append(msg)
|
.append(msg)
|
||||||
.trigger("msg", [
|
.trigger("msg", [
|
||||||
target,
|
target,
|
||||||
data.msg
|
data
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (data.msg.self) {
|
if (data.msg.self) {
|
||||||
@ -846,7 +853,6 @@ $(function() {
|
|||||||
self.addClass("active")
|
self.addClass("active")
|
||||||
.find(".badge")
|
.find(".badge")
|
||||||
.removeClass("highlight")
|
.removeClass("highlight")
|
||||||
.data("count", 0)
|
|
||||||
.empty();
|
.empty();
|
||||||
|
|
||||||
if (sidebar.find(".highlight").length === 0) {
|
if (sidebar.find(".highlight").length === 0) {
|
||||||
@ -955,6 +961,9 @@ $(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
chat.on("msg", ".messages", function(e, target, msg) {
|
chat.on("msg", ".messages", function(e, target, msg) {
|
||||||
|
var unread = msg.unread;
|
||||||
|
msg = msg.msg;
|
||||||
|
|
||||||
if (msg.self) {
|
if (msg.self) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1004,23 +1013,14 @@ $(function() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var whitelistedActions = [
|
if (!unread) {
|
||||||
"message",
|
|
||||||
"notice",
|
|
||||||
"action",
|
|
||||||
];
|
|
||||||
if (whitelistedActions.indexOf(msg.type) === -1) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var badge = button.find(".badge");
|
var badge = button.find(".badge").html(Handlebars.helpers.roundBadgeNumber(unread));
|
||||||
if (badge.length !== 0) {
|
|
||||||
var i = (badge.data("count") || 0) + 1;
|
if (msg.highlight) {
|
||||||
badge.data("count", i);
|
badge.addClass("highlight");
|
||||||
badge.html(Handlebars.helpers.roundBadgeNumber(i));
|
|
||||||
if (msg.highlight) {
|
|
||||||
badge.addClass("highlight");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{{#each channels}}
|
{{#each channels}}
|
||||||
<div data-id="{{id}}" data-target="#chan-{{id}}" data-title="{{name}}" class="chan {{type}}">
|
<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>
|
<button class="close" aria-label="Close"></button>
|
||||||
<span class="name" title="{{name}}">{{name}}</span>
|
<span class="name" title="{{name}}">{{name}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -63,7 +63,8 @@ function Client(manager, name, config) {
|
|||||||
config = {};
|
config = {};
|
||||||
}
|
}
|
||||||
_.merge(this, {
|
_.merge(this, {
|
||||||
activeChannel: -1,
|
lastActiveChannel: -1,
|
||||||
|
attachedClients: {},
|
||||||
config: config,
|
config: config,
|
||||||
id: id++,
|
id: id++,
|
||||||
name: name,
|
name: name,
|
||||||
@ -201,7 +202,7 @@ Client.prototype.connect = function(args) {
|
|||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
type: Msg.Type.ERROR,
|
type: Msg.Type.ERROR,
|
||||||
text: "Hostname you specified is not allowed."
|
text: "Hostname you specified is not allowed."
|
||||||
}));
|
}), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +215,7 @@ Client.prototype.connect = function(args) {
|
|||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
type: Msg.Type.ERROR,
|
type: Msg.Type.ERROR,
|
||||||
text: "You must specify a hostname to connect."
|
text: "You must specify a hostname to connect."
|
||||||
}));
|
}), true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,6 +320,13 @@ Client.prototype.inputLine = function(data) {
|
|||||||
var client = this;
|
var client = this;
|
||||||
var text = data.text;
|
var text = data.text;
|
||||||
var target = client.find(data.target);
|
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 '/'
|
// This is either a normal message or a command escaped with a leading '/'
|
||||||
if (text.charAt(0) !== "/" || text.charAt(1) === "/") {
|
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);
|
var target = this.find(data);
|
||||||
if (target) {
|
if (!target) {
|
||||||
target.chan.firstUnread = 0;
|
return;
|
||||||
target.chan.unread = 0;
|
|
||||||
target.chan.highlight = false;
|
|
||||||
this.activeChannel = target.chan.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
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;
|
var timer;
|
||||||
Client.prototype.save = function(force) {
|
Client.prototype.save = function(force) {
|
||||||
var client = this;
|
var client = this;
|
||||||
|
@ -28,11 +28,20 @@ function Chan(attr) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Chan.prototype.pushMessage = function(client, msg) {
|
Chan.prototype.pushMessage = function(client, msg, increasesUnread) {
|
||||||
client.emit("msg", {
|
var obj = {
|
||||||
chan: this.id,
|
chan: this.id,
|
||||||
msg: msg
|
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
|
// Never store messages in public mode as the session
|
||||||
// is completely destroyed when the page gets closed
|
// 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);
|
this.messages.splice(0, this.messages.length - Helper.config.maxHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!msg.self && this.id !== client.activeChannel) {
|
if (!msg.self && !isOpen) {
|
||||||
if (!this.firstUnread) {
|
if (!this.firstUnread) {
|
||||||
this.firstUnread = msg.id;
|
this.firstUnread = msg.id;
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,13 @@ module.exports = function(irc, network) {
|
|||||||
|
|
||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
text: "Network created, connecting to " + network.host + ":" + network.port + "..."
|
text: "Network created, connecting to " + network.host + ":" + network.port + "..."
|
||||||
}));
|
}), true);
|
||||||
|
|
||||||
irc.on("registered", function() {
|
irc.on("registered", function() {
|
||||||
if (network.irc.network.cap.enabled.length > 0) {
|
if (network.irc.network.cap.enabled.length > 0) {
|
||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
text: "Enabled capabilities: " + network.irc.network.cap.enabled.join(", ")
|
text: "Enabled capabilities: " + network.irc.network.cap.enabled.join(", ")
|
||||||
}));
|
}), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var delay = 1000;
|
var delay = 1000;
|
||||||
@ -54,13 +54,13 @@ module.exports = function(irc, network) {
|
|||||||
|
|
||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
text: "Connected to the network."
|
text: "Connected to the network."
|
||||||
}));
|
}), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
irc.on("close", function() {
|
irc.on("close", function() {
|
||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
text: "Disconnected from the network, and will not reconnect. Use /connect to reconnect again."
|
text: "Disconnected from the network, and will not reconnect. Use /connect to reconnect again."
|
||||||
}));
|
}), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (identd.isEnabled()) {
|
if (identd.isEnabled()) {
|
||||||
@ -91,19 +91,19 @@ module.exports = function(irc, network) {
|
|||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
type: Msg.Type.ERROR,
|
type: Msg.Type.ERROR,
|
||||||
text: "Socket error: " + err
|
text: "Socket error: " + err
|
||||||
}));
|
}), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
irc.on("reconnecting", function(data) {
|
irc.on("reconnecting", function(data) {
|
||||||
network.channels[0].pushMessage(client, new Msg({
|
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 + ")"
|
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() {
|
irc.on("ping timeout", function() {
|
||||||
network.channels[0].pushMessage(client, new Msg({
|
network.channels[0].pushMessage(client, new Msg({
|
||||||
text: "Ping timeout, disconnecting…"
|
text: "Ping timeout, disconnecting…"
|
||||||
}));
|
}), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
irc.on("server options", function(data) {
|
irc.on("server options", function(data) {
|
||||||
|
@ -15,7 +15,7 @@ module.exports = function(irc, network) {
|
|||||||
type: Msg.Type.ERROR,
|
type: Msg.Type.ERROR,
|
||||||
text: text,
|
text: text,
|
||||||
});
|
});
|
||||||
lobby.pushMessage(client, msg);
|
lobby.pushMessage(client, msg, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
irc.on("nick in use", function(data) {
|
irc.on("nick in use", function(data) {
|
||||||
@ -24,7 +24,7 @@ module.exports = function(irc, network) {
|
|||||||
type: Msg.Type.ERROR,
|
type: Msg.Type.ERROR,
|
||||||
text: data.nick + ": " + (data.reason || "Nickname is already in use."),
|
text: data.nick + ": " + (data.reason || "Nickname is already in use."),
|
||||||
});
|
});
|
||||||
lobby.pushMessage(client, msg);
|
lobby.pushMessage(client, msg, true);
|
||||||
|
|
||||||
if (irc.connection.registered === false) {
|
if (irc.connection.registered === false) {
|
||||||
var random = (data.nick || irc.user.nick) + Math.floor(10 + (Math.random() * 89));
|
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,
|
type: Msg.Type.ERROR,
|
||||||
text: data.nick + ": " + (data.reason || "Nickname is invalid."),
|
text: data.nick + ": " + (data.reason || "Nickname is invalid."),
|
||||||
});
|
});
|
||||||
lobby.pushMessage(client, msg);
|
lobby.pushMessage(client, msg, true);
|
||||||
|
|
||||||
if (irc.connection.registered === false) {
|
if (irc.connection.registered === false) {
|
||||||
var random = "i" + Math.random().toString(36).substr(2, 10); // 'i' so it never begins with a number
|
var random = "i" + Math.random().toString(36).substr(2, 10); // 'i' so it never begins with a number
|
||||||
|
@ -79,10 +79,6 @@ module.exports = function(irc, network) {
|
|||||||
highlight = network.highlightRegex.test(data.message);
|
highlight = network.highlightRegex.test(data.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self && chan.id !== client.activeChannel) {
|
|
||||||
chan.unread++;
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg = new Msg({
|
var msg = new Msg({
|
||||||
type: data.type,
|
type: data.type,
|
||||||
time: data.time,
|
time: data.time,
|
||||||
@ -92,6 +88,6 @@ module.exports = function(irc, network) {
|
|||||||
self: self,
|
self: self,
|
||||||
highlight: highlight
|
highlight: highlight
|
||||||
});
|
});
|
||||||
chan.pushMessage(client, msg);
|
chan.pushMessage(client, msg, !self);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@ module.exports = function(irc, network) {
|
|||||||
msg = new Msg({
|
msg = new Msg({
|
||||||
text: "You're now known as " + data.new_nick,
|
text: "You're now known as " + data.new_nick,
|
||||||
});
|
});
|
||||||
lobby.pushMessage(client, msg);
|
lobby.pushMessage(client, msg, true);
|
||||||
self = true;
|
self = true;
|
||||||
client.save();
|
client.save();
|
||||||
client.emit("nick", {
|
client.emit("nick", {
|
||||||
|
@ -15,6 +15,6 @@ module.exports = function(irc, network) {
|
|||||||
type: Msg.Type.UNHANDLED,
|
type: Msg.Type.UNHANDLED,
|
||||||
command: command.command,
|
command: command.command,
|
||||||
params: command.params
|
params: command.params
|
||||||
}));
|
}), true);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -147,6 +147,11 @@ function init(socket, client) {
|
|||||||
} else {
|
} else {
|
||||||
socket.emit("authorized");
|
socket.emit("authorized");
|
||||||
|
|
||||||
|
socket.on("disconnect", function() {
|
||||||
|
client.clientDetach(socket.id);
|
||||||
|
});
|
||||||
|
client.clientAttach(socket.id);
|
||||||
|
|
||||||
socket.on(
|
socket.on(
|
||||||
"input",
|
"input",
|
||||||
function(data) {
|
function(data) {
|
||||||
@ -215,7 +220,7 @@ function init(socket, client) {
|
|||||||
socket.on(
|
socket.on(
|
||||||
"open",
|
"open",
|
||||||
function(data) {
|
function(data) {
|
||||||
client.open(data);
|
client.open(socket.id, data);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
socket.on(
|
socket.on(
|
||||||
@ -232,7 +237,7 @@ function init(socket, client) {
|
|||||||
);
|
);
|
||||||
socket.join(client.id);
|
socket.join(client.id);
|
||||||
socket.emit("init", {
|
socket.emit("init", {
|
||||||
active: client.activeChannel,
|
active: client.lastActiveChannel,
|
||||||
networks: client.networks,
|
networks: client.networks,
|
||||||
token: client.config.token || null
|
token: client.config.token || null
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user