From 0dbc7e0d21c1e5f3389fcb00085123acd1864782 Mon Sep 17 00:00:00 2001 From: Riken Shah Date: Sat, 10 Jul 2021 17:33:45 +0000 Subject: [PATCH] compose: Improve how we handle over character limit message error. We improved it in the following ways: * Show the error message with the maximum character limit. * Disable the send button. * When the user tries to send the message via hotkeys i.e, When "Press enter to send" is enabled or the user uses "Shift" + "Enter" shortcut, Flash the red border around the compose box. Also renamed `check_and_set_overflow_text` to `check_overflow_text` for better clarity. --- frontend_tests/node_tests/compose_validate.js | 17 +++++++--- static/js/compose.js | 4 +-- static/js/compose_actions.js | 2 +- static/js/compose_validate.js | 32 ++++++++++++++++--- static/js/composebox_typeahead.js | 6 +++- static/styles/compose.css | 13 ++++++++ 6 files changed, 61 insertions(+), 13 deletions(-) diff --git a/frontend_tests/node_tests/compose_validate.js b/frontend_tests/node_tests/compose_validate.js index 20c28ff942..aa163e96fb 100644 --- a/frontend_tests/node_tests/compose_validate.js +++ b/frontend_tests/node_tests/compose_validate.js @@ -462,29 +462,38 @@ test_ui("test_validate_stream_message_post_policy_full_members_only", ({override ); }); -test_ui("test_check_and_set_overflow_text", () => { +test_ui("test_check_overflow_text", () => { page_params.max_message_length = 10000; const textarea = $("#compose-textarea"); const indicator = $("#compose_limit_indicator"); + const send_button = $("#compose-send-button"); // Indicator should show red colored text textarea.val("a".repeat(10000 + 1)); - compose_validate.check_and_set_overflow_text(); + compose_validate.check_overflow_text(); assert.ok(indicator.hasClass("over_limit")); assert.equal(indicator.text(), "10001/10000"); assert.ok(textarea.hasClass("over_limit")); + assert.equal( + $("#compose-error-msg").html(), + "translated HTML: Message length should'nt be greatar than 10000 characters.", + ); + assert.ok(send_button.prop("disabled")); + + $("#compose-send-status").stop = () => ({fadeOut: () => {}}); // Indicator should show orange colored text textarea.val("a".repeat(9000 + 1)); - compose_validate.check_and_set_overflow_text(); + compose_validate.check_overflow_text(); assert.ok(!indicator.hasClass("over_limit")); assert.equal(indicator.text(), "9001/10000"); assert.ok(!textarea.hasClass("over_limit")); + assert.ok(!send_button.prop("disabled")); // Indicator must be empty textarea.val("a".repeat(9000)); - compose_validate.check_and_set_overflow_text(); + compose_validate.check_overflow_text(); assert.ok(!indicator.hasClass("over_limit")); assert.equal(indicator.text(), ""); assert.ok(!textarea.hasClass("over_limit")); diff --git a/static/js/compose.js b/static/js/compose.js index 5bdc541456..c80f718aac 100644 --- a/static/js/compose.js +++ b/static/js/compose.js @@ -180,7 +180,7 @@ export function create_message_object() { export function clear_compose_box() { $("#compose-textarea").val("").trigger("focus"); - compose_validate.check_and_set_overflow_text(); + compose_validate.check_overflow_text(); drafts.delete_active_draft(); compose_ui.autosize_textarea($("#compose-textarea")); $("#compose-send-status").hide(0); @@ -617,7 +617,7 @@ export function initialize() { }); $("#compose-textarea").on("input propertychange", () => { - compose_validate.check_and_set_overflow_text(); + compose_validate.check_overflow_text(); }); $("#compose form").on("submit", (e) => { diff --git a/static/js/compose_actions.js b/static/js/compose_actions.js index e6f9152422..722c8e9adb 100644 --- a/static/js/compose_actions.js +++ b/static/js/compose_actions.js @@ -113,7 +113,7 @@ function clear_box() { compose_validate.set_user_acknowledged_announce_flag(undefined); clear_textarea(); - compose_validate.check_and_set_overflow_text(); + compose_validate.check_overflow_text(); $("#compose-textarea").removeData("draft-id"); compose_ui.autosize_textarea($("#compose-textarea")); $("#compose-send-status").hide(0); diff --git a/static/js/compose_validate.js b/static/js/compose_validate.js index 4329308d75..948b8f3eae 100644 --- a/static/js/compose_validate.js +++ b/static/js/compose_validate.js @@ -464,7 +464,7 @@ function validate_private_message() { return true; } -export function check_and_set_overflow_text() { +export function check_overflow_text() { const text = compose_state.message_content(); const max_length = page_params.max_message_length; const indicator = $("#compose_limit_indicator"); @@ -473,20 +473,45 @@ export function check_and_set_overflow_text() { indicator.addClass("over_limit"); $("#compose-textarea").addClass("over_limit"); indicator.text(text.length + "/" + max_length); + compose_error.show( + $t_html( + { + defaultMessage: + "Message length should'nt be greatar than {max_length} characters.", + }, + {max_length}, + ), + ); + $("#compose-send-button").prop("disabled", true); } else if (text.length > 0.9 * max_length) { indicator.removeClass("over_limit"); $("#compose-textarea").removeClass("over_limit"); indicator.text(text.length + "/" + max_length); + + $("#compose-send-button").prop("disabled", false); + if ($("#compose-send-status").hasClass("alert-error")) { + $("#compose-send-status").stop(true).fadeOut(); + } } else { indicator.text(""); $("#compose-textarea").removeClass("over_limit"); + $("#compose-send-button").prop("disabled", false); if ($("#compose-send-status").hasClass("alert-error")) { $("#compose-send-status").stop(true).fadeOut(); } } } +export function warn_for_text_overflow_when_tries_to_send() { + if (compose_state.message_content().length > page_params.max_message_length) { + $("#compose-textarea").addClass("flash"); + setTimeout(() => $("#compose-textarea").removeClass("flash"), 1500); + return false; + } + return true; +} + export function validate() { $("#compose-send-button").prop("disabled", true).trigger("blur"); const message_content = compose_state.message_content(); @@ -513,10 +538,7 @@ export function validate() { ); return false; } - - if (message_content.length > page_params.max_message_length) { - // We don't display an error message, since the red box already - // communicates clearly what you did wrong. + if (!warn_for_text_overflow_when_tries_to_send()) { return false; } diff --git a/static/js/composebox_typeahead.js b/static/js/composebox_typeahead.js index d8edbe19d8..68eb0470b6 100644 --- a/static/js/composebox_typeahead.js +++ b/static/js/composebox_typeahead.js @@ -12,6 +12,7 @@ import * as compose from "./compose"; import * as compose_pm_pill from "./compose_pm_pill"; import * as compose_state from "./compose_state"; import * as compose_ui from "./compose_ui"; +import * as compose_validate from "./compose_validate"; import {$t} from "./i18n"; import * as message_store from "./message_store"; import * as muted_users from "./muted_users"; @@ -218,7 +219,10 @@ function handle_keydown(e) { // Enter if (should_enter_send(e)) { e.preventDefault(); - if (!$("#compose-send-button").prop("disabled")) { + if ( + compose_validate.warn_for_text_overflow_when_tries_to_send() && + !$("#compose-send-button").prop("disabled") + ) { $("#compose-send-button").prop("disabled", true); compose.finish(); } diff --git a/static/styles/compose.css b/static/styles/compose.css index e405747b93..974f76e89e 100644 --- a/static/styles/compose.css +++ b/static/styles/compose.css @@ -353,9 +353,22 @@ textarea.new_message_textarea { resize: vertical !important; margin-top: 5px; + @keyframes flash { + 0% { + box-shadow: none; + } + 100% { + box-shadow: 0 0 0 1pt hsl(0, 100%, 50%); + } + } + &.over_limit, &.over_limit:focus { box-shadow: 0 0 0 1pt hsl(0, 100%, 50%); + + &.flash { + animation: flash 0.5s ease-in-out infinite; + } } }