Support save prompt on back arrow (#1270)

* Support save prompt on back arrow
* Add lifetime warning comment
This commit is contained in:
Kyle Reed 2023-07-13 09:38:40 -07:00 committed by GitHub
parent e1a79a0ff1
commit 4985d836ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 34 deletions

View file

@ -301,6 +301,38 @@ void TextEditorMenu::hide_children(bool hidden) {
/* TextEditorView ***************************************************/ /* 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<void()> on_save,
std::function<void()> 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) TextEditorView::TextEditorView(NavigationView& nav)
: nav_{nav} { : nav_{nav} {
add_children( add_children(
@ -381,9 +413,7 @@ TextEditorView::TextEditorView(NavigationView& nav)
}; };
menu.on_exit() = [this]() { menu.on_exit() = [this]() {
show_save_prompt([this]() {
nav_.pop(); nav_.pop();
});
}; };
button_menu.on_select = [this]() { button_menu.on_select = [this]() {
@ -402,7 +432,15 @@ TextEditorView::TextEditorView(NavigationView& nav, const fs::path& path)
} }
TextEditorView::~TextEditorView() { 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() { void TextEditorView::on_show() {
@ -415,7 +453,7 @@ void TextEditorView::on_show() {
void TextEditorView::open_file(const fs::path& path) { void TextEditorView::open_file(const fs::path& path) {
file_.reset(); file_.reset();
viewer.clear_file(); viewer.clear_file();
delete_temp_file(); delete_temp_file(path_);
path_ = {}; path_ = {};
file_dirty_ = false; file_dirty_ = false;
@ -516,13 +554,10 @@ void TextEditorView::show_save_prompt(std::function<void()> continuation) {
return; return;
} }
nav_.display_modal( ui::show_save_prompt(
"Save?", "Save changes?", YESNO, nav_,
[this](bool choice) { [this]() { save_temp_file(); },
if (choice) continuation);
save_temp_file();
});
nav_.set_on_pop(continuation);
} }
void TextEditorView::prepare_for_write() { void TextEditorView::prepare_for_write() {
@ -533,31 +568,16 @@ void TextEditorView::prepare_for_write() {
// Copy to temp file on write. // Copy to temp file on write.
has_temp_file_ = true; has_temp_file_ = true;
delete_temp_file(); delete_temp_file(path_);
copy_file(path_, get_temp_path()); copy_file(path_, get_temp_path(path_));
file_->assume_file(get_temp_path()); file_->assume_file(get_temp_path(path_));
}
void TextEditorView::delete_temp_file() const {
auto temp_path = get_temp_path();
if (!temp_path.empty()) {
delete_file(temp_path);
}
} }
void TextEditorView::save_temp_file() { void TextEditorView::save_temp_file() {
if (file_dirty_) { if (file_dirty_) {
delete_file(path_); ui::save_temp_file(path_);
copy_file(get_temp_path(), path_);
file_dirty_ = false; file_dirty_ = false;
} }
} }
fs::path TextEditorView::get_temp_path() const {
if (!path_.empty())
return path_ + "~";
return {};
}
} // namespace ui } // namespace ui

View file

@ -229,10 +229,7 @@ class TextEditorView : public View {
void show_save_prompt(std::function<void()> continuation); void show_save_prompt(std::function<void()> continuation);
void prepare_for_write(); void prepare_for_write();
void create_temp_file() const;
void delete_temp_file() const;
void save_temp_file(); void save_temp_file();
std::filesystem::path get_temp_path() const;
NavigationView& nav_; NavigationView& nav_;
std::unique_ptr<FileWrapper> file_{}; std::unique_ptr<FileWrapper> file_{};