mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 13:03:29 +00:00
search suggestion: Consistently show user pills in typeahead.
Fixes #23365.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import Handlebars from "handlebars/runtime";
|
||||
import _ from "lodash";
|
||||
import assert from "minimalistic-assert";
|
||||
|
||||
@@ -10,7 +11,9 @@ import * as message_parser from "./message_parser";
|
||||
import * as message_store from "./message_store";
|
||||
import type {Message} from "./message_store";
|
||||
import {page_params} from "./page_params";
|
||||
import type {User} from "./people";
|
||||
import * as people from "./people";
|
||||
import type {UserPillItem} from "./search_suggestion";
|
||||
import {realm} from "./state_data";
|
||||
import type {NarrowTerm} from "./state_data";
|
||||
import * as stream_data from "./stream_data";
|
||||
@@ -54,8 +57,17 @@ type Part =
|
||||
type: "prefix_for_operator";
|
||||
prefix_for_operator: string;
|
||||
operand: string;
|
||||
}
|
||||
| {
|
||||
type: "user_pill";
|
||||
operator: string;
|
||||
users: ValidOrInvalidUser[];
|
||||
};
|
||||
|
||||
type ValidOrInvalidUser =
|
||||
| {valid_user: true; user_pill_context: UserPillItem}
|
||||
| {valid_user: false; operand: string};
|
||||
|
||||
// TODO: When "stream" is renamed to "channel", these placeholders
|
||||
// should be removed, or replaced with helper functions similar
|
||||
// to util.is_topic_synonym.
|
||||
@@ -254,6 +266,28 @@ function message_matches_search_term(message: Message, operator: string, operand
|
||||
return true; // unknown operators return true (effectively ignored)
|
||||
}
|
||||
|
||||
// For when we don't need to do highlighting
|
||||
export function create_user_pill_context(user: User): UserPillItem {
|
||||
const avatar_url = people.small_avatar_url_for_person(user);
|
||||
|
||||
return {
|
||||
id: user.user_id,
|
||||
display_value: new Handlebars.SafeString(user.full_name),
|
||||
has_image: true,
|
||||
img_src: avatar_url,
|
||||
should_add_guest_user_indicator: people.should_add_guest_user_indicator(user.user_id),
|
||||
};
|
||||
}
|
||||
|
||||
const USER_OPERATORS = new Set([
|
||||
"dm-including",
|
||||
"dm",
|
||||
"sender",
|
||||
"from",
|
||||
"pm-with",
|
||||
"group-pm-with",
|
||||
]);
|
||||
|
||||
export class Filter {
|
||||
_terms: NarrowTerm[];
|
||||
_sub?: StreamSubscription | undefined;
|
||||
@@ -371,9 +405,7 @@ export class Filter {
|
||||
|
||||
static decodeOperand(encoded: string, operator: string): string {
|
||||
encoded = encoded.replaceAll('"', "");
|
||||
if (
|
||||
!["dm-including", "dm", "sender", "from", "pm-with", "group-pm-with"].includes(operator)
|
||||
) {
|
||||
if (!USER_OPERATORS.has(operator)) {
|
||||
encoded = encoded.replaceAll("+", " ");
|
||||
}
|
||||
return util.robust_url_decode(encoded).trim();
|
||||
@@ -640,6 +672,27 @@ export class Filter {
|
||||
canonicalized_operator,
|
||||
term.negated,
|
||||
);
|
||||
if (USER_OPERATORS.has(canonicalized_operator)) {
|
||||
const user_emails = operand.split(",");
|
||||
const users: ValidOrInvalidUser[] = user_emails.map((email) => {
|
||||
const person = people.get_by_email(email);
|
||||
if (person === undefined) {
|
||||
return {
|
||||
valid_user: false,
|
||||
operand: email,
|
||||
};
|
||||
}
|
||||
return {
|
||||
valid_user: true,
|
||||
user_pill_context: create_user_pill_context(person),
|
||||
};
|
||||
});
|
||||
return {
|
||||
type: "user_pill",
|
||||
operator: prefix_for_operator,
|
||||
users,
|
||||
};
|
||||
}
|
||||
if (prefix_for_operator !== "") {
|
||||
return {
|
||||
type: "prefix_for_operator",
|
||||
|
||||
@@ -5,7 +5,7 @@ import render_user_pill from "../templates/user_pill.hbs";
|
||||
|
||||
import * as common from "./common";
|
||||
import * as direct_message_group_data from "./direct_message_group_data";
|
||||
import {Filter} from "./filter";
|
||||
import {Filter, create_user_pill_context} from "./filter";
|
||||
import * as narrow_state from "./narrow_state";
|
||||
import {page_params} from "./page_params";
|
||||
import * as people from "./people";
|
||||
@@ -16,7 +16,7 @@ import * as stream_topic_history from "./stream_topic_history";
|
||||
import * as stream_topic_history_util from "./stream_topic_history_util";
|
||||
import * as typeahead_helper from "./typeahead_helper";
|
||||
|
||||
type UserPillItem = {
|
||||
export type UserPillItem = {
|
||||
id: number;
|
||||
display_value: Handlebars.SafeString;
|
||||
has_image: boolean;
|
||||
@@ -41,18 +41,6 @@ export type Suggestion = {
|
||||
}
|
||||
);
|
||||
|
||||
function create_user_pill_context(user: User): UserPillItem {
|
||||
const avatar_url = people.small_avatar_url_for_person(user);
|
||||
|
||||
return {
|
||||
id: user.user_id,
|
||||
display_value: new Handlebars.SafeString(user.full_name),
|
||||
has_image: true,
|
||||
img_src: avatar_url,
|
||||
should_add_guest_user_indicator: people.should_add_guest_user_indicator(user.user_id),
|
||||
};
|
||||
}
|
||||
|
||||
export const max_num_of_search_results = 12;
|
||||
|
||||
function channel_matches_query(channel_name: string, q: string): boolean {
|
||||
|
||||
@@ -14,6 +14,17 @@
|
||||
{{~!-- squash whitespace --~}}
|
||||
{{this.prefix_for_operator}} {{this.operand}}
|
||||
{{~!-- squash whitespace --~}}
|
||||
{{else if (eq this.type "user_pill")}}
|
||||
{{~!-- squash whitespace --~}}
|
||||
{{this.operator}}
|
||||
{{~#each this.users}}
|
||||
{{#if this.valid_user}}
|
||||
{{> user_pill}}
|
||||
{{else}}
|
||||
{{this.operand}}
|
||||
{{/if}}
|
||||
{{~/each~}}
|
||||
{{~!-- squash whitespace --~}}
|
||||
{{else if (eq this.type "is_operator")}}
|
||||
{{#if (eq this.operand "mentioned")}}
|
||||
{{~!-- squash whitespace --~}}
|
||||
|
||||
Reference in New Issue
Block a user