Replace quadratic emote list impl with Map
This commit is contained in:
parent
8399eab33f
commit
0f9bc44925
7 changed files with 57 additions and 153 deletions
|
|
@ -1,96 +1,42 @@
|
|||
var ChannelModule = require("./module");
|
||||
var XSS = require("../xss");
|
||||
|
||||
function EmoteList(defaults) {
|
||||
if (!defaults) {
|
||||
defaults = [];
|
||||
class EmoteList {
|
||||
constructor(list) {
|
||||
if (!list) {
|
||||
list = [];
|
||||
}
|
||||
|
||||
this.emotes = new Map(list.map(e => [e.name, e]));
|
||||
}
|
||||
|
||||
this.emotes = defaults.map(validateEmote).filter(function (f) {
|
||||
return f !== false;
|
||||
});
|
||||
toJSON() {
|
||||
let list = [];
|
||||
|
||||
for (let [key, value] of this.emotes.entries()) {
|
||||
list.push(value);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
hasEmote(name) {
|
||||
return this.emotes.has(name);
|
||||
}
|
||||
|
||||
setEmote(name, emote) {
|
||||
this.emotes.set(name, emote);
|
||||
}
|
||||
|
||||
deleteEmote(name) {
|
||||
return this.emotes.delete(name);
|
||||
}
|
||||
|
||||
size() {
|
||||
return this.emotes.size;
|
||||
}
|
||||
}
|
||||
|
||||
EmoteList.prototype = {
|
||||
pack: function () {
|
||||
return Array.prototype.slice.call(this.emotes);
|
||||
},
|
||||
|
||||
importList: function (emotes) {
|
||||
this.emotes = Array.prototype.slice.call(emotes);
|
||||
},
|
||||
|
||||
emoteExists: function (emote){
|
||||
if(this.emotes.filter((item)=>{ return item.name === emote.name }).length){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
renameEmote: function (emote) {
|
||||
var found = false;
|
||||
for (var i = 0; i < this.emotes.length; i++) {
|
||||
if (this.emotes[i].name === emote.old) {
|
||||
found = true;
|
||||
this.emotes[i] = emote;
|
||||
delete this.emotes[i].old;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(found){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
updateEmote: function (emote) {
|
||||
var found = false;
|
||||
for (var i = 0; i < this.emotes.length; i++) {
|
||||
if (this.emotes[i].name === emote.name) {
|
||||
found = true;
|
||||
this.emotes[i] = emote;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no emote was updated, add a new one */
|
||||
if (!found) {
|
||||
this.emotes.push(emote);
|
||||
}
|
||||
},
|
||||
|
||||
removeEmote: function (emote) {
|
||||
var found = false;
|
||||
for (var i = 0; i < this.emotes.length; i++) {
|
||||
if (this.emotes[i].name === emote.name) {
|
||||
this.emotes.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
moveEmote: function (from, to) {
|
||||
if (from < 0 || to < 0 ||
|
||||
from >= this.emotes.length || to >= this.emotes.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var f = this.emotes[from];
|
||||
/* Offset from/to indexes to account for the fact that removing
|
||||
an element changes the position of one of them.
|
||||
|
||||
I could have just done a swap, but it's already implemented this way
|
||||
and it works. */
|
||||
to = to > from ? to + 1 : to;
|
||||
from = to > from ? from : from + 1;
|
||||
|
||||
this.emotes.splice(to, 0, f);
|
||||
this.emotes.splice(from, 1);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
function validateEmote(f) {
|
||||
if (typeof f.name !== "string" || typeof f.image !== "string") {
|
||||
return false;
|
||||
|
|
@ -126,21 +72,19 @@ EmoteModule.prototype = Object.create(ChannelModule.prototype);
|
|||
|
||||
EmoteModule.prototype.load = function (data) {
|
||||
if ("emotes" in data) {
|
||||
for (var i = 0; i < data.emotes.length; i++) {
|
||||
this.emotes.updateEmote(data.emotes[i]);
|
||||
}
|
||||
this.emotes = new EmoteList(data.emotes);
|
||||
}
|
||||
|
||||
this.dirty = false;
|
||||
};
|
||||
|
||||
EmoteModule.prototype.save = function (data) {
|
||||
data.emotes = this.emotes.pack();
|
||||
data.emotes = this.emotes.toJSON();
|
||||
};
|
||||
|
||||
EmoteModule.prototype.packInfo = function (data, isAdmin) {
|
||||
if (isAdmin) {
|
||||
data.emoteCount = this.emotes.emotes.length;
|
||||
data.emoteCount = this.emotes.size();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -148,13 +92,12 @@ EmoteModule.prototype.onUserPostJoin = function (user) {
|
|||
user.socket.on("renameEmote", this.handleRenameEmote.bind(this, user));
|
||||
user.socket.on("updateEmote", this.handleUpdateEmote.bind(this, user));
|
||||
user.socket.on("importEmotes", this.handleImportEmotes.bind(this, user));
|
||||
user.socket.on("moveEmote", this.handleMoveEmote.bind(this, user));
|
||||
user.socket.on("removeEmote", this.handleRemoveEmote.bind(this, user));
|
||||
this.sendEmotes([user]);
|
||||
};
|
||||
|
||||
EmoteModule.prototype.sendEmotes = function (users) {
|
||||
var f = this.emotes.pack();
|
||||
var f = this.emotes.toJSON();
|
||||
var chan = this.channel;
|
||||
users.forEach(function (u) {
|
||||
u.socket.emit("emoteList", f);
|
||||
|
|
@ -178,7 +121,7 @@ EmoteModule.prototype.handleRenameEmote = function (user, data) {
|
|||
return;
|
||||
}
|
||||
|
||||
var e = this.emotes.emoteExists(data);
|
||||
var e = this.emotes.hasEmote(data.name);
|
||||
var f = validateEmote(data);
|
||||
if (!f || e) {
|
||||
var message = "Unable to rename emote '" + JSON.stringify(data) + "'. " +
|
||||
|
|
@ -197,9 +140,17 @@ EmoteModule.prototype.handleRenameEmote = function (user, data) {
|
|||
return;
|
||||
}
|
||||
|
||||
// See comment above
|
||||
var success = this.emotes.renameEmote(Object.assign({}, f));
|
||||
if(!success){ return; }
|
||||
var hadOld = this.emotes.deleteEmote(f.old);
|
||||
|
||||
if (!hadOld) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.emotes.setEmote(f.name, {
|
||||
name: f.name,
|
||||
source: f.source,
|
||||
image: f.image
|
||||
});
|
||||
|
||||
this.dirty = true;
|
||||
|
||||
|
|
@ -232,7 +183,11 @@ EmoteModule.prototype.handleUpdateEmote = function (user, data) {
|
|||
return;
|
||||
}
|
||||
|
||||
this.emotes.updateEmote(f);
|
||||
this.emotes.setEmote(f.name, {
|
||||
name: f.name,
|
||||
source: f.source,
|
||||
image: f.image
|
||||
});
|
||||
|
||||
this.dirty = true;
|
||||
|
||||
|
|
@ -254,9 +209,7 @@ EmoteModule.prototype.handleImportEmotes = function (user, data) {
|
|||
return;
|
||||
}
|
||||
|
||||
this.emotes.importList(data.map(validateEmote).filter(function (f) {
|
||||
return f !== false;
|
||||
}));
|
||||
this.emotes = new EmoteList(data.map(validateEmote).filter(f => f));
|
||||
|
||||
this.dirty = true;
|
||||
|
||||
|
|
@ -276,7 +229,7 @@ EmoteModule.prototype.handleRemoveEmote = function (user, data) {
|
|||
return;
|
||||
}
|
||||
|
||||
this.emotes.removeEmote(data);
|
||||
this.emotes.deleteEmote(data.name);
|
||||
|
||||
this.dirty = true;
|
||||
|
||||
|
|
@ -284,22 +237,4 @@ EmoteModule.prototype.handleRemoveEmote = function (user, data) {
|
|||
this.channel.broadcastAll("removeEmote", data);
|
||||
};
|
||||
|
||||
EmoteModule.prototype.handleMoveEmote = function (user, data) {
|
||||
if (typeof data !== "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.channel.modules.permissions.canEditEmotes(user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof data.to !== "number" || typeof data.from !== "number") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.emotes.moveEmote(data.from, data.to);
|
||||
|
||||
this.dirty = true;
|
||||
};
|
||||
|
||||
module.exports = EmoteModule;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue