mirror of https://github.com/zulip/zulip.git
message_edit: Restore focus to the message being edited.
When user is editing a message and we rerender it, we should always set focus back to the textarea.
This commit is contained in:
parent
753b8e1f6f
commit
b8cec0ff2a
|
@ -205,6 +205,67 @@ function get_users_for_recipient_row(message) {
|
||||||
return users.sort(compare_by_name);
|
return users.sort(compare_by_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let message_id_to_focus_after_processing_message_events = {
|
||||||
|
id: undefined,
|
||||||
|
selectionStart: undefined,
|
||||||
|
selectionEnd: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
function reset_restore_message_edit_focus_state() {
|
||||||
|
message_id_to_focus_after_processing_message_events = {
|
||||||
|
id: undefined,
|
||||||
|
selectionStart: undefined,
|
||||||
|
selectionEnd: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function capture_user_message_editing_state() {
|
||||||
|
if (document.activeElement?.classList.contains("message_edit_content")) {
|
||||||
|
message_id_to_focus_after_processing_message_events = {
|
||||||
|
id: rows.get_message_id(document.activeElement),
|
||||||
|
selectionStart: document.activeElement.selectionStart,
|
||||||
|
selectionEnd: document.activeElement.selectionEnd,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
reset_restore_message_edit_focus_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function maybe_restore_focus_to_message_edit_form() {
|
||||||
|
if (
|
||||||
|
// It is possible that selected message might not be the one
|
||||||
|
// user was editing but is less likely the case. It makes
|
||||||
|
// things complicated to think about with selected message being different
|
||||||
|
// from the message edit form we are trying to restore focus to.
|
||||||
|
// So, we simply only restore focus if the selected message is the
|
||||||
|
// one user was editing.
|
||||||
|
message_lists.current?.data.selected_id() !==
|
||||||
|
message_id_to_focus_after_processing_message_events.id
|
||||||
|
) {
|
||||||
|
// If user has navigated away from the message they were editing,
|
||||||
|
// we don't want to restore focus to the message edit form since
|
||||||
|
// we don't want to capture hotkey inside the message edit form
|
||||||
|
// when they navigate back to the message they were editing.
|
||||||
|
reset_restore_message_edit_focus_state();
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const $message_edit_content = message_lists.current
|
||||||
|
?.selected_row()
|
||||||
|
.find(".message_edit_content");
|
||||||
|
if (!$message_edit_content || $message_edit_content.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$message_edit_content.trigger("focus");
|
||||||
|
$message_edit_content[0].setSelectionRange(
|
||||||
|
message_id_to_focus_after_processing_message_events.selectionStart,
|
||||||
|
message_id_to_focus_after_processing_message_events.selectionEnd,
|
||||||
|
);
|
||||||
|
reset_restore_message_edit_focus_state();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
function populate_group_from_message_container(group, message_container) {
|
function populate_group_from_message_container(group, message_container) {
|
||||||
group.is_stream = message_container.msg.is_stream;
|
group.is_stream = message_container.msg.is_stream;
|
||||||
group.is_private = message_container.msg.is_private;
|
group.is_private = message_container.msg.is_private;
|
||||||
|
@ -827,6 +888,8 @@ export class MessageListView {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
capture_user_message_editing_state();
|
||||||
|
|
||||||
const list = this.list; // for convenience
|
const list = this.list; // for convenience
|
||||||
let orig_scrolltop_offset;
|
let orig_scrolltop_offset;
|
||||||
|
|
||||||
|
@ -982,6 +1045,7 @@ export class MessageListView {
|
||||||
|
|
||||||
// After all the messages are rendered, resize any message edit textarea if required.
|
// After all the messages are rendered, resize any message edit textarea if required.
|
||||||
autosize.update(this.$list.find(".message_edit_content"));
|
autosize.update(this.$list.find(".message_edit_content"));
|
||||||
|
maybe_restore_focus_to_message_edit_form();
|
||||||
|
|
||||||
restore_scroll_position();
|
restore_scroll_position();
|
||||||
|
|
||||||
|
@ -1390,6 +1454,11 @@ export class MessageListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
rerender_messages(messages, message_content_edited) {
|
rerender_messages(messages, message_content_edited) {
|
||||||
|
// this.render is never called in this code path, we use
|
||||||
|
// `_rerender_message` instead which is optimized for this use
|
||||||
|
// case.
|
||||||
|
capture_user_message_editing_state();
|
||||||
|
|
||||||
// We need to destroy all the tippy instances from the DOM before re-rendering to
|
// We need to destroy all the tippy instances from the DOM before re-rendering to
|
||||||
// prevent the appearance of tooltips whose reference has been removed.
|
// prevent the appearance of tooltips whose reference has been removed.
|
||||||
message_list_tooltips.destroy_all_message_list_tooltips();
|
message_list_tooltips.destroy_all_message_list_tooltips();
|
||||||
|
@ -1426,6 +1495,7 @@ export class MessageListView {
|
||||||
|
|
||||||
if (message_lists.current === this.list && narrow_state.is_message_feed_visible()) {
|
if (message_lists.current === this.list && narrow_state.is_message_feed_visible()) {
|
||||||
this.update_sticky_recipient_headers();
|
this.update_sticky_recipient_headers();
|
||||||
|
maybe_restore_focus_to_message_edit_form();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1485,6 +1555,7 @@ export class MessageListView {
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_table() {
|
clear_table() {
|
||||||
|
capture_user_message_editing_state();
|
||||||
// We do not want to call .empty() because that also clears
|
// We do not want to call .empty() because that also clears
|
||||||
// jQuery data. This does mean, however, that we need to be
|
// jQuery data. This does mean, however, that we need to be
|
||||||
// mindful of memory leaks.
|
// mindful of memory leaks.
|
||||||
|
|
Loading…
Reference in New Issue