mirror of https://github.com/zulip/zulip.git
typeahead: Add typescript type definitions for typeahead.
This allows us to import typeahead from people.ts with types. This is possible since #22586 was merged. And since "sort_emojis" is always supposed to be called with valid emoji objects that have "reaction_type" with an optional "emoji_code", we add a check before we see if the emoji is popular to avoid poking popular_set with an undefined value. Signed-off-by: Zixuan James Li <p359101898@gmail.com>
This commit is contained in:
parent
9808bdf1d3
commit
53aa3f6c71
|
@ -28,7 +28,23 @@ export const popular_emojis = [
|
|||
|
||||
const unicode_marks = /\p{M}/gu;
|
||||
|
||||
export function remove_diacritics(s) {
|
||||
type Emoji =
|
||||
| {
|
||||
emoji_name: string;
|
||||
reaction_type: "realm_emoji" | "zulip_extra_emoji";
|
||||
is_realm_emoji: true;
|
||||
}
|
||||
| UnicodeEmoji;
|
||||
|
||||
// emoji_code is only available for unicode emojis.
|
||||
type UnicodeEmoji = {
|
||||
emoji_name: string;
|
||||
emoji_code: string;
|
||||
reaction_type: "unicode_emoji";
|
||||
is_realm_emoji: false;
|
||||
};
|
||||
|
||||
export function remove_diacritics(s: string): string {
|
||||
return s.normalize("NFKD").replace(unicode_marks, "");
|
||||
}
|
||||
|
||||
|
@ -36,7 +52,11 @@ export function remove_diacritics(s) {
|
|||
// * query is the user-entered search query
|
||||
// * source_str is the string we're matching in, e.g. a user's name
|
||||
// * split_char is the separator for this syntax (e.g. ' ').
|
||||
export function query_matches_string(query, source_str, split_char) {
|
||||
export function query_matches_string(
|
||||
query: string,
|
||||
source_str: string,
|
||||
split_char: string,
|
||||
): boolean {
|
||||
source_str = source_str.toLowerCase();
|
||||
source_str = remove_diacritics(source_str);
|
||||
|
||||
|
@ -53,7 +73,7 @@ export function query_matches_string(query, source_str, split_char) {
|
|||
return source_str.startsWith(query) || source_str.includes(split_char + query);
|
||||
}
|
||||
|
||||
function clean_query(query) {
|
||||
function clean_query(query: string): string {
|
||||
query = remove_diacritics(query);
|
||||
// When `abc ` with a space at the end is typed in a
|
||||
// contenteditable widget such as the composebox PM section, the
|
||||
|
@ -64,19 +84,19 @@ function clean_query(query) {
|
|||
return query;
|
||||
}
|
||||
|
||||
export function clean_query_lowercase(query) {
|
||||
export function clean_query_lowercase(query: string): string {
|
||||
query = query.toLowerCase();
|
||||
query = clean_query(query);
|
||||
return query;
|
||||
}
|
||||
|
||||
export const parse_unicode_emoji_code = (code) =>
|
||||
export const parse_unicode_emoji_code = (code: string): string =>
|
||||
code
|
||||
.split("-")
|
||||
.map((hex) => String.fromCodePoint(Number.parseInt(hex, 16)))
|
||||
.join("");
|
||||
|
||||
export function get_emoji_matcher(query) {
|
||||
export function get_emoji_matcher(query: string): (emoji: Emoji) => boolean {
|
||||
// replace spaces with underscores for emoji matching
|
||||
query = query.replace(/ /g, "_");
|
||||
query = clean_query_lowercase(query);
|
||||
|
@ -89,7 +109,11 @@ export function get_emoji_matcher(query) {
|
|||
};
|
||||
}
|
||||
|
||||
export function triage(query, objs, get_item) {
|
||||
export function triage<T>(
|
||||
query: string,
|
||||
objs: T[],
|
||||
get_item: (x: T) => string,
|
||||
): {matches: T[]; rest: T[]} {
|
||||
/*
|
||||
We split objs into four groups:
|
||||
|
||||
|
@ -128,20 +152,24 @@ export function triage(query, objs, get_item) {
|
|||
};
|
||||
}
|
||||
|
||||
export function sort_emojis(objs, query) {
|
||||
export function sort_emojis<T extends Emoji>(objs: T[], query: string): T[] {
|
||||
// replace spaces with underscores for emoji matching
|
||||
query = query.replace(/ /g, "_");
|
||||
query = query.toLowerCase();
|
||||
|
||||
function decent_match(name) {
|
||||
function decent_match(name: string): boolean {
|
||||
const pieces = name.toLowerCase().split("_");
|
||||
return pieces.some((piece) => piece.startsWith(query));
|
||||
}
|
||||
|
||||
const popular_set = new Set(popular_emojis);
|
||||
|
||||
function is_popular(obj) {
|
||||
return popular_set.has(obj.emoji_code) && decent_match(obj.emoji_name);
|
||||
function is_popular(obj: Emoji): boolean {
|
||||
return (
|
||||
obj.reaction_type === "unicode_emoji" &&
|
||||
popular_set.has(obj.emoji_code) &&
|
||||
decent_match(obj.emoji_name)
|
||||
);
|
||||
}
|
||||
|
||||
const realm_emoji_names = new Set(
|
||||
|
@ -153,7 +181,7 @@ export function sort_emojis(objs, query) {
|
|||
|
||||
const triage_results = triage(query, others, (x) => x.emoji_name);
|
||||
|
||||
function prioritise_realm_emojis(emojis) {
|
||||
function prioritise_realm_emojis(emojis: T[]): T[] {
|
||||
return [
|
||||
...emojis.filter((emoji) => emoji.is_realm_emoji),
|
||||
...emojis.filter((emoji) => !emoji.is_realm_emoji),
|
||||
|
@ -168,7 +196,7 @@ export function sort_emojis(objs, query) {
|
|||
// remove unicode emojis with same code but different names
|
||||
// and unicode emojis overridden by realm emojis with same names
|
||||
const unicode_emoji_codes = new Set();
|
||||
const sorted_unique_results = [];
|
||||
const sorted_unique_results: T[] = [];
|
||||
for (const emoji of sorted_results_with_possible_duplicates) {
|
||||
if (emoji.reaction_type !== "unicode_emoji") {
|
||||
sorted_unique_results.push(emoji);
|
Loading…
Reference in New Issue