diff --git a/web/src/compose_recipient.js b/web/src/compose_recipient.js index 1b0ccdf790..65b08da84a 100644 --- a/web/src/compose_recipient.js +++ b/web/src/compose_recipient.js @@ -120,7 +120,7 @@ export function get_posting_policy_error_message() { export function check_posting_policy_for_compose_box() { const banner_text = get_posting_policy_error_message(); if (banner_text === "") { - $(".message-send-controls").removeClass("disabled-message-send-controls"); + compose_validate.set_recipient_disallowed(false); compose_banner.clear_errors(); return; } @@ -129,7 +129,7 @@ export function check_posting_policy_for_compose_box() { if (compose_state.selected_recipient_id === "direct") { banner_classname = compose_banner.CLASSNAMES.private_messages_disabled; } - $(".message-send-controls").addClass("disabled-message-send-controls"); + compose_validate.set_recipient_disallowed(true); compose_banner.show_error_message(banner_text, banner_classname, $("#compose_banners")); } diff --git a/web/src/compose_tooltips.js b/web/src/compose_tooltips.js index 66ad143bb4..67697e5bde 100644 --- a/web/src/compose_tooltips.js +++ b/web/src/compose_tooltips.js @@ -6,6 +6,7 @@ import render_narrow_to_compose_recipients_tooltip from "../templates/narrow_to_ import * as compose_recipient from "./compose_recipient"; import * as compose_state from "./compose_state"; +import * as compose_validate from "./compose_validate"; import {$t} from "./i18n"; import * as narrow_state from "./narrow_state"; import * as popover_menus from "./popover_menus"; @@ -133,7 +134,9 @@ export function initialize() { // in the new design target: [".disabled-message-send-controls"], maxWidth: 350, - content: () => compose_recipient.get_posting_policy_error_message(), + content: () => + compose_recipient.get_posting_policy_error_message() || + compose_validate.get_disabled_send_tooltip(), appendTo: () => document.body, onHidden(instance) { instance.destroy(); diff --git a/web/src/compose_validate.js b/web/src/compose_validate.js index bb47e30dc1..5929b218f5 100644 --- a/web/src/compose_validate.js +++ b/web/src/compose_validate.js @@ -23,9 +23,43 @@ import * as sub_store from "./sub_store"; import * as util from "./util"; let user_acknowledged_wildcard = false; +let upload_in_progress = false; +let message_too_long = false; +let recipient_disallowed = false; export let wildcard_mention_large_stream_threshold = 15; +export function set_upload_in_progress(status) { + upload_in_progress = status; + update_send_button_status(); +} + +function set_message_too_long(status) { + message_too_long = status; + update_send_button_status(); +} + +export function set_recipient_disallowed(status) { + recipient_disallowed = status; + update_send_button_status(); +} + +function update_send_button_status() { + $(".message-send-controls").toggleClass( + "disabled-message-send-controls", + message_too_long || upload_in_progress || recipient_disallowed, + ); +} + +export function get_disabled_send_tooltip() { + if (message_too_long) { + return $t({defaultMessage: "Message length shouldn't be greater than 10000 characters."}); + } else if (upload_in_progress) { + return $t({defaultMessage: "Cannot send message while files are being uploaded."}); + } + return ""; +} + export function needs_subscribe_warning(user_id, stream_id) { // This returns true if all of these conditions are met: // * the user is valid @@ -655,7 +689,7 @@ export function check_overflow_text() { compose_banner.CLASSNAMES.message_too_long, $("#compose_banners"), ); - $("#compose-send-button").prop("disabled", true); + set_message_too_long(true); } else if (text.length > 0.9 * max_length) { $indicator.removeClass("over_limit"); $("textarea#compose-textarea").removeClass("over_limit"); @@ -665,13 +699,13 @@ export function check_overflow_text() { max_length, }), ); - $("#compose-send-button").prop("disabled", false); + set_message_too_long(false); $(`#compose_banners .${CSS.escape(compose_banner.CLASSNAMES.message_too_long)}`).remove(); } else { $indicator.text(""); $("textarea#compose-textarea").removeClass("over_limit"); - $("#compose-send-button").prop("disabled", false); + set_message_too_long(false); $(`#compose_banners .${CSS.escape(compose_banner.CLASSNAMES.message_too_long)}`).remove(); } diff --git a/web/src/upload.js b/web/src/upload.js index 863f8210bc..37c4a6558e 100644 --- a/web/src/upload.js +++ b/web/src/upload.js @@ -9,6 +9,7 @@ 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 * as compose_validate from "./compose_validate"; import {csrf_token} from "./csrf"; import {$t} from "./i18n"; import * as message_lists from "./message_lists"; @@ -129,7 +130,11 @@ export function get_item(key, config, file_id) { export function hide_upload_banner(uppy, config, file_id) { get_item("upload_banner", config, file_id).remove(); if (uppy.getFiles().length === 0) { - get_item("send_button", config).prop("disabled", false); + if (config.mode === "compose") { + compose_validate.set_upload_in_progress(false); + } else { + get_item("send_button", config).prop("disabled", false); + } } } @@ -157,7 +162,6 @@ export function show_error_message( message = $t({defaultMessage: "An unknown error occurred."}), file_id = null, ) { - get_item("send_button", config).prop("disabled", false); if (file_id) { $(`${get_item("upload_banner_identifier", config, file_id)} .moving_bar`).hide(); get_item("upload_banner", config, file_id).removeClass("info").addClass("error"); @@ -195,8 +199,6 @@ export async function upload_files(uppy, config, files) { get_item("markdown_preview_hide_button", config).trigger("click"); } - get_item("send_button", config).prop("disabled", true); - for (const file of files) { try { compose_ui.insert_syntax_and_focus( @@ -217,6 +219,11 @@ export async function upload_files(uppy, config, files) { continue; } + if (config.mode === "compose") { + compose_validate.set_upload_in_progress(true); + } else { + get_item("send_button", config).prop("disabled", true); + } add_upload_banner( config, "info", @@ -405,16 +412,16 @@ export function setup_upload(config) { }); uppy.on("upload-error", (file, _error, response) => { + // The files with failed upload should be removed since uppy doesn't allow files in the store + // to be re-uploaded again. + uppy.removeFile(file.id); + const message = response ? response.body.msg : undefined; // Hide the upload status banner on error so only the error banner shows hide_upload_banner(uppy, config, file.id); show_error_message(config, message, file.id); compose_ui.replace_syntax(get_translated_status(file), "", get_item("textarea", config)); compose_ui.autosize_textarea(get_item("textarea", config)); - - // The files with failed upload should be removed since uppy doesn't allow files in the store - // to be re-uploaded again. - uppy.removeFile(file.id); }); uppy.on("restriction-failed", (file) => { diff --git a/web/tests/compose_validate.test.js b/web/tests/compose_validate.test.js index e8d0b595a3..906ed1880f 100644 --- a/web/tests/compose_validate.test.js +++ b/web/tests/compose_validate.test.js @@ -561,7 +561,6 @@ test_ui("test_check_overflow_text", ({mock_template}) => { const $textarea = $("textarea#compose-textarea"); const $indicator = $("#compose-limit-indicator"); - const $send_button = $("#compose-send-button"); let banner_rendered = false; mock_template("compose_banner/compose_banner.hbs", false, (data) => { assert.equal(data.classname, compose_banner.CLASSNAMES.message_too_long); @@ -585,7 +584,7 @@ test_ui("test_check_overflow_text", ({mock_template}) => { assert.equal(limit_indicator_html, "10001​/10000\n"); assert.ok($textarea.hasClass("over_limit")); assert.ok(banner_rendered); - assert.ok($send_button.prop("disabled")); + assert.ok($(".message-send-controls").hasClass("disabled-message-send-controls")); // Indicator should show orange colored text banner_rendered = false; @@ -594,7 +593,7 @@ test_ui("test_check_overflow_text", ({mock_template}) => { assert.ok(!$indicator.hasClass("over_limit")); assert.equal(limit_indicator_html, "9001​/10000\n"); assert.ok(!$textarea.hasClass("over_limit")); - assert.ok(!$send_button.prop("disabled")); + assert.ok(!$(".message-send-controls").hasClass("disabled-message-send-controls")); assert.ok(!banner_rendered); // Indicator must be empty diff --git a/web/tests/upload.test.js b/web/tests/upload.test.js index a3b6374fb8..b30be12880 100644 --- a/web/tests/upload.test.js +++ b/web/tests/upload.test.js @@ -194,7 +194,7 @@ test("show_error_message", ({mock_template}) => { $("#compose-send-button").prop("disabled", true); upload.show_error_message({mode: "compose"}, "Error message"); - assert.equal($("#compose-send-button").prop("disabled"), false); + assert.ok(!$(".message-send-controls").hasClass("disabled-message-send-controls")); assert.ok(banner_shown); mock_template("compose_banner/upload_banner.hbs", false, (data) => { @@ -237,9 +237,9 @@ test("upload_files", async ({mock_template, override_rewire}) => { assert.equal(config.mode, "compose"); }); const config = {mode: "compose"}; - $("#compose-send-button").prop("disabled", false); + $(".message-send-controls").removeClass("disabled-message-send-controls"); await upload.upload_files(uppy, config, []); - assert.ok(!$("#compose-send-button").prop("disabled")); + assert.ok(!$(".message-send-controls").hasClass("disabled-message-send-controls")); let banner_shown = false; mock_template("compose_banner/upload_banner.hbs", false, (data) => { @@ -277,7 +277,7 @@ test("upload_files", async ({mock_template, override_rewire}) => { $("#compose .undo_markdown_preview").on("click", () => { markdown_preview_hide_button_clicked = true; }); - $("#compose-send-button").prop("disabled", false); + $(".message-send-controls").removeClass("disabled-message-send-controls"); $("#compose_banners .upload_banner").remove(); $("#compose .undo_markdown_preview").show(); @@ -286,7 +286,7 @@ test("upload_files", async ({mock_template, override_rewire}) => { banner_shown = true; }); await upload.upload_files(uppy, config, files); - assert.ok($("#compose-send-button").prop("disabled")); + assert.ok($(".message-send-controls").hasClass("disabled-message-send-controls")); assert.ok(banner_shown); assert.ok(compose_ui_insert_syntax_and_focus_called); assert.ok(compose_ui_autosize_textarea_called);