From 4985d836ea8ac63db144676bb7cb0546fe589812 Mon Sep 17 00:00:00 2001 From: Kyle Reed <3761006+kallanreed@users.noreply.github.com> Date: Thu, 13 Jul 2023 09:38:40 -0700 Subject: [PATCH] Support save prompt on back arrow (#1270) * Support save prompt on back arrow * Add lifetime warning comment --- firmware/application/apps/ui_text_editor.cpp | 82 ++++++++++++-------- firmware/application/apps/ui_text_editor.hpp | 3 - 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/firmware/application/apps/ui_text_editor.cpp b/firmware/application/apps/ui_text_editor.cpp index 346db1bde..efb9e8e49 100644 --- a/firmware/application/apps/ui_text_editor.cpp +++ b/firmware/application/apps/ui_text_editor.cpp @@ -301,6 +301,38 @@ void TextEditorMenu::hide_children(bool hidden) { /* TextEditorView ***************************************************/ +static fs::path get_temp_path(const fs::path& path) { + if (!path.empty()) + return path + "~"; + + return {}; +} + +static void delete_temp_file(const fs::path& path) { + auto temp_path = get_temp_path(path); + if (!temp_path.empty()) { + delete_file(temp_path); + } +} + +static void save_temp_file(const fs::path& path) { + delete_file(path); + copy_file(get_temp_path(path), path); +} + +static void show_save_prompt( + NavigationView& nav, + std::function on_save, + std::function continuation) { + nav.display_modal( + "Save?", "Save changes?", YESNO, + [on_save](bool choice) { + if (choice && on_save) + on_save(); + }); + nav.set_on_pop(continuation); +} + TextEditorView::TextEditorView(NavigationView& nav) : nav_{nav} { add_children( @@ -381,9 +413,7 @@ TextEditorView::TextEditorView(NavigationView& nav) }; menu.on_exit() = [this]() { - show_save_prompt([this]() { - nav_.pop(); - }); + nav_.pop(); }; button_menu.on_select = [this]() { @@ -402,7 +432,15 @@ TextEditorView::TextEditorView(NavigationView& nav, const fs::path& path) } TextEditorView::~TextEditorView() { - delete_temp_file(); + // NB: Be careful here. The UI will render after this instance + // has been destroyed. Everything needed to render the UI + // and perform the save actions must be value captured. + if (file_dirty_) { + ui::show_save_prompt( + nav_, + [p = path_]() { ui::save_temp_file(p); }, + [p = std::move(path_)]() { delete_temp_file(p); }); + } } void TextEditorView::on_show() { @@ -415,7 +453,7 @@ void TextEditorView::on_show() { void TextEditorView::open_file(const fs::path& path) { file_.reset(); viewer.clear_file(); - delete_temp_file(); + delete_temp_file(path_); path_ = {}; file_dirty_ = false; @@ -516,13 +554,10 @@ void TextEditorView::show_save_prompt(std::function continuation) { return; } - nav_.display_modal( - "Save?", "Save changes?", YESNO, - [this](bool choice) { - if (choice) - save_temp_file(); - }); - nav_.set_on_pop(continuation); + ui::show_save_prompt( + nav_, + [this]() { save_temp_file(); }, + continuation); } void TextEditorView::prepare_for_write() { @@ -533,31 +568,16 @@ void TextEditorView::prepare_for_write() { // Copy to temp file on write. has_temp_file_ = true; - delete_temp_file(); - copy_file(path_, get_temp_path()); - file_->assume_file(get_temp_path()); -} - -void TextEditorView::delete_temp_file() const { - auto temp_path = get_temp_path(); - if (!temp_path.empty()) { - delete_file(temp_path); - } + delete_temp_file(path_); + copy_file(path_, get_temp_path(path_)); + file_->assume_file(get_temp_path(path_)); } void TextEditorView::save_temp_file() { if (file_dirty_) { - delete_file(path_); - copy_file(get_temp_path(), path_); + ui::save_temp_file(path_); file_dirty_ = false; } } -fs::path TextEditorView::get_temp_path() const { - if (!path_.empty()) - return path_ + "~"; - - return {}; -} - } // namespace ui diff --git a/firmware/application/apps/ui_text_editor.hpp b/firmware/application/apps/ui_text_editor.hpp index 296cc24fc..d543f32d9 100644 --- a/firmware/application/apps/ui_text_editor.hpp +++ b/firmware/application/apps/ui_text_editor.hpp @@ -229,10 +229,7 @@ class TextEditorView : public View { void show_save_prompt(std::function continuation); void prepare_for_write(); - void create_temp_file() const; - void delete_temp_file() const; void save_temp_file(); - std::filesystem::path get_temp_path() const; NavigationView& nav_; std::unique_ptr file_{};