From 541d3ffa064b522682fd8dba123603882a61e033 Mon Sep 17 00:00:00 2001 From: evykassirer Date: Tue, 3 Jan 2023 00:35:18 -0800 Subject: [PATCH] compose: Replace empty message banner with red outline for compose box. Previously, we showed an empty message banner if the user tried to send an empty message. We only showed it for users with "ctrl+enter to send" because we thought it might be easy for a user to press just enter accidentally. However, this missed the case where the user clicks on the Enter button. We want to show the user something in this case to tell them that they're missing message content. To avoid more complicated logic, this PR removes the banner completely and changes the compose box border to red if the user tries to send an empty message (for all cases). The red line goes away as soon as the composebox has non-whitespace characters. --- frontend_tests/node_tests/compose.js | 11 ++++++----- frontend_tests/node_tests/compose_validate.js | 9 ++++----- static/js/compose.js | 3 +++ static/js/compose_banner.ts | 1 - static/js/compose_validate.js | 12 +----------- static/styles/compose.css | 6 ++++++ static/styles/dark_theme.css | 8 ++++++++ 7 files changed, 28 insertions(+), 22 deletions(-) diff --git a/frontend_tests/node_tests/compose.js b/frontend_tests/node_tests/compose.js index 9ac809a1e9..dd8b6267f4 100644 --- a/frontend_tests/node_tests/compose.js +++ b/frontend_tests/node_tests/compose.js @@ -287,6 +287,7 @@ test_ui("send_message", ({override, override_rewire, mock_template}) => { test_ui("enter_with_preview_open", ({override, override_rewire}) => { mock_banners(); + $("#compose-textarea").toggleClass = noop; override_rewire(compose_banner, "clear_message_sent_banners", () => {}); override(reminder, "is_deferred_delivery", () => false); override(document, "to_$", () => $("document-stub")); @@ -333,7 +334,7 @@ test_ui("enter_with_preview_open", ({override, override_rewire}) => { compose.enter_with_preview_open(); }); -test_ui("finish", ({override, override_rewire, mock_template}) => { +test_ui("finish", ({override, override_rewire}) => { mock_banners(); override_rewire(compose_banner, "clear_message_sent_banners", () => {}); override(reminder, "is_deferred_delivery", () => false); @@ -345,10 +346,10 @@ test_ui("finish", ({override, override_rewire, mock_template}) => { }); (function test_when_compose_validation_fails() { - mock_template("compose_banner/compose_banner.hbs", false, (data) => { - assert.equal(data.classname, "empty_message"); - assert.equal(data.banner_text, $t({defaultMessage: "You have nothing to send!"})); - }); + $("#compose-textarea").toggleClass = (classname, value) => { + assert.equal(classname, "invalid"); + assert.equal(value, true); + }; $("#compose_invite_users").show(); $("#compose-send-button").prop("disabled", false); $("#compose-send-button").trigger("focus"); diff --git a/frontend_tests/node_tests/compose_validate.js b/frontend_tests/node_tests/compose_validate.js index 1629efd0af..f060f93f01 100644 --- a/frontend_tests/node_tests/compose_validate.js +++ b/frontend_tests/node_tests/compose_validate.js @@ -214,7 +214,6 @@ test_ui("validate", ({override, mock_template}) => { assert.ok(compose_validate.validate()); let zephyr_error_rendered = false; - let empty_message_error_rendered = false; mock_template("compose_banner/compose_banner.hbs", false, (data) => { if (data.classname === compose_banner.CLASSNAMES.zephyr_not_running) { assert.equal( @@ -225,17 +224,17 @@ test_ui("validate", ({override, mock_template}) => { }), ); zephyr_error_rendered = true; - } else if (data.classname === compose_banner.CLASSNAMES.empty_message) { - assert.equal(data.banner_text, $t({defaultMessage: "You have nothing to send!"})); - empty_message_error_rendered = true; } }); initialize_pm_pill(); compose_state.private_message_recipient("welcome-bot@example.com"); + $("#compose-textarea").toggleClass = (classname, value) => { + assert.equal(classname, "invalid"); + assert.equal(value, true); + }; assert.ok(!compose_validate.validate()); assert.ok(!$("#compose-send-button .loader").visible()); assert.equal($("#compose-send-button").prop("disabled"), false); - assert.ok(empty_message_error_rendered); compose_validate.validate(); add_content_to_compose_box(); diff --git a/static/js/compose.js b/static/js/compose.js index 40c16d3af1..f9d1a9595c 100644 --- a/static/js/compose.js +++ b/static/js/compose.js @@ -445,6 +445,9 @@ export function initialize() { $("#compose-textarea").on("input propertychange", () => { compose_validate.warn_if_topic_resolved(false); const compose_text_length = compose_validate.check_overflow_text(); + if (compose_text_length !== 0 && $("#compose-textarea").hasClass("invalid")) { + $("#compose-textarea").toggleClass("invalid", false); + } // Change compose close button tooltip as per condition. // We save compose text in draft only if its length is > 2. if (compose_text_length > 2) { diff --git a/static/js/compose_banner.ts b/static/js/compose_banner.ts index 3faf531dbd..e9eed70ecd 100644 --- a/static/js/compose_banner.ts +++ b/static/js/compose_banner.ts @@ -25,7 +25,6 @@ export const CLASSNAMES = { wildcard_warning: "wildcard_warning", private_stream_warning: "private_stream_warning", // errors - empty_message: "empty_message", wildcards_not_allowed: "wildcards_not_allowed", subscription_error: "subscription_error", stream_does_not_exist: "stream_does_not_exist", diff --git a/static/js/compose_validate.js b/static/js/compose_validate.js index 10801b6308..3f9bc75477 100644 --- a/static/js/compose_validate.js +++ b/static/js/compose_validate.js @@ -18,7 +18,6 @@ import * as people from "./people"; import * as settings_config from "./settings_config"; import * as settings_data from "./settings_data"; import * as stream_data from "./stream_data"; -import {user_settings} from "./user_settings"; import * as util from "./util"; let user_acknowledged_wildcard = false; @@ -611,18 +610,9 @@ export function warn_for_text_overflow_when_tries_to_send() { export function validate() { const message_content = compose_state.message_content(); if (/^\s*$/.test(message_content)) { - // Avoid showing an error message when "enter sends" is enabled, - // as it is more likely that the user has hit "Enter" accidentally. - if (!user_settings.enter_sends) { - compose_banner.show_error_message( - $t({defaultMessage: "You have nothing to send!"}), - compose_banner.CLASSNAMES.empty_message, - $("#compose-textarea"), - ); - } + $("#compose-textarea").toggleClass("invalid", true); return false; } - $(`#compose_banners .${compose_banner.CLASSNAMES.empty_message}`).remove(); if ($("#zephyr-mirror-error").is(":visible")) { compose_banner.show_error_message( diff --git a/static/styles/compose.css b/static/styles/compose.css index 42d495b526..3c27b84c5e 100644 --- a/static/styles/compose.css +++ b/static/styles/compose.css @@ -487,6 +487,12 @@ textarea.new_message_textarea { cursor: not-allowed; background-color: hsl(0, 0%, 93%); } + + &.invalid, + &.invalid:focus { + border: 1px solid hsl(3, 57%, 33%); + box-shadow: 0 0 2px hsl(3, 57%, 33%); + } } textarea.new_message_textarea, diff --git a/static/styles/dark_theme.css b/static/styles/dark_theme.css index 7a11e138c7..eb875b35b5 100644 --- a/static/styles/dark_theme.css +++ b/static/styles/dark_theme.css @@ -288,6 +288,14 @@ } } + textarea.new_message_textarea { + &.invalid, + &.invalid:focus { + border-color: hsl(3, 73%, 74%); + box-shadow: 0 0 2px hsl(3, 73%, 74%); + } + } + .message_embed .data-container::after { background: linear-gradient(0deg, hsl(212, 28%, 18%), transparent 100%); }