diff --git a/tools/test-js-with-node b/tools/test-js-with-node index 201db2b752..9ab227ec98 100755 --- a/tools/test-js-with-node +++ b/tools/test-js-with-node @@ -65,6 +65,7 @@ EXEMPT_FILES = make_set( "web/src/compose_banner.ts", "web/src/compose_closed_ui.js", "web/src/compose_fade.js", + "web/src/compose_recipient.js", "web/src/compose_state.js", "web/src/compose_ui.js", "web/src/compose_validate.js", diff --git a/web/src/compose.js b/web/src/compose.js index 1897566283..d203c17682 100644 --- a/web/src/compose.js +++ b/web/src/compose.js @@ -7,7 +7,6 @@ import * as channel from "./channel"; import * as compose_actions from "./compose_actions"; import * as compose_banner from "./compose_banner"; import {get_recipient_label} from "./compose_closed_ui"; -import * as compose_fade from "./compose_fade"; import * as compose_state from "./compose_state"; import * as compose_ui from "./compose_ui"; import * as compose_validate from "./compose_validate"; @@ -95,27 +94,6 @@ export function clear_preview_area() { autosize.update($("#compose-textarea")); } -function update_fade() { - if (!compose_state.composing()) { - return; - } - - const msg_type = compose_state.get_message_type(); - - // It's possible that the new topic is not a resolved topic - // so we clear the older warning. - compose_validate.clear_topic_resolved_warning(); - - compose_validate.warn_if_topic_resolved(); - compose_fade.set_focused_recipient(msg_type); - compose_fade.update_all(); -} - -export function update_on_recipient_change() { - update_fade(); - compose_actions.update_narrow_to_recipient_visibility(); -} - export function abort_xhr() { $("#compose-send-button").prop("disabled", false); uppy.cancelAll(); @@ -445,17 +423,7 @@ export function render_and_show_preview($preview_spinner, $preview_content_box, export function initialize() { $("#below-compose-content .video_link").toggle(compute_show_video_chat_button()); - // `keyup` isn't relevant for streams since it registers as a change only - // when an item in the dropdown is selected. - $("#stream_message_recipient_topic,#private_message_recipient").on( - "keyup", - update_on_recipient_change, - ); - // changes for the stream dropdown are handled in on_compose_select_stream_update - $("#stream_message_recipient_topic,#private_message_recipient").on("change", () => { - update_on_recipient_change(); - compose_state.set_recipient_edited_manually(true); - }); + $("#compose-textarea").on("keydown", (event) => { compose_ui.handle_keydown(event, $("#compose-textarea").expectOne()); }); diff --git a/web/src/compose_actions.js b/web/src/compose_actions.js index c1c0050ade..ca0fd140cf 100644 --- a/web/src/compose_actions.js +++ b/web/src/compose_actions.js @@ -1,6 +1,5 @@ import autosize from "autosize"; import $ from "jquery"; -import _ from "lodash"; import * as fenced_code from "../shared/src/fenced_code"; @@ -9,6 +8,7 @@ import * as compose from "./compose"; import * as compose_banner from "./compose_banner"; import * as compose_fade from "./compose_fade"; import * as compose_pm_pill from "./compose_pm_pill"; +import * as compose_recipient from "./compose_recipient"; import * as compose_state from "./compose_state"; import * as compose_ui from "./compose_ui"; import * as compose_validate from "./compose_validate"; @@ -29,7 +29,6 @@ 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"; -import * as util from "./util"; export function blur_compose_inputs() { $(".message_comp").find("input, textarea, button, #private_message_recipient").trigger("blur"); @@ -70,13 +69,6 @@ function get_focus_area(msg_type, opts) { // Export for testing export const _get_focus_area = get_focus_area; -export function open_compose_stream_dropup() { - if ($("#id_compose_select_stream").hasClass("open")) { - return; - } - $("#id_compose_select_stream > .dropdown-toggle").dropdown("toggle"); -} - export function set_focus(msg_type, opts) { if (window.getSelection().toString() === "" || opts.trigger !== "message click") { const focus_area = get_focus_area(msg_type, opts); @@ -147,60 +139,6 @@ export function expand_compose_box() { $(".message_comp").show(); } -function composing_to_current_topic_narrow() { - return ( - util.lower_same(compose_state.stream_name(), narrow_state.stream() || "") && - util.lower_same(compose_state.topic(), narrow_state.topic() || "") - ); -} - -function composing_to_current_private_message_narrow() { - const compose_state_recipient = compose_state.private_message_recipient(); - const narrow_state_recipient = narrow_state.pm_emails_string(); - return ( - compose_state_recipient && - narrow_state_recipient && - _.isEqual( - compose_state_recipient - .split(",") - .map((s) => s.trim()) - .sort(), - narrow_state_recipient - .split(",") - .map((s) => s.trim()) - .sort(), - ) - ); -} - -export function update_narrow_to_recipient_visibility() { - const message_type = compose_state.get_message_type(); - if (message_type === "stream") { - const stream_name = compose_state.stream_name(); - const stream_exists = Boolean(stream_data.get_stream_id(stream_name)); - - if ( - stream_exists && - !composing_to_current_topic_narrow() && - compose_state.has_full_recipient() - ) { - $(".narrow_to_compose_recipients").toggleClass("invisible", false); - return; - } - } else if (message_type === "private") { - const recipients = compose_state.private_message_recipient(); - if ( - recipients && - !composing_to_current_private_message_narrow() && - compose_state.has_full_recipient() - ) { - $(".narrow_to_compose_recipients").toggleClass("invisible", false); - return; - } - } - $(".narrow_to_compose_recipients").toggleClass("invisible", true); -} - export function complete_starting_tasks(msg_type, opts) { // This is sort of a kitchen sink function, and it's called only // by compose.start() for now. Having this as a separate function @@ -211,7 +149,7 @@ export function complete_starting_tasks(msg_type, opts) { stream_bar.decorate(opts.stream, $("#compose-stream-recipient .message_header_stream")); $(document).trigger(new $.Event("compose_started.zulip", opts)); update_placeholder_text(); - update_narrow_to_recipient_visibility(); + compose_recipient.update_narrow_to_recipient_visibility(); } export function maybe_scroll_up_selected_message() { @@ -328,7 +266,7 @@ export function start(msg_type, opts) { clear_box(); } - compose_ui.compose_stream_widget.render(opts.stream); + compose_recipient.compose_stream_widget.render(opts.stream); const $stream_header_colorblock = $("#compose_stream_selection_dropdown").find( ".stream_header_colorblock", ); diff --git a/web/src/compose_banner.ts b/web/src/compose_banner.ts index 5013c56b85..82709fa127 100644 --- a/web/src/compose_banner.ts +++ b/web/src/compose_banner.ts @@ -99,7 +99,10 @@ export function show_stream_does_not_exist_error(stream_name: string): void { $compose_banner_area.append(new_row); hide_compose_spinner(); - // TODO: Replace with compose_actions.open_compose_stream_dropup() when it is converted to ts. + // A copy of `compose_recipient.open_compose_stream_dropup()` that + // can't be imported due to typescript and import circles. + // TODO: Once we use stream IDs, not names, as the fundamental + // compose_state storage for streams, this error will be impossible. if ($("#id_compose_select_stream").hasClass("open")) { return; } diff --git a/web/src/compose_recipient.js b/web/src/compose_recipient.js new file mode 100644 index 0000000000..8cc77a6e2e --- /dev/null +++ b/web/src/compose_recipient.js @@ -0,0 +1,182 @@ +import $ from "jquery"; +import _ from "lodash"; + +import * as compose_fade from "./compose_fade"; +import * as compose_state from "./compose_state"; +import * as compose_validate from "./compose_validate"; +import {DropdownListWidget} from "./dropdown_list_widget"; +import {$t} from "./i18n"; +import * as narrow_state from "./narrow_state"; +import * as stream_bar from "./stream_bar"; +import * as stream_data from "./stream_data"; +import * as util from "./util"; + +export let compose_stream_widget; + +function composing_to_current_topic_narrow() { + return ( + util.lower_same(compose_state.stream_name(), narrow_state.stream() || "") && + util.lower_same(compose_state.topic(), narrow_state.topic() || "") + ); +} + +function composing_to_current_private_message_narrow() { + const compose_state_recipient = compose_state.private_message_recipient(); + const narrow_state_recipient = narrow_state.pm_emails_string(); + return ( + compose_state_recipient && + narrow_state_recipient && + _.isEqual( + compose_state_recipient + .split(",") + .map((s) => s.trim()) + .sort(), + narrow_state_recipient + .split(",") + .map((s) => s.trim()) + .sort(), + ) + ); +} + +export function update_narrow_to_recipient_visibility() { + const message_type = compose_state.get_message_type(); + if (message_type === "stream") { + const stream_name = compose_state.stream_name(); + const stream_exists = Boolean(stream_data.get_stream_id(stream_name)); + + if ( + stream_exists && + !composing_to_current_topic_narrow() && + compose_state.has_full_recipient() + ) { + $(".narrow_to_compose_recipients").toggleClass("invisible", false); + return; + } + } else if (message_type === "private") { + const recipients = compose_state.private_message_recipient(); + if ( + recipients && + !composing_to_current_private_message_narrow() && + compose_state.has_full_recipient() + ) { + $(".narrow_to_compose_recipients").toggleClass("invisible", false); + return; + } + } + $(".narrow_to_compose_recipients").toggleClass("invisible", true); +} + +function update_fade() { + if (!compose_state.composing()) { + return; + } + + const msg_type = compose_state.get_message_type(); + + // It's possible that the new topic is not a resolved topic + // so we clear the older warning. + compose_validate.clear_topic_resolved_warning(); + + compose_validate.warn_if_topic_resolved(); + compose_fade.set_focused_recipient(msg_type); + compose_fade.update_all(); +} + +export function update_on_recipient_change() { + update_fade(); + update_narrow_to_recipient_visibility(); +} + +export function open_compose_stream_dropup() { + if ($("#id_compose_select_stream").hasClass("open")) { + return; + } + $("#id_compose_select_stream > .dropdown-toggle").dropdown("toggle"); +} + +export function on_compose_select_stream_update(new_value) { + const $stream_header_colorblock = $("#compose_stream_selection_dropdown").find( + ".stream_header_colorblock", + ); + stream_bar.decorate(new_value, $stream_header_colorblock); + update_on_recipient_change(); + $("#stream_message_recipient_topic").trigger("focus").trigger("select"); +} + +export function update_stream_dropdown_options() { + const streams_list = stream_data + .subscribed_subs() + .filter((stream) => stream_data.can_post_messages_in_stream(stream)) + .map((stream) => ({ + name: stream.name, + value: stream.name, + stream, + })) + .sort((a, b) => { + if (a.name.toLowerCase() < b.name.toLowerCase()) { + return -1; + } + if (a.name.toLowerCase() > b.name.toLowerCase()) { + return 1; + } + return 0; + }); + compose_stream_widget.replace_data(streams_list); +} + +export function possibly_update_dropdown_selection(old_stream_name, new_stream_name) { + const selected_stream = compose_state.stream_name(); + if (selected_stream === old_stream_name) { + compose_state.set_stream_name(new_stream_name); + } +} + +export function initialize() { + const streams_list = stream_data + .subscribed_subs() + .filter((stream) => stream_data.can_post_messages_in_stream(stream)) + .map((stream) => ({ + name: stream.name, + value: stream.name, + stream, + })) + .sort((a, b) => { + if (a.name.toLowerCase() < b.name.toLowerCase()) { + return -1; + } + if (a.name.toLowerCase() > b.name.toLowerCase()) { + return 1; + } + return 0; + }); + const opts = { + widget_name: "compose_select_stream", + data: streams_list, + default_text: $t({defaultMessage: "Select a stream"}), + value: null, + on_update: on_compose_select_stream_update, + }; + compose_stream_widget = new DropdownListWidget(opts); + compose_stream_widget.setup(); + + $("#compose_select_stream_widget").on("select", (e) => { + // We often focus on input fields to bring the user to fill it out. + // In this situation, a focus on the dropdown div opens the dropdown + // menu so that the user can select an option. + open_compose_stream_dropup(); + e.stopPropagation(); + }); + + // `keyup` isn't relevant for streams since it registers as a change only + // when an item in the dropdown is selected. + $("#stream_message_recipient_topic,#private_message_recipient").on( + "keyup", + update_on_recipient_change, + ); + // changes for the stream dropdown are handled in on_compose_select_stream_update + $("#stream_message_recipient_topic,#private_message_recipient").on("change", () => { + update_on_recipient_change(); + compose_state.set_recipient_edited_manually(true); + }); +} diff --git a/web/src/compose_state.js b/web/src/compose_state.js index 49d972b13a..43276c7d2b 100644 --- a/web/src/compose_state.js +++ b/web/src/compose_state.js @@ -1,7 +1,7 @@ import $ from "jquery"; import * as compose_pm_pill from "./compose_pm_pill"; -import * as compose_ui from "./compose_ui"; +import * as compose_recipient from "./compose_recipient"; let message_type = false; // 'stream', 'private', or false-y let recipient_edited_manually = false; @@ -68,13 +68,13 @@ function get_or_set(fieldname, keep_leading_whitespace, no_trim) { } export function stream_name() { - return compose_ui.compose_stream_widget.value(); + return compose_recipient.compose_stream_widget.value(); } export function set_stream_name(newval) { - if (newval !== undefined && newval !== "" && compose_ui.compose_stream_widget) { - compose_ui.compose_stream_widget.render(newval); - compose_ui.on_compose_select_stream_update(newval); + if (newval !== undefined && newval !== "" && compose_recipient.compose_stream_widget) { + compose_recipient.compose_stream_widget.render(newval); + compose_recipient.on_compose_select_stream_update(newval); } } diff --git a/web/src/compose_ui.js b/web/src/compose_ui.js index 403f179268..4f670d11aa 100644 --- a/web/src/compose_ui.js +++ b/web/src/compose_ui.js @@ -3,17 +3,11 @@ import $ from "jquery"; import {insert, replace, set, wrapSelection} from "text-field-edit"; import * as common from "./common"; -import * as compose from "./compose"; -import * as compose_actions from "./compose_actions"; -import * as compose_state from "./compose_state"; -import {DropdownListWidget} from "./dropdown_list_widget"; import {$t} from "./i18n"; import * as loading from "./loading"; import * as people from "./people"; import * as popover_menus from "./popover_menus"; import * as rtl from "./rtl"; -import * as stream_bar from "./stream_bar"; -import * as stream_data from "./stream_data"; import * as user_status from "./user_status"; export let compose_spinner_visible = false; @@ -512,77 +506,3 @@ export function get_submit_button() { } return $("#compose-send-button"); } - -export function on_compose_select_stream_update(new_value) { - const $stream_header_colorblock = $("#compose_stream_selection_dropdown").find( - ".stream_header_colorblock", - ); - stream_bar.decorate(new_value, $stream_header_colorblock); - compose.update_on_recipient_change(); - $("#stream_message_recipient_topic").trigger("focus").trigger("select"); -} - -export let compose_stream_widget; -export function initialize_compose_stream_dropdown() { - const streams_list = stream_data - .subscribed_subs() - .filter((stream) => stream_data.can_post_messages_in_stream(stream)) - .map((stream) => ({ - name: stream.name, - value: stream.name, - stream, - })) - .sort((a, b) => { - if (a.name.toLowerCase() < b.name.toLowerCase()) { - return -1; - } - if (a.name.toLowerCase() > b.name.toLowerCase()) { - return 1; - } - return 0; - }); - const opts = { - widget_name: "compose_select_stream", - data: streams_list, - default_text: $t({defaultMessage: "Select a stream"}), - value: null, - on_update: on_compose_select_stream_update, - }; - compose_stream_widget = new DropdownListWidget(opts); - compose_stream_widget.setup(); - - $("#compose_select_stream_widget").on("select", (e) => { - // We often focus on input fields to bring the user to fill it out. - // In this situation, a focus on the dropdown div opens the dropdown - // menu so that the user can select an option. - compose_actions.open_compose_stream_dropup(); - e.stopPropagation(); - }); -} - -export function update_stream_dropdown_options() { - const streams_list = stream_data - .subscribed_subs() - .filter((stream) => stream_data.can_post_messages_in_stream(stream)) - .map((stream) => ({ - name: stream.name, - value: stream.name, - })) - .sort((a, b) => { - if (a.name.toLowerCase() < b.name.toLowerCase()) { - return -1; - } - if (a.name.toLowerCase() > b.name.toLowerCase()) { - return 1; - } - return 0; - }); - compose_stream_widget.replace_data(streams_list); -} - -export function possibly_update_dropdown_selection(old_stream_name, new_stream_name) { - const selected_stream = compose_state.stream_name(); - if (selected_stream === old_stream_name) { - compose_state.set_stream_name(new_stream_name); - } -} diff --git a/web/src/input_pill.js b/web/src/input_pill.js index 1e65419561..68f82a17c7 100644 --- a/web/src/input_pill.js +++ b/web/src/input_pill.js @@ -5,7 +5,7 @@ import $ from "jquery"; import render_input_pill from "../templates/input_pill.hbs"; import * as blueslip from "./blueslip"; -import * as compose from "./compose"; +import * as compose_recipient from "./compose_recipient"; import * as keydown_util from "./keydown_util"; import * as ui_util from "./ui_util"; @@ -360,7 +360,7 @@ export function create(opts) { funcs.removePill($pill[0]); $next.trigger("focus"); - compose.update_on_recipient_change(); + compose_recipient.update_on_recipient_change(); }); store.$parent.on("click", function (e) { diff --git a/web/src/narrow.js b/web/src/narrow.js index 31627d3c80..3698e30e9a 100644 --- a/web/src/narrow.js +++ b/web/src/narrow.js @@ -7,6 +7,7 @@ import * as compose_actions from "./compose_actions"; import * as compose_banner from "./compose_banner"; import * as compose_closed_ui from "./compose_closed_ui"; import * as compose_fade from "./compose_fade"; +import * as compose_recipient from "./compose_recipient"; import * as compose_state from "./compose_state"; import * as condense from "./condense"; import {Filter} from "./filter"; @@ -183,7 +184,7 @@ export function reset_ui_state() { export function handle_middle_pane_transition() { if (compose_state.composing) { - compose_actions.update_narrow_to_recipient_visibility(); + compose_recipient.update_narrow_to_recipient_visibility(); } } diff --git a/web/src/server_events_dispatch.js b/web/src/server_events_dispatch.js index 132cb6e52d..d85487e761 100644 --- a/web/src/server_events_dispatch.js +++ b/web/src/server_events_dispatch.js @@ -11,7 +11,7 @@ import * as compose from "./compose"; import * as compose_actions from "./compose_actions"; import * as compose_fade from "./compose_fade"; import * as compose_pm_pill from "./compose_pm_pill"; -import * as compose_ui from "./compose_ui"; +import * as compose_recipient from "./compose_recipient"; import * as composebox_typeahead from "./composebox_typeahead"; import * as dark_theme from "./dark_theme"; import * as emoji from "./emoji"; @@ -496,7 +496,7 @@ export function dispatch_normal_event(event) { stream_settings_ui.remove_stream(stream.stream_id); if (was_subscribed) { stream_list.remove_sidebar_row(stream.stream_id); - compose_ui.update_stream_dropdown_options(); + compose_recipient.update_stream_dropdown_options(); } settings_streams.update_default_streams_table(); stream_data.remove_default_stream(stream.stream_id); diff --git a/web/src/stream_events.js b/web/src/stream_events.js index ba9f9ecfcd..32cd433480 100644 --- a/web/src/stream_events.js +++ b/web/src/stream_events.js @@ -2,7 +2,7 @@ import $ from "jquery"; import * as blueslip from "./blueslip"; import * as color_data from "./color_data"; -import * as compose_ui from "./compose_ui"; +import * as compose_recipient from "./compose_recipient"; import * as message_lists from "./message_lists"; import * as message_view_header from "./message_view_header"; import * as narrow_state from "./narrow_state"; @@ -63,8 +63,8 @@ export function update_property(stream_id, property, value, other_values) { break; case "name": stream_settings_ui.update_stream_name(sub, value); - compose_ui.update_stream_dropdown_options(); - compose_ui.possibly_update_dropdown_selection(sub.name, value); + compose_recipient.update_stream_dropdown_options(); + compose_recipient.possibly_update_dropdown_selection(sub.name, value); break; case "description": stream_settings_ui.update_stream_description( @@ -87,7 +87,7 @@ export function update_property(stream_id, property, value, other_values) { is_web_public: other_values.is_web_public, }); // Force a re-render to get the right privacy icon - compose_ui.possibly_update_dropdown_selection(sub.name, sub.name); + compose_recipient.possibly_update_dropdown_selection(sub.name, sub.name); break; case "stream_post_policy": stream_settings_ui.update_stream_post_policy(sub, value); @@ -132,7 +132,7 @@ export function mark_subscribed(sub, subscribers, color) { stream_settings_ui.set_color(sub.stream_id, color); } stream_data.subscribe_myself(sub); - compose_ui.update_stream_dropdown_options(); + compose_recipient.update_stream_dropdown_options(); if (subscribers) { peer_data.set_subscribers(sub.stream_id, subscribers); } @@ -162,7 +162,7 @@ export function mark_unsubscribed(sub) { return; } else if (sub.subscribed) { stream_data.unsubscribe_myself(sub); - compose_ui.update_stream_dropdown_options(); + compose_recipient.update_stream_dropdown_options(); if (overlays.streams_open()) { stream_settings_ui.update_settings_for_unsubscribed(sub); } diff --git a/web/src/ui_init.js b/web/src/ui_init.js index 90f2d98e02..b08dd1bdde 100644 --- a/web/src/ui_init.js +++ b/web/src/ui_init.js @@ -23,7 +23,7 @@ import * as common from "./common"; import * as compose from "./compose"; import * as compose_closed_ui from "./compose_closed_ui"; import * as compose_pm_pill from "./compose_pm_pill"; -import * as compose_ui from "./compose_ui"; +import * as compose_recipient from "./compose_recipient"; import * as composebox_typeahead from "./composebox_typeahead"; import * as condense from "./condense"; import * as copy_and_paste from "./copy_and_paste"; @@ -626,14 +626,12 @@ export function initialize_everything() { scroll_bar.initialize(); message_viewport.initialize(); navbar_alerts.initialize(); - compose_closed_ui.initialize(); initialize_kitchen_sink_stuff(); echo.initialize(); stream_edit.initialize(); user_group_edit.initialize(); stream_edit_subscribers.initialize(); stream_data.initialize(stream_data_params); - compose_ui.initialize_compose_stream_dropdown(); user_group_edit_members.initialize(); pm_conversations.recent.initialize(pm_conversations_params); user_topics.initialize(); @@ -653,7 +651,9 @@ export function initialize_everything() { message_view_header.initialize(); server_events.initialize(); user_status.initialize(user_status_params); + compose_recipient.initialize(); compose_pm_pill.initialize(); + compose_closed_ui.initialize(); search_pill_widget.initialize(); reload.initialize(); user_groups.initialize(user_groups_params); diff --git a/web/tests/compose.test.js b/web/tests/compose.test.js index 290b53b0db..91e75f020f 100644 --- a/web/tests/compose.test.js +++ b/web/tests/compose.test.js @@ -52,6 +52,7 @@ const upload = mock_esm("../src/upload"); const compose_ui = zrequire("compose_ui"); const compose_banner = zrequire("compose_banner"); const compose_closed_ui = zrequire("compose_closed_ui"); +const compose_recipient = zrequire("compose_recipient"); const compose_state = zrequire("compose_state"); const compose = zrequire("compose"); const echo = zrequire("echo"); @@ -307,10 +308,10 @@ test_ui("enter_with_preview_open", ({override, override_rewire}) => { $("#compose-textarea").toggleClass = noop; override_rewire(stream_bar, "decorate", noop); mock_stream_header_colorblock(); - compose_actions.open_compose_stream_dropup = noop; - compose.update_on_recipient_change = noop; + compose_recipient.open_compose_stream_dropup = noop; + override_rewire(compose_recipient, "update_on_recipient_change", noop); let stream_value = ""; - compose_ui.compose_stream_widget = { + compose_recipient.compose_stream_widget = { value() { return stream_value; }, @@ -370,6 +371,7 @@ test_ui("finish", ({override, override_rewire}) => { mock_stream_header_colorblock(); override_rewire(stream_bar, "decorate", noop); + override_rewire(compose_recipient, "update_on_recipient_change", noop); override_rewire(compose_banner, "clear_message_sent_banners", () => {}); override(reminder, "is_deferred_delivery", () => false); override(document, "to_$", () => $("document-stub")); @@ -531,13 +533,10 @@ test_ui("initialize", ({override}) => { })(); }); -test_ui("update_fade", ({override}) => { +test_ui("update_fade", ({override, override_rewire}) => { mock_banners(); initialize_handlers({override}); - const selector = "#stream_message_recipient_topic,#private_message_recipient"; - const keyup_handler_func = $(selector).get_on_handler("change"); - let set_focused_recipient_checked = false; let update_all_called = false; let update_narrow_to_recipient_visibility_called = false; @@ -551,12 +550,12 @@ test_ui("update_fade", ({override}) => { update_all_called = true; }); - override(compose_actions, "update_narrow_to_recipient_visibility", () => { + override_rewire(compose_recipient, "update_narrow_to_recipient_visibility", () => { update_narrow_to_recipient_visibility_called = true; }); compose_state.set_message_type(false); - keyup_handler_func(); + compose_recipient.update_on_recipient_change(); assert.ok(!set_focused_recipient_checked); assert.ok(!update_all_called); assert.ok(update_narrow_to_recipient_visibility_called); @@ -564,7 +563,7 @@ test_ui("update_fade", ({override}) => { update_narrow_to_recipient_visibility_called = false; compose_state.set_message_type("private"); - keyup_handler_func(); + compose_recipient.update_on_recipient_change(); assert.ok(set_focused_recipient_checked); assert.ok(update_all_called); assert.ok(update_narrow_to_recipient_visibility_called); @@ -767,6 +766,7 @@ test_ui("on_events", ({override}) => { test_ui("create_message_object", ({override, override_rewire}) => { mock_stream_header_colorblock(); override_rewire(stream_bar, "decorate", noop); + override_rewire(compose_recipient, "update_on_recipient_change", noop); compose_state.set_stream_name("social"); $("#stream_message_recipient_topic").val("lunch"); diff --git a/web/tests/compose_actions.test.js b/web/tests/compose_actions.test.js index 290fd18edc..9f81f5de30 100644 --- a/web/tests/compose_actions.test.js +++ b/web/tests/compose_actions.test.js @@ -24,20 +24,12 @@ mock_esm("autosize", {default: autosize}); const channel = mock_esm("../src/channel"); const compose_fade = mock_esm("../src/compose_fade", { clear_compose: noop, + set_focused_recipient: noop, + update_all: noop, }); const compose_pm_pill = mock_esm("../src/compose_pm_pill"); -let stream_value = ""; const compose_ui = mock_esm("../src/compose_ui", { autosize_textarea: noop, - on_compose_select_stream_update: noop, - compose_stream_widget: { - value() { - return stream_value; - }, - render(val) { - stream_value = val; - }, - }, is_full_size: () => false, }); const hash_util = mock_esm("../src/hash_util"); @@ -74,6 +66,17 @@ const compose_actions = zrequire("compose_actions"); const message_lists = zrequire("message_lists"); const stream_data = zrequire("stream_data"); const stream_bar = zrequire("stream_bar"); +const compose_recipient = zrequire("compose_recipient"); + +let stream_value = ""; +compose_recipient.compose_stream_widget = { + value() { + return stream_value; + }, + render(val) { + stream_value = val; + }, +}; const start = compose_actions.start; const cancel = compose_actions.cancel; @@ -82,6 +85,8 @@ 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; +compose_recipient.update_narrow_to_recipient_visibility = noop; + function assert_visible(sel) { assert.ok($(sel).visible()); } @@ -125,6 +130,7 @@ test("start", ({override, override_rewire}) => { override_rewire(compose_actions, "complete_starting_tasks", () => {}); override_rewire(compose_actions, "blur_compose_inputs", () => {}); override_rewire(compose_actions, "clear_textarea", () => {}); + override_rewire(compose_recipient, "update_on_recipient_change", () => {}); stream_bar.decorate = () => {}; mock_stream_header_colorblock(); @@ -247,6 +253,7 @@ test("respond_to_message", ({override, override_rewire}) => { override_rewire(compose_actions, "set_focus", () => {}); override_rewire(compose_actions, "complete_starting_tasks", () => {}); override_rewire(compose_actions, "clear_textarea", () => {}); + override_rewire(compose_recipient, "update_on_recipient_change", () => {}); override_private_message_recipient({override}); mock_stream_header_colorblock(); diff --git a/web/tests/compose_fade.test.js b/web/tests/compose_fade.test.js index 4796e0bc3e..899be88c11 100644 --- a/web/tests/compose_fade.test.js +++ b/web/tests/compose_fade.test.js @@ -23,10 +23,10 @@ const stream_data = zrequire("stream_data"); const peer_data = zrequire("peer_data"); const people = zrequire("people"); const compose_fade = zrequire("compose_fade"); -const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); const compose_fade_helper = zrequire("compose_fade_helper"); -compose_ui.compose_stream_widget = { +compose_recipient.compose_stream_widget = { value() { return "social"; }, diff --git a/web/tests/compose_state.test.js b/web/tests/compose_state.test.js index 2add327ff0..b12742430b 100644 --- a/web/tests/compose_state.test.js +++ b/web/tests/compose_state.test.js @@ -11,13 +11,13 @@ const compose_pm_pill = mock_esm("../src/compose_pm_pill"); const compose_state = zrequire("compose_state"); const compose_fade = zrequire("compose_fade"); -const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); const stream_bar = zrequire("stream_bar"); const noop = () => {}; let stream_value = ""; -compose_ui.compose_stream_widget = { +compose_recipient.compose_stream_widget = { value() { return stream_value; }, diff --git a/web/tests/compose_validate.test.js b/web/tests/compose_validate.test.js index 211392fd9b..741aba8da1 100644 --- a/web/tests/compose_validate.test.js +++ b/web/tests/compose_validate.test.js @@ -23,10 +23,10 @@ const resolved_topic = zrequire("../shared/src/resolved_topic"); const settings_config = zrequire("settings_config"); const settings_data = mock_esm("../src/settings_data"); const stream_data = zrequire("stream_data"); -const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); let stream_value = ""; -compose_ui.compose_stream_widget = { +compose_recipient.compose_stream_widget = { value() { return stream_value; }, @@ -149,7 +149,7 @@ test_ui("validate_stream_message_address_info", ({mock_template}) => { test_ui("validate", ({mock_template}) => { compose_actions.update_placeholder_text = () => {}; - compose_ui.on_compose_select_stream_update = () => {}; + compose_recipient.on_compose_select_stream_update = () => {}; function initialize_pm_pill() { $.clear_all_elements(); diff --git a/web/tests/composebox_typeahead.test.js b/web/tests/composebox_typeahead.test.js index 0462424260..0453e21598 100644 --- a/web/tests/composebox_typeahead.test.js +++ b/web/tests/composebox_typeahead.test.js @@ -43,6 +43,7 @@ const stream_data = zrequire("stream_data"); const compose = zrequire("compose"); const compose_pm_pill = zrequire("compose_pm_pill"); const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); const composebox_typeahead = zrequire("composebox_typeahead"); const settings_config = zrequire("settings_config"); const pygments_data = zrequire("../generated/pygments_data.json"); @@ -55,7 +56,7 @@ const ct = composebox_typeahead; ct.__Rewire__("max_num_items", 15); let stream_value = ""; -compose_ui.compose_stream_widget = { +compose_recipient.compose_stream_widget = { value() { return stream_value; }, @@ -675,7 +676,7 @@ function sorted_names_from(subs) { test("initialize", ({override, override_rewire, mock_template}) => { mock_stream_header_colorblock(); - compose.update_on_recipient_change = noop; + override_rewire(compose_recipient, "update_on_recipient_change", noop); override_rewire(stream_bar, "decorate", noop); let pill_items = []; @@ -1724,6 +1725,7 @@ test("PM recipients sorted according to stream / topic being viewed", ({override ); mock_stream_header_colorblock(); override_rewire(stream_bar, "decorate", noop); + override_rewire(compose_recipient, "update_on_recipient_change", noop); // When viewing no stream, sorting is alphabetical compose_state.set_stream_name(""); diff --git a/web/tests/dispatch_subs.test.js b/web/tests/dispatch_subs.test.js index c2e6e2e21b..3fd5c5538d 100644 --- a/web/tests/dispatch_subs.test.js +++ b/web/tests/dispatch_subs.test.js @@ -23,7 +23,7 @@ const stream_list = mock_esm("../src/stream_list"); const stream_settings_ui = mock_esm("../src/stream_settings_ui"); message_lists.current = {}; -const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); const peer_data = zrequire("peer_data"); const people = zrequire("people"); const server_events_dispatch = zrequire("server_events_dispatch"); @@ -199,7 +199,7 @@ test("stream create", ({override}) => { }); test("stream delete (normal)", ({override, override_rewire}) => { - override_rewire(compose_ui, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); const event = event_fixtures.stream__delete; @@ -242,7 +242,7 @@ test("stream delete (normal)", ({override, override_rewire}) => { }); test("stream delete (special streams)", ({override, override_rewire}) => { - override_rewire(compose_ui, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); const event = event_fixtures.stream__delete; diff --git a/web/tests/drafts.test.js b/web/tests/drafts.test.js index ac81b954f8..88424120bb 100644 --- a/web/tests/drafts.test.js +++ b/web/tests/drafts.test.js @@ -15,13 +15,13 @@ const user_pill = zrequire("user_pill"); const people = zrequire("people"); const compose_fade = zrequire("compose_fade"); const compose_state = zrequire("compose_state"); -const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); const sub_store = zrequire("sub_store"); const stream_bar = zrequire("stream_bar"); const stream_data = zrequire("stream_data"); let stream_value = ""; -compose_ui.compose_stream_widget = { +compose_recipient.compose_stream_widget = { value() { return stream_value; }, diff --git a/web/tests/narrow.test.js b/web/tests/narrow.test.js index 7c6171da4e..1d207a359b 100644 --- a/web/tests/narrow.test.js +++ b/web/tests/narrow.test.js @@ -17,7 +17,7 @@ const stream_data = zrequire("stream_data"); const {Filter} = zrequire("../src/filter"); const narrow = zrequire("narrow"); const settings_config = zrequire("settings_config"); -const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); const compose_pm_pill = mock_esm("../src/compose_pm_pill"); mock_esm("../src/spectators", { @@ -28,7 +28,7 @@ const recent_topics_util = mock_esm("../src/recent_topics_util", { }); let stream_value = ""; -compose_ui.compose_stream_widget = { +compose_recipient.compose_stream_widget = { value() { return stream_value; }, @@ -650,7 +650,7 @@ run_test("show_invalid_narrow_message", ({mock_template}) => { }); run_test("narrow_to_compose_target errors", ({disallow_rewire}) => { - compose_ui.on_compose_select_stream_update = () => {}; + compose_recipient.on_compose_select_stream_update = () => {}; disallow_rewire(narrow, "activate"); // No-op when not composing. diff --git a/web/tests/narrow_activate.test.js b/web/tests/narrow_activate.test.js index caa7fa89bb..048c0eac28 100644 --- a/web/tests/narrow_activate.test.js +++ b/web/tests/narrow_activate.test.js @@ -52,6 +52,7 @@ mock_esm("../src/user_topics", { is_topic_muted: () => false, }); +const compose_recipient = zrequire("compose_recipient"); const util = zrequire("util"); const narrow_state = zrequire("narrow_state"); const stream_data = zrequire("stream_data"); @@ -88,7 +89,7 @@ function test_helper() { stub(message_view_header, "initialize"); stub(top_left_corner, "handle_narrow_activated"); stub(typing_events, "render_notifications_for_narrow"); - stub(compose_actions, "update_narrow_to_recipient_visibility"); + stub(compose_recipient, "update_narrow_to_recipient_visibility"); stub(unread_ops, "process_visible"); stub(compose_closed_ui, "update_buttons_for_stream"); stub(compose_closed_ui, "update_buttons_for_private"); @@ -202,7 +203,7 @@ run_test("basics", () => { [stream_list, "handle_narrow_activated"], [typing_events, "render_notifications_for_narrow"], [message_view_header, "initialize"], - [compose_actions, "update_narrow_to_recipient_visibility"], + [compose_recipient, "update_narrow_to_recipient_visibility"], ]); message_lists.current.selected_id = () => -1; diff --git a/web/tests/stream_events.test.js b/web/tests/stream_events.test.js index 9c9e5e1add..93077600ee 100644 --- a/web/tests/stream_events.test.js +++ b/web/tests/stream_events.test.js @@ -41,7 +41,7 @@ const peer_data = zrequire("peer_data"); const people = zrequire("people"); const stream_data = zrequire("stream_data"); const stream_events = zrequire("stream_events"); -const compose_ui = zrequire("compose_ui"); +const compose_recipient = zrequire("compose_recipient"); const george = { email: "george@zulip.com", @@ -88,8 +88,8 @@ function test(label, f) { } test("update_property", ({override, override_rewire}) => { - override_rewire(compose_ui, "update_stream_dropdown_options", noop); - override_rewire(compose_ui, "possibly_update_dropdown_selection", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "possibly_update_dropdown_selection", noop); const sub = {...frontend}; stream_data.add_sub(sub); @@ -284,7 +284,7 @@ test("marked_subscribed (normal)", ({override, override_rewire}) => { const sub = {...frontend}; stream_data.add_sub(sub); override(stream_color, "update_stream_color", noop); - override_rewire(compose_ui, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); narrow_to_frontend(); @@ -323,7 +323,7 @@ test("marked_subscribed (color)", ({override, override_rewire}) => { override(stream_list, "add_sidebar_row", noop); override(stream_list, "update_subscribe_to_more_streams_link", noop); override(unread_ui, "update_unread_counts", noop); - override_rewire(compose_ui, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); const sub = { subscribed: false, @@ -356,7 +356,7 @@ test("marked_subscribed (emails)", ({override, override_rewire}) => { const sub = {...frontend}; stream_data.add_sub(sub); override(stream_color, "update_stream_color", noop); - override_rewire(compose_ui, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); // Test assigning subscriber emails // narrow state is undefined @@ -395,7 +395,7 @@ test("mark_unsubscribed (update_settings_for_unsubscribed)", ({override, overrid $("#streams_overlay_container .stream-row:not(.notdisplayed)").length = 0; - override_rewire(compose_ui, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); stream_events.mark_unsubscribed(sub); const args = stub.get_args("sub"); assert.deepEqual(args.sub, sub); @@ -422,7 +422,7 @@ test("mark_unsubscribed (render_title_area)", ({override, override_rewire}) => { $("#streams_overlay_container .stream-row:not(.notdisplayed)").length = 0; - override_rewire(compose_ui, "update_stream_dropdown_options", noop); + override_rewire(compose_recipient, "update_stream_dropdown_options", noop); stream_events.mark_unsubscribed(sub); assert.equal(message_view_header_stub.num_calls, 1);