From 2f711a070d16c904e90eeb12ca183e9053f45b06 Mon Sep 17 00:00:00 2001 From: paxapy Date: Wed, 26 Oct 2016 22:03:04 +0300 Subject: [PATCH] bugdown: Add autocomplete for #StreamName links. Fixes #1858. --- .../node_tests/composebox_typeahead.js | 11 +++++-- static/js/composebox_typeahead.js | 31 +++++++++++++++++-- static/js/typeahead_helper.js | 5 +++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/frontend_tests/node_tests/composebox_typeahead.js b/frontend_tests/node_tests/composebox_typeahead.js index 56403641f3..7109b58401 100644 --- a/frontend_tests/node_tests/composebox_typeahead.js +++ b/frontend_tests/node_tests/composebox_typeahead.js @@ -2,8 +2,12 @@ var ct = require('js/composebox_typeahead.js'); var emoji_list = [{emoji_name: "tada", emoji_url: "TBD"}, {emoji_name: "moneybags", emoji_url: "TBD"}]; +var stream_list = ['Denmark', 'Sweden']; set_global('emoji', {emojis: emoji_list}); +set_global('stream_data', {subscribed_streams: function () { + return stream_list; +}}); global.stub_out_jquery(); add_dependencies({ @@ -35,8 +39,8 @@ global.people.add({ // Stub out split_at_cursor that uses $(':focus') ct.split_at_cursor = function (word) { return [word, '']; }; - var begin_typehead_this = {options: {completions: {emoji: true, - mention: true}}}; + var begin_typehead_this = {options: {completions: { + emoji: true, mention: true, stream: true}}}; function assert_typeahead_equals(input, reference) { var returned = ct.compose_content_begins_typeahead.call(begin_typehead_this, input); @@ -62,4 +66,7 @@ global.people.add({ assert_typeahead_equals("hi emoji :ta", emoji_list); assert_typeahead_equals("hi emoji :da", emoji_list); + assert_typeahead_equals("test #", false); + assert_typeahead_equals("test #D", stream_list); + assert_typeahead_equals("#s", stream_list); }()); diff --git a/static/js/composebox_typeahead.js b/static/js/composebox_typeahead.js index 311a5ac0d4..36f822ccde 100644 --- a/static/js/composebox_typeahead.js +++ b/static/js/composebox_typeahead.js @@ -64,7 +64,10 @@ function query_matches_person(query, person) { return ( person.email .toLowerCase().indexOf(query) !== -1 || person.full_name.toLowerCase().indexOf(query) !== -1); +} +function query_matches_stream(query, stream) { + return ( stream.toLowerCase().indexOf(query.toLowerCase()) !== -1); } // Case-insensitive @@ -249,6 +252,20 @@ exports.compose_content_begins_typeahead = function (query) { return [].concat(persons, [all_item, everyone_item]); } + if (this.options.completions.stream && current_token[0] === '#') { + if (!autocomplete_checks(q, '#')) { + return false; + } + + current_token = q.substring(q.lastIndexOf('#') + 1); + if (current_token.length < 1) { + return false; + } + + this.completing = 'stream'; + this.token = current_token.substring(current_token.indexOf("#")+1); + return stream_data.subscribed_streams(); + } return false; }; @@ -258,6 +275,8 @@ exports.content_highlighter = function (item) { } else if (this.completing === 'mention') { var item_formatted = typeahead_helper.render_person(item); return typeahead_helper.highlight_with_escaping(this.token, item_formatted); + } else if (this.completing === 'stream') { + return typeahead_helper.highlight_with_escaping(this.token, item); } }; @@ -277,6 +296,10 @@ exports.content_typeahead_selected = function (item) { beginning = (beginning.substring(0, beginning.length - this.token.length-1) + '@**' + item.full_name + '** '); $(document).trigger('usermention_completed.zulip', {mentioned: item}); + } else if (this.completing === 'stream') { + beginning = (beginning.substring(0, beginning.length - this.token.length-1) + + '#**' + item + '** '); + $(document).trigger('streamname_completed.zulip', {stream: item}); } // Keep the cursor after the newly inserted text, as Bootstrap will call textbox.change() to overwrite the text @@ -288,7 +311,7 @@ exports.content_typeahead_selected = function (item) { }; exports.initialize_compose_typeahead = function (selector, completions) { - completions = $.extend({mention: false, emoji: false}, completions); + completions = $.extend({mention: false, emoji: false, stream: false}, completions); $(selector).typeahead({ items: 5, @@ -301,6 +324,8 @@ exports.initialize_compose_typeahead = function (selector, completions) { return query_matches_emoji(this.token, item); } else if (this.completing === 'mention') { return query_matches_person(this.token, item); + } else if (this.completing === 'stream') { + return query_matches_stream(this.token, item); } }, sorter: function (matches) { @@ -308,6 +333,8 @@ exports.initialize_compose_typeahead = function (selector, completions) { return typeahead_helper.sort_emojis(matches, this.token); } else if (this.completing === 'mention') { return typeahead_helper.sort_recipients(matches, this.token); + } else if (this.completing === 'stream') { + return typeahead_helper.sort_streams(matches, this.token); } }, updater: exports.content_typeahead_selected, @@ -418,7 +445,7 @@ exports.initialize = function () { stopAdvance: true // Do not advance to the next field on a tab or enter }); - exports.initialize_compose_typeahead("#new_message_content", {mention: true, emoji: true}); + exports.initialize_compose_typeahead("#new_message_content", {mention: true, emoji: true, stream: true}); $( "#private_message_recipient" ).blur(function (event) { var val = $(this).val(); diff --git a/static/js/typeahead_helper.js b/static/js/typeahead_helper.js index 37e0677149..cffc1c08a2 100644 --- a/static/js/typeahead_helper.js +++ b/static/js/typeahead_helper.js @@ -147,6 +147,11 @@ exports.sort_emojis = function (matches, query) { return results.matches.concat(results.rest); }; +exports.sort_streams = function (matches, query) { + var results = prefix_sort(query, matches, function (x) { return x; }); + return results.matches.concat(results.rest); +}; + exports.sort_recipientbox_typeahead = function (matches) { // input_text may be one or more pm recipients var cleaned = composebox_typeahead.get_cleaned_pm_recipients(this.query);