mirror of
https://github.com/zulip/zulip.git
synced 2025-11-10 17:07:07 +00:00
compose: Have at least 2 new lines before and after a quoted message.
Uptil now, 1 new line was added before and 1 after a quoted message. Now for more breathing room around a quoted message, new lines are inserted to space it from any content before and after by at least 2 new lines. Fixes: #23608.
This commit is contained in:
@@ -536,25 +536,17 @@ export function quote_and_reply(opts) {
|
||||
const message = message_lists.current.selected_message();
|
||||
const quoting_placeholder = $t({defaultMessage: "[Quoting…]"});
|
||||
|
||||
if (compose_state.has_message_content()) {
|
||||
// The user already started typing a message,
|
||||
// so we won't re-open the compose box.
|
||||
if (!compose_state.has_message_content()) {
|
||||
// The user has not started typing a message,
|
||||
// so we will re-open the compose box.
|
||||
// (If you did re-open the compose box, you
|
||||
// are prone to glitches where you select the
|
||||
// text, plus it's a complicated codepath that
|
||||
// can have other unintended consequences.)
|
||||
|
||||
if ($textarea.caret() !== 0) {
|
||||
// Insert a newline before quoted message if there is
|
||||
// already some content in the compose box and quoted
|
||||
// message is not being inserted at the beginning.
|
||||
$textarea.caret("\n");
|
||||
}
|
||||
} else {
|
||||
respond_to_message(opts);
|
||||
}
|
||||
|
||||
compose_ui.insert_syntax_and_focus(quoting_placeholder + "\n", $textarea);
|
||||
compose_ui.insert_syntax_and_focus(quoting_placeholder, $textarea, "block");
|
||||
|
||||
function replace_content(message) {
|
||||
// Final message looks like:
|
||||
|
||||
@@ -30,7 +30,7 @@ export function autosize_textarea($textarea) {
|
||||
}
|
||||
}
|
||||
|
||||
export function smart_insert($textarea, syntax) {
|
||||
export function smart_insert_inline($textarea, syntax) {
|
||||
function is_space(c) {
|
||||
return c === " " || c === "\t" || c === "\n";
|
||||
}
|
||||
@@ -68,11 +68,69 @@ export function smart_insert($textarea, syntax) {
|
||||
autosize_textarea($textarea);
|
||||
}
|
||||
|
||||
export function insert_syntax_and_focus(syntax, $textarea = $("#compose-textarea")) {
|
||||
export function smart_insert_block($textarea, syntax) {
|
||||
const pos = $textarea.caret();
|
||||
const before_str = $textarea.val().slice(0, pos);
|
||||
const after_str = $textarea.val().slice(pos);
|
||||
|
||||
if (pos > 0) {
|
||||
// Insert newline/s before the content block if there is
|
||||
// already some content in the compose box and the content
|
||||
// block is not being inserted at the beginning, such
|
||||
// that there are at least 2 new lines between the content
|
||||
// and start of the content block.
|
||||
let new_lines_before_count = 0;
|
||||
let current_pos = pos - 1;
|
||||
while (
|
||||
current_pos >= 0 &&
|
||||
before_str.charAt(current_pos) === "\n" &&
|
||||
new_lines_before_count < 2
|
||||
) {
|
||||
// count up to 2 new lines before cursor
|
||||
current_pos -= 1;
|
||||
new_lines_before_count += 1;
|
||||
}
|
||||
const new_lines_needed_before_count = 2 - new_lines_before_count;
|
||||
syntax = "\n".repeat(new_lines_needed_before_count) + syntax;
|
||||
}
|
||||
|
||||
let new_lines_after_count = 0;
|
||||
let current_pos = 0;
|
||||
while (
|
||||
current_pos < after_str.length &&
|
||||
after_str.charAt(current_pos) === "\n" &&
|
||||
new_lines_after_count < 2
|
||||
) {
|
||||
// count up to 2 new lines after cursor
|
||||
current_pos += 1;
|
||||
new_lines_after_count += 1;
|
||||
}
|
||||
// Insert newline/s after the content block, such that there
|
||||
// are at least 2 new lines between the content block and
|
||||
// the content after the cursor, if any.
|
||||
const new_lines_needed_after_count = 2 - new_lines_after_count;
|
||||
syntax = syntax + "\n".repeat(new_lines_needed_after_count);
|
||||
|
||||
// text-field-edit ensures `$textarea` is focused before inserting
|
||||
// the new syntax.
|
||||
insert($textarea[0], syntax);
|
||||
|
||||
autosize_textarea($textarea);
|
||||
}
|
||||
|
||||
export function insert_syntax_and_focus(
|
||||
syntax,
|
||||
$textarea = $("#compose-textarea"),
|
||||
mode = "inline",
|
||||
) {
|
||||
// Generic helper for inserting syntax into the main compose box
|
||||
// where the cursor was and focusing the area. Mostly a thin
|
||||
// wrapper around smart_insert.
|
||||
smart_insert($textarea, syntax);
|
||||
// wrapper around smart_insert_inline and smart_inline_block.
|
||||
if (mode === "inline") {
|
||||
smart_insert_inline($textarea, syntax);
|
||||
} else if (mode === "block") {
|
||||
smart_insert_block($textarea, syntax);
|
||||
}
|
||||
}
|
||||
|
||||
export function replace_syntax(old_syntax, new_syntax, $textarea = $("#compose-textarea")) {
|
||||
|
||||
@@ -359,8 +359,9 @@ test("quote_and_reply", ({disallow, override, override_rewire}) => {
|
||||
|
||||
override(message_lists.current, "selected_id", () => 100);
|
||||
|
||||
override(compose_ui, "insert_syntax_and_focus", (syntax) => {
|
||||
assert.equal(syntax, "translated: [Quoting…]\n");
|
||||
override(compose_ui, "insert_syntax_and_focus", (syntax, $textarea, mode) => {
|
||||
assert.equal(syntax, "translated: [Quoting…]");
|
||||
assert.equal(mode, "block");
|
||||
});
|
||||
|
||||
const opts = {
|
||||
|
||||
@@ -120,34 +120,34 @@ run_test("smart_insert", ({override}) => {
|
||||
});
|
||||
}
|
||||
override_with_expected_syntax(" :smile: ");
|
||||
compose_ui.smart_insert($textbox, ":smile:");
|
||||
compose_ui.smart_insert_inline($textbox, ":smile:");
|
||||
|
||||
override_with_expected_syntax(" :airplane: ");
|
||||
compose_ui.smart_insert($textbox, ":airplane:");
|
||||
compose_ui.smart_insert_inline($textbox, ":airplane:");
|
||||
|
||||
$textbox.caret(0);
|
||||
override_with_expected_syntax(":octopus: ");
|
||||
compose_ui.smart_insert($textbox, ":octopus:");
|
||||
compose_ui.smart_insert_inline($textbox, ":octopus:");
|
||||
|
||||
$textbox.caret($textbox.val().length);
|
||||
override_with_expected_syntax(" :heart: ");
|
||||
compose_ui.smart_insert($textbox, ":heart:");
|
||||
compose_ui.smart_insert_inline($textbox, ":heart:");
|
||||
|
||||
// Test handling of spaces for ```quote
|
||||
$textbox = make_textbox("");
|
||||
$textbox.caret(0);
|
||||
override_with_expected_syntax("```quote\nquoted message\n```\n");
|
||||
compose_ui.smart_insert($textbox, "```quote\nquoted message\n```\n");
|
||||
override_with_expected_syntax("```quote\nquoted message\n```\n\n");
|
||||
compose_ui.smart_insert_block($textbox, "```quote\nquoted message\n```");
|
||||
|
||||
$textbox = make_textbox("");
|
||||
$textbox.caret(0);
|
||||
override_with_expected_syntax("translated: [Quoting…]\n");
|
||||
compose_ui.smart_insert($textbox, "translated: [Quoting…]\n");
|
||||
override_with_expected_syntax("translated: [Quoting…]\n\n");
|
||||
compose_ui.smart_insert_block($textbox, "translated: [Quoting…]");
|
||||
|
||||
$textbox = make_textbox("abc");
|
||||
$textbox.caret(3);
|
||||
override_with_expected_syntax(" test with space ");
|
||||
compose_ui.smart_insert($textbox, " test with space");
|
||||
override_with_expected_syntax("\n\n test with space\n\n");
|
||||
compose_ui.smart_insert_block($textbox, " test with space");
|
||||
|
||||
// Note that we don't have any special logic for strings that are
|
||||
// already surrounded by spaces, since we are usually inserting things
|
||||
@@ -281,23 +281,28 @@ run_test("quote_and_reply", ({override, override_rewire}) => {
|
||||
textarea_caret_pos = arg;
|
||||
return this;
|
||||
}
|
||||
/* istanbul ignore if */
|
||||
if (typeof arg !== "string") {
|
||||
console.info(arg);
|
||||
throw new Error("We expected the actual code to pass in a string.");
|
||||
|
||||
/* This next block of mocking code is currently unused, but
|
||||
is preserved, since it may be useful in the future. */
|
||||
/* istanbul ignore next */
|
||||
{
|
||||
if (typeof arg !== "string") {
|
||||
console.info(arg);
|
||||
throw new Error("We expected the actual code to pass in a string.");
|
||||
}
|
||||
|
||||
const before = textarea_val.slice(0, textarea_caret_pos);
|
||||
const after = textarea_val.slice(textarea_caret_pos);
|
||||
|
||||
textarea_val = before + arg + after;
|
||||
textarea_caret_pos += arg.length;
|
||||
return this;
|
||||
}
|
||||
|
||||
const before = textarea_val.slice(0, textarea_caret_pos);
|
||||
const after = textarea_val.slice(textarea_caret_pos);
|
||||
|
||||
textarea_val = before + arg + after;
|
||||
textarea_caret_pos += arg.length;
|
||||
return this;
|
||||
};
|
||||
$("#compose-textarea")[0] = "compose-textarea";
|
||||
override(text_field_edit, "insert", (elt, syntax) => {
|
||||
assert.equal(elt, "compose-textarea");
|
||||
assert.equal(syntax, "translated: [Quoting…]\n");
|
||||
assert.equal(syntax, "\n\ntranslated: [Quoting…]\n\n");
|
||||
});
|
||||
|
||||
function set_compose_content_with_caret(content) {
|
||||
@@ -343,7 +348,11 @@ run_test("quote_and_reply", ({override, override_rewire}) => {
|
||||
reset_test_state();
|
||||
|
||||
// If the caret is initially positioned at 0, it should not
|
||||
// add a newline before the quoted message.
|
||||
// add newlines before the quoted message.
|
||||
override(text_field_edit, "insert", (elt, syntax) => {
|
||||
assert.equal(elt, "compose-textarea");
|
||||
assert.equal(syntax, "translated: [Quoting…]\n\n");
|
||||
});
|
||||
set_compose_content_with_caret("%hello there");
|
||||
compose_actions.quote_and_reply();
|
||||
|
||||
@@ -387,6 +396,40 @@ run_test("quote_and_reply", ({override, override_rewire}) => {
|
||||
success_function({
|
||||
raw_content: quote_text,
|
||||
});
|
||||
|
||||
reset_test_state();
|
||||
|
||||
// When there is already 1 newline before and after the caret,
|
||||
// only 1 newline is added before and after the quoted message.
|
||||
override(text_field_edit, "insert", (elt, syntax) => {
|
||||
assert.equal(elt, "compose-textarea");
|
||||
assert.equal(syntax, "\ntranslated: [Quoting…]\n");
|
||||
});
|
||||
set_compose_content_with_caret("1st line\n%\n2nd line");
|
||||
compose_actions.quote_and_reply();
|
||||
|
||||
quote_text = "Testing with caret on a new line between 2 lines of text.";
|
||||
override_with_quote_text(quote_text);
|
||||
success_function({
|
||||
raw_content: quote_text,
|
||||
});
|
||||
|
||||
reset_test_state();
|
||||
|
||||
// When there are many (>=2) newlines before and after the caret,
|
||||
// no newline is added before or after the quoted message.
|
||||
override(text_field_edit, "insert", (elt, syntax) => {
|
||||
assert.equal(elt, "compose-textarea");
|
||||
assert.equal(syntax, "translated: [Quoting…]");
|
||||
});
|
||||
set_compose_content_with_caret("lots of\n\n\n\n%\n\n\nnewlines");
|
||||
compose_actions.quote_and_reply();
|
||||
|
||||
quote_text = "Testing with caret on a new line between many empty newlines.";
|
||||
override_with_quote_text(quote_text);
|
||||
success_function({
|
||||
raw_content: quote_text,
|
||||
});
|
||||
});
|
||||
|
||||
run_test("set_compose_box_top", () => {
|
||||
|
||||
Reference in New Issue
Block a user