diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 206630c176..51813bc225 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -266,7 +266,7 @@ EXEMPT_FILES = make_set( "web/src/unread_ui.ts", "web/src/upload.ts", "web/src/upload_widget.ts", - "web/src/user_card_popover.js", + "web/src/user_card_popover.ts", "web/src/user_deactivation_ui.ts", "web/src/user_events.js", "web/src/user_group_components.ts", diff --git a/web/src/copied_tooltip.ts b/web/src/copied_tooltip.ts index 97c1c7bd69..2494e1a460 100644 --- a/web/src/copied_tooltip.ts +++ b/web/src/copied_tooltip.ts @@ -3,10 +3,7 @@ import * as tippy from "tippy.js"; import {$t} from "./i18n.ts"; -function show_copied_tooltip( - copy_button: HTMLElement, - on_hide_callback?: () => void, -): tippy.Instance { +function show_copied_tooltip(copy_button: Element, on_hide_callback?: () => void): tippy.Instance { // Display a tooltip to notify the user the message or code was copied. const instance = tippy.default(copy_button, { placement: "top", @@ -25,18 +22,18 @@ function show_copied_tooltip( return instance; } -function show_check_icon(copy_button: HTMLElement): void { +function show_check_icon(copy_button: Element): void { $(copy_button).addClass("copy-button-success"); $(copy_button).find(".zulip-icon").removeClass("zulip-icon-copy").addClass("zulip-icon-check"); } -function remove_check_icon(copy_button: HTMLElement): void { +function remove_check_icon(copy_button: Element): void { $(copy_button).removeClass("copy-button-success"); $(copy_button).find(".zulip-icon").addClass("zulip-icon-copy").removeClass("zulip-icon-check"); } export function show_copied_confirmation( - copy_button: HTMLElement, + copy_button: Element, opts?: { show_check_icon?: boolean; timeout_in_ms?: number; diff --git a/web/src/drafts_overlay_ui.js b/web/src/drafts_overlay_ui.js index feae3d11dc..a447c6ba24 100644 --- a/web/src/drafts_overlay_ui.js +++ b/web/src/drafts_overlay_ui.js @@ -12,7 +12,7 @@ import * as messages_overlay_ui from "./messages_overlay_ui.ts"; import * as overlays from "./overlays.ts"; import * as people from "./people.ts"; import * as rendered_markdown from "./rendered_markdown.ts"; -import * as user_card_popover from "./user_card_popover.js"; +import * as user_card_popover from "./user_card_popover.ts"; import * as user_group_popover from "./user_group_popover.ts"; function restore_draft(draft_id) { @@ -193,9 +193,11 @@ export function launch() { restore_draft(draft_id); }); - $("#drafts_table .restore-overlay-message").on("click", ".user-mention", (e) => { - user_card_popover.unsaved_message_user_mention_event_handler(e); - }); + $("#drafts_table .restore-overlay-message").on( + "click", + ".user-mention", + user_card_popover.unsaved_message_user_mention_event_handler, + ); $("#drafts_table .restore-overlay-message").on("click", ".user-group-mention", (e) => { user_group_popover.toggle_user_group_info_popover(e.currentTarget, undefined); diff --git a/web/src/hotkey.js b/web/src/hotkey.js index d42f1ef6d9..3ffe9ab7bb 100644 --- a/web/src/hotkey.js +++ b/web/src/hotkey.js @@ -59,7 +59,7 @@ import * as stream_popover from "./stream_popover.ts"; import * as stream_settings_ui from "./stream_settings_ui.ts"; import * as topic_list from "./topic_list.ts"; import * as unread_ops from "./unread_ops.ts"; -import * as user_card_popover from "./user_card_popover.js"; +import * as user_card_popover from "./user_card_popover.ts"; import * as user_group_popover from "./user_group_popover.ts"; import {user_settings} from "./user_settings.ts"; import * as user_topics_ui from "./user_topics_ui.ts"; diff --git a/web/src/popover_menus.ts b/web/src/popover_menus.ts index 5defde5f41..9b3fc5e85a 100644 --- a/web/src/popover_menus.ts +++ b/web/src/popover_menus.ts @@ -78,7 +78,7 @@ export function popover_items_handle_keyboard(key: string, $items?: JQuery): voi $items.eq(index).trigger("focus"); } -export function focus_first_popover_item($items: JQuery, index = 0): void { +export function focus_first_popover_item($items: JQuery | undefined, index = 0): void { if (!$items) { return; } diff --git a/web/src/ui_init.js b/web/src/ui_init.js index 224c3dc3ed..1cbc087bb9 100644 --- a/web/src/ui_init.js +++ b/web/src/ui_init.js @@ -141,7 +141,7 @@ import * as unread from "./unread.ts"; import * as unread_ops from "./unread_ops.ts"; import * as unread_ui from "./unread_ui.ts"; import * as upload from "./upload.ts"; -import * as user_card_popover from "./user_card_popover.js"; +import * as user_card_popover from "./user_card_popover.ts"; import * as user_group_edit from "./user_group_edit.js"; import * as user_group_edit_members from "./user_group_edit_members.ts"; import * as user_group_popover from "./user_group_popover.ts"; diff --git a/web/src/user_card_popover.js b/web/src/user_card_popover.ts similarity index 77% rename from web/src/user_card_popover.js rename to web/src/user_card_popover.ts index 1194efc7f6..437591c890 100644 --- a/web/src/user_card_popover.js +++ b/web/src/user_card_popover.ts @@ -28,6 +28,7 @@ import * as message_view from "./message_view.ts"; import * as muted_users from "./muted_users.ts"; import * as overlays from "./overlays.ts"; import {page_params} from "./page_params.ts"; +import type {User} from "./people.ts"; import * as people from "./people.ts"; import * as popover_menus from "./popover_menus.ts"; import {hide_all} from "./popovers.ts"; @@ -39,15 +40,17 @@ import * as timerender from "./timerender.ts"; import * as ui_report from "./ui_report.ts"; import * as ui_util from "./ui_util.ts"; import * as user_deactivation_ui from "./user_deactivation_ui.ts"; +import type {CustomProfileFieldData} from "./user_profile.ts"; import * as user_profile from "./user_profile.ts"; import {user_settings} from "./user_settings.ts"; import * as user_status from "./user_status.ts"; import * as user_status_ui from "./user_status_ui.ts"; +import {the} from "./util.ts"; -let current_user_sidebar_user_id; +let current_user_sidebar_user_id: number | undefined; -export function confirm_mute_user(user_id) { - function on_click() { +export function confirm_mute_user(user_id: number): void { + function on_click(): void { muted_users.mute_user(user_id); } @@ -64,32 +67,30 @@ export function confirm_mute_user(user_id) { } class PopoverMenu { + instance: tippy.Instance | undefined; + constructor() { - this.instance = null; + this.instance = undefined; } - is_open() { + is_open(): boolean { return Boolean(this.instance); } - hide() { - if (this.is_open()) { + hide(): void { + if (this.instance) { this.instance.destroy(); this.instance = undefined; } } - handle_keyboard(key) { - if (!this.is_open()) { + handle_keyboard(key: string): void { + if (!this.instance) { blueslip.error("Trying to get the items when popover is closed."); return; } - const $popover = $(this.instance?.popper); - if (!$popover) { - blueslip.error("Cannot find popover data."); - return; - } + const $popover = $(this.instance.popper); const $items = $("[tabindex='0']", $popover).filter(":visible"); @@ -101,15 +102,11 @@ export const user_sidebar = new PopoverMenu(); export const message_user_card = new PopoverMenu(); export const user_card = new PopoverMenu(); -function popover_items_handle_keyboard_with_overrides(key, $items) { +function popover_items_handle_keyboard_with_overrides(key: string, $items: JQuery): void { /* Variant of popover_items_handle_keyboard for focusing on the user card popover menu options first, instead of other tabbable buttons and links which can be distracting. */ - if (!$items) { - return; - } - const index = $items.index($items.filter(":focus")); if (index === -1) { @@ -124,7 +121,9 @@ function popover_items_handle_keyboard_with_overrides(key, $items) { popover_menus.popover_items_handle_keyboard(key, $items); } -function get_popover_classname(popover) { +function get_popover_classname( + popover: "user_sidebar" | "message_user_card" | "user_card", +): string { const popovers = { user_sidebar: "user-sidebar-popover-root", message_user_card: "message-user-card-popover-root", @@ -145,32 +144,30 @@ const user_card_popovers = { user_card, }; -export function any_active() { +export function any_active(): boolean { return Object.values(user_card_popovers).some((instance) => instance.is_open()); } -export function hide_all_instances() { - for (const key in user_card_popovers) { - if (user_card_popovers[key].hide) { - user_card_popovers[key].hide(); - } +export function hide_all_instances(): void { + for (const popover of Object.values(user_card_popovers)) { + popover.hide(); } } -export function hide_all_user_card_popovers() { +export function hide_all_user_card_popovers(): void { hide_all_instances(); } -export function clear_for_testing() { +export function clear_for_testing(): void { message_user_card.instance = undefined; user_card.instance = undefined; } -function elem_to_user_id($elem) { - return Number.parseInt($elem.attr("data-user-id"), 10); +function elem_to_user_id($elem: JQuery): number { + return Number.parseInt($elem.attr("data-user-id")!, 10); } -function clipboard_enable(arg) { +function clipboard_enable(arg: HTMLElement | string): ClipboardJS { // arg is a selector or element // We extract this function for testing purpose. return new ClipboardJS(arg); @@ -178,7 +175,7 @@ function clipboard_enable(arg) { // Functions related to user card popover. -export function toggle_user_card_popover(element, user) { +export function toggle_user_card_popover(element: HTMLElement, user: User): void { show_user_card_popover( user, $(element), @@ -190,7 +187,7 @@ export function toggle_user_card_popover(element, user) { ); } -function toggle_user_card_popover_for_bot_owner(element, user) { +function toggle_user_card_popover_for_bot_owner(element: HTMLElement, user: User): void { show_user_card_popover( user, $(element), @@ -203,12 +200,49 @@ function toggle_user_card_popover_for_bot_owner(element, user) { ); } +type UserCardPopoverData = { + invisible_mode: boolean; + can_send_private_message: boolean; + display_profile_fields: CustomProfileFieldData[]; + has_message_context: boolean; + is_active: boolean; + is_bot: boolean; + is_me: boolean; + is_sender_popover: boolean; + pm_with_url: string; + user_circle_class: string; + private_message_class: string; + sent_by_url: string; + user_email: string | null; + user_full_name: string; + user_id: number; + user_last_seen_time_status: string; + user_time: string | undefined; + user_type: string | undefined; + status_content_available: boolean; + status_text: string | undefined; + status_emoji_info: user_status.UserStatusEmojiInfo | undefined; + show_placeholder_for_status_text: false | user_status.UserStatusEmojiInfo | undefined; + user_mention_syntax: string; + date_joined: string | undefined; + spectator_view: boolean; + should_add_guest_user_indicator: boolean; + user_avatar: string; + user_is_guest: boolean; + show_manage_section: boolean; + can_mute: boolean; + can_unmute: boolean; + can_manage_user: boolean; + is_system_bot?: boolean; + bot_owner?: User; +}; + function get_user_card_popover_data( - user, - has_message_context, - is_sender_popover, - private_msg_class, -) { + user: User, + has_message_context: boolean, + is_sender_popover: boolean, + private_msg_class: string, +): UserCardPopoverData { const is_me = people.is_my_user_id(user.user_id); let invisible_mode = false; @@ -249,7 +283,7 @@ function get_user_card_popover_data( const can_send_private_message = user_can_send_direct_message(user_id_string) && is_active && !is_me; - const args = { + const args: UserCardPopoverData = { invisible_mode, can_send_private_message, display_profile_fields, @@ -268,7 +302,7 @@ function get_user_card_popover_data( user_last_seen_time_status: buddy_data.user_last_seen_time_status(user.user_id), user_time: people.get_user_time(user.user_id), user_type: people.get_user_type(user.user_id), - status_content_available: Boolean(status_text || status_emoji_info), + status_content_available: Boolean(status_text ?? status_emoji_info), status_text, status_emoji_info, show_placeholder_for_status_text: !status_text && status_emoji_info, @@ -289,7 +323,7 @@ function get_user_card_popover_data( if (is_system_bot) { args.is_system_bot = is_system_bot; } else if (bot_owner_id) { - const bot_owner = people.get_bot_owner_user(user); + const bot_owner = people.get_user_by_id_assert_valid(bot_owner_id); args.bot_owner = bot_owner; } } @@ -298,16 +332,16 @@ function get_user_card_popover_data( } function show_user_card_popover( - user, - $popover_element, - is_sender_popover, - has_message_context, - private_msg_class, - template_class, - popover_placement, - show_as_overlay, - on_mount, -) { + user: User, + $popover_element: JQuery, + is_sender_popover: boolean, + has_message_context: boolean, + private_msg_class: string, + template_class: "user_sidebar" | "message_user_card" | "user_card", + popover_placement: tippy.Placement, + show_as_overlay = false, + on_mount?: (instance: tippy.Instance) => void, +): void { let popover_html; let args; if (user.is_inaccessible_user) { @@ -330,7 +364,7 @@ function show_user_card_popover( } popover_menus.toggle_popover_menu( - $popover_element[0], + the($popover_element), { theme: "popover-menu", placement: popover_placement, @@ -369,7 +403,7 @@ function show_user_card_popover( ); } -function init_email_clipboard() { +function init_email_clipboard(): void { /* This shows (and enables) the copy-text icon for folks who have names that would overflow past the right @@ -399,7 +433,7 @@ function init_email_clipboard() { }); } -function init_email_tooltip(user) { +function init_email_tooltip(user: User): void { /* This displays the email tooltip for folks who have names that would overflow past the right @@ -416,13 +450,13 @@ function init_email_tooltip(user) { }); } -function load_medium_avatar(user, $elt) { +function load_medium_avatar(user: User, $elt: JQuery): void { const user_avatar_url = people.medium_avatar_url_for_person(user); const sender_avatar_medium = new Image(); sender_avatar_medium.src = user_avatar_url; $(sender_avatar_medium).on("load", function () { - $elt.attr("src", $(this).attr("src")); + $elt.attr("src", $(this).attr("src")!); }); } @@ -433,12 +467,12 @@ function load_medium_avatar(user, $elt) { // sender_id is the user id of the sender for the message we are // showing the popover from. function toggle_user_card_popover_for_message( - element, - user, - sender_id, - has_message_context, - on_mount, -) { + element: HTMLElement, + user: User, + sender_id: number, + has_message_context: boolean, + on_mount?: (instance: tippy.Instance) => void, +): void { const $elt = $(element); const is_sender_popover = sender_id === user.user_id; @@ -455,10 +489,13 @@ function toggle_user_card_popover_for_message( ); } -export function unsaved_message_user_mention_event_handler(e) { +export function unsaved_message_user_mention_event_handler( + this: HTMLElement, + e: JQuery.ClickEvent, +): void { e.stopPropagation(); - const id_string = $(e.currentTarget).attr("data-user-id"); + const id_string = $(this).attr("data-user-id")!; // Do not open popover for @all mention if (id_string === "*") { return; @@ -467,12 +504,12 @@ export function unsaved_message_user_mention_event_handler(e) { const user_id = Number.parseInt(id_string, 10); const user = people.get_by_user_id(user_id); - toggle_user_card_popover_for_message($(e.target), user, current_user.user_id, false); + toggle_user_card_popover_for_message(this, user, current_user.user_id, false); } // This function serves as the entry point for toggling // the user card popover via keyboard shortcut. -export function toggle_sender_info() { +export function toggle_sender_info(): void { if (message_user_card.is_open()) { // We need to call the hide method here because // the event wasn't triggered by the mouse. @@ -491,32 +528,33 @@ export function toggle_sender_info() { assert(message_lists.current !== undefined); const message = message_lists.current.get(rows.id($message)); + assert(message !== undefined); const user = people.get_by_user_id(message.sender_id); - toggle_user_card_popover_for_message($sender[0], user, message.sender_id, true, () => { + toggle_user_card_popover_for_message(the($sender), user, message.sender_id, true, () => { if (!page_params.is_spectator) { focus_user_card_popover_item(); } }); } -function focus_user_card_popover_item() { +function focus_user_card_popover_item(): void { // For now I recommend only calling this when the user opens the menu with a hotkey. // Our popup menus act kind of funny when you mix keyboard and mouse. const $items = get_user_card_popover_for_message_items(); popover_menus.focus_first_popover_item($items); } -function get_user_card_popover_for_message_items() { +function get_user_card_popover_for_message_items(): JQuery | undefined { if (!message_user_card.is_open()) { blueslip.error("Trying to get menu items when message user card popover is closed."); return undefined; } - const $popover = $(message_user_card.instance.popper); - if (!$popover) { + if (message_user_card.instance === undefined) { blueslip.error("Cannot find popover data for message user card menu."); return undefined; } + const $popover = $(message_user_card.instance.popper); // Return only the popover menu options that are visible, and not the // copy buttons or the link items in the custom profile fields. @@ -525,7 +563,7 @@ function get_user_card_popover_for_message_items() { // Functions related to the user card popover in the user sidebar. -function toggle_sidebar_user_card_popover($target) { +function toggle_sidebar_user_card_popover($target: JQuery): void { const user_id = elem_to_user_id($target); const user = people.get_by_user_id(user_id); @@ -558,17 +596,22 @@ function toggle_sidebar_user_card_popover($target) { current_user_sidebar_user_id = user.user_id; } -function register_click_handlers() { - $("#main_div").on("click", ".sender_name, .inline_profile_picture", function (e) { - const $row = $(this).closest(".message_row"); - e.stopPropagation(); - assert(message_lists.current !== undefined); - const message = message_lists.current.get(rows.id($row)); - const user = people.get_by_user_id(message.sender_id); - toggle_user_card_popover_for_message(this, user, message.sender_id, true); - }); +function register_click_handlers(): void { + $("#main_div").on( + "click", + ".sender_name, .inline_profile_picture", + function (this: HTMLElement, e) { + const $row = $(this).closest(".message_row"); + e.stopPropagation(); + assert(message_lists.current !== undefined); + const message = message_lists.current.get(rows.id($row)); + assert(message !== undefined); + const user = people.get_by_user_id(message.sender_id); + toggle_user_card_popover_for_message(this, user, message.sender_id, true); + }, + ); - $("#main_div").on("click", ".user-mention", function (e) { + $("#main_div").on("click", ".user-mention", function (this: HTMLElement, e) { const id_string = $(this).attr("data-user-id"); // We fallback to email to handle legacy Markdown that was rendered // before we cut over to using data-user-id @@ -580,12 +623,13 @@ function register_click_handlers() { e.stopPropagation(); assert(message_lists.current !== undefined); const message = message_lists.current.get(rows.id($row)); + assert(message !== undefined); let user; if (id_string) { const user_id = Number.parseInt(id_string, 10); user = people.get_by_user_id(user_id); } else { - user = people.get_by_email(email); + user = email === undefined ? undefined : people.get_by_email(email); if (user === undefined) { // There can be a case when user is undefined if // the user is an inaccessible user as we do not @@ -603,8 +647,8 @@ function register_click_handlers() { // that run before this one and call stopPropagation. $("body").on("click", ".messagebox .user-mention", unsaved_message_user_mention_event_handler); - $("body").on("click", ".user-card-popover-actions .narrow_to_private_messages", (e) => { - const user_id = elem_to_user_id($(e.target).parents("ul")); + $("body").on("click", ".user-card-popover-actions .narrow_to_private_messages", function (e) { + const user_id = elem_to_user_id($(this).parents("ul")); const email = people.get_by_user_id(user_id).email; message_view.show( [ @@ -623,8 +667,8 @@ function register_click_handlers() { e.preventDefault(); }); - $("body").on("click", ".user-card-popover-actions .narrow_to_messages_sent", (e) => { - const user_id = elem_to_user_id($(e.target).parents("ul")); + $("body").on("click", ".user-card-popover-actions .narrow_to_messages_sent", function (e) { + const user_id = elem_to_user_id($(this).parents("ul")); const email = people.get_by_user_id(user_id).email; message_view.show( [ @@ -645,9 +689,7 @@ function register_click_handlers() { $("body").on("click", ".user-card-popover-actions .user-card-clear-status-button", (e) => { e.preventDefault(); - const me = elem_to_user_id($(e.target).parents("ul")); user_status.server_update_status({ - user_id: me, status_text: "", emoji_name: "", emoji_code: "", @@ -657,12 +699,12 @@ function register_click_handlers() { }); }); - $("body").on("click", ".sidebar-popover-reactivate-user", (e) => { - const user_id = elem_to_user_id($(e.target).parents("ul")); + $("body").on("click", ".sidebar-popover-reactivate-user", function (e) { + const user_id = elem_to_user_id($(this).parents("ul")); hide_all(); e.stopPropagation(); e.preventDefault(); - function handle_confirm() { + function handle_confirm(): void { const url = "/json/users/" + encodeURIComponent(user_id) + "/reactivate"; channel.post({ url, @@ -678,8 +720,8 @@ function register_click_handlers() { user_deactivation_ui.confirm_reactivation(user_id, handle_confirm, true); }); - $("body").on("click", ".user-card-popover-actions .view_full_user_profile", (e) => { - const user_id = elem_to_user_id($(e.target).parents("ul")); + $("body").on("click", ".user-card-popover-actions .view_full_user_profile", function (e) { + const user_id = elem_to_user_id($(this).parents("ul")); const current_hash = window.location.hash; // If any overlay is already open, we want the user profile to behave // as a modal rather than an overlay. @@ -692,7 +734,7 @@ function register_click_handlers() { e.stopPropagation(); e.preventDefault(); }); - $("body").on("click", ".user-card-popover-root .mention_user", (e) => { + $("body").on("click", ".user-card-popover-root .mention_user", function (e) { if (!compose_state.composing()) { compose_actions.start({ message_type: "stream", @@ -700,7 +742,7 @@ function register_click_handlers() { keep_composebox_empty: true, }); } - const user_id = elem_to_user_id($(e.target).parents("ul")); + const user_id = elem_to_user_id($(this).parents("ul")); const name = people.get_by_user_id(user_id).full_name; const mention = people.get_mention_syntax(name, user_id); compose_ui.insert_syntax_and_focus(mention); @@ -710,14 +752,14 @@ function register_click_handlers() { e.preventDefault(); }); - $("body").on("click", ".message-user-card-popover-root .mention_user", (e) => { + $("body").on("click", ".message-user-card-popover-root .mention_user", function (e) { if (!compose_state.composing()) { compose_reply.respond_to_message({ trigger: "user sidebar popover", keep_composebox_empty: true, }); } - const user_id = elem_to_user_id($(e.target).parents("ul")); + const user_id = elem_to_user_id($(this).parents("ul")); const name = people.get_by_user_id(user_id).full_name; const is_active = people.is_active_user_for_popover(user_id); const mention = people.get_mention_syntax(name, user_id, !is_active); @@ -727,18 +769,22 @@ function register_click_handlers() { e.preventDefault(); }); - $("body").on("click", ".view_user_profile, .person_picker .pill[data-user-id]", (e) => { - const user_id = Number.parseInt($(e.currentTarget).attr("data-user-id"), 10); - const user = people.get_by_user_id(user_id); - if ($(e.target).closest(".user-card-popover-bot-owner-field").length > 0) { - hide_all_user_card_popovers(); - toggle_user_card_popover_for_bot_owner(e.target, user); - } else { - toggle_user_card_popover(e.target, user); - } - e.stopPropagation(); - e.preventDefault(); - }); + $("body").on( + "click", + ".view_user_profile, .person_picker .pill[data-user-id]", + function (this: HTMLElement, e) { + const user_id = Number.parseInt($(e.currentTarget).attr("data-user-id")!, 10); + const user = people.get_by_user_id(user_id); + if ($(this).closest(".user-card-popover-bot-owner-field").length > 0) { + hide_all_user_card_popovers(); + toggle_user_card_popover_for_bot_owner(this, user); + } else { + toggle_user_card_popover(this, user); + } + e.stopPropagation(); + e.preventDefault(); + }, + ); /* These click handlers are implemented as just deep links to the * relevant part of the Zulip UI, so we don't want preventDefault, @@ -758,7 +804,7 @@ function register_click_handlers() { e.preventDefault(); }); - function open_user_status_modal(e) { + function open_user_status_modal(e: JQuery.ClickEvent): void { hide_all(); user_status_ui.open_user_status_modal(); @@ -790,24 +836,24 @@ function register_click_handlers() { toggle_sidebar_user_card_popover($target); }); - $("body").on("click", ".sidebar-popover-mute-user", (e) => { - const user_id = elem_to_user_id($(e.target).parents("ul")); + $("body").on("click", ".sidebar-popover-mute-user", function (e) { + const user_id = elem_to_user_id($(this).parents("ul")); hide_all_user_card_popovers(); e.stopPropagation(); e.preventDefault(); confirm_mute_user(user_id); }); - $("body").on("click", ".sidebar-popover-unmute-user", (e) => { - const user_id = elem_to_user_id($(e.target).parents("ul")); + $("body").on("click", ".sidebar-popover-unmute-user", function (e) { + const user_id = elem_to_user_id($(this).parents("ul")); hide_all_user_card_popovers(); muted_users.unmute_user(user_id); e.stopPropagation(); e.preventDefault(); }); - $("body").on("click", ".respond_personal_button, .compose_private_message", (e) => { - const user_id = elem_to_user_id($(e.target).parents("ul")); + $("body").on("click", ".respond_personal_button, .compose_private_message", function (e) { + const user_id = elem_to_user_id($(this).parents("ul")); const email = people.get_by_user_id(user_id).email; compose_actions.start({ message_type: "private", @@ -828,9 +874,9 @@ function register_click_handlers() { e.preventDefault(); }); - $("body").on("click", ".sidebar-popover-manage-user", (e) => { + $("body").on("click", ".sidebar-popover-manage-user", function () { hide_all(); - const user_id = elem_to_user_id($(e.target).parents("ul")); + const user_id = elem_to_user_id($(this).parents("ul")); const user = people.get_by_user_id(user_id); user_profile.show_user_profile(user, "manage-profile-tab"); }); @@ -842,8 +888,8 @@ function register_click_handlers() { }); new ClipboardJS(".copy-custom-profile-field-link", { - text(trigger) { - return $(trigger).parent().find(".custom-profile-field-link").attr("href"); + text(trigger): string { + return $(trigger).parent().find(".custom-profile-field-link").attr("href")!; }, }).on("success", (e) => { show_copied_confirmation(e.trigger, { @@ -852,7 +898,7 @@ function register_click_handlers() { }); } -export function initialize() { +export function initialize(): void { register_click_handlers(); clipboard_enable(".copy_mention_syntax"); } diff --git a/web/src/user_profile.ts b/web/src/user_profile.ts index 8aceee366f..0db5b6f395 100644 --- a/web/src/user_profile.ts +++ b/web/src/user_profile.ts @@ -61,7 +61,7 @@ import type {UserGroup} from "./user_groups.ts"; import * as user_pill from "./user_pill.ts"; import * as util from "./util.ts"; -type CustomProfileFieldData = { +export type CustomProfileFieldData = { id: number; name: string; is_user_field: boolean;