compose: Add button to save draft and start a new message.

This commit is contained in:
evykassirer 2024-01-19 14:12:26 -08:00 committed by Tim Abbott
parent fd4246def5
commit 3ef4e80dff
6 changed files with 50 additions and 2 deletions

View File

@ -305,6 +305,7 @@ export function start(raw_opts: ComposeActionsStartOpts): void {
// If we're not explicitly opening a different draft, restore the last // If we're not explicitly opening a different draft, restore the last
// saved draft (if it exists). // saved draft (if it exists).
if ( if (
compose_state.can_restore_drafts() &&
!opts.content && !opts.content &&
opts.draft_id === undefined && opts.draft_id === undefined &&
compose_state.message_content().length === 0 compose_state.message_content().length === 0

View File

@ -190,6 +190,11 @@ export function has_message_content(): boolean {
return message_content() !== ""; return message_content() !== "";
} }
export const MINIMUM_MESSAGE_LENGTH_TO_SAVE_DRAFT = 2;
export function has_savable_message_content(): boolean {
return message_content().length > MINIMUM_MESSAGE_LENGTH_TO_SAVE_DRAFT;
}
export function has_full_recipient(): boolean { export function has_full_recipient(): boolean {
if (message_type === "stream") { if (message_type === "stream") {
return stream_id() !== undefined && topic() !== ""; return stream_id() !== undefined && topic() !== "";
@ -208,3 +213,16 @@ export function update_email(user_id: number, new_email: string): void {
private_message_recipient(reply_to); private_message_recipient(reply_to);
} }
let _can_restore_drafts = true;
export function prevent_draft_restoring(): void {
_can_restore_drafts = false;
}
export function allow_draft_restoring(): void {
_can_restore_drafts = true;
}
export function can_restore_drafts(): boolean {
return _can_restore_drafts;
}

View File

@ -281,7 +281,10 @@ export function rename_stream_recipient(
} }
export function snapshot_message(): LocalStorageDraft | undefined { export function snapshot_message(): LocalStorageDraft | undefined {
if (!compose_state.composing() || compose_state.message_content().length <= 2) { if (
!compose_state.composing() ||
compose_state.message_content().length <= compose_state.MINIMUM_MESSAGE_LENGTH_TO_SAVE_DRAFT
) {
// If you aren't in the middle of composing the body of a // If you aren't in the middle of composing the body of a
// message or the message is shorter than 2 characters long, don't try to snapshot. // message or the message is shorter than 2 characters long, don't try to snapshot.
return undefined; return undefined;

View File

@ -68,6 +68,8 @@ export function reset_ui_state() {
message_feed_top_notices.hide_top_of_narrow_notices(); message_feed_top_notices.hide_top_of_narrow_notices();
message_feed_loading.hide_indicators(); message_feed_loading.hide_indicators();
unread_ui.reset_unread_banner(); unread_ui.reset_unread_banner();
// We sometimes prevent draft restoring until the narrow resets.
compose_state.allow_draft_restoring();
} }
export function changehash(newhash) { export function changehash(newhash) {

View File

@ -9,6 +9,7 @@ import * as blueslip from "./blueslip";
import * as channel from "./channel"; import * as channel from "./channel";
import * as common from "./common"; import * as common from "./common";
import * as compose from "./compose"; import * as compose from "./compose";
import * as compose_state from "./compose_state";
import * as compose_validate from "./compose_validate"; import * as compose_validate from "./compose_validate";
import * as drafts from "./drafts"; import * as drafts from "./drafts";
import * as flatpickr from "./flatpickr"; import * as flatpickr from "./flatpickr";
@ -151,11 +152,15 @@ export function initialize() {
onShow(instance) { onShow(instance) {
const formatted_send_later_time = const formatted_send_later_time =
scheduled_messages.get_formatted_selected_send_later_time(); scheduled_messages.get_formatted_selected_send_later_time();
// If there's existing text in the composebox, show an option
// to keep/save the current draft and start a new message.
const show_compose_new_message = compose_state.has_savable_message_content();
instance.setContent( instance.setContent(
parse_html( parse_html(
render_send_later_popover({ render_send_later_popover({
enter_sends_true: user_settings.enter_sends, enter_sends_true: user_settings.enter_sends,
formatted_send_later_time, formatted_send_later_time,
show_compose_new_message,
}), }),
), ),
); );
@ -203,6 +208,19 @@ export function initialize() {
open_send_later_menu(); open_send_later_menu();
popover_menus.hide_current_popover_if_visible(instance); popover_menus.hide_current_popover_if_visible(instance);
}); });
$popper.one("click", ".compose_new_message", () => {
drafts.update_draft();
// If they want to compose a new message instead
// of seeing the draft, remember this and don't
// restore drafts in this narrow until the user
// switches narrows. This allows a user to send
// a bunch of messages in a conversation without
// clicking the "start a new draft" button every
// time.
compose_state.prevent_draft_restoring();
compose.clear_compose_box();
popover_menus.hide_current_popover_if_visible(instance);
});
}, },
onHidden(instance) { onHidden(instance) {
instance.destroy(); instance.destroy();

View File

@ -51,6 +51,12 @@
</li> </li>
<hr class="drafts-item-in-popover" /> <hr class="drafts-item-in-popover" />
<li class="drafts-item-in-popover"> <li class="drafts-item-in-popover">
<a href="#drafts">{{t "Drafts"}} <span class="compose-drafts-count-container">(<span class="compose-drafts-count"></span>)</span></a> <a href="#drafts">{{t "Drafts" }} <span class="compose-drafts-count-container">(<span class="compose-drafts-count"></span>)</span></a>
</li> </li>
{{#if show_compose_new_message}}
<hr />
<li>
<a class="compose_new_message" tabindex=="0">{{t "Save draft and start a new message" }}</a>
</li>
{{/if}}
</ul> </ul>