From 26e34a163ef44aa33531abc97b725d394a583a86 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Tue, 3 Oct 2023 02:40:45 -0700 Subject: [PATCH] popover_menus: Extract scheduled_messages_popover module. Signed-off-by: Anders Kaseorg --- tools/test-js-with-node | 1 + web/src/compose.js | 16 +-- web/src/popover_menus.js | 164 ------------------------ web/src/scheduled_messages.js | 6 +- web/src/scheduled_messages_popover.js | 174 ++++++++++++++++++++++++++ web/src/ui_init.js | 2 + 6 files changed, 190 insertions(+), 173 deletions(-) create mode 100644 web/src/scheduled_messages_popover.js diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 74477484bb..8045d8f875 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -163,6 +163,7 @@ EXEMPT_FILES = make_set( "web/src/rows.js", "web/src/scheduled_messages.js", "web/src/scheduled_messages_overlay_ui.js", + "web/src/scheduled_messages_popover.js", "web/src/scroll_bar.ts", "web/src/scroll_util.ts", "web/src/search.js", diff --git a/web/src/compose.js b/web/src/compose.js index e36d6d5f2a..5cb9cfa1b7 100644 --- a/web/src/compose.js +++ b/web/src/compose.js @@ -25,10 +25,10 @@ import * as message_events from "./message_events"; import * as narrow from "./narrow"; import {page_params} from "./page_params"; import * as people from "./people"; -import * as popover_menus from "./popover_menus"; import * as rendered_markdown from "./rendered_markdown"; import * as resize from "./resize"; import * as rows from "./rows"; +import * as scheduled_messages_popover from "./scheduled_messages_popover"; import * as sent_messages from "./sent_messages"; import * as server_events from "./server_events"; import * as stream_data from "./stream_data"; @@ -212,7 +212,7 @@ export function clear_compose_box() { compose_banner.clear_warnings(); compose_banner.clear_uploads(); compose_ui.hide_compose_spinner(); - popover_menus.reset_selected_schedule_timestamp(); + scheduled_messages_popover.reset_selected_schedule_timestamp(); } export function send_message_success(local_id, message_id, locally_echoed) { @@ -524,7 +524,7 @@ export function initialize() { if (is_edit_input) { message_edit.save_message_row_edit($row); } else if (event.target.dataset.validationTrigger === "schedule") { - popover_menus.open_send_later_menu(); + scheduled_messages_popover.open_send_later_menu(); // We need to set this flag to true here because `open_send_later_menu` validates the message and sets // the user acknowledged wildcard flag back to 'false' and we don't want that to happen because then it @@ -601,8 +601,9 @@ export function initialize() { )} .main-view-banner-action-button`, (event) => { event.preventDefault(); - const send_at_timestamp = popover_menus.get_selected_send_later_timestamp(); - popover_menus.do_schedule_message(send_at_timestamp); + const send_at_timestamp = + scheduled_messages_popover.get_selected_send_later_timestamp(); + scheduled_messages_popover.do_schedule_message(send_at_timestamp); }, ); @@ -812,8 +813,9 @@ export function initialize() { function schedule_message_to_custom_date() { const compose_message_object = create_message_object(); - const deliver_at = popover_menus.get_formatted_selected_send_later_time(); - const scheduled_delivery_timestamp = popover_menus.get_selected_send_later_timestamp(); + const deliver_at = scheduled_messages_popover.get_formatted_selected_send_later_time(); + const scheduled_delivery_timestamp = + scheduled_messages_popover.get_selected_send_later_timestamp(); const message_type = compose_message_object.type; let req_type; diff --git a/web/src/popover_menus.js b/web/src/popover_menus.js index 4fc52c2478..a81576cd14 100644 --- a/web/src/popover_menus.js +++ b/web/src/popover_menus.js @@ -14,23 +14,18 @@ import render_compose_select_enter_behaviour_popover from "../templates/compose_ import render_delete_topic_modal from "../templates/confirm_dialog/confirm_delete_topic.hbs"; import render_drafts_sidebar_actions from "../templates/drafts_sidebar_action.hbs"; import render_mobile_message_buttons_popover_content from "../templates/mobile_message_buttons_popover_content.hbs"; -import render_send_later_modal from "../templates/send_later_modal.hbs"; -import render_send_later_popover from "../templates/send_later_popover.hbs"; import render_starred_messages_sidebar_actions from "../templates/starred_messages_sidebar_actions.hbs"; import render_topic_sidebar_actions from "../templates/topic_sidebar_actions.hbs"; import * as blueslip from "./blueslip"; import * as channel from "./channel"; import * as common from "./common"; -import * as compose from "./compose"; import * as compose_actions from "./compose_actions"; -import * as compose_validate from "./compose_validate"; import * as condense from "./condense"; import * as confirm_dialog from "./confirm_dialog"; import {show_copied_confirmation} from "./copied_tooltip"; import * as drafts from "./drafts"; import * as emoji_picker from "./emoji_picker"; -import * as flatpickr from "./flatpickr"; import * as giphy from "./giphy"; import {$t_html} from "./i18n"; import * as message_edit from "./message_edit"; @@ -43,18 +38,15 @@ import * as popover_menus_data from "./popover_menus_data"; import * as popovers from "./popovers"; import * as read_receipts from "./read_receipts"; import * as rows from "./rows"; -import * as scheduled_messages from "./scheduled_messages"; import * as starred_messages from "./starred_messages"; import * as starred_messages_ui from "./starred_messages_ui"; import * as stream_popover from "./stream_popover"; -import * as timerender from "./timerender"; import {parse_html} from "./ui_util"; import * as unread_ops from "./unread_ops"; import {user_settings} from "./user_settings"; import * as user_topics from "./user_topics"; let message_actions_popover_keyboard_toggle = false; -let selected_send_later_timestamp; // On mobile web, opening the keyboard can trigger a resize event // (which in turn can trigger a scroll event). This will have the @@ -142,34 +134,6 @@ export function get_topic_menu_popover() { return popover_instances.topics_menu; } -export function get_selected_send_later_timestamp() { - if (!selected_send_later_timestamp) { - return undefined; - } - return selected_send_later_timestamp; -} - -export function get_formatted_selected_send_later_time() { - const current_time = Date.now() / 1000; // seconds, like selected_send_later_timestamp - if ( - scheduled_messages.is_send_later_timestamp_missing_or_expired( - selected_send_later_timestamp, - current_time, - ) - ) { - return undefined; - } - return timerender.get_full_datetime(new Date(selected_send_later_timestamp * 1000), "time"); -} - -export function set_selected_schedule_timestamp(timestamp) { - selected_send_later_timestamp = timestamp; -} - -export function reset_selected_schedule_timestamp() { - selected_send_later_timestamp = undefined; -} - export function get_scheduled_messages_popover() { return popover_instances.send_later; } @@ -363,101 +327,6 @@ export function toggle_message_actions_menu(message) { return true; } -function set_compose_box_schedule(element) { - const selected_send_at_time = element.dataset.sendStamp / 1000; - return selected_send_at_time; -} - -export function open_send_later_menu() { - if (!compose_validate.validate(true)) { - return; - } - - // Only show send later options that are possible today. - const date = new Date(); - const filtered_send_opts = scheduled_messages.get_filtered_send_opts(date); - $("body").append(render_send_later_modal(filtered_send_opts)); - let interval; - - overlays.open_modal("send_later_modal", { - autoremove: true, - on_show() { - interval = setInterval( - scheduled_messages.update_send_later_options, - scheduled_messages.SCHEDULING_MODAL_UPDATE_INTERVAL_IN_MILLISECONDS, - ); - - const $send_later_modal = $("#send_later_modal"); - - // Upon the first keydown event, we focus on the first element in the list, - // enabling keyboard navigation that is handled by `hotkey.js` and `list_util.ts`. - $send_later_modal.one("keydown", () => { - const $options = $send_later_modal.find("a"); - $options[0].focus(); - - $send_later_modal.on("keydown", (e) => { - if (e.key === "Enter") { - e.target.click(); - } - }); - }); - - $send_later_modal.on("click", ".send_later_custom", (e) => { - const $send_later_modal_content = $send_later_modal.find(".modal__content"); - const current_time = new Date(); - flatpickr.show_flatpickr( - $(".send_later_custom")[0], - do_schedule_message, - new Date(current_time.getTime() + 60 * 60 * 1000), - { - minDate: new Date( - current_time.getTime() + - scheduled_messages.MINIMUM_SCHEDULED_MESSAGE_DELAY_SECONDS * 1000, - ), - onClose() { - // Return to normal state. - $send_later_modal_content.css("pointer-events", "all"); - }, - }, - ); - // Disable interaction with rest of the options in the modal. - $send_later_modal_content.css("pointer-events", "none"); - e.preventDefault(); - e.stopPropagation(); - }); - $send_later_modal.one( - "click", - ".send_later_today, .send_later_tomorrow, .send_later_monday", - (e) => { - const send_at_time = set_compose_box_schedule(e.currentTarget); - do_schedule_message(send_at_time); - e.preventDefault(); - e.stopPropagation(); - }, - ); - }, - on_shown() { - // When shown, we should give the modal focus to correctly handle keyboard events. - const $send_later_modal_overlay = $("#send_later_modal .modal__overlay"); - $send_later_modal_overlay.trigger("focus"); - }, - on_hide() { - clearInterval(interval); - }, - }); -} - -export function do_schedule_message(send_at_time) { - overlays.close_modal_if_open("send_later_modal"); - - if (!Number.isInteger(send_at_time)) { - // Convert to timestamp if this is not a timestamp. - send_at_time = Math.floor(Date.parse(send_at_time) / 1000); - } - selected_send_later_timestamp = send_at_time; - compose.finish(true); -} - export function initialize() { // compose box buttons popover shown on mobile widths. // We want this click event to propagate and hide other popovers @@ -1033,39 +902,6 @@ export function initialize() { }, }); - delegate("body", { - ...default_popover_props, - target: "#send_later i", - onUntrigger() { - // This is only called when the popover is closed by clicking on `target`. - $("#compose-textarea").trigger("focus"); - }, - onShow(instance) { - const formatted_send_later_time = get_formatted_selected_send_later_time(); - instance.setContent( - parse_html( - render_send_later_popover({ - formatted_send_later_time, - }), - ), - ); - popover_instances.send_later = instance; - $(instance.popper).one("click", instance.hide); - }, - onMount(instance) { - const $popper = $(instance.popper); - $popper.one("click", ".send_later_selected_send_later_time", () => { - const send_at_timestamp = get_selected_send_later_timestamp(); - do_schedule_message(send_at_timestamp); - }); - $popper.one("click", ".open_send_later_modal", open_send_later_menu); - }, - onHidden(instance) { - instance.destroy(); - popover_instances.send_later = undefined; - }, - }); - /* Configure popovers to hide when toggling overlays. */ overlays.register_pre_open_hook(popovers.hide_all); overlays.register_pre_close_hook(popovers.hide_all); diff --git a/web/src/scheduled_messages.js b/web/src/scheduled_messages.js index 40b48f8d53..a35c26d9ab 100644 --- a/web/src/scheduled_messages.js +++ b/web/src/scheduled_messages.js @@ -11,7 +11,7 @@ import * as compose_ui from "./compose_ui"; import {$t} from "./i18n"; import * as narrow from "./narrow"; import * as people from "./people"; -import * as popover_menus from "./popover_menus"; +import * as scheduled_messages_popover from "./scheduled_messages_popover"; import * as sub_store from "./sub_store"; import * as timerender from "./timerender"; @@ -134,7 +134,9 @@ export function open_scheduled_message_in_compose(scheduled_msg, should_narrow_t compose_banner.clear_message_sent_banners(false); compose_actions.start(compose_args.type, compose_args); compose_ui.autosize_textarea($("#compose-textarea")); - popover_menus.set_selected_schedule_timestamp(scheduled_msg.scheduled_delivery_timestamp); + scheduled_messages_popover.set_selected_schedule_timestamp( + scheduled_msg.scheduled_delivery_timestamp, + ); } function show_message_unscheduled_banner(scheduled_delivery_timestamp) { diff --git a/web/src/scheduled_messages_popover.js b/web/src/scheduled_messages_popover.js new file mode 100644 index 0000000000..227fd5e4c2 --- /dev/null +++ b/web/src/scheduled_messages_popover.js @@ -0,0 +1,174 @@ +import $ from "jquery"; +import {delegate} from "tippy.js"; + +import render_send_later_modal from "../templates/send_later_modal.hbs"; +import render_send_later_popover from "../templates/send_later_popover.hbs"; + +import * as compose from "./compose"; +import * as compose_validate from "./compose_validate"; +import * as flatpickr from "./flatpickr"; +import * as overlays from "./overlays"; +import * as popover_menus from "./popover_menus"; +import * as scheduled_messages from "./scheduled_messages"; +import * as timerender from "./timerender"; +import {parse_html} from "./ui_util"; + +let selected_send_later_timestamp; + +export function get_selected_send_later_timestamp() { + if (!selected_send_later_timestamp) { + return undefined; + } + return selected_send_later_timestamp; +} + +export function get_formatted_selected_send_later_time() { + const current_time = Date.now() / 1000; // seconds, like selected_send_later_timestamp + if ( + scheduled_messages.is_send_later_timestamp_missing_or_expired( + selected_send_later_timestamp, + current_time, + ) + ) { + return undefined; + } + return timerender.get_full_datetime(new Date(selected_send_later_timestamp * 1000), "time"); +} + +export function set_selected_schedule_timestamp(timestamp) { + selected_send_later_timestamp = timestamp; +} + +export function reset_selected_schedule_timestamp() { + selected_send_later_timestamp = undefined; +} + +function set_compose_box_schedule(element) { + const selected_send_at_time = element.dataset.sendStamp / 1000; + return selected_send_at_time; +} + +export function open_send_later_menu() { + if (!compose_validate.validate(true)) { + return; + } + + // Only show send later options that are possible today. + const date = new Date(); + const filtered_send_opts = scheduled_messages.get_filtered_send_opts(date); + $("body").append(render_send_later_modal(filtered_send_opts)); + let interval; + + overlays.open_modal("send_later_modal", { + autoremove: true, + on_show() { + interval = setInterval( + scheduled_messages.update_send_later_options, + scheduled_messages.SCHEDULING_MODAL_UPDATE_INTERVAL_IN_MILLISECONDS, + ); + + const $send_later_modal = $("#send_later_modal"); + + // Upon the first keydown event, we focus on the first element in the list, + // enabling keyboard navigation that is handled by `hotkey.js` and `list_util.ts`. + $send_later_modal.one("keydown", () => { + const $options = $send_later_modal.find("a"); + $options[0].focus(); + + $send_later_modal.on("keydown", (e) => { + if (e.key === "Enter") { + e.target.click(); + } + }); + }); + + $send_later_modal.on("click", ".send_later_custom", (e) => { + const $send_later_modal_content = $send_later_modal.find(".modal__content"); + const current_time = new Date(); + flatpickr.show_flatpickr( + $(".send_later_custom")[0], + do_schedule_message, + new Date(current_time.getTime() + 60 * 60 * 1000), + { + minDate: new Date( + current_time.getTime() + + scheduled_messages.MINIMUM_SCHEDULED_MESSAGE_DELAY_SECONDS * 1000, + ), + onClose() { + // Return to normal state. + $send_later_modal_content.css("pointer-events", "all"); + }, + }, + ); + // Disable interaction with rest of the options in the modal. + $send_later_modal_content.css("pointer-events", "none"); + e.preventDefault(); + e.stopPropagation(); + }); + $send_later_modal.one( + "click", + ".send_later_today, .send_later_tomorrow, .send_later_monday", + (e) => { + const send_at_time = set_compose_box_schedule(e.currentTarget); + do_schedule_message(send_at_time); + e.preventDefault(); + e.stopPropagation(); + }, + ); + }, + on_shown() { + // When shown, we should give the modal focus to correctly handle keyboard events. + const $send_later_modal_overlay = $("#send_later_modal .modal__overlay"); + $send_later_modal_overlay.trigger("focus"); + }, + on_hide() { + clearInterval(interval); + }, + }); +} + +export function do_schedule_message(send_at_time) { + overlays.close_modal_if_open("send_later_modal"); + + if (!Number.isInteger(send_at_time)) { + // Convert to timestamp if this is not a timestamp. + send_at_time = Math.floor(Date.parse(send_at_time) / 1000); + } + selected_send_later_timestamp = send_at_time; + compose.finish(true); +} + +export function initialize() { + delegate("body", { + ...popover_menus.default_popover_props, + target: "#send_later i", + onUntrigger() { + // This is only called when the popover is closed by clicking on `target`. + $("#compose-textarea").trigger("focus"); + }, + onShow(instance) { + const formatted_send_later_time = get_formatted_selected_send_later_time(); + instance.setContent( + parse_html( + render_send_later_popover({ + formatted_send_later_time, + }), + ), + ); + popover_menus.popover_instances.send_later = instance; + $(instance.popper).one("click", instance.hide); + }, + onMount(instance) { + const $popper = $(instance.popper); + $popper.one("click", ".send_later_selected_send_later_time", () => { + const send_at_timestamp = get_selected_send_later_timestamp(); + do_schedule_message(send_at_timestamp); + }); + $popper.one("click", ".open_send_later_modal", open_send_later_menu); + }, + onHidden(instance) { + instance.destroy(); + popover_menus.popover_instances.send_later = undefined; + }, + }); +} diff --git a/web/src/ui_init.js b/web/src/ui_init.js index 83c9a3181c..b66bd69c95 100644 --- a/web/src/ui_init.js +++ b/web/src/ui_init.js @@ -83,6 +83,7 @@ import * as rendered_markdown from "./rendered_markdown"; import * as resize from "./resize"; import * as scheduled_messages from "./scheduled_messages"; import * as scheduled_messages_overlay_ui from "./scheduled_messages_overlay_ui"; +import * as scheduled_messages_popover from "./scheduled_messages_popover"; import * as scroll_bar from "./scroll_bar"; import * as scroll_util from "./scroll_util"; import * as search from "./search"; @@ -525,6 +526,7 @@ export function initialize_everything() { // This populates data for scheduled messages. scheduled_messages.initialize(scheduled_messages_params); popover_menus.initialize(); + scheduled_messages_popover.initialize(); realm_user_settings_defaults.initialize(realm_settings_defaults_params); people.initialize(page_params.user_id, people_params);