diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 79d0145926..f28d7cfa2f 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -144,6 +144,7 @@ EXEMPT_FILES = make_set( "web/src/message_view_header.js", "web/src/message_viewport.js", "web/src/messages_overlay_ui.ts", + "web/src/modals.ts", "web/src/muted_users_ui.js", "web/src/narrow.js", "web/src/narrow_history.js", diff --git a/web/src/dialog_widget.ts b/web/src/dialog_widget.ts index 8de4dee01b..23ec6ed927 100644 --- a/web/src/dialog_widget.ts +++ b/web/src/dialog_widget.ts @@ -6,7 +6,7 @@ import render_dialog_widget from "../templates/dialog_widget.hbs"; import type {AjaxRequestHandler} from "./channel"; import {$t_html} from "./i18n"; import * as loading from "./loading"; -import * as overlays from "./overlays"; +import * as modals from "./modals"; import * as ui_report from "./ui_report"; /* @@ -22,7 +22,7 @@ import * as ui_report from "./ui_report"; * to avoid interference from other elements. * * 3) For settings, we have a click handler in settings.js - * that will close the dialog via overlays.close_active_modal. + * that will close the dialog via modals.close_active_modal. * * 4) We assume that since this is a modal, you will * only ever have one confirm dialog active at any @@ -99,7 +99,7 @@ export function show_dialog_spinner(): void { // Supports a callback to be called once the modal finishes closing. export function close_modal(on_hidden_callback?: () => void): void { - overlays.close_modal("dialog_widget_modal", {on_hidden: on_hidden_callback}); + modals.close_modal("dialog_widget_modal", {on_hidden: on_hidden_callback}); } export function launch(conf: DialogWidgetConfig): void { @@ -210,7 +210,7 @@ export function launch(conf: DialogWidgetConfig): void { conf.on_click(e); }); - overlays.open_modal("dialog_widget_modal", { + modals.open_modal("dialog_widget_modal", { autoremove: true, on_show() { if (conf.focus_submit_on_open) { diff --git a/web/src/hotkey.js b/web/src/hotkey.js index e49ccdbe9c..cd030cc452 100644 --- a/web/src/hotkey.js +++ b/web/src/hotkey.js @@ -31,6 +31,7 @@ import * as message_edit from "./message_edit"; import * as message_edit_history from "./message_edit_history"; import * as message_lists from "./message_lists"; import * as message_scroll_state from "./message_scroll_state"; +import * as modals from "./modals"; import * as narrow from "./narrow"; import * as narrow_state from "./narrow_state"; import * as navigate from "./navigate"; @@ -279,8 +280,8 @@ export function process_escape_key(e) { return true; } - if (overlays.is_modal_open()) { - overlays.close_active_modal(); + if (modals.is_modal_open()) { + modals.close_active_modal(); return true; } @@ -485,7 +486,7 @@ export function process_enter_key(e) { // All custom logic for overlays/modals is above; if we're in a // modal at this point, let the browser handle the event. - if (overlays.is_modal_open()) { + if (modals.is_modal_open()) { return false; } @@ -694,7 +695,7 @@ export function process_hotkey(e, hotkey) { } // `list_util` will process the event in send later modal. - if (overlays.is_modal_open() && overlays.active_modal() !== "#send_later_modal") { + if (modals.is_modal_open() && modals.active_modal() !== "#send_later_modal") { return false; } diff --git a/web/src/modals.ts b/web/src/modals.ts new file mode 100644 index 0000000000..8b22a9a7c2 --- /dev/null +++ b/web/src/modals.ts @@ -0,0 +1,239 @@ +import $ from "jquery"; +import Micromodal from "micromodal"; + +import * as blueslip from "./blueslip"; +import * as overlay_util from "./overlay_util"; + +type Hook = () => void; + +export type ModalConfig = { + autoremove?: boolean; + on_show?: () => void; + on_shown?: () => void; + on_hide?: () => void; + on_hidden?: () => void; +}; + +const pre_open_hooks: Hook[] = []; +const pre_close_hooks: Hook[] = []; + +export function register_pre_open_hook(func: Hook): void { + pre_open_hooks.push(func); +} + +export function register_pre_close_hook(func: Hook): void { + pre_close_hooks.push(func); +} + +function call_hooks(func_list: Hook[]): void { + for (const element of func_list) { + element(); + } +} + +export function is_modal_open(): boolean { + return $(".micromodal").hasClass("modal--open"); +} + +export function active_modal(): string | undefined { + if (!is_modal_open()) { + blueslip.error("Programming error — Called active_modal when there is no modal open"); + return undefined; + } + + const $micromodal = $(".micromodal.modal--open"); + return `#${CSS.escape($micromodal.attr("id")!)}`; +} + +// If conf.autoremove is true, the modal element will be removed from the DOM +// once the modal is hidden. +// conf also accepts the following optional properties: +// on_show: Callback to run when the modal is triggered to show. +// on_shown: Callback to run when the modal is shown. +// on_hide: Callback to run when the modal is triggered to hide. +// on_hidden: Callback to run when the modal is hidden. +export function open_modal( + modal_id: string, + conf: ModalConfig & {recursive_call_count?: number} = {}, +): void { + if (modal_id === undefined) { + blueslip.error("Undefined id was passed into open_modal"); + return; + } + + // Don't accept hash-based selector to enforce modals to have unique ids and + // since micromodal doesn't accept hash based selectors. + if (modal_id.startsWith("#")) { + blueslip.error("hash-based selector passed in to open_modal", {modal_id}); + return; + } + + if (is_modal_open()) { + /* + Our modal system doesn't directly support opening a modal + when one is already open, because the `is_modal_open` CSS + class doesn't update until Micromodal has finished its + animations, which can take 100ms or more. + + We can likely fix that, but in the meantime, we should + handle this situation correctly, by closing the current + modal, waiting for it to finish closing, and then attempting + to open the current modal again. + */ + if (!conf.recursive_call_count) { + conf.recursive_call_count = 1; + } else { + conf.recursive_call_count += 1; + } + if (conf.recursive_call_count > 50) { + blueslip.error("Modal incorrectly is still open", {modal_id}); + return; + } + + close_active_modal(); + setTimeout(() => { + open_modal(modal_id, conf); + }, 10); + return; + } + + blueslip.debug("open modal: " + modal_id); + + // Micromodal gets elements using the getElementById DOM function + // which doesn't require the hash. We add it manually here. + const id_selector = `#${CSS.escape(modal_id)}`; + const $micromodal = $(id_selector); + + $micromodal.find(".modal__container").on("animationend", (event) => { + const animation_name = (event.originalEvent as AnimationEvent).animationName; + if (animation_name === "mmfadeIn") { + // Micromodal adds the is-open class before the modal animation + // is complete, which isn't really helpful since a modal is open after the + // animation is complete. So, we manually add a class after the + // animation is complete. + $micromodal.addClass("modal--open"); + $micromodal.removeClass("modal--opening"); + + if (conf.on_shown) { + conf.on_shown(); + } + } else if (animation_name === "mmfadeOut") { + // Call the on_hidden callback after the modal finishes hiding. + + $micromodal.removeClass("modal--open"); + if (conf.autoremove) { + $micromodal.remove(); + } + if (conf.on_hidden) { + conf.on_hidden(); + } + } + }); + + $micromodal.find(".modal__overlay").on("click", (e) => { + /* Micromodal's data-micromodal-close feature doesn't check for + range selections; this means dragging a selection of text in an + input inside the modal too far will weirdly close the modal. + See https://github.com/ghosh/Micromodal/issues/505. + Work around this with our own implementation. */ + if (!$(e.target).is(".modal__overlay")) { + return; + } + + if (document.getSelection()?.type === "Range") { + return; + } + close_modal(modal_id); + }); + + function on_show_callback(): void { + if (conf.on_show) { + conf.on_show(); + } + overlay_util.disable_scrolling(); + call_hooks(pre_open_hooks); + } + + function on_close_callback(): void { + if (conf.on_hide) { + conf.on_hide(); + } + overlay_util.enable_scrolling(); + call_hooks(pre_close_hooks); + } + + Micromodal.show(modal_id, { + disableFocus: true, + openClass: "modal--opening", + onShow: on_show_callback, + onClose: on_close_callback, + }); +} + +// `conf` is an object with the following optional properties: +// * on_hidden: Callback to run when the modal finishes hiding. +export function close_modal(modal_id: string, conf: Pick = {}): void { + if (modal_id === undefined) { + blueslip.error("Undefined id was passed into close_modal"); + return; + } + + if (!is_modal_open()) { + blueslip.warn("close_active_modal() called without checking is_modal_open()"); + return; + } + + if (active_modal() !== `#${CSS.escape(modal_id)}`) { + blueslip.error("Trying to close modal when other is open", {modal_id, active_modal}); + return; + } + + blueslip.debug("close modal: " + modal_id); + + const id_selector = `#${CSS.escape(modal_id)}`; + const $micromodal = $(id_selector); + + // On-hidden hooks should typically be registered in + // overlays.open_modal. However, we offer this alternative + // mechanism as a convenience for hooks only known when + // closing the modal. + $micromodal.find(".modal__container").on("animationend", (event) => { + const animation_name = (event.originalEvent as AnimationEvent).animationName; + if (animation_name === "mmfadeOut" && conf.on_hidden) { + conf.on_hidden(); + } + }); + + Micromodal.close(modal_id); +} + +export function close_modal_if_open(modal_id: string): void { + if (modal_id === undefined) { + blueslip.error("Undefined id was passed into close_modal_if_open"); + return; + } + + if (!is_modal_open()) { + return; + } + + const $micromodal = $(".micromodal.modal--open"); + const active_modal_id = CSS.escape(`${CSS.escape($micromodal.attr("id") ?? "")}`); + if (active_modal_id === `${CSS.escape(modal_id)}`) { + Micromodal.close(`${CSS.escape($micromodal.attr("id") ?? "")}`); + } else { + blueslip.info( + `${active_modal_id} is the currently active modal and ${modal_id} is already closed.`, + ); + } +} + +export function close_active_modal(): void { + if (!is_modal_open()) { + blueslip.warn("close_active_modal() called without checking is_modal_open()"); + return; + } + + const $micromodal = $(".micromodal.modal--open"); + Micromodal.close(`${CSS.escape($micromodal.attr("id") ?? "")}`); +} diff --git a/web/src/overlays.ts b/web/src/overlays.ts index 068c7dbf99..310d4518b0 100644 --- a/web/src/overlays.ts +++ b/web/src/overlays.ts @@ -1,5 +1,4 @@ import $ from "jquery"; -import Micromodal from "micromodal"; import * as blueslip from "./blueslip"; import * as overlay_util from "./overlay_util"; @@ -17,20 +16,9 @@ type Overlay = { close_handler: () => void; }; -export type ModalConfig = { - autoremove?: boolean; - on_show?: () => void; - on_shown?: () => void; - on_hide?: () => void; - on_hidden?: () => void; -}; - let active_overlay: Overlay | undefined; let open_overlay_name: string | undefined; -// Used for both overlays and modals. -// We could split these hooks so that they are separate for -// overlays and modals if we need to. const pre_open_hooks: Hook[] = []; const pre_close_hooks: Hook[] = []; @@ -57,10 +45,6 @@ export function is_active(): boolean { return Boolean(open_overlay_name); } -export function is_modal_open(): boolean { - return $(".micromodal").hasClass("modal--open"); -} - export function info_overlay_open(): boolean { return open_overlay_name === "informationalOverlays"; } @@ -89,16 +73,6 @@ export function scheduled_messages_open(): boolean { return open_overlay_name === "scheduled"; } -export function active_modal(): string | undefined { - if (!is_modal_open()) { - blueslip.error("Programming error — Called active_modal when there is no modal open"); - return undefined; - } - - const $micromodal = $(".micromodal.modal--open"); - return `#${CSS.escape($micromodal.attr("id")!)}`; -} - export function open_overlay(opts: OverlayOptions): void { call_hooks(pre_open_hooks); @@ -141,131 +115,6 @@ export function open_overlay(opts: OverlayOptions): void { $("#navbar-fixed-container").attr("aria-hidden", "true"); } -// If conf.autoremove is true, the modal element will be removed from the DOM -// once the modal is hidden. -// conf also accepts the following optional properties: -// on_show: Callback to run when the modal is triggered to show. -// on_shown: Callback to run when the modal is shown. -// on_hide: Callback to run when the modal is triggered to hide. -// on_hidden: Callback to run when the modal is hidden. -export function open_modal( - modal_id: string, - conf: ModalConfig & {recursive_call_count?: number} = {}, -): void { - if (modal_id === undefined) { - blueslip.error("Undefined id was passed into open_modal"); - return; - } - - // Don't accept hash-based selector to enforce modals to have unique ids and - // since micromodal doesn't accept hash based selectors. - if (modal_id.startsWith("#")) { - blueslip.error("hash-based selector passed in to open_modal", {modal_id}); - return; - } - - if (is_modal_open()) { - /* - Our modal system doesn't directly support opening a modal - when one is already open, because the `is_modal_open` CSS - class doesn't update until Micromodal has finished its - animations, which can take 100ms or more. - - We can likely fix that, but in the meantime, we should - handle this situation correctly, by closing the current - modal, waiting for it to finish closing, and then attempting - to open the current modal again. - */ - if (!conf.recursive_call_count) { - conf.recursive_call_count = 1; - } else { - conf.recursive_call_count += 1; - } - if (conf.recursive_call_count > 50) { - blueslip.error("Modal incorrectly is still open", {modal_id}); - return; - } - - close_active_modal(); - setTimeout(() => { - open_modal(modal_id, conf); - }, 10); - return; - } - - blueslip.debug("open modal: " + modal_id); - - // Micromodal gets elements using the getElementById DOM function - // which doesn't require the hash. We add it manually here. - const id_selector = `#${CSS.escape(modal_id)}`; - const $micromodal = $(id_selector); - - $micromodal.find(".modal__container").on("animationend", (event) => { - const animation_name = (event.originalEvent as AnimationEvent).animationName; - if (animation_name === "mmfadeIn") { - // Micromodal adds the is-open class before the modal animation - // is complete, which isn't really helpful since a modal is open after the - // animation is complete. So, we manually add a class after the - // animation is complete. - $micromodal.addClass("modal--open"); - $micromodal.removeClass("modal--opening"); - - if (conf.on_shown) { - conf.on_shown(); - } - } else if (animation_name === "mmfadeOut") { - // Call the on_hidden callback after the modal finishes hiding. - - $micromodal.removeClass("modal--open"); - if (conf.autoremove) { - $micromodal.remove(); - } - if (conf.on_hidden) { - conf.on_hidden(); - } - } - }); - - $micromodal.find(".modal__overlay").on("click", (e) => { - /* Micromodal's data-micromodal-close feature doesn't check for - range selections; this means dragging a selection of text in an - input inside the modal too far will weirdly close the modal. - See https://github.com/ghosh/Micromodal/issues/505. - Work around this with our own implementation. */ - if (!$(e.target).is(".modal__overlay")) { - return; - } - - if (document.getSelection()?.type === "Range") { - return; - } - close_modal(modal_id); - }); - - function on_show_callback(): void { - if (conf.on_show) { - conf.on_show(); - } - overlay_util.disable_scrolling(); - call_hooks(pre_open_hooks); - } - - function on_close_callback(): void { - if (conf.on_hide) { - conf.on_hide(); - } - overlay_util.enable_scrolling(); - call_hooks(pre_close_hooks); - } - - Micromodal.show(modal_id, { - disableFocus: true, - openClass: "modal--opening", - onShow: on_show_callback, - onClose: on_close_callback, - }); -} - export function close_overlay(name: string): void { call_hooks(pre_close_hooks); @@ -304,74 +153,6 @@ export function close_active(): void { close_overlay(open_overlay_name); } -// `conf` is an object with the following optional properties: -// * on_hidden: Callback to run when the modal finishes hiding. -export function close_modal(modal_id: string, conf: Pick = {}): void { - if (modal_id === undefined) { - blueslip.error("Undefined id was passed into close_modal"); - return; - } - - if (!is_modal_open()) { - blueslip.warn("close_active_modal() called without checking is_modal_open()"); - return; - } - - if (active_modal() !== `#${CSS.escape(modal_id)}`) { - blueslip.error("Trying to close modal when other is open", {modal_id, active_modal}); - return; - } - - blueslip.debug("close modal: " + modal_id); - - const id_selector = `#${CSS.escape(modal_id)}`; - const $micromodal = $(id_selector); - - // On-hidden hooks should typically be registered in - // overlays.open_modal. However, we offer this alternative - // mechanism as a convenience for hooks only known when - // closing the modal. - $micromodal.find(".modal__container").on("animationend", (event) => { - const animation_name = (event.originalEvent as AnimationEvent).animationName; - if (animation_name === "mmfadeOut" && conf.on_hidden) { - conf.on_hidden(); - } - }); - - Micromodal.close(modal_id); -} - -export function close_modal_if_open(modal_id: string): void { - if (modal_id === undefined) { - blueslip.error("Undefined id was passed into close_modal_if_open"); - return; - } - - if (!is_modal_open()) { - return; - } - - const $micromodal = $(".micromodal.modal--open"); - const active_modal_id = CSS.escape(`${CSS.escape($micromodal.attr("id") ?? "")}`); - if (active_modal_id === `${CSS.escape(modal_id)}`) { - Micromodal.close(`${CSS.escape($micromodal.attr("id") ?? "")}`); - } else { - blueslip.info( - `${active_modal_id} is the currently active modal and ${modal_id} is already closed.`, - ); - } -} - -export function close_active_modal(): void { - if (!is_modal_open()) { - blueslip.warn("close_active_modal() called without checking is_modal_open()"); - return; - } - - const $micromodal = $(".micromodal.modal--open"); - Micromodal.close(`${CSS.escape($micromodal.attr("id") ?? "")}`); -} - export function close_for_hash_change(): void { if (open_overlay_name) { close_overlay(open_overlay_name); diff --git a/web/src/overlays_modals.ts b/web/src/overlays_modals.ts index a24958ea35..4534187116 100644 --- a/web/src/overlays_modals.ts +++ b/web/src/overlays_modals.ts @@ -1,5 +1,6 @@ -import * as overlays from './overlays'; +import * as modals from "./modals"; +import * as overlays from "./overlays"; export function any_active(): boolean { - return overlays.is_active() || overlays.is_modal_open(); + return overlays.is_active() || modals.is_modal_open(); } diff --git a/web/src/popover_menus.js b/web/src/popover_menus.js index 00d2d7cf08..ca26b39568 100644 --- a/web/src/popover_menus.js +++ b/web/src/popover_menus.js @@ -7,6 +7,7 @@ import tippy from "tippy.js"; import * as blueslip from "./blueslip"; import {media_breakpoints_num} from "./css_variables"; +import * as modals from "./modals"; import * as overlays from "./overlays"; import * as popovers from "./popovers"; @@ -259,6 +260,8 @@ export function initialize() { /* Configure popovers to hide when toggling overlays. */ overlays.register_pre_open_hook(popovers.hide_all); overlays.register_pre_close_hook(popovers.hide_all); + modals.register_pre_open_hook(popovers.hide_all); + modals.register_pre_close_hook(popovers.hide_all); let last_scroll = 0; diff --git a/web/src/read_receipts.js b/web/src/read_receipts.js index c45003dfed..cadd879d13 100644 --- a/web/src/read_receipts.js +++ b/web/src/read_receipts.js @@ -8,13 +8,13 @@ import * as channel from "./channel"; import {$t, $t_html} from "./i18n"; import * as loading from "./loading"; import * as message_store from "./message_store"; -import * as overlays from "./overlays"; +import * as modals from "./modals"; import * as people from "./people"; import * as ui_report from "./ui_report"; export function show_user_list(message_id) { $("body").append(render_read_receipts_modal()); - overlays.open_modal("read_receipts_modal", { + modals.open_modal("read_receipts_modal", { autoremove: true, on_show() { const message = message_store.get(message_id); diff --git a/web/src/scheduled_messages_popover.js b/web/src/scheduled_messages_popover.js index e41a12c99f..01d452e8ce 100644 --- a/web/src/scheduled_messages_popover.js +++ b/web/src/scheduled_messages_popover.js @@ -8,7 +8,7 @@ import render_send_later_modal_options from "../templates/send_later_modal_optio import * as compose from "./compose"; import * as compose_validate from "./compose_validate"; import * as flatpickr from "./flatpickr"; -import * as overlays from "./overlays"; +import * as modals from "./modals"; import * as popover_menus from "./popover_menus"; import * as scheduled_messages from "./scheduled_messages"; import {parse_html} from "./ui_util"; @@ -31,7 +31,7 @@ export function open_send_later_menu() { $("body").append(render_send_later_modal(filtered_send_opts)); let interval; - overlays.open_modal("send_later_modal", { + modals.open_modal("send_later_modal", { autoremove: true, on_show() { interval = setInterval( @@ -100,7 +100,7 @@ export function open_send_later_menu() { } export function do_schedule_message(send_at_time) { - overlays.close_modal_if_open("send_later_modal"); + modals.close_modal_if_open("send_later_modal"); if (!Number.isInteger(send_at_time)) { // Convert to timestamp if this is not a timestamp. diff --git a/web/src/settings.js b/web/src/settings.js index 9e0a49dc02..df3ceeb53d 100644 --- a/web/src/settings.js +++ b/web/src/settings.js @@ -8,6 +8,7 @@ import render_settings_tab from "../templates/settings_tab.hbs"; import * as browser_history from "./browser_history"; import * as flatpickr from "./flatpickr"; import {$t} from "./i18n"; +import * as modals from "./modals"; import * as overlays from "./overlays"; import {page_params} from "./page_params"; import * as people from "./people"; @@ -25,7 +26,7 @@ export let settings_label; $(() => { $("#settings_overlay_container").on("click", (e) => { - if (!overlays.is_modal_open()) { + if (!modals.is_modal_open()) { return; } if ($(e.target).closest(".micromodal").length > 0) { @@ -38,7 +39,7 @@ $(() => { // event to the parent container otherwise the modal will not open. This // is so because this event handler will get fired on any click in settings // overlay and subsequently close any open modal. - overlays.close_active_modal(); + modals.close_active_modal(); }); }); diff --git a/web/src/settings_account.js b/web/src/settings_account.js index 04785a5b6c..4a519d6692 100644 --- a/web/src/settings_account.js +++ b/web/src/settings_account.js @@ -17,6 +17,7 @@ import * as custom_profile_fields_ui from "./custom_profile_fields_ui"; import * as dialog_widget from "./dialog_widget"; import {$t_html} from "./i18n"; import * as keydown_util from "./keydown_util"; +import * as modals from "./modals"; import * as overlays from "./overlays"; import {page_params} from "./page_params"; import * as people from "./people"; @@ -361,7 +362,7 @@ export function set_up() { $("body").append(render_settings_api_key_modal()); setup_api_key_modal(); $("#api_key_status").hide(); - overlays.open_modal("api_key_modal", { + modals.open_modal("api_key_modal", { autoremove: true, on_show() { $("#get_api_key_password").trigger("focus"); diff --git a/web/src/spectators.ts b/web/src/spectators.ts index 75a1e0178a..fb7e444908 100644 --- a/web/src/spectators.ts +++ b/web/src/spectators.ts @@ -10,7 +10,7 @@ import $ from "jquery"; import render_login_to_access_modal from "../templates/login_to_access.hbs"; import * as browser_history from "./browser_history"; -import * as overlays from "./overlays"; +import * as modals from "./modals"; import {page_params} from "./page_params"; export function current_hash_as_next(): string { @@ -40,7 +40,7 @@ export function login_to_access(empty_narrow?: boolean): void { }), ); - overlays.open_modal("login_to_access_modal", { + modals.open_modal("login_to_access_modal", { autoremove: true, on_hide() { browser_history.return_to_web_public_hash(); diff --git a/web/src/user_profile.js b/web/src/user_profile.js index 27d5b21e3c..16d59b52f9 100644 --- a/web/src/user_profile.js +++ b/web/src/user_profile.js @@ -24,7 +24,7 @@ import {$t, $t_html} from "./i18n"; import * as integration_url_modal from "./integration_url_modal"; import * as ListWidget from "./list_widget"; import * as loading from "./loading"; -import * as overlays from "./overlays"; +import * as modals from "./modals"; import {page_params} from "./page_params"; import * as people from "./people"; import * as settings_config from "./settings_config"; @@ -74,7 +74,7 @@ function compare_by_name(a, b) { } export function get_user_id_if_user_profile_modal_open() { - if (overlays.is_modal_open() && overlays.active_modal() === "#user-profile-modal") { + if (modals.is_modal_open() && modals.active_modal() === "#user-profile-modal") { const user_id = $("#user-profile-modal").data("user-id"); return user_id; } @@ -294,7 +294,7 @@ export function get_custom_profile_field_data(user, field, field_types) { export function hide_user_profile() { user_streams_list_widget = undefined; - overlays.close_modal_if_open("user-profile-modal"); + modals.close_modal_if_open("user-profile-modal"); } function show_manage_user_tab(target) { @@ -370,7 +370,7 @@ export function show_user_profile(user, default_tab_key = "profile-tab") { } $("#user-profile-modal-holder").html(render_user_profile_modal(args)); - overlays.open_modal("user-profile-modal", {autoremove: true}); + modals.open_modal("user-profile-modal", {autoremove: true}); $(".tabcontent").hide(); let default_tab = 0; diff --git a/web/tests/hotkey.test.js b/web/tests/hotkey.test.js index d2134b48ce..3210663110 100644 --- a/web/tests/hotkey.test.js +++ b/web/tests/hotkey.test.js @@ -55,6 +55,10 @@ const narrow_state = mock_esm("../src/narrow_state", { is_message_feed_visible: () => true, }); const navigate = mock_esm("../src/navigate"); +const modals = mock_esm("../src/modals", { + is_modal_open: () => false, + active_modal: () => undefined, +}); const overlays = mock_esm("../src/overlays", { is_active: () => false, settings_open: () => false, @@ -63,8 +67,6 @@ const overlays = mock_esm("../src/overlays", { drafts_open: () => false, scheduled_messages_open: () => false, info_overlay_open: () => false, - is_modal_open: () => false, - active_modal: () => undefined, }); const popovers = mock_esm("../src/user_card_popover", { manage_menu: { @@ -348,7 +350,7 @@ run_test("drafts closed launch", ({override}) => { }); run_test("modal open", ({override}) => { - override(overlays, "is_modal_open", () => true); + override(modals, "is_modal_open", () => true); test_normal_typing(); });