mirror of https://github.com/zulip/zulip.git
Refactor typeahead for user names (PM and @reply).
Get data directly from the main user list, rather than maintaining a separate list just for autocomplete. Fixes trac #1362 -- Does not depend on historical messages, so will do the correct autocomplete after a single reload. (imported from commit 6b35a709dba3384530082e8cfacf0151f9e0eb26)
This commit is contained in:
parent
fbed3e23a8
commit
9322e63d32
|
@ -34,14 +34,16 @@ function get_last_recipient_in_pm(query_string) {
|
|||
}
|
||||
|
||||
function composebox_typeahead_highlighter(item) {
|
||||
var query = this.query;
|
||||
if ($(this.$element).attr('id') === 'private_message_recipient') {
|
||||
// There could be multiple recipients in a private message,
|
||||
// we want to decide what to highlight based only on the most
|
||||
// recent one we're entering.
|
||||
query = get_last_recipient_in_pm(this.query);
|
||||
}
|
||||
return typeahead_helper.highlight_with_escaping(query, item);
|
||||
return typeahead_helper.highlight_with_escaping(this.query, item);
|
||||
}
|
||||
|
||||
function query_matches_person (query, person) {
|
||||
// Case-insensitive.
|
||||
query = query.toLowerCase();
|
||||
|
||||
return ( person.email .toLowerCase().indexOf(query) !== -1
|
||||
|| person.full_name.toLowerCase().indexOf(query) !== -1);
|
||||
|
||||
}
|
||||
|
||||
// nextFocus is set on a keydown event to indicate where we should focus on keyup.
|
||||
|
@ -206,10 +208,14 @@ exports.initialize = function () {
|
|||
});
|
||||
|
||||
$( "#private_message_recipient" ).typeahead({
|
||||
source: typeahead_helper.private_message_typeahead_list,
|
||||
source: page_params.people_list,
|
||||
items: 5,
|
||||
dropup: true,
|
||||
highlighter: composebox_typeahead_highlighter,
|
||||
highlighter: function (item) {
|
||||
var query = get_last_recipient_in_pm(this.query);
|
||||
var item_formatted = typeahead_helper.render_person(item);
|
||||
return typeahead_helper.highlight_with_escaping(query, item_formatted);
|
||||
},
|
||||
matcher: function (item) {
|
||||
var current_recipient = get_last_recipient_in_pm(this.query);
|
||||
// If the name is only whitespace (does not contain any non-whitespace),
|
||||
|
@ -218,8 +224,7 @@ exports.initialize = function () {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Case-insensitive.
|
||||
return (item.toLowerCase().indexOf(current_recipient.toLowerCase()) !== -1);
|
||||
return query_matches_person(current_recipient, item);
|
||||
},
|
||||
sorter: typeahead_helper.sort_recipientbox_typeahead,
|
||||
updater: function (item) {
|
||||
|
@ -229,15 +234,18 @@ exports.initialize = function () {
|
|||
if (previous_recipients.length !== 0) {
|
||||
previous_recipients += ", ";
|
||||
}
|
||||
return previous_recipients + typeahead_helper.private_message_mapped[item].email + ", ";
|
||||
return previous_recipients + item.email + ", ";
|
||||
},
|
||||
stopAdvance: true // Do not advance to the next field on a tab or enter
|
||||
});
|
||||
|
||||
$( "#new_message_content" ).typeahead({
|
||||
source: typeahead_helper.private_message_typeahead_list,
|
||||
source: page_params.people_list,
|
||||
items: 5,
|
||||
highlighter: composebox_typeahead_highlighter,
|
||||
highlighter: function (item) {
|
||||
var item_formatted = typeahead_helper.render_person(item);
|
||||
return typeahead_helper.highlight_with_escaping(this.query, item_formatted);
|
||||
},
|
||||
dropup: true,
|
||||
matcher: function (item) {
|
||||
var query = exports.split_at_cursor(this.query)[0];
|
||||
|
@ -250,10 +258,8 @@ exports.initialize = function () {
|
|||
if (current_recipient.length < 2 || current_recipient.charAt(0) !== "@") {
|
||||
return false;
|
||||
}
|
||||
current_recipient = current_recipient.substring(1);
|
||||
|
||||
// Case-insensitive.
|
||||
return (item.toLowerCase().indexOf(current_recipient.toLowerCase()) !== -1);
|
||||
return query_matches_person(current_recipient.substring(1), item);
|
||||
},
|
||||
sorter: typeahead_helper.sort_textbox_typeahead,
|
||||
updater: function (item) {
|
||||
|
@ -261,7 +267,7 @@ exports.initialize = function () {
|
|||
var beginning = pieces[0];
|
||||
var rest = pieces[1];
|
||||
|
||||
beginning = beginning.replace(/@\S+$/, "") + "@**" + typeahead_helper.private_message_mapped[item].full_name + "**";
|
||||
beginning = beginning.replace(/@\S+$/, "") + "@**" + item.full_name + "**";
|
||||
// Keep the cursor after the newly inserted name, as Bootstrap will call textbox.change() to overwrite the text
|
||||
// in the textbox.
|
||||
setTimeout(function () {
|
||||
|
|
|
@ -159,7 +159,7 @@ function searchbox_sorter(items) {
|
|||
// Get the first object in sorted order.
|
||||
if (action === 'private_message' || action === 'sender') {
|
||||
objs.sort(function (x, y) {
|
||||
return typeahead_helper.compare_by_pms(get_person(x), get_person(y));
|
||||
return typeahead_helper.compare_by_pms(get_query(x), get_query(y));
|
||||
});
|
||||
} else if (action !== 'stream') {
|
||||
// streams are already sorted
|
||||
|
|
|
@ -145,24 +145,16 @@ exports.sorter = function (query, objs, get_item) {
|
|||
return results.matches.concat(results.rest);
|
||||
};
|
||||
|
||||
exports.compare_by_pms = function(user_a, user_b) {
|
||||
var x_count = 0, y_count = 0;
|
||||
if (typeahead_helper.private_message_mapped[user_a]) {
|
||||
x_count = typeahead_helper.private_message_mapped[user_a].count;
|
||||
}
|
||||
if (typeahead_helper.private_message_mapped[user_b]) {
|
||||
y_count = typeahead_helper.private_message_mapped[user_b].count;
|
||||
}
|
||||
|
||||
if (x_count > y_count) {
|
||||
exports.compare_by_pms = function (user_a, user_b) {
|
||||
if (user_a.pm_recipient_count > user_b.pm_recipient_count) {
|
||||
return -1;
|
||||
} else if (x_count < y_count) {
|
||||
} else if (user_a.pm_recipient_count < user_b.pm_recipient_count) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// We use alpha sort as a tiebreaker, which might be helpful for
|
||||
// new users.
|
||||
if (user_a < user_b)
|
||||
if (user_a.full_name < user_b.full_name)
|
||||
return -1;
|
||||
else if (user_a === user_b)
|
||||
return 0;
|
||||
|
@ -171,10 +163,7 @@ exports.compare_by_pms = function(user_a, user_b) {
|
|||
};
|
||||
|
||||
exports.sort_by_pms = function(objs) {
|
||||
objs.sort(function (x, y) {
|
||||
return exports.compare_by_pms(x, y);
|
||||
});
|
||||
|
||||
objs.sort(exports.compare_by_pms);
|
||||
return objs;
|
||||
};
|
||||
|
||||
|
@ -182,17 +171,13 @@ function identity(item) {
|
|||
return item;
|
||||
}
|
||||
|
||||
function email_from_identity(identity) {
|
||||
return exports.private_message_mapped[identity].email;
|
||||
}
|
||||
|
||||
exports.sort_subjects = function (items) {
|
||||
return exports.sorter(this.query, items, identity);
|
||||
};
|
||||
|
||||
exports.sort_recipients = function (matches, query) {
|
||||
var name_results = prefix_sort(query, matches, identity);
|
||||
var email_results = prefix_sort(query, name_results.rest, email_from_identity);
|
||||
var name_results = prefix_sort(query, matches, function (x) { return x.full_name; });
|
||||
var email_results = prefix_sort(query, name_results.rest, function (x) { return x.email; });
|
||||
var matches_sorted_by_pms = exports.sort_by_pms(name_results.matches.concat(email_results.matches));
|
||||
var rest_sorted_by_pms = exports.sort_by_pms(email_results.rest);
|
||||
return matches_sorted_by_pms.concat(rest_sorted_by_pms);
|
||||
|
|
|
@ -1571,7 +1571,6 @@ $(function () {
|
|||
});
|
||||
|
||||
// initialize other stuff
|
||||
typeahead_helper.update_all_recipients(page_params.people_list);
|
||||
composebox_typeahead.initialize();
|
||||
search.initialize();
|
||||
notifications.initialize();
|
||||
|
|
|
@ -43,6 +43,7 @@ var pointer_update_in_flight = false;
|
|||
function add_person(person) {
|
||||
page_params.people_list.push(person);
|
||||
people_dict[person.email] = person;
|
||||
person.pm_recipient_count = 0;
|
||||
}
|
||||
|
||||
function remove_person(person) {
|
||||
|
@ -59,11 +60,15 @@ function remove_person(person) {
|
|||
$(function () {
|
||||
$.each(page_params.people_list, function (idx, person) {
|
||||
people_dict[person.email] = person;
|
||||
person.pm_recipient_count = 0;
|
||||
});
|
||||
|
||||
// The special account feedback@humbughq.com is used for in-app
|
||||
// feedback and should always show up as an autocomplete option.
|
||||
typeahead_helper.update_your_recipients([{"email": "feedback@humbughq.com",
|
||||
"full_name": "Humbug Feedback Bot"}]);
|
||||
if (people_dict['feedback@humbughq.com'] === undefined){
|
||||
add_person({"email": "feedback@humbughq.com",
|
||||
"full_name": "Humbug Feedback Bot"});
|
||||
}
|
||||
|
||||
$.each(page_params.initial_presences, function (email, presence) {
|
||||
activity.set_user_status(email, presence, page_params.initial_servertime);
|
||||
|
@ -577,12 +582,6 @@ function add_message_metadata(message, dummy) {
|
|||
message.display_reply_to = get_private_message_recipient(message, 'full_name');
|
||||
|
||||
involved_people = message.display_recipient;
|
||||
|
||||
if (message.sent_by_me) {
|
||||
typeahead_helper.update_your_recipients(involved_people);
|
||||
} else {
|
||||
typeahead_helper.update_all_recipients(involved_people);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -592,9 +591,12 @@ function add_message_metadata(message, dummy) {
|
|||
// with keys like "hasOwnProperty"
|
||||
if (people_dict[person.email] === undefined) {
|
||||
add_person(person);
|
||||
if (!typeahead_helper.known_to_typeahead(person)) {
|
||||
typeahead_helper.autocomplete_needs_update(true);
|
||||
}
|
||||
typeahead_helper.autocomplete_needs_update(true);
|
||||
}
|
||||
|
||||
if (message.type === 'private' && message.sent_by_me) {
|
||||
// Track the number of PMs we've sent to this person to improve autocomplete
|
||||
people_dict[person.email].pm_recipient_count += 1;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -849,10 +851,8 @@ function get_updates(options) {
|
|||
case 'realm_user':
|
||||
if (event.op === 'add') {
|
||||
add_person(event.person);
|
||||
typeahead_helper.update_all_recipients([event.person]);
|
||||
} else if (event.op === 'remove') {
|
||||
remove_person(event.person);
|
||||
typeahead_helper.remove_recipient([event.person]);
|
||||
}
|
||||
typeahead_helper.autocomplete_needs_update(true);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue