mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 13:03:29 +00:00
message_edit: Add message length limit indicator in edit message UI.
Adds a message length limit indicator similar to the one in the compose box. The tooltip message for the disabled save button now appears dynamically based on whether the message exceeds the length limit or the editing time has expired. Fixes #25271.
This commit is contained in:
@@ -54,6 +54,17 @@ function set_message_too_long_for_compose(status: boolean): void {
|
||||
update_send_button_status();
|
||||
}
|
||||
|
||||
function set_message_too_long_for_edit(status: boolean, $container: JQuery): void {
|
||||
message_too_long = status;
|
||||
const $message_edit_save_container = $container.find(".message_edit_save_container");
|
||||
const save_is_disabled =
|
||||
message_too_long ||
|
||||
$message_edit_save_container.hasClass("message-edit-time-limit-expired");
|
||||
|
||||
$container.find(".message_edit_save").prop("disabled", save_is_disabled);
|
||||
$message_edit_save_container.toggleClass("disabled-message-edit-save", save_is_disabled);
|
||||
}
|
||||
|
||||
export function set_recipient_disallowed(status: boolean): void {
|
||||
recipient_disallowed = status;
|
||||
update_send_button_status();
|
||||
@@ -78,6 +89,25 @@ export function get_disabled_send_tooltip(): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
export function get_disabled_save_tooltip($container: JQuery): string {
|
||||
const $button_wrapper = $container.find(".message_edit_save_container");
|
||||
if ($button_wrapper.hasClass("message-edit-time-limit-expired")) {
|
||||
return $t({
|
||||
defaultMessage: "You can no longer save changes to this message.",
|
||||
});
|
||||
}
|
||||
if (message_too_long) {
|
||||
return $t(
|
||||
{
|
||||
defaultMessage: `Message length shouldn't be greater than {max_length} characters.`,
|
||||
},
|
||||
{
|
||||
max_length: realm.max_message_length,
|
||||
},
|
||||
);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
export function needs_subscribe_warning(user_id: number, stream_id: number): boolean {
|
||||
// This returns true if all of these conditions are met:
|
||||
// * the user is valid
|
||||
@@ -727,6 +757,7 @@ export function check_overflow_text($container: JQuery): number {
|
||||
const max_length = realm.max_message_length;
|
||||
const remaining_characters = max_length - text.length;
|
||||
const $indicator = $container.find(".message-limit-indicator");
|
||||
const is_edit_container = $textarea.closest(".message_row").length > 0;
|
||||
|
||||
if (text.length > max_length) {
|
||||
$indicator.addClass("over_limit");
|
||||
@@ -736,7 +767,11 @@ export function check_overflow_text($container: JQuery): number {
|
||||
remaining_characters,
|
||||
}),
|
||||
);
|
||||
set_message_too_long_for_compose(true);
|
||||
if (is_edit_container) {
|
||||
set_message_too_long_for_edit(true, $container);
|
||||
} else {
|
||||
set_message_too_long_for_compose(true);
|
||||
}
|
||||
} else if (remaining_characters <= 900) {
|
||||
$indicator.removeClass("over_limit");
|
||||
$textarea.removeClass("over_limit");
|
||||
@@ -745,12 +780,20 @@ export function check_overflow_text($container: JQuery): number {
|
||||
remaining_characters,
|
||||
}),
|
||||
);
|
||||
set_message_too_long_for_compose(false);
|
||||
if (is_edit_container) {
|
||||
set_message_too_long_for_edit(false, $container);
|
||||
} else {
|
||||
set_message_too_long_for_compose(false);
|
||||
}
|
||||
} else {
|
||||
$indicator.text("");
|
||||
$textarea.removeClass("over_limit");
|
||||
|
||||
set_message_too_long_for_compose(false);
|
||||
if (is_edit_container) {
|
||||
set_message_too_long_for_edit(false, $container);
|
||||
} else {
|
||||
set_message_too_long_for_compose(false);
|
||||
}
|
||||
}
|
||||
|
||||
return text.length;
|
||||
|
||||
@@ -404,6 +404,7 @@ function handle_message_edit_enter(
|
||||
// Prevent default to avoid new-line on pressing
|
||||
// Enter inside the textarea in this case
|
||||
e.preventDefault();
|
||||
compose_validate.validate_message_length($row);
|
||||
return;
|
||||
}
|
||||
save_message_row_edit($row);
|
||||
@@ -538,6 +539,10 @@ function edit_message($row: JQuery, raw_content: string): void {
|
||||
}
|
||||
});
|
||||
|
||||
$form.on("input propertychange", () => {
|
||||
compose_validate.check_overflow_text($row);
|
||||
});
|
||||
|
||||
$form
|
||||
.find(".message-edit-feature-group .video_link")
|
||||
.toggle(compose_call.compute_show_video_chat_button());
|
||||
@@ -595,7 +600,8 @@ function edit_message($row: JQuery, raw_content: string): void {
|
||||
// the half-finished edit around so that they can copy-paste it, but we don't want
|
||||
// people to think "Save" will save the half-finished edit.
|
||||
$message_edit_save.prop("disabled", true);
|
||||
$message_edit_save_container.addClass("tippy-zulip-tooltip");
|
||||
$message_edit_save_container.addClass("message-edit-time-limit-expired");
|
||||
$message_edit_save_container.addClass("disabled-message-edit-save");
|
||||
$message_edit_countdown_timer.addClass("expired");
|
||||
$message_edit_countdown_timer.text($t({defaultMessage: "Time's up!"}));
|
||||
} else {
|
||||
@@ -614,6 +620,7 @@ function edit_message($row: JQuery, raw_content: string): void {
|
||||
if (contents) {
|
||||
$message_edit_content.val(contents);
|
||||
}
|
||||
compose_validate.check_overflow_text($row);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import render_message_edit_notice_tooltip from "../templates/message_edit_notice
|
||||
import render_message_inline_image_tooltip from "../templates/message_inline_image_tooltip.hbs";
|
||||
import render_narrow_tooltip from "../templates/narrow_tooltip.hbs";
|
||||
|
||||
import * as compose_validate from "./compose_validate.ts";
|
||||
import {$t} from "./i18n.ts";
|
||||
import * as message_lists from "./message_lists.ts";
|
||||
import type {Message} from "./message_store.ts";
|
||||
@@ -282,6 +283,19 @@ export function initialize(): void {
|
||||
},
|
||||
});
|
||||
|
||||
message_list_tooltip(".disabled-message-edit-save", {
|
||||
onShow(instance) {
|
||||
const $elem = $(instance.reference);
|
||||
const $row = $elem.closest(".message_row");
|
||||
assert($row !== undefined);
|
||||
instance.setContent(compose_validate.get_disabled_save_tooltip($row));
|
||||
return undefined;
|
||||
},
|
||||
onHidden(instance) {
|
||||
instance.destroy();
|
||||
},
|
||||
});
|
||||
|
||||
message_list_tooltip(".recipient_row_date > span", {
|
||||
onHidden(instance) {
|
||||
instance.destroy();
|
||||
|
||||
@@ -327,16 +327,6 @@
|
||||
border-color: var(--color-message-content-container-border-focus);
|
||||
}
|
||||
|
||||
&:has(.new_message_textarea.over_limit),
|
||||
&:has(.new_message_textarea.over_limit:focus) {
|
||||
box-shadow: 0 0 0 1pt
|
||||
var(--color-message-content-container-border-over-limit);
|
||||
}
|
||||
|
||||
&:has(.new_message_textarea.over_limit.flash) {
|
||||
animation: message-limit-flash 0.5s ease-in-out 3;
|
||||
}
|
||||
|
||||
&:has(.new_message_textarea.invalid),
|
||||
&:has(.new_message_textarea.invalid:focus) {
|
||||
border-color: hsl(3deg 57% 33%);
|
||||
@@ -344,6 +334,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
#message-content-container:has(.new_message_textarea.over_limit),
|
||||
#message-content-container:has(.new_message_textarea.over_limit:focus),
|
||||
.edit-content-container:has(.message_edit_content.over_limit),
|
||||
.edit-content-container:has(.message_edit_content.over_limit:focus) {
|
||||
box-shadow: 0 0 0 1pt
|
||||
var(--color-message-content-container-border-over-limit);
|
||||
}
|
||||
|
||||
#message-content-container:has(.new_message_textarea.over_limit.flash),
|
||||
.edit-content-container:has(.message_edit_content.over_limit.flash) {
|
||||
animation: message-limit-flash 0.5s ease-in-out 3;
|
||||
}
|
||||
|
||||
#message-content-container .composebox-buttons {
|
||||
grid-area: composebox-buttons;
|
||||
/* z-index is needed to avoid flickering of cursor and the
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<span class="copy_message copy-button copy-button-square tippy-zulip-tooltip" data-tippy-content="{{t 'Copy and close' }}" aria-label="{{t 'Copy and close' }}" role="button">
|
||||
<i class="zulip-icon zulip-icon-copy" aria-hidden="true"></i>
|
||||
</span>
|
||||
<textarea class="message_edit_content" maxlength="{{ max_message_length }}">{{content}}</textarea>
|
||||
<textarea class="message_edit_content message-textarea">{{content}}</textarea>
|
||||
</div>
|
||||
<div class="scrolling_list preview_message_area" id="preview_message_area_{{message_id}}" style="display:none;">
|
||||
<div class="markdown_preview_spinner"></div>
|
||||
@@ -24,14 +24,14 @@
|
||||
{{/if}}
|
||||
<div class="message-edit-buttons-and-timer">
|
||||
{{#if is_editable}}
|
||||
<div class="message_edit_save_container"
|
||||
data-tippy-content="{{t 'You can no longer save changes to this message.' }}">
|
||||
<div class="message_edit_save_container">
|
||||
<button type="button" class="message-actions-button message_edit_save">
|
||||
<img class="loader" alt="" src="" />
|
||||
<span>{{t "Save" }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="message-actions-button message_edit_cancel"><span>{{t "Cancel" }}</span></button>
|
||||
<span class="tippy-zulip-tooltip message-limit-indicator" data-tippy-content="{{t 'Maximum message length: {max_message_length} characters' }}"></span>
|
||||
<div class="message-edit-timer">
|
||||
<span class="message_edit_countdown_timer
|
||||
tippy-zulip-tooltip" data-tippy-content="{{t 'This organization is configured to restrict editing of message content to {minutes_to_edit} minutes after it is sent.' }}"></span>
|
||||
|
||||
@@ -140,6 +140,15 @@ const everyone = {
|
||||
|
||||
user_groups.initialize({realm_user_groups: [nobody, everyone]});
|
||||
|
||||
function stub_message_row($textarea) {
|
||||
const $stub = $.create("message_row_stub");
|
||||
$textarea.closest = (selector) => {
|
||||
assert.equal(selector, ".message_row");
|
||||
$stub.length = 0;
|
||||
return $stub;
|
||||
};
|
||||
}
|
||||
|
||||
function test_ui(label, f) {
|
||||
// TODO: initialize data more aggressively.
|
||||
run_test(label, f);
|
||||
@@ -181,6 +190,7 @@ test_ui("send_message_success", ({override, override_rewire}) => {
|
||||
const $elem = $("#send_message_form");
|
||||
const $textarea = $("textarea#compose-textarea");
|
||||
const $indicator = $("#compose-limit-indicator");
|
||||
stub_message_row($textarea);
|
||||
$elem.set_find_results(".message-textarea", $textarea);
|
||||
$elem.set_find_results(".message-limit-indicator", $indicator);
|
||||
|
||||
@@ -248,6 +258,7 @@ test_ui("send_message", ({override, override_rewire, mock_template}) => {
|
||||
const $elem = $("#send_message_form");
|
||||
const $textarea = $("textarea#compose-textarea");
|
||||
const $indicator = $("#compose-limit-indicator");
|
||||
stub_message_row($textarea);
|
||||
$elem.set_find_results(".message-textarea", $textarea);
|
||||
$elem.set_find_results(".message-limit-indicator", $indicator);
|
||||
|
||||
|
||||
@@ -126,6 +126,15 @@ function test(label, f) {
|
||||
});
|
||||
}
|
||||
|
||||
function stub_message_row($textarea) {
|
||||
const $stub = $.create("message_row_stub");
|
||||
$textarea.closest = (selector) => {
|
||||
assert.equal(selector, ".message_row");
|
||||
$stub.length = 0;
|
||||
return $stub;
|
||||
};
|
||||
}
|
||||
|
||||
test("initial_state", () => {
|
||||
assert.equal(compose_state.composing(), false);
|
||||
assert.equal(compose_state.get_message_type(), undefined);
|
||||
@@ -143,6 +152,7 @@ test("start", ({override, override_rewire, mock_template}) => {
|
||||
const $elem = $("#send_message_form");
|
||||
const $textarea = $("textarea#compose-textarea");
|
||||
const $indicator = $("#compose-limit-indicator");
|
||||
stub_message_row($textarea);
|
||||
$elem.set_find_results(".message-textarea", $textarea);
|
||||
$elem.set_find_results(".message-limit-indicator", $indicator);
|
||||
|
||||
@@ -290,6 +300,7 @@ test("respond_to_message", ({override, override_rewire, mock_template}) => {
|
||||
const $elem = $("#send_message_form");
|
||||
const $textarea = $("textarea#compose-textarea");
|
||||
const $indicator = $("#compose-limit-indicator");
|
||||
stub_message_row($textarea);
|
||||
$elem.set_find_results(".message-textarea", $textarea);
|
||||
$elem.set_find_results(".message-limit-indicator", $indicator);
|
||||
|
||||
@@ -351,6 +362,7 @@ test("reply_with_mention", ({override, override_rewire, mock_template}) => {
|
||||
const $elem = $("#send_message_form");
|
||||
const $textarea = $("textarea#compose-textarea");
|
||||
const $indicator = $("#compose-limit-indicator");
|
||||
stub_message_row($textarea);
|
||||
$elem.set_find_results(".message-textarea", $textarea);
|
||||
$elem.set_find_results(".message-limit-indicator", $indicator);
|
||||
|
||||
@@ -411,6 +423,7 @@ test("quote_and_reply", ({disallow, override, override_rewire}) => {
|
||||
const $elem = $("#send_message_form");
|
||||
const $textarea = $("textarea#compose-textarea");
|
||||
const $indicator = $("#compose-limit-indicator");
|
||||
stub_message_row($textarea);
|
||||
$elem.set_find_results(".message-textarea", $textarea);
|
||||
$elem.set_find_results(".message-limit-indicator", $indicator);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user