Merge pull request #2152 from thelounge/yamanickill/sort-channels-on-join

Insert channel/user into channel list at alphabetically sorted point, not just the end
This commit is contained in:
Jérémie Astori 2018-03-13 00:37:59 -04:00 committed by GitHub
commit 288aaac465
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 232 additions and 12 deletions

View File

@ -10,11 +10,12 @@ const sidebar = $("#sidebar");
socket.on("join", function(data) { socket.on("join", function(data) {
const id = data.network; const id = data.network;
const network = sidebar.find(`#network-${id}`); const network = sidebar.find(`#network-${id}`);
network.append( const channels = network.children();
templates.chan({ const position = $(channels[data.index || channels.length - 1]); // Put channel in correct position, or the end if we don't have one
const sidebarEntry = templates.chan({
channels: [data.chan], channels: [data.chan],
}) });
); $(sidebarEntry).insertAfter(position);
chat.append( chat.append(
templates.chat({ templates.chat({
channels: [data.chan], channels: [data.chan],

View File

@ -128,6 +128,28 @@ Network.prototype.getNetworkStatus = function() {
return status; return status;
}; };
Network.prototype.addChannel = function(newChan) {
let index = this.channels.length; // Default to putting as the last item in the array
// Don't sort special channels in amongst channels/users.
if (newChan.type === Chan.Type.CHANNEL || newChan.type === Chan.Type.QUERY) {
// We start at 1 so we don't test against the lobby
for (let i = 1; i < this.channels.length; i++) {
const compareChan = this.channels[i];
// Negative if the new chan is alphabetically before the next chan in the list, positive if after
if (newChan.name.localeCompare(compareChan.name, {sensitivity: "base"}) <= 0
|| (compareChan.type !== Chan.Type.CHANNEL && compareChan.type !== Chan.Type.QUERY)) {
index = i;
break;
}
}
}
this.channels.splice(index, 0, newChan);
return index;
};
Network.prototype.export = function() { Network.prototype.export = function() {
const network = _.pick(this, [ const network = _.pick(this, [
"uuid", "uuid",

View File

@ -47,11 +47,12 @@ exports.input = function(network, chan, cmd, args) {
type: Chan.Type.QUERY, type: Chan.Type.QUERY,
name: target, name: target,
}); });
network.channels.push(newChan);
this.emit("join", { this.emit("join", {
network: network.id, network: network.id,
chan: newChan.getFilteredClone(true), chan: newChan.getFilteredClone(true),
shouldOpen: true, shouldOpen: true,
index: network.addChannel(newChan),
}); });
this.save(); this.save();
newChan.loadMessages(this, network); newChan.loadMessages(this, network);

View File

@ -37,10 +37,10 @@ module.exports = function(irc, network) {
type: Chan.Type.SPECIAL, type: Chan.Type.SPECIAL,
name: chanName, name: chanName,
}); });
network.channels.push(chan);
client.emit("join", { client.emit("join", {
network: network.id, network: network.id,
chan: chan.getFilteredClone(true), chan: chan.getFilteredClone(true),
index: network.addChannel(chan),
}); });
} }

View File

@ -15,12 +15,13 @@ module.exports = function(irc, network) {
name: data.channel, name: data.channel,
state: Chan.State.JOINED, state: Chan.State.JOINED,
}); });
network.channels.push(chan);
client.save();
client.emit("join", { client.emit("join", {
network: network.id, network: network.id,
chan: chan.getFilteredClone(true), chan: chan.getFilteredClone(true),
index: network.addChannel(chan),
}); });
client.save();
chan.loadMessages(client, network); chan.loadMessages(client, network);

View File

@ -46,10 +46,11 @@ module.exports = function(irc, network) {
type: Chan.Type.SPECIAL, type: Chan.Type.SPECIAL,
name: "Channel List", name: "Channel List",
}); });
network.channels.push(chan);
client.emit("join", { client.emit("join", {
network: network.id, network: network.id,
chan: chan.getFilteredClone(true), chan: chan.getFilteredClone(true),
index: network.addChannel(chan),
}); });
} }

View File

@ -67,11 +67,13 @@ module.exports = function(irc, network) {
type: Chan.Type.QUERY, type: Chan.Type.QUERY,
name: target, name: target,
}); });
network.channels.push(chan);
client.emit("join", { client.emit("join", {
network: network.id, network: network.id,
chan: chan.getFilteredClone(true), chan: chan.getFilteredClone(true),
index: network.addChannel(chan),
}); });
client.save();
chan.loadMessages(client, network); chan.loadMessages(client, network);
} }
} }

View File

@ -13,13 +13,15 @@ module.exports = function(irc, network) {
type: Chan.Type.QUERY, type: Chan.Type.QUERY,
name: data.nick, name: data.nick,
}); });
network.channels.push(chan);
client.emit("join", { client.emit("join", {
shouldOpen: true, shouldOpen: true,
network: network.id, network: network.id,
chan: chan.getFilteredClone(true), chan: chan.getFilteredClone(true),
index: network.addChannel(chan),
}); });
chan.loadMessages(client, network); chan.loadMessages(client, network);
client.save();
} }
let msg; let msg;

View File

@ -147,4 +147,194 @@ describe("Network", function() {
); );
}); });
}); });
describe("#addChannel(newChan)", function() {
it("should add channel", function() {
const chan = new Chan({name: "#thelounge"});
const network = new Network({
channels: [
chan,
],
});
// Lobby and initial channel
expect(network.channels.length).to.equal(2);
const newChan = new Chan({name: "#freenode"});
network.addChannel(newChan);
expect(network.channels.length).to.equal(3);
});
it("should add channel alphabetically", function() {
const chan1 = new Chan({name: "#abc"});
const chan2 = new Chan({name: "#thelounge"});
const chan3 = new Chan({name: "#zero"});
const network = new Network({
channels: [
chan1,
chan2,
chan3,
],
name: "freenode",
});
const newChan = new Chan({name: "#freenode"});
network.addChannel(newChan);
expect(network.channels[0].name).to.equal("freenode");
expect(network.channels[1]).to.equal(chan1);
expect(network.channels[2]).to.equal(newChan);
expect(network.channels[3]).to.equal(chan2);
expect(network.channels[4]).to.equal(chan3);
});
it("should sort case-insensitively", function() {
const chan1 = new Chan({name: "#abc"});
const chan2 = new Chan({name: "#THELOUNGE"});
const network = new Network({
channels: [
chan1,
chan2,
],
});
const newChan = new Chan({name: "#freenode"});
network.addChannel(newChan);
expect(network.channels[1]).to.equal(chan1);
expect(network.channels[2]).to.equal(newChan);
expect(network.channels[3]).to.equal(chan2);
});
it("should sort users separately from channels", function() {
const chan1 = new Chan({name: "#abc"});
const chan2 = new Chan({name: "#THELOUNGE"});
const network = new Network({
channels: [
chan1,
chan2,
],
});
const newUser = new Chan({name: "mcinkay", type: Chan.Type.QUERY});
network.addChannel(newUser);
expect(network.channels[1]).to.equal(chan1);
expect(network.channels[2]).to.equal(chan2);
expect(network.channels[3]).to.equal(newUser);
});
it("should sort users alphabetically", function() {
const chan1 = new Chan({name: "#abc"});
const chan2 = new Chan({name: "#THELOUNGE"});
const user1 = new Chan({name: "astorije", type: Chan.Type.QUERY});
const user2 = new Chan({name: "xpaw", type: Chan.Type.QUERY});
const network = new Network({
channels: [
chan1,
chan2,
user1,
user2,
],
});
const newUser = new Chan({name: "mcinkay", type: Chan.Type.QUERY});
network.addChannel(newUser);
expect(network.channels[1]).to.equal(chan1);
expect(network.channels[2]).to.equal(chan2);
expect(network.channels[3]).to.equal(user1);
expect(network.channels[4]).to.equal(newUser);
expect(network.channels[5]).to.equal(user2);
});
it("should not sort special channels", function() {
const chan1 = new Chan({name: "#abc"});
const chan2 = new Chan({name: "#THELOUNGE"});
const user1 = new Chan({name: "astorije", type: Chan.Type.QUERY});
const user2 = new Chan({name: "xpaw", type: Chan.Type.QUERY});
const network = new Network({
channels: [
chan1,
chan2,
user1,
user2,
],
});
const newBanlist = new Chan({name: "Banlist for #THELOUNGE", type: Chan.Type.SPECIAL});
network.addChannel(newBanlist);
expect(network.channels[1]).to.equal(chan1);
expect(network.channels[2]).to.equal(chan2);
expect(network.channels[3]).to.equal(user1);
expect(network.channels[4]).to.equal(user2);
expect(network.channels[5]).to.equal(newBanlist);
});
it("should not compare against special channels", function() {
const chan1 = new Chan({name: "#abc"});
const chan2 = new Chan({name: "#THELOUNGE"});
const user1 = new Chan({name: "astorije", type: Chan.Type.QUERY});
const network = new Network({
channels: [
chan1,
chan2,
user1,
],
});
const newBanlist = new Chan({name: "Banlist for #THELOUNGE", type: Chan.Type.SPECIAL});
network.addChannel(newBanlist);
const newUser = new Chan({name: "mcinkay", type: Chan.Type.QUERY});
network.addChannel(newUser);
expect(network.channels[1]).to.equal(chan1);
expect(network.channels[2]).to.equal(chan2);
expect(network.channels[3]).to.equal(user1);
expect(network.channels[4]).to.equal(newUser);
expect(network.channels[5]).to.equal(newBanlist);
});
it("should insert before first special channel", function() {
const banlist = new Chan({name: "Banlist for #THELOUNGE", type: Chan.Type.SPECIAL});
const chan1 = new Chan({name: "#thelounge"});
const user1 = new Chan({name: "astorije", type: Chan.Type.QUERY});
const network = new Network({
channels: [
banlist,
chan1,
user1,
],
});
const newChan = new Chan({name: "#freenode"});
network.addChannel(newChan);
expect(network.channels[1]).to.equal(newChan);
expect(network.channels[2]).to.equal(banlist);
expect(network.channels[3]).to.equal(chan1);
expect(network.channels[4]).to.equal(user1);
});
it("should never add something in front of the lobby", function() {
const network = new Network({
name: "freenode",
channels: [],
});
const newUser = new Chan({name: "astorije"});
network.addChannel(newUser);
expect(network.channels[1]).to.equal(newUser);
});
});
}); });