input_pill: Remove InputPillItem now that details are handled elsewhere.

This commit is contained in:
evykassirer 2024-07-29 22:21:29 -07:00 committed by Tim Abbott
parent 6e47d851ec
commit 271efb70fa
10 changed files with 48 additions and 70 deletions

View File

@ -4,20 +4,19 @@ import render_input_pill from "../templates/input_pill.hbs";
import * as blueslip from "./blueslip";
import * as input_pill from "./input_pill";
import type {InputPillItem} from "./input_pill";
import * as keydown_util from "./keydown_util";
import type {User} from "./people";
import * as pill_typeahead from "./pill_typeahead";
import * as stream_pill from "./stream_pill";
import type {CombinedPill, CombinedPillContainer, CombinedPillItem} from "./typeahead_helper";
import type {CombinedPill, CombinedPillContainer} from "./typeahead_helper";
import * as user_group_pill from "./user_group_pill";
import * as user_groups from "./user_groups";
import * as user_pill from "./user_pill";
function create_item_from_text(
text: string,
current_items: CombinedPillItem[],
): CombinedPillItem | undefined {
current_items: CombinedPill[],
): CombinedPill | undefined {
const funcs = [
stream_pill.create_item_from_stream_name,
user_group_pill.create_item_from_group_name,
@ -32,7 +31,7 @@ function create_item_from_text(
return undefined;
}
function get_text_from_item(item: CombinedPillItem): string {
function get_text_from_item(item: CombinedPill): string {
let text: string;
switch (item.type) {
case "stream":
@ -66,7 +65,7 @@ function set_up_pill_typeahead({
pill_typeahead.set_up_combined($pill_container.find(".input"), pill_widget, opts);
}
function get_display_value_from_item(item: InputPillItem<CombinedPill>): string {
function get_display_value_from_item(item: CombinedPill): string {
if (item.type === "user_group") {
return user_group_pill.display_pill(user_groups.get_user_group_from_id(item.group_id));
} else if (item.type === "stream") {
@ -76,7 +75,7 @@ function get_display_value_from_item(item: InputPillItem<CombinedPill>): string
return user_pill.get_display_value_from_item(item);
}
function generate_pill_html(item: InputPillItem<CombinedPill>): string {
function generate_pill_html(item: CombinedPill): string {
if (item.type === "user_group") {
return render_input_pill({
display_value: get_display_value_from_item(item),

View File

@ -1,6 +1,6 @@
import $ from "jquery";
import type {InputPillConfig, InputPillItem} from "./input_pill";
import type {InputPillConfig} from "./input_pill";
import * as input_pill from "./input_pill";
import type {User} from "./people";
import * as people from "./people";
@ -23,8 +23,7 @@ export function initialize_pill(): UserPillWidget {
create_item_from_text: user_pill.create_item_from_email,
get_text_from_item: user_pill.get_email_from_item,
get_display_value_from_item: user_pill.get_display_value_from_item,
generate_pill_html: (item: InputPillItem<UserPill>) =>
user_pill.generate_pill_html(item, true),
generate_pill_html: (item: UserPill) => user_pill.generate_pill_html(item, true),
});
return pill;

View File

@ -1,7 +1,8 @@
import type {InputPillConfig, InputPillContainer, InputPillItem} from "./input_pill";
import type {InputPillConfig, InputPillContainer} from "./input_pill";
import * as input_pill from "./input_pill";
type EmailPill = {
type: "email";
email: string;
};
@ -11,8 +12,8 @@ const email_regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
export function create_item_from_email(
email: string,
current_items: InputPillItem<EmailPill>[],
): InputPillItem<EmailPill> | undefined {
current_items: EmailPill[],
): EmailPill | undefined {
if (!email_regex.test(email)) {
return undefined;
}
@ -28,7 +29,7 @@ export function create_item_from_email(
};
}
export function get_email_from_item(item: InputPillItem<EmailPill>): string {
export function get_email_from_item(item: EmailPill): string {
return item.email;
}

View File

@ -5,17 +5,12 @@ import assert from "minimalistic-assert";
import render_input_pill from "../templates/input_pill.hbs";
import * as blueslip from "./blueslip";
import * as keydown_util from "./keydown_util";
import type {SearchUserPill} from "./search_pill";
import * as ui_util from "./ui_util";
// See https://zulip.readthedocs.io/en/latest/subsystems/input-pills.html
export type InputPillItem<ItemType> = {
type: string;
} & ItemType;
export type InputPillConfig = {
exclude_inaccessible_users?: boolean;
};
@ -27,16 +22,16 @@ type InputPillCreateOptions<ItemType> = {
convert_to_pill_on_enter?: boolean;
create_item_from_text: (
text: string,
existing_items: InputPillItem<ItemType>[],
existing_items: ItemType[],
pill_config?: InputPillConfig | undefined,
) => InputPillItem<ItemType> | undefined;
get_text_from_item: (item: InputPillItem<ItemType>) => string;
get_display_value_from_item: (item: InputPillItem<ItemType>) => string;
generate_pill_html?: (item: InputPillItem<ItemType>) => string;
) => ItemType | undefined;
get_text_from_item: (item: ItemType) => string;
get_display_value_from_item: (item: ItemType) => string;
generate_pill_html?: (item: ItemType) => string;
};
type InputPill<ItemType> = {
item: InputPillItem<ItemType>;
item: ItemType;
$element: JQuery;
};
@ -60,9 +55,9 @@ type InputPillStore<ItemType> = {
// These are the functions that are exposed to other modules.
export type InputPillContainer<ItemType> = {
appendValue: (text: string) => void;
appendValidatedData: (item: InputPillItem<ItemType>) => void;
appendValidatedData: (item: ItemType) => void;
getByElement: (element: HTMLElement) => InputPill<ItemType> | undefined;
items: () => InputPillItem<ItemType>[];
items: () => ItemType[];
onPillCreate: (callback: () => void) => void;
onPillRemove: (
callback: (pill: InputPill<ItemType>, trigger: RemovePillTrigger) => void,
@ -78,7 +73,7 @@ export type InputPillContainer<ItemType> = {
export type RemovePillTrigger = "close" | "backspace" | "clear";
export function create<ItemType>(
export function create<ItemType extends {type: string}>(
opts: InputPillCreateOptions<ItemType>,
): InputPillContainer<ItemType> {
// a stateful object of this `pill_container` instance.
@ -140,11 +135,7 @@ export function create<ItemType>(
// This is generally called by typeahead logic, where we have all
// the data we need (as opposed to, say, just a user-typed email).
appendValidatedData(item: InputPillItem<ItemType>) {
if (!item.type) {
blueslip.error("no type defined for the item");
return;
}
appendValidatedData(item: ItemType) {
let pill_html;
if (store.generate_pill_html !== undefined) {
pill_html = store.generate_pill_html(item);
@ -230,7 +221,7 @@ export function create<ItemType>(
// TODO: Figure out how to get this typed correctly.
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const user_pill_container = store.pills[container_idx]!
.item as unknown as InputPillItem<SearchUserPill>;
.item as unknown as SearchUserPill;
// If there's only one user in this pill, delete the whole pill.
if (user_pill_container.users.length === 1) {

View File

@ -4,7 +4,8 @@ import * as input_pill from "./input_pill";
import {set_up_stream} from "./pill_typeahead";
import * as stream_data from "./stream_data";
import * as stream_pill from "./stream_pill";
import type {CombinedPillItem} from "./typeahead_helper";
import type {StreamPill} from "./stream_pill";
import type {CombinedPill} from "./typeahead_helper";
type SetUpPillTypeaheadConfig = {
pill_widget: stream_pill.StreamPillWidget;
@ -13,8 +14,8 @@ type SetUpPillTypeaheadConfig = {
function create_item_from_stream_name(
stream_name: string,
current_items: CombinedPillItem[],
): input_pill.InputPillItem<stream_pill.StreamPill> | undefined {
current_items: CombinedPill[],
): StreamPill | undefined {
const stream_prefix_required = false;
const get_allowed_streams = stream_data.get_invite_stream_data;
const show_stream_sub_count = false;

View File

@ -1,11 +1,11 @@
import assert from "minimalistic-assert";
import {$t} from "./i18n";
import type {InputPillContainer, InputPillItem} from "./input_pill";
import type {InputPillContainer} from "./input_pill";
import * as peer_data from "./peer_data";
import * as stream_data from "./stream_data";
import type {StreamSubscription} from "./sub_store";
import type {CombinedPillContainer, CombinedPillItem} from "./typeahead_helper";
import type {CombinedPill, CombinedPillContainer} from "./typeahead_helper";
export type StreamPill = {
type: "stream";
@ -27,11 +27,11 @@ function format_stream_name_and_subscriber_count(sub: StreamSubscription): strin
export function create_item_from_stream_name(
stream_name: string,
current_items: CombinedPillItem[],
current_items: CombinedPill[],
stream_prefix_required = true,
get_allowed_streams: () => StreamSubscription[] = stream_data.get_unsorted_subs,
show_subscriber_count = true,
): InputPillItem<StreamPill> | undefined {
): StreamPill | undefined {
stream_name = stream_name.trim();
if (stream_prefix_required) {
if (!stream_name.startsWith("#")) {
@ -65,7 +65,7 @@ export function create_item_from_stream_name(
};
}
export function get_stream_name_from_item(item: InputPillItem<StreamPill>): string {
export function get_stream_name_from_item(item: StreamPill): string {
return item.stream.name;
}

View File

@ -10,7 +10,7 @@ import {MAX_ITEMS} from "./bootstrap_typeahead";
import * as buddy_data from "./buddy_data";
import * as compose_state from "./compose_state";
import type {LanguageSuggestion, SlashCommandSuggestion} from "./composebox_typeahead";
import type {InputPillContainer, InputPillItem} from "./input_pill";
import type {InputPillContainer} from "./input_pill";
import * as people from "./people";
import type {PseudoMentionUser, User} from "./people";
import * as pm_conversations from "./pm_conversations";
@ -36,7 +36,6 @@ export type UserOrMentionPillData = UserOrMention & {
export type CombinedPill = StreamPill | UserGroupPill | UserPill;
export type CombinedPillContainer = InputPillContainer<CombinedPill>;
export type CombinedPillItem = InputPillItem<CombinedPill>;
export function build_highlight_regex(query: string): RegExp {
const regex = new RegExp("(" + _.escapeRegExp(query) + ")", "ig");

View File

@ -1,7 +1,7 @@
import {$t_html} from "./i18n";
import type {InputPillContainer, InputPillItem} from "./input_pill";
import type {InputPillContainer} from "./input_pill";
import * as people from "./people";
import type {CombinedPillContainer, CombinedPillItem} from "./typeahead_helper";
import type {CombinedPill, CombinedPillContainer} from "./typeahead_helper";
import type {UserGroup} from "./user_groups";
import * as user_groups from "./user_groups";
@ -28,8 +28,8 @@ export function display_pill(group: UserGroup): string {
export function create_item_from_group_name(
group_name: string,
current_items: CombinedPillItem[],
): InputPillItem<UserGroupPill> | undefined {
current_items: CombinedPill[],
): UserGroupPill | undefined {
group_name = group_name.trim();
const group = user_groups.get_user_group_from_name(group_name);
if (!group) {
@ -47,7 +47,7 @@ export function create_item_from_group_name(
};
}
export function get_group_name_from_item(item: InputPillItem<UserGroupPill>): string {
export function get_group_name_from_item(item: UserGroupPill): string {
return item.group_name;
}

View File

@ -2,12 +2,12 @@ import render_input_pill from "../templates/input_pill.hbs";
import * as blueslip from "./blueslip";
import type {EmojiRenderingDetails} from "./emoji";
import type {InputPillConfig, InputPillContainer, InputPillItem} from "./input_pill";
import type {InputPillConfig, InputPillContainer} from "./input_pill";
import * as input_pill from "./input_pill";
import type {User} from "./people";
import * as people from "./people";
import {realm} from "./state_data";
import type {CombinedPillContainer, CombinedPillItem} from "./typeahead_helper";
import type {CombinedPill, CombinedPillContainer} from "./typeahead_helper";
import * as user_status from "./user_status";
// This will be used for pills for things like composing
@ -30,9 +30,9 @@ export type UserPillData = {type: "user"; user: User};
export function create_item_from_email(
email: string,
current_items: CombinedPillItem[],
current_items: CombinedPill[],
pill_config?: InputPillConfig | undefined,
): InputPillItem<UserPill> | undefined {
): UserPill | undefined {
// For normal Zulip use, we need to validate the email for our realm.
const user = people.get_by_email(email);
@ -68,7 +68,7 @@ export function create_item_from_email(
const status_emoji_info = user_status.get_status_emoji(user.user_id);
const item: InputPillItem<UserPill> = {
const item: UserPill = {
type: "user",
full_name: user.full_name,
user_id: user.user_id,
@ -92,7 +92,7 @@ export function create_item_from_email(
return item;
}
export function get_email_from_item(item: InputPillItem<UserPill>): string {
export function get_email_from_item(item: UserPill): string {
return item.email;
}
@ -105,7 +105,7 @@ export function append_person(opts: {
const avatar_url = people.small_avatar_url_for_person(person);
const status_emoji_info = user_status.get_status_emoji(opts.person.user_id);
const pill_data: InputPillItem<UserPill> = {
const pill_data: UserPill = {
type: "user",
full_name: person.full_name,
user_id: person.user_id,
@ -169,10 +169,7 @@ export function get_display_value_from_item(item: UserPill): string {
return item.full_name ?? item.email;
}
export function generate_pill_html(
item: InputPillItem<UserPill>,
show_user_status_emoji = false,
): string {
export function generate_pill_html(item: UserPill, show_user_status_emoji = false): string {
let status_emoji_info;
let has_status;
if (show_user_status_emoji) {

View File

@ -4,7 +4,6 @@ const {strict: assert} = require("assert");
const {mock_esm, set_global, zrequire} = require("./lib/namespace");
const {run_test, noop} = require("./lib/test");
const blueslip = require("./lib/zblueslip");
const $ = require("./lib/zjquery");
set_global("document", {});
@ -505,11 +504,9 @@ run_test("exit button on pill", ({mock_template}) => {
run_test("misc things", () => {
const info = set_up();
const config = info.config;
const $container = info.$container;
const $pill_input = info.$pill_input;
const widget = input_pill.create(config);
input_pill.create(info.config);
// animation
const animation_end_handler = $container.get_on_handler("animationend", ".input");
@ -528,12 +525,6 @@ run_test("misc things", () => {
animation_end_handler.call(input_stub);
assert.ok(shake_class_removed);
// bad data
blueslip.expect("error", "no type defined for the item");
widget.appendValidatedData({
language: "js",
});
// click on container
const container_click_handler = $container.get_on_handler("click");