From 6a26014b81004416f32a23ead7d770e96f6622f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Astori?= Date: Fri, 30 Dec 2016 00:32:27 -0500 Subject: [PATCH 1/4] Implement fuzzy-matching for the user list --- client/js/lounge.js | 31 +++++++++++++++++++++---------- package.json | 1 + webpack.config.js | 1 + 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/client/js/lounge.js b/client/js/lounge.js index 1857339e..4090b898 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -6,6 +6,7 @@ const $ = require("jquery"); const moment = require("moment"); const Mousetrap = require("mousetrap"); const URI = require("urijs"); +const fuzzy = require("fuzzy"); // our libraries require("./libs/jquery/inputhistory"); @@ -1067,16 +1068,26 @@ $(function() { }); chat.on("input", ".search", function() { - var value = $(this).val().toLowerCase(); - var names = $(this).closest(".users").find(".names"); - names.find(".user").each(function() { - var btn = $(this); - var name = btn.text().toLowerCase().replace(/[+%@~]/, ""); - if (name.indexOf(value) > -1) { - btn.show(); - } else { - btn.hide(); - } + const value = $(this).val().toLowerCase(); + const names = $(this).closest(".users").find(".names"); + + names.find(".user").each((i, el) => { + $(el).text($(el).text().replace(/<\/?b>;/, "")).hide(); + }); + + const fuzzyOptions = { + pre: "", + post: "", + extract: el => $(el).text().toLowerCase().replace(/[+%@~]/, "") + }; + + fuzzy.filter( + value, + names.find(".user").toArray(), + fuzzyOptions + ).forEach(el => { + const firstChar = $(el.original).text()[0].replace(/[^+%@~]/, ""); + $(el.original).html(firstChar + el.string).show(); }); }); diff --git a/package.json b/package.json index a23c0366..d2d88b0d 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "chai": "3.5.0", "eslint": "3.19.0", "font-awesome": "4.7.0", + "fuzzy": "0.1.3", "handlebars": "4.0.6", "handlebars-loader": "1.5.0", "jquery": "3.2.1", diff --git a/webpack.config.js b/webpack.config.js index b54015cb..cf2e9990 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -18,6 +18,7 @@ let config = { "mousetrap", "socket.io-client", "urijs", + "fuzzy", ], }, devtool: "source-map", From cfa9da17a728ea0e2b8799c2cf6df7caca018b60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Astori?= Date: Sun, 1 Jan 2017 21:20:48 -0500 Subject: [PATCH 2/4] Rely on fuzzy's case insensitivity, do not trim mode --- client/js/lounge.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/js/lounge.js b/client/js/lounge.js index 4090b898..5fd07abe 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -1068,7 +1068,7 @@ $(function() { }); chat.on("input", ".search", function() { - const value = $(this).val().toLowerCase(); + const value = $(this).val(); const names = $(this).closest(".users").find(".names"); names.find(".user").each((i, el) => { @@ -1078,7 +1078,7 @@ $(function() { const fuzzyOptions = { pre: "", post: "", - extract: el => $(el).text().toLowerCase().replace(/[+%@~]/, "") + extract: el => $(el).text() }; fuzzy.filter( @@ -1086,8 +1086,7 @@ $(function() { names.find(".user").toArray(), fuzzyOptions ).forEach(el => { - const firstChar = $(el.original).text()[0].replace(/[^+%@~]/, ""); - $(el.original).html(firstChar + el.string).show(); + $(el.original).html(el.string).show(); }); }); From b1e9a7ffda5bdca68b29c9229d8f954b2d9b0cb0 Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sat, 28 Jan 2017 19:37:26 +0200 Subject: [PATCH 3/4] Use separate container for search results --- client/css/style.css | 4 ++++ client/js/lounge.js | 21 +++++++++++++-------- client/views/index.js | 1 + client/views/user.tpl | 3 ++- client/views/user_filtered.tpl | 5 +++++ 5 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 client/views/user_filtered.tpl diff --git a/client/css/style.css b/client/css/style.css index 7fbd6492..1327f271 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -1219,6 +1219,10 @@ kbd { content: "Users"; } +#chat .user-mode-search:before { + content: "Search Results"; +} + #loading { font-size: 14px; z-index: 1; diff --git a/client/js/lounge.js b/client/js/lounge.js index 5fd07abe..3d27ec68 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -1069,11 +1069,15 @@ $(function() { chat.on("input", ".search", function() { const value = $(this).val(); - const names = $(this).closest(".users").find(".names"); + const parent = $(this).closest(".users"); + const names = parent.find(".names-original"); + const container = parent.find(".names-filtered"); - names.find(".user").each((i, el) => { - $(el).text($(el).text().replace(/<\/?b>;/, "")).hide(); - }); + if (!value.length) { + container.hide(); + names.show(); + return; + } const fuzzyOptions = { pre: "", @@ -1081,13 +1085,14 @@ $(function() { extract: el => $(el).text() }; - fuzzy.filter( + const result = fuzzy.filter( value, names.find(".user").toArray(), fuzzyOptions - ).forEach(el => { - $(el.original).html(el.string).show(); - }); + ); + + names.hide(); + container.html(templates.user_filtered({matches: result})).show(); }); chat.on("msg", ".messages", function(e, target, msg) { diff --git a/client/views/index.js b/client/views/index.js index fa1916ee..201690ee 100644 --- a/client/views/index.js +++ b/client/views/index.js @@ -30,4 +30,5 @@ module.exports = { toggle: require("./toggle.tpl"), unread_marker: require("./unread_marker.tpl"), user: require("./user.tpl"), + user_filtered: require("./user_filtered.tpl"), }; diff --git a/client/views/user.tpl b/client/views/user.tpl index 23a3a9f0..29a6872c 100644 --- a/client/views/user.tpl +++ b/client/views/user.tpl @@ -2,8 +2,9 @@
+
{{/if}} -
+
{{#diff "reset"}}{{/diff}} {{#each users}} {{#diff mode}} diff --git a/client/views/user_filtered.tpl b/client/views/user_filtered.tpl new file mode 100644 index 00000000..1b86f99d --- /dev/null +++ b/client/views/user_filtered.tpl @@ -0,0 +1,5 @@ + From c583d6edf9d01276e6be03e372146bd44dae452c Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Sat, 22 Apr 2017 15:49:01 +0300 Subject: [PATCH 4/4] Correctly update user list and search filtering on user updates --- client/css/style.css | 19 +++++++------------ client/js/libs/handlebars/users.js | 5 ----- client/js/lounge.js | 19 +++++++++++++++++-- client/views/chat.tpl | 10 +++++++++- client/views/user.tpl | 28 ++++++++++------------------ 5 files changed, 43 insertions(+), 38 deletions(-) delete mode 100644 client/js/libs/handlebars/users.js diff --git a/client/css/style.css b/client/css/style.css index 1327f271..89b01c94 100644 --- a/client/css/style.css +++ b/client/css/style.css @@ -768,6 +768,9 @@ kbd { overflow: auto; -webkit-overflow-scrolling: touch; position: absolute; +} + +#chat .channel .chat { right: 180px; } @@ -791,18 +794,6 @@ kbd { transform: translateZ(0); } -#chat .lobby .chat, -#chat .special .chat, -#chat .query .chat { - right: 0; -} - -#chat .lobby .sidebar, -#chat .special .sidebar, -#chat .query .sidebar { - display: none; -} - #chat .show-more { display: none; padding: 10px; @@ -1180,6 +1171,10 @@ kbd { width: 100%; } +#chat .names-filtered { + display: none; +} + #chat .names .user { display: block; line-height: 1.6; diff --git a/client/js/libs/handlebars/users.js b/client/js/libs/handlebars/users.js deleted file mode 100644 index d962423c..00000000 --- a/client/js/libs/handlebars/users.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; - -module.exports = function(count) { - return count + " " + (count === 1 ? "user" : "users"); -}; diff --git a/client/js/lounge.js b/client/js/lounge.js index 3d27ec68..a0e52e60 100644 --- a/client/js/lounge.js +++ b/client/js/lounge.js @@ -258,7 +258,10 @@ $(function() { function renderChannel(data) { renderChannelMessages(data); - renderChannelUsers(data); + + if (data.type === "channel") { + renderChannelUsers(data); + } } function renderChannelMessages(data) { @@ -318,7 +321,19 @@ $(function() { return (oldSortOrder[a] || Number.MAX_VALUE) - (oldSortOrder[b] || Number.MAX_VALUE); }); - users.html(templates.user(data)).data("nicks", nicks); + const search = users + .find(".search") + .attr("placeholder", nicks.length + " " + (nicks.length === 1 ? "user" : "users")); + + users + .find(".names-original") + .html(templates.user(data)) + .data("nicks", nicks); + + // Refresh user search + if (search.val().length) { + search.trigger("input"); + } } function renderNetworks(data) { diff --git a/client/views/chat.tpl b/client/views/chat.tpl index 9ccb6391..898dd75b 100644 --- a/client/views/chat.tpl +++ b/client/views/chat.tpl @@ -19,8 +19,16 @@
+ {{#equal type "channel"}} + {{/equal}} {{/each}} diff --git a/client/views/user.tpl b/client/views/user.tpl index 29a6872c..b0af2a0c 100644 --- a/client/views/user.tpl +++ b/client/views/user.tpl @@ -1,19 +1,11 @@ -{{#if users.length}} -
- -
-
-{{/if}} -
- {{#diff "reset"}}{{/diff}} - {{#each users}} - {{#diff mode}} - {{#unless @first}} -
- {{/unless}} -
- {{/diff}} - {{mode}}{{name}} - {{/each}} -
+{{#diff "reset"}}{{/diff}} +{{#each users}} + {{#diff mode}} + {{#unless @first}} + + {{/unless}} +
+ {{/diff}} + {{mode}}{{name}} +{{/each}}