From 971a0031804306870f1455871b669800a1147d14 Mon Sep 17 00:00:00 2001 From: Anders Kaseorg Date: Thu, 5 Oct 2023 16:43:50 -0700 Subject: [PATCH] compose_actions: Extract compose_reply module. Signed-off-by: Anders Kaseorg --- tools/test-js-with-node | 1 + web/src/click_handlers.js | 3 +- web/src/compose_actions.js | 156 +------------------------- web/src/compose_closed_ui.js | 4 - web/src/compose_reply.js | 172 +++++++++++++++++++++++++++++ web/src/hotkey.js | 11 +- web/src/message_actions_popover.js | 6 +- web/src/ui_init.js | 2 + web/src/upload.js | 7 +- web/src/user_card_popover.js | 3 +- web/tests/compose_actions.test.js | 7 +- web/tests/compose_ui.test.js | 16 +-- web/tests/hotkey.test.js | 9 +- web/tests/upload.test.js | 7 +- 14 files changed, 214 insertions(+), 190 deletions(-) create mode 100644 web/src/compose_reply.js diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 88441bbfa2..0ed40956a1 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -69,6 +69,7 @@ EXEMPT_FILES = make_set( "web/src/compose_fade.js", "web/src/compose_popovers.js", "web/src/compose_recipient.js", + "web/src/compose_reply.js", "web/src/compose_setup.js", "web/src/compose_state.js", "web/src/compose_textarea.ts", diff --git a/web/src/click_handlers.js b/web/src/click_handlers.js index 3c39f94e09..c08c774ae8 100644 --- a/web/src/click_handlers.js +++ b/web/src/click_handlers.js @@ -13,6 +13,7 @@ import * as buddy_data from "./buddy_data"; import * as channel from "./channel"; import * as compose from "./compose"; import * as compose_actions from "./compose_actions"; +import * as compose_reply from "./compose_reply"; import * as compose_state from "./compose_state"; import {media_breakpoints_num} from "./css_variables"; import * as dark_theme from "./dark_theme"; @@ -207,7 +208,7 @@ export function initialize() { if (page_params.is_spectator) { return; } - compose_actions.respond_to_message({trigger: "message click"}); + compose_reply.respond_to_message({trigger: "message click"}); e.stopPropagation(); }; diff --git a/web/src/compose_actions.js b/web/src/compose_actions.js index ddb8bceff4..07a3388f3a 100644 --- a/web/src/compose_actions.js +++ b/web/src/compose_actions.js @@ -3,9 +3,6 @@ import autosize from "autosize"; import $ from "jquery"; -import * as fenced_code from "../shared/src/fenced_code"; - -import * as channel from "./channel"; import * as compose_banner from "./compose_banner"; import * as compose_fade from "./compose_fade"; import * as compose_pm_pill from "./compose_pm_pill"; @@ -14,22 +11,17 @@ import * as compose_state from "./compose_state"; import * as compose_ui from "./compose_ui"; import * as compose_validate from "./compose_validate"; import * as drafts from "./drafts"; -import * as hash_util from "./hash_util"; -import {$t} from "./i18n"; import * as message_lists from "./message_lists"; import * as message_viewport from "./message_viewport"; import * as narrow_state from "./narrow_state"; import {page_params} from "./page_params"; import * as people from "./people"; -import * as recent_view_ui from "./recent_view_ui"; -import * as recent_view_util from "./recent_view_util"; import * as reload_state from "./reload_state"; import * as resize from "./resize"; import * as settings_config from "./settings_config"; import * as spectators from "./spectators"; import * as stream_bar from "./stream_bar"; import * as stream_data from "./stream_data"; -import * as unread_ops from "./unread_ops"; const compose_clear_box_hooks = []; const compose_cancel_hooks = []; @@ -153,7 +145,7 @@ export function maybe_scroll_up_selected_message() { } } -function fill_in_opts_from_current_narrowed_view(msg_type, opts) { +export function fill_in_opts_from_current_narrowed_view(msg_type, opts) { return { message_type: msg_type, stream_id: "", @@ -314,99 +306,6 @@ export function cancel() { $(document).trigger("compose_canceled.zulip"); } -export function respond_to_message(opts) { - let message; - let msg_type; - if (recent_view_util.is_visible()) { - message = recent_view_ui.get_focused_row_message(); - if (message === undefined) { - // Open empty compose with nothing pre-filled since - // user is not focused on any table row. - start("stream", {trigger: "recent_view_nofocus"}); - return; - } - } else { - message = message_lists.current.selected_message(); - - if (message === undefined) { - // empty narrow implementation - if ( - !narrow_state.narrowed_by_pm_reply() && - !narrow_state.narrowed_by_stream_reply() && - !narrow_state.narrowed_by_topic_reply() - ) { - start("stream", {trigger: "empty_narrow_compose"}); - return; - } - const current_filter = narrow_state.filter(); - const first_term = current_filter.operators()[0]; - const first_operator = first_term.operator; - const first_operand = first_term.operand; - - if (first_operator === "stream" && !stream_data.is_subscribed_by_name(first_operand)) { - start("stream", {trigger: "empty_narrow_compose"}); - return; - } - - // Set msg_type to stream by default in the case of an empty - // home view. - msg_type = "stream"; - if (narrow_state.narrowed_by_pm_reply()) { - msg_type = "private"; - } - - const new_opts = fill_in_opts_from_current_narrowed_view(msg_type, opts); - start(new_opts.message_type, new_opts); - return; - } - - if (message_lists.current.can_mark_messages_read()) { - unread_ops.notify_server_message_read(message); - } - } - - // Important note: A reply_type of 'personal' is for the R hotkey - // (replying to a message's sender with a direct message). All - // other replies can just copy message.type. - if (opts.reply_type === "personal" || message.type === "private") { - msg_type = "private"; - } else { - msg_type = message.type; - } - - let stream_id = ""; - let topic = ""; - let pm_recipient = ""; - if (msg_type === "stream") { - stream_id = message.stream_id; - topic = message.topic; - } else { - pm_recipient = message.reply_to; - if (opts.reply_type === "personal") { - // reply_to for direct messages is everyone involved, so for - // personals replies we need to set the direct message - // recipient to just the sender - pm_recipient = people.get_by_user_id(message.sender_id).email; - } else { - pm_recipient = people.pm_reply_to(message); - } - } - - start(msg_type, { - stream_id, - topic, - private_message_recipient: pm_recipient, - trigger: opts.trigger, - }); -} - -export function reply_with_mention(opts) { - respond_to_message(opts); - const message = message_lists.current.selected_message(); - const mention = people.get_mention_syntax(message.sender_full_name, message.sender_id); - compose_ui.insert_syntax_and_focus(mention); -} - export function on_topic_narrow() { if (!compose_state.composing()) { // If our compose box is closed, then just @@ -456,59 +355,6 @@ export function on_topic_narrow() { $("#compose-textarea").trigger("focus"); } -export function quote_and_reply(opts) { - const $textarea = $("#compose-textarea"); - const message_id = message_lists.current.selected_id(); - const message = message_lists.current.selected_message(); - const quoting_placeholder = $t({defaultMessage: "[Quoting…]"}); - - if (!compose_state.has_message_content()) { - // The user has not started typing a message, - // so we will re-open the compose box. - // (If you did re-open the compose box, you - // are prone to glitches where you select the - // text, plus it's a complicated codepath that - // can have other unintended consequences.) - respond_to_message(opts); - } - - compose_ui.insert_syntax_and_focus(quoting_placeholder, $textarea, "block"); - - function replace_content(message) { - // Final message looks like: - // @_**Iago|5** [said](link to message): - // ```quote - // message content - // ``` - let content = $t( - {defaultMessage: "{username} [said]({link_to_message}):"}, - { - username: `@_**${message.sender_full_name}|${message.sender_id}**`, - link_to_message: `${hash_util.by_conversation_and_time_url(message)}`, - }, - ); - content += "\n"; - const fence = fenced_code.get_unused_fence(message.raw_content); - content += `${fence}quote\n${message.raw_content}\n${fence}`; - - compose_ui.replace_syntax(quoting_placeholder, content, $textarea); - compose_ui.autosize_textarea($("#compose-textarea")); - } - - if (message && message.raw_content) { - replace_content(message); - return; - } - - channel.get({ - url: "/json/messages/" + message_id, - success(data) { - message.raw_content = data.raw_content; - replace_content(message); - }, - }); -} - export function on_narrow(opts) { // We use force_close when jumping between direct message narrows with // the "p" key, so that we don't have an open compose box that makes diff --git a/web/src/compose_closed_ui.js b/web/src/compose_closed_ui.js index 92def3f3d1..896e058651 100644 --- a/web/src/compose_closed_ui.js +++ b/web/src/compose_closed_ui.js @@ -175,8 +175,4 @@ export function initialize() { $("body").on("click", ".compose_private_button", () => { compose_actions.start("private", {trigger: "new direct message"}); }); - - $("body").on("click", ".compose_reply_button", () => { - compose_actions.respond_to_message({trigger: "reply button"}); - }); } diff --git a/web/src/compose_reply.js b/web/src/compose_reply.js new file mode 100644 index 0000000000..f85456f9a4 --- /dev/null +++ b/web/src/compose_reply.js @@ -0,0 +1,172 @@ +import $ from "jquery"; + +import * as fenced_code from "../shared/src/fenced_code"; + +import * as channel from "./channel"; +import * as compose_actions from "./compose_actions"; +import * as compose_state from "./compose_state"; +import * as compose_ui from "./compose_ui"; +import * as hash_util from "./hash_util"; +import {$t} from "./i18n"; +import * as message_lists from "./message_lists"; +import * as narrow_state from "./narrow_state"; +import * as people from "./people"; +import * as recent_view_ui from "./recent_view_ui"; +import * as recent_view_util from "./recent_view_util"; +import * as stream_data from "./stream_data"; +import * as unread_ops from "./unread_ops"; + +export function respond_to_message(opts) { + let message; + let msg_type; + if (recent_view_util.is_visible()) { + message = recent_view_ui.get_focused_row_message(); + if (message === undefined) { + // Open empty compose with nothing pre-filled since + // user is not focused on any table row. + compose_actions.start("stream", {trigger: "recent_view_nofocus"}); + return; + } + } else { + message = message_lists.current.selected_message(); + + if (message === undefined) { + // empty narrow implementation + if ( + !narrow_state.narrowed_by_pm_reply() && + !narrow_state.narrowed_by_stream_reply() && + !narrow_state.narrowed_by_topic_reply() + ) { + compose_actions.start("stream", {trigger: "empty_narrow_compose"}); + return; + } + const current_filter = narrow_state.filter(); + const first_term = current_filter.operators()[0]; + const first_operator = first_term.operator; + const first_operand = first_term.operand; + + if (first_operator === "stream" && !stream_data.is_subscribed_by_name(first_operand)) { + compose_actions.start("stream", {trigger: "empty_narrow_compose"}); + return; + } + + // Set msg_type to stream by default in the case of an empty + // home view. + msg_type = "stream"; + if (narrow_state.narrowed_by_pm_reply()) { + msg_type = "private"; + } + + const new_opts = compose_actions.fill_in_opts_from_current_narrowed_view( + msg_type, + opts, + ); + compose_actions.start(new_opts.message_type, new_opts); + return; + } + + if (message_lists.current.can_mark_messages_read()) { + unread_ops.notify_server_message_read(message); + } + } + + // Important note: A reply_type of 'personal' is for the R hotkey + // (replying to a message's sender with a direct message). All + // other replies can just copy message.type. + if (opts.reply_type === "personal" || message.type === "private") { + msg_type = "private"; + } else { + msg_type = message.type; + } + + let stream_id = ""; + let topic = ""; + let pm_recipient = ""; + if (msg_type === "stream") { + stream_id = message.stream_id; + topic = message.topic; + } else { + pm_recipient = message.reply_to; + if (opts.reply_type === "personal") { + // reply_to for direct messages is everyone involved, so for + // personals replies we need to set the direct message + // recipient to just the sender + pm_recipient = people.get_by_user_id(message.sender_id).email; + } else { + pm_recipient = people.pm_reply_to(message); + } + } + + compose_actions.start(msg_type, { + stream_id, + topic, + private_message_recipient: pm_recipient, + trigger: opts.trigger, + }); +} + +export function reply_with_mention(opts) { + respond_to_message(opts); + const message = message_lists.current.selected_message(); + const mention = people.get_mention_syntax(message.sender_full_name, message.sender_id); + compose_ui.insert_syntax_and_focus(mention); +} + +export function quote_and_reply(opts) { + const $textarea = $("#compose-textarea"); + const message_id = message_lists.current.selected_id(); + const message = message_lists.current.selected_message(); + const quoting_placeholder = $t({defaultMessage: "[Quoting…]"}); + + if (!compose_state.has_message_content()) { + // The user has not started typing a message, + // so we will re-open the compose box. + // (If you did re-open the compose box, you + // are prone to glitches where you select the + // text, plus it's a complicated codepath that + // can have other unintended consequences.) + respond_to_message(opts); + } + + compose_ui.insert_syntax_and_focus(quoting_placeholder, $textarea, "block"); + + function replace_content(message) { + // Final message looks like: + // @_**Iago|5** [said](link to message): + // ```quote + // message content + // ``` + let content = $t( + {defaultMessage: "{username} [said]({link_to_message}):"}, + { + username: `@_**${message.sender_full_name}|${message.sender_id}**`, + link_to_message: `${hash_util.by_conversation_and_time_url(message)}`, + }, + ); + content += "\n"; + const fence = fenced_code.get_unused_fence(message.raw_content); + content += `${fence}quote\n${message.raw_content}\n${fence}`; + + compose_ui.replace_syntax(quoting_placeholder, content, $textarea); + compose_ui.autosize_textarea($("#compose-textarea")); + } + + if (message && message.raw_content) { + replace_content(message); + return; + } + + channel.get({ + url: "/json/messages/" + message_id, + success(data) { + message.raw_content = data.raw_content; + replace_content(message); + }, + }); +} + +export function initialize() { + $("body").on("click", ".compose_reply_button", () => { + respond_to_message({trigger: "reply button"}); + }); +} diff --git a/web/src/hotkey.js b/web/src/hotkey.js index 65f9ce32c1..6f55746ce0 100644 --- a/web/src/hotkey.js +++ b/web/src/hotkey.js @@ -8,6 +8,7 @@ import * as compose from "./compose"; import * as compose_actions from "./compose_actions"; import * as compose_banner from "./compose_banner"; import * as compose_recipient from "./compose_recipient"; +import * as compose_reply from "./compose_reply"; import * as compose_state from "./compose_state"; import * as compose_textarea from "./compose_textarea"; import * as condense from "./condense"; @@ -544,7 +545,7 @@ export function process_enter_key(e) { return true; } - compose_actions.respond_to_message({trigger: "hotkey enter"}); + compose_reply.respond_to_message({trigger: "hotkey enter"}); return true; } @@ -927,7 +928,7 @@ export function process_hotkey(e, hotkey) { case "reply_message": // 'r': respond to message // Note that you can "Enter" to respond to messages as well, // but that is handled in process_enter_key(). - compose_actions.respond_to_message({trigger: "hotkey"}); + compose_reply.respond_to_message({trigger: "hotkey"}); return true; case "compose": // 'c': compose if (!compose_state.composing()) { @@ -1027,10 +1028,10 @@ export function process_hotkey(e, hotkey) { deprecated_feature_notice.maybe_show_deprecation_notice("Shift + S"); return true; case "respond_to_author": // 'R': respond to author - compose_actions.respond_to_message({reply_type: "personal", trigger: "hotkey pm"}); + compose_reply.respond_to_message({reply_type: "personal", trigger: "hotkey pm"}); return true; case "compose_reply_with_mention": // '@': respond to message with mention to author - compose_actions.reply_with_mention({trigger: "hotkey"}); + compose_reply.reply_with_mention({trigger: "hotkey"}); return true; case "show_lightbox": lightbox.show_from_selected_message(); @@ -1085,7 +1086,7 @@ export function process_hotkey(e, hotkey) { unread_ops.mark_as_unread_from_here(msg.id); return true; case "compose_quote_reply": // > : respond to selected message with quote - compose_actions.quote_and_reply({trigger: "hotkey"}); + compose_reply.quote_and_reply({trigger: "hotkey"}); return true; case "edit_message": { const $row = message_lists.current.get_row(msg.id); diff --git a/web/src/message_actions_popover.js b/web/src/message_actions_popover.js index 8c90e0fc2a..e0573534d4 100644 --- a/web/src/message_actions_popover.js +++ b/web/src/message_actions_popover.js @@ -4,7 +4,7 @@ import $ from "jquery"; import render_actions_popover from "../templates/popovers/actions_popover.hbs"; import * as blueslip from "./blueslip"; -import * as compose_actions from "./compose_actions"; +import * as compose_reply from "./compose_reply"; import * as condense from "./condense"; import {show_copied_confirmation} from "./copied_tooltip"; import * as emoji_picker from "./emoji_picker"; @@ -97,9 +97,9 @@ export function initialize() { // Arguably, we should fetch the message ID to respond to from // e.target, but that should always be the current selected // message in the current message list (and - // compose_actions.respond_to_message doesn't take a message + // compose_reply.respond_to_message doesn't take a message // argument). - compose_actions.quote_and_reply({trigger: "popover respond"}); + compose_reply.quote_and_reply({trigger: "popover respond"}); e.preventDefault(); e.stopPropagation(); instance.hide(); diff --git a/web/src/ui_init.js b/web/src/ui_init.js index 0fbc9c3a31..838aee7008 100644 --- a/web/src/ui_init.js +++ b/web/src/ui_init.js @@ -26,6 +26,7 @@ import * as compose_closed_ui from "./compose_closed_ui"; import * as compose_pm_pill from "./compose_pm_pill"; import * as compose_popovers from "./compose_popovers"; import * as compose_recipient from "./compose_recipient"; +import * as compose_reply from "./compose_reply"; import * as compose_setup from "./compose_setup"; import * as compose_textarea from "./compose_textarea"; import * as compose_tooltips from "./compose_tooltips"; @@ -638,6 +639,7 @@ export function initialize_everything() { on_pill_create_or_remove: compose_recipient.update_placeholder_text, }); compose_closed_ui.initialize(); + compose_reply.initialize(); reload_setup.initialize(); unread.initialize(unread_params); bot_data.initialize(bot_params); // Must happen after people.initialize() diff --git a/web/src/upload.js b/web/src/upload.js index 573d881f27..0b91c3daab 100644 --- a/web/src/upload.js +++ b/web/src/upload.js @@ -6,6 +6,7 @@ import render_upload_banner from "../templates/compose_banner/upload_banner.hbs" import * as compose_actions from "./compose_actions"; import * as compose_banner from "./compose_banner"; +import * as compose_reply from "./compose_reply"; import * as compose_state from "./compose_state"; import * as compose_ui from "./compose_ui"; import {csrf_token} from "./csrf"; @@ -312,7 +313,7 @@ export function setup_upload(config) { event.stopPropagation(); const files = event.originalEvent.dataTransfer.files; if (config.mode === "compose" && !compose_state.composing()) { - compose_actions.respond_to_message({trigger: "file drop or paste"}); + compose_reply.respond_to_message({trigger: "file drop or paste"}); } upload_files(uppy, config, files); }); @@ -339,7 +340,7 @@ export function setup_upload(config) { // present a plain-text version of the file name. event.preventDefault(); if (config.mode === "compose" && !compose_state.composing()) { - compose_actions.respond_to_message({trigger: "file drop or paste"}); + compose_reply.respond_to_message({trigger: "file drop or paste"}); } upload_files(uppy, config, files); }); @@ -459,7 +460,7 @@ export function initialize() { upload_files(edit_upload_object, {mode: "edit", row: row_id}, files); } else if (message_lists.current.selected_message()) { // Start a reply to selected message, if viewing a message feed. - compose_actions.respond_to_message({trigger: "drag_drop_file"}); + compose_reply.respond_to_message({trigger: "drag_drop_file"}); upload_files(compose_upload_object, {mode: "compose"}, files); } else { // Start a new message in other views. diff --git a/web/src/user_card_popover.js b/web/src/user_card_popover.js index e19b564ab6..645491d160 100644 --- a/web/src/user_card_popover.js +++ b/web/src/user_card_popover.js @@ -12,6 +12,7 @@ import * as blueslip from "./blueslip"; import * as buddy_data from "./buddy_data"; import * as channel from "./channel"; import * as compose_actions from "./compose_actions"; +import * as compose_reply from "./compose_reply"; import * as compose_state from "./compose_state"; import * as compose_ui from "./compose_ui"; import * as confirm_dialog from "./confirm_dialog"; @@ -736,7 +737,7 @@ function register_click_handlers() { $("body").on("click", ".message-user-card-popover-root .mention_user", (e) => { if (!compose_state.composing()) { - compose_actions.respond_to_message({trigger: "user sidebar popover"}); + compose_reply.respond_to_message({trigger: "user sidebar popover"}); } const user_id = elem_to_user_id($(e.target).parents("ul")); const name = people.get_by_user_id(user_id).full_name; diff --git a/web/tests/compose_actions.test.js b/web/tests/compose_actions.test.js index 53c63f8f56..72679f9065 100644 --- a/web/tests/compose_actions.test.js +++ b/web/tests/compose_actions.test.js @@ -64,15 +64,16 @@ const people = zrequire("people"); const compose_setup = zrequire("compose_setup"); const compose_state = zrequire("compose_state"); const compose_actions = zrequire("compose_actions"); +const compose_reply = zrequire("compose_reply"); const message_lists = zrequire("message_lists"); const stream_data = zrequire("stream_data"); const compose_recipient = zrequire("compose_recipient"); const start = compose_actions.start; const cancel = compose_actions.cancel; -const respond_to_message = compose_actions.respond_to_message; -const reply_with_mention = compose_actions.reply_with_mention; -const quote_and_reply = compose_actions.quote_and_reply; +const respond_to_message = compose_reply.respond_to_message; +const reply_with_mention = compose_reply.reply_with_mention; +const quote_and_reply = compose_reply.quote_and_reply; function assert_visible(sel) { assert.ok($(sel).visible()); diff --git a/web/tests/compose_ui.test.js b/web/tests/compose_ui.test.js index 05d22ef387..4e94fd5ef3 100644 --- a/web/tests/compose_ui.test.js +++ b/web/tests/compose_ui.test.js @@ -25,7 +25,7 @@ const people = zrequire("people"); const user_status = zrequire("user_status"); const hash_util = mock_esm("../src/hash_util"); const channel = mock_esm("../src/channel"); -const compose_actions = zrequire("compose_actions"); +const compose_reply = zrequire("compose_reply"); const message_lists = zrequire("message_lists"); const text_field_edit = mock_esm("text-field-edit"); @@ -352,7 +352,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => { let quote_text = "Testing caret position"; override_with_quote_text(quote_text); set_compose_content_with_caret("hello %there"); // "%" is used to encode/display position of focus before change - compose_actions.quote_and_reply(); + compose_reply.quote_and_reply(); success_function({ raw_content: quote_text, @@ -367,7 +367,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => { assert.equal(syntax, "translated: [Quoting…]\n\n"); }); set_compose_content_with_caret("%hello there"); - compose_actions.quote_and_reply(); + compose_reply.quote_and_reply(); quote_text = "Testing with caret initially positioned at 0."; override_with_quote_text(quote_text); @@ -375,7 +375,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => { raw_content: quote_text, }); - override_rewire(compose_actions, "respond_to_message", () => { + override_rewire(compose_reply, "respond_to_message", () => { // Reset compose state to replicate the re-opening of compose-box. textarea_val = ""; textarea_caret_pos = 0; @@ -387,7 +387,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => { // If the compose-box is close, or open with no content while // quoting a message, the quoted message should be placed // at the beginning of compose-box. - compose_actions.quote_and_reply(); + compose_reply.quote_and_reply(); quote_text = "Testing with compose-box closed initially."; override_with_quote_text(quote_text); @@ -402,7 +402,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => { // newlines), the compose-box should re-open and thus the quoted // message should start from the beginning of compose-box. set_compose_content_with_caret(" \n\n \n %"); - compose_actions.quote_and_reply(); + compose_reply.quote_and_reply(); quote_text = "Testing with compose-box containing whitespaces and newlines only."; override_with_quote_text(quote_text); @@ -419,7 +419,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => { assert.equal(syntax, "\ntranslated: [Quoting…]\n"); }); set_compose_content_with_caret("1st line\n%\n2nd line"); - compose_actions.quote_and_reply(); + compose_reply.quote_and_reply(); quote_text = "Testing with caret on a new line between 2 lines of text."; override_with_quote_text(quote_text); @@ -436,7 +436,7 @@ run_test("quote_and_reply", ({override, override_rewire}) => { assert.equal(syntax, "translated: [Quoting…]"); }); set_compose_content_with_caret("lots of\n\n\n\n%\n\n\nnewlines"); - compose_actions.quote_and_reply(); + compose_reply.quote_and_reply(); quote_text = "Testing with caret on a new line between many empty newlines."; override_with_quote_text(quote_text); diff --git a/web/tests/hotkey.test.js b/web/tests/hotkey.test.js index 9e08a3dd67..dac2656f60 100644 --- a/web/tests/hotkey.test.js +++ b/web/tests/hotkey.test.js @@ -34,6 +34,7 @@ set_global("document", "document-stub"); const browser_history = mock_esm("../src/browser_history"); const compose_actions = mock_esm("../src/compose_actions"); +const compose_reply = mock_esm("../src/compose_reply"); const condense = mock_esm("../src/condense"); const drafts_overlay_ui = mock_esm("../src/drafts_overlay_ui"); const emoji_picker = mock_esm("../src/emoji_picker", { @@ -370,14 +371,14 @@ run_test("misc", ({override}) => { // TODO: Similar check for being in the subs page - assert_mapping("@", compose_actions, "reply_with_mention"); + assert_mapping("@", compose_reply, "reply_with_mention"); assert_mapping("+", reactions, "toggle_emoji_reaction"); // Without an existing emoji reaction, this next one will only // call get_message_reactions, so we verify just that. assert_mapping("=", reactions, "get_message_reactions"); assert_mapping("-", condense, "toggle_collapse"); - assert_mapping("r", compose_actions, "respond_to_message"); - assert_mapping("R", compose_actions, "respond_to_message", true); + assert_mapping("r", compose_reply, "respond_to_message"); + assert_mapping("R", compose_reply, "respond_to_message", true); assert_mapping("j", navigate, "down"); assert_mapping("J", navigate, "page_down"); assert_mapping("k", navigate, "up"); @@ -385,7 +386,7 @@ run_test("misc", ({override}) => { assert_mapping("u", popovers, "toggle_sender_info"); assert_mapping("i", message_actions_popover, "toggle_message_actions_menu"); assert_mapping(":", emoji_picker, "toggle_emoji_popover", true); - assert_mapping(">", compose_actions, "quote_and_reply"); + assert_mapping(">", compose_reply, "quote_and_reply"); assert_mapping("e", message_edit, "start"); override(narrow_state, "narrowed_by_topic_reply", () => true); diff --git a/web/tests/upload.test.js b/web/tests/upload.test.js index b31d72feeb..816f7857d0 100644 --- a/web/tests/upload.test.js +++ b/web/tests/upload.test.js @@ -21,6 +21,7 @@ mock_esm("@uppy/core", { mock_esm("@uppy/xhr-upload", {default: class XHRUpload {}}); const compose_actions = mock_esm("../src/compose_actions"); +const compose_reply = mock_esm("../src/compose_reply"); const compose_state = mock_esm("../src/compose_state"); mock_esm("../src/csrf", {csrf_token: "csrf_token"}); const rows = mock_esm("../src/rows"); @@ -445,7 +446,7 @@ test("file_drop", ({override, override_rewire}) => { upload_files_called = true; }); let compose_actions_start_called = false; - override(compose_actions, "respond_to_message", () => { + override(compose_reply, "respond_to_message", () => { compose_actions_start_called = true; }); drop_handler(drop_event); @@ -484,7 +485,7 @@ test("copy_paste", ({override, override_rewire}) => { upload_files_called = true; }); let compose_actions_start_called = false; - override(compose_actions, "respond_to_message", () => { + override(compose_reply, "respond_to_message", () => { compose_actions_start_called = true; }); @@ -710,7 +711,7 @@ test("main_file_drop_compose_mode", ({override, override_rewire}) => { compose_actions.start = () => { compose_actions_start_called = true; }; - compose_actions.respond_to_message = () => { + compose_reply.respond_to_message = () => { compose_actions_respond_to_message_called = true; }; drop_handler(drop_event);