Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 123 additions & 1 deletion lib/microreader/screens/MainMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,141 @@ void MainMenu::update(const ButtonState& buttons, DrawBuffer& buf, IRuntime& run
buf.full_refresh();
}

// === DELETE CONFIRMATION MODE ===
if (delete_pending_) {
Button btn;
while (buttons.next_press(btn)) {
if (btn == Button::Button1) {
do_delete_(buf, runtime);
return;
}
if (btn == Button::Button0) {
cancel_delete_(buf, runtime);
return;
}
}
draw_all_(buf, runtime.battery_percentage());
buf.refresh();
return;
}

// === NORMAL MODE ===

// Track Button1 hold duration (time-based for frame-rate independence)
if (buttons.is_down(Button::Button1))
button1_hold_ms_ += runtime.frame_time_ms();
else
button1_hold_ms_ = 0;

// Let parent handle up/down/back navigation.
// on_select() stores the index but no longer opens the book immediately.
ListMenuScreen::update(buttons, buf, runtime);

// Handle pending selection (set by on_select above)
if (pending_select_idx_ >= 0) {
// Button released → short press → open the book
if (!buttons.is_down(Button::Button1)) {
pending_select_idx_ = -1;
app_->push_screen(ScreenId::Reader);
return;
}
// Long press threshold reached → enter delete confirmation
if (button1_hold_ms_ >= kLongPressMs) {
const int idx = pending_select_idx_;
pending_select_idx_ = -1;
button1_hold_ms_ = 0;
delete_pending_ = true;
delete_index_ = idx;
delete_book_label_ = entries_[idx].label;
title_ = "Delete?";
set_item_label(idx, "Back=No Sel=Yes");
draw_all_(buf, runtime.battery_percentage());
buf.refresh();
return;
}
// Button still held but not yet long enough — wait another frame
}
}

void MainMenu::on_select(int index) {
// Don't open the book immediately — update() handles short-press vs long-press
last_selected_path_ = entries_[index].path;
app_->reader()->set_path(entries_[index].path.c_str());
app_->push_screen(ScreenId::Reader);
pending_select_idx_ = index;
}

void MainMenu::on_back() {
app_->push_screen(ScreenId::Settings);
}

void MainMenu::do_delete_(DrawBuffer& buf, IRuntime& runtime) {
const std::string& epub_path = entries_[delete_index_].path;
const char* path_cstr = epub_path.c_str();

MR_LOGI("menu", "deleting %s", path_cstr);

// 1. Delete the EPUB file
(void)std::remove(path_cstr);

// 2. Delete the MRB cache directory (<data_dir>/cache/<basename>/)
if (app_ && app_->data_dir_) {
std::string cache_dir = std::string(app_->data_dir_) + "/cache/";
const char* name = path_cstr;
const char* sep = std::strrchr(name, '/');
#ifdef _WIN32
const char* bsep = std::strrchr(name, '\\');
if (bsep && (!sep || bsep > sep))
sep = bsep;
#endif
if (sep)
name = sep + 1;
const char* dot = std::strrchr(name, '.');
if (dot)
cache_dir.append(name, static_cast<size_t>(dot - name));
else
cache_dir.append(name);

#ifdef ESP_PLATFORM
DIR* d = opendir(cache_dir.c_str());
if (d) {
struct dirent* ent;
char fpath[300];
while ((ent = readdir(d)) != nullptr) {
if (ent->d_name[0] == '.')
continue;
std::snprintf(fpath, sizeof(fpath), "%s/%s", cache_dir.c_str(), ent->d_name);
std::remove(fpath);
}
closedir(d);
rmdir(cache_dir.c_str());
}
#else
if (fs::exists(cache_dir))
fs::remove_all(cache_dir);
#endif
}

// Reset state and rescan
button1_hold_ms_ = 0;
delete_pending_ = false;
delete_index_ = -1;
title_ = "Microreader";
scan_directory_(buf);
populate_list_();
draw_all_(buf, runtime.battery_percentage());
buf.full_refresh();
}

void MainMenu::cancel_delete_(DrawBuffer& buf, IRuntime& runtime) {
set_item_label(delete_index_, delete_book_label_);
button1_hold_ms_ = 0;
delete_pending_ = false;
delete_index_ = -1;
title_ = "Microreader";
draw_all_(buf, runtime.battery_percentage());
buf.refresh();
}

void MainMenu::scan_directory_(DrawBuffer& buf) {
if (!books_dir_ || !app_->data_dir_)
return;
Expand Down
16 changes: 16 additions & 0 deletions lib/microreader/screens/MainMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class MainMenu final : public ListMenuScreen {
books_dir_ = dir;
}

// Force the book list to rescan on the next update.
void request_rescan() {
needs_scan_ = true;
}

// Restore the book list selection to the entry matching this path.
// Call before start(); applied after directory scan.
void set_initial_selection(const char* path) {
Expand Down Expand Up @@ -83,6 +88,17 @@ class MainMenu final : public ListMenuScreen {
BookListFormat list_format_ = BookListFormat::TitleOnly;
bool needs_scan_ = false;

// Long-press delete state
int pending_select_idx_ = -1; // index selected via on_select, pending resolution
int delete_index_ = -1; // book to delete when confirmed
bool delete_pending_ = false; // waiting for confirm/cancel on delete prompt
uint32_t button1_hold_ms_ = 0; // accumulated hold time for Button1
std::string delete_book_label_; // original label of book pending deletion
static constexpr uint32_t kLongPressMs = 800;

void do_delete_(DrawBuffer& buf, IRuntime& runtime);
void cancel_delete_(DrawBuffer& buf, IRuntime& runtime);

struct BookEntry {
std::string path;
std::string label;
Expand Down