diff --git a/channel.js b/channel.js
index 63a72c28..cb50d1c6 100644
--- a/channel.js
+++ b/channel.js
@@ -88,7 +88,7 @@ var Channel = function(name, Server) {
};
this.filters = [
new Filter("monospace", "`([^`]+)`", "g", "$1
"),
- new Filter("bold", "(.)\\*([^\\*]+)\\*", "g", "$1$2"),
+ new Filter("bold", "(^|\\s)\\*([^\\*]+)\\*", "g", "$1$2"),
new Filter("italic", "(^| )_([^_]+)_", "g", "$1$2"),
new Filter("strikethrough", "~~([^~]+)~~", "g", "$1"),
new Filter("inline spoiler", "\\[spoiler\\](.*)\\[\\/spoiler\\]", "ig", "$1"),
diff --git a/www/assets/js/util.js b/www/assets/js/util.js
index 0fc77531..b2aae050 100644
--- a/www/assets/js/util.js
+++ b/www/assets/js/util.js
@@ -272,6 +272,42 @@ function calcUserBreakdown() {
return breakdown;
}
+function sortUserlist() {
+ var slice = Array.prototype.slice;
+ var list = slice.call($("#userlist .userlist_item"));
+ list.sort(function (a, b) {
+ var r1 = $(a).data("dropdown-info").rank;
+ var r2 = $(b).data("dropdown-info").rank;
+ var afk1 = $(a).find(".icon-time").length > 0;
+ var afk2 = $(b).find(".icon-time").length > 0;
+ var name1 = a.children[1].innerHTML.toLowerCase();
+ var name2 = b.children[1].innerHTML.toLowerCase();
+
+ if(USEROPTS.sort_afk) {
+ if(afk1 && !afk2)
+ return 1;
+ if(!afk1 && afk2)
+ return -1;
+ }
+
+ if(USEROPTS.sort_rank) {
+ if(r1 < r2)
+ return 1;
+ if(r1 > r2)
+ return -1;
+ }
+
+ return name1 === name2 ? 0 : (name1 < name2 ? -1 : 1);
+ });
+
+ list.forEach(function (item) {
+ $(item).detach();
+ });
+ list.forEach(function (item) {
+ $(item).appendTo($("#userlist"));
+ });
+}
+
/* queue stuff */
function scrollQueue() {
@@ -541,6 +577,18 @@ function showOptionsMenu() {
showts.prop("checked", USEROPTS.show_timestamps);
addOption("Show timestamps", tscontainer);
+ var srcontainer = $("").addClass("checkbox")
+ .text("Sort userlist by rank");
+ var sr = $("").attr("type", "checkbox").appendTo(srcontainer);
+ sr.prop("checked", USEROPTS.sort_rank);
+ addOption("Userlist sort", srcontainer);
+
+ var sacontainer = $("").addClass("checkbox")
+ .text("AFKers at bottom of userlist");
+ var sa = $("").attr("type", "checkbox").appendTo(sacontainer);
+ sa.prop("checked", USEROPTS.sort_afk);
+ addOption("Userlist sort", sacontainer);
+
var blinkcontainer = $("").addClass("checkbox")
.text("Flash title on every incoming message");
var blink = $("").attr("type", "checkbox").appendTo(blinkcontainer);
@@ -596,6 +644,9 @@ function showOptionsMenu() {
USEROPTS.qbtn_idontlikechange = oqbtn.prop("checked");
USEROPTS.ignore_channelcss = nocss.prop("checked");
USEROPTS.ignore_channeljs = nojs.prop("checked");
+ USEROPTS.sort_rank = sr.prop("checked");
+ USEROPTS.sort_afk = sa.prop("checked");
+ sortUserlist();
if(CLIENT.rank >= Rank.Moderator) {
USEROPTS.modhat = modhat.prop("checked");
USEROPTS.joinmessage = join.prop("checked");
@@ -1237,9 +1288,11 @@ function formatChatMessage(data) {
}
if(data.superadminflair)
skip = false;
- if(data.msgclass == "server-whisper") {
+ if(data.msgclass == "server-whisper")
skip = true;
- }
+ // Prevent impersonation by abuse of the bold filter
+ if(data.msg.match(/^\s*\w+\s*:\s*<\/strong>\s*/))
+ skip = false;
LASTCHATNAME = data.username;
LASTCHATTIME = data.time;
var div = $("");