fix: small QoL: return to the last selected menu location (#1629)

## Summary

* **What is the goal of this PR?** Small UX improvement to the Home
screen by preserving the last selected cursor position when returning to
it.

It supersedes #985 and #1103, which are both significantly outdated and
hundreds of commits behind master.

---

### AI Usage

Did you use AI tools to help write this code? _**< YES >**_
This commit is contained in:
Uri Tauber
2026-05-19 08:41:39 -05:00
committed by GitHub
parent dac7fef49d
commit 08461c08e7
7 changed files with 77 additions and 29 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ void Activity::requestUpdate(bool immediate) { activityManager.requestUpdate(imm
void Activity::requestUpdateAndWait() { activityManager.requestUpdateAndWait(); } void Activity::requestUpdateAndWait() { activityManager.requestUpdateAndWait(); }
void Activity::onGoHome() { activityManager.goHome(); } void Activity::onGoHome(HomeMenuItem item) { activityManager.goHome(item); }
void Activity::onSelectBook(const std::string& path) { activityManager.goToReader(path); } void Activity::onSelectBook(const std::string& path) { activityManager.goToReader(path); }
+1 -1
View File
@@ -58,6 +58,6 @@ class Activity {
// Convenience method to facilitate API transition to ActivityManager // Convenience method to facilitate API transition to ActivityManager
// TODO: remove this in near future // TODO: remove this in near future
void onGoHome(); void onGoHome(HomeMenuItem item = HomeMenuItem::NONE);
void onSelectBook(const std::string& path); void onSelectBook(const std::string& path);
}; };
+17 -2
View File
@@ -207,10 +207,25 @@ void ActivityManager::goToFullScreenMessage(std::string message, EpdFontFamily::
replaceActivity(std::make_unique<FullScreenMessageActivity>(renderer, mappedInput, std::move(message), style)); replaceActivity(std::make_unique<FullScreenMessageActivity>(renderer, mappedInput, std::move(message), style));
} }
void ActivityManager::goHome(HomeMenuItem initialMenuItem) {
if (initialMenuItem == HomeMenuItem::NONE && currentActivity) {
const auto& activityName = currentActivity->name;
if (activityName == "FileBrowser") {
initialMenuItem = HomeMenuItem::FILE_BROWSER;
} else if (activityName == "RecentBooks") {
initialMenuItem = HomeMenuItem::RECENTS;
} else if (activityName == "OpdsBookBrowser") {
initialMenuItem = HomeMenuItem::OPDS_BROWSER;
} else if (activityName == "CrossPointWebServer") {
initialMenuItem = HomeMenuItem::FILE_TRANSFER;
} else if (activityName == "Settings") {
initialMenuItem = HomeMenuItem::SETTINGS_MENU;
}
}
replaceActivity(std::make_unique<HomeActivity>(renderer, mappedInput, initialMenuItem));
}
void ActivityManager::goToCrashReport() { replaceActivity(std::make_unique<CrashActivity>(renderer, mappedInput)); } void ActivityManager::goToCrashReport() { replaceActivity(std::make_unique<CrashActivity>(renderer, mappedInput)); }
void ActivityManager::goHome() { replaceActivity(std::make_unique<HomeActivity>(renderer, mappedInput)); }
void ActivityManager::pushActivity(std::unique_ptr<Activity>&& activity) { void ActivityManager::pushActivity(std::unique_ptr<Activity>&& activity) {
if (pendingActivity) { if (pendingActivity) {
// Should never happen in practice // Should never happen in practice
+3 -1
View File
@@ -16,6 +16,8 @@
class Activity; // forward declaration class Activity; // forward declaration
class RenderLock; // forward declaration class RenderLock; // forward declaration
enum class HomeMenuItem { NONE, FILE_BROWSER, RECENTS, OPDS_BROWSER, FILE_TRANSFER, SETTINGS_MENU };
/** /**
* ActivityManager * ActivityManager
* *
@@ -88,7 +90,7 @@ class ActivityManager {
void goToBoot(); void goToBoot();
void goToFullScreenMessage(std::string message, EpdFontFamily::Style style = EpdFontFamily::REGULAR); void goToFullScreenMessage(std::string message, EpdFontFamily::Style style = EpdFontFamily::REGULAR);
void goToCrashReport(); void goToCrashReport();
void goHome(); void goHome(HomeMenuItem initialMenuItem = HomeMenuItem::NONE);
// This will move current activity to stack instead of deleting it // This will move current activity to stack instead of deleting it
void pushActivity(std::unique_ptr<Activity>&& activity); void pushActivity(std::unique_ptr<Activity>&& activity);
+19 -16
View File
@@ -113,11 +113,12 @@ void HomeActivity::onEnter() {
hasOpdsServers = OPDS_STORE.hasServers(); hasOpdsServers = OPDS_STORE.hasServers();
selectorIndex = 0;
const auto& metrics = UITheme::getInstance().getMetrics(); const auto& metrics = UITheme::getInstance().getMetrics();
loadRecentBooks(metrics.homeRecentBooksCount); loadRecentBooks(metrics.homeRecentBooksCount);
const auto base = static_cast<int>(recentBooks.size());
selectorIndex = initialMenuItem == HomeMenuItem::NONE ? 0 : base + menuItemToIndex(initialMenuItem, hasOpdsServers);
// Trigger first update // Trigger first update
requestUpdate(); requestUpdate();
} }
@@ -179,27 +180,29 @@ void HomeActivity::loop() {
}); });
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
// Calculate dynamic indices based on which options are available
int idx = 0;
int menuSelectedIndex = selectorIndex - static_cast<int>(recentBooks.size());
const int fileBrowserIdx = idx++;
const int recentsIdx = idx++;
const int opdsLibraryIdx = hasOpdsServers ? idx++ : -1;
const int fileTransferIdx = idx++;
const int settingsIdx = idx;
if (selectorIndex < recentBooks.size()) { if (selectorIndex < recentBooks.size()) {
onSelectBook(recentBooks[selectorIndex].path); onSelectBook(recentBooks[selectorIndex].path);
} else if (menuSelectedIndex == fileBrowserIdx) { } else {
const int menuIndex = selectorIndex - static_cast<int>(recentBooks.size());
switch (indexToMenuItem(menuIndex, hasOpdsServers)) {
case HomeMenuItem::FILE_BROWSER:
onFileBrowserOpen(); onFileBrowserOpen();
} else if (menuSelectedIndex == recentsIdx) { break;
case HomeMenuItem::RECENTS:
onRecentsOpen(); onRecentsOpen();
} else if (menuSelectedIndex == opdsLibraryIdx) { break;
case HomeMenuItem::OPDS_BROWSER:
onOpdsBrowserOpen(); onOpdsBrowserOpen();
} else if (menuSelectedIndex == fileTransferIdx) { break;
case HomeMenuItem::FILE_TRANSFER:
onFileTransferOpen(); onFileTransferOpen();
} else if (menuSelectedIndex == settingsIdx) { break;
case HomeMenuItem::SETTINGS_MENU:
onSettingsOpen(); onSettingsOpen();
break;
default:
break;
}
} }
} }
} }
+30 -2
View File
@@ -28,6 +28,33 @@ class HomeActivity final : public Activity {
int coverRectW = 0; int coverRectW = 0;
int coverRectH = 0; int coverRectH = 0;
std::vector<RecentBook> recentBooks; std::vector<RecentBook> recentBooks;
const HomeMenuItem initialMenuItem;
// Convert HomeMenuItem to menu index (used in onEnter)
static int menuItemToIndex(HomeMenuItem item, bool hasOpdsUrl) {
int i = 0;
if (item == HomeMenuItem::FILE_BROWSER) return i;
++i;
if (item == HomeMenuItem::RECENTS) return i;
++i;
if (item == HomeMenuItem::OPDS_BROWSER) return hasOpdsUrl ? i : 0;
if (hasOpdsUrl) ++i;
if (item == HomeMenuItem::FILE_TRANSFER) return i;
++i;
if (item == HomeMenuItem::SETTINGS_MENU) return i;
return 0;
}
// Convert menu index to HomeMenuItem (used in loop)
static HomeMenuItem indexToMenuItem(int idx, bool hasOpdsUrl) {
int i = 0;
if (idx == i++) return HomeMenuItem::FILE_BROWSER;
if (idx == i++) return HomeMenuItem::RECENTS;
if (hasOpdsUrl && idx == i++) return HomeMenuItem::OPDS_BROWSER;
if (idx == i++) return HomeMenuItem::FILE_TRANSFER;
if (idx == i) return HomeMenuItem::SETTINGS_MENU;
return HomeMenuItem::NONE;
}
void onSelectBook(const std::string& path); void onSelectBook(const std::string& path);
void onFileBrowserOpen(); void onFileBrowserOpen();
void onRecentsOpen(); void onRecentsOpen();
@@ -43,8 +70,9 @@ class HomeActivity final : public Activity {
void loadRecentCovers(int coverHeight); void loadRecentCovers(int coverHeight);
public: public:
explicit HomeActivity(GfxRenderer& renderer, MappedInputManager& mappedInput) explicit HomeActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
: Activity("Home", renderer, mappedInput) {} HomeMenuItem initialMenuItemValue = HomeMenuItem::NONE)
: Activity("Home", renderer, mappedInput), initialMenuItem(initialMenuItemValue) {}
void onEnter() override; void onEnter() override;
void onExit() override; void onExit() override;
void loop() override; void loop() override;
@@ -34,7 +34,7 @@ void OpdsServerListActivity::onExit() { Activity::onExit(); }
void OpdsServerListActivity::loop() { void OpdsServerListActivity::loop() {
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) { if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
if (pickerMode) { if (pickerMode) {
activityManager.goHome(); activityManager.goHome(HomeMenuItem::OPDS_BROWSER);
} else { } else {
finish(); finish();
} }