#pragma once #include #include #include #include "dialog_model.h" #include "key_event.h" #include "note_text.h" #include "services/clock_service.h" #include "services/power_service.h" #include "services/storage_service.h" #include "ui/canvas.h" namespace roro { // Edits one text file of up to 16 KB (F1, Q143-Q145): the Notes App's editor, and the Storage // App's for `e`. It saves by itself: five seconds after the last key, when the screen turns off, // and on close. A save writes `.tmp`, then puts it in the note's place, so the note on the // card is always a whole one. class NoteEditor { public: static constexpr int kCols = 38, kRows = 8; static constexpr uint32_t kSaveAfterMs = 5000; NoteEditor(StorageService& storage, ClockService& clock, PowerService& power) : storage_(storage), clock_(clock), power_(power) {} std::string open(const std::string& path); // "" or why it can't be edited std::string openNew(const std::string& folder); // the same; no file until there's something to save (Q142) void close(); // saves what isn't yet bool isOpen() const { return static_cast(text_); } const std::string& path() const { return path_; } // "" for a new note nothing was typed in bool onKey(const KeyEvent& e); // false: done, and saved bool update(uint32_t nowMs); // true: draw again void draw(Canvas& c); private: enum class Ask { None, Recover, LeaveUnsaved }; bool dirty() const { return text_ && text_->revision() != savedRevision_; } bool save(); // true if the card has it now (or there was nothing to save) void say(const std::string& text); StorageService& storage_; ClockService& clock_; PowerService& power_; std::unique_ptr text_; std::string path_, folder_; uint32_t savedRevision_ = 0, lastKeyMs_ = 0, lastTryMs_ = 0; std::string recovered_; // what a temporary file left behind holds, until the user has chosen Ask ask_ = Ask::None; std::unique_ptr dialog_; std::string message_, problem_; uint32_t messageMs_ = 0; bool redraw_ = false; }; } // namespace roro