Add configurable default home screen action

Themes can now specify an initialAction in home screen config to set the default selected action when entering home normally. Falls back to this theme setting when no explicit action is requested, but explicit firmware navigation still takes precedence.
This commit is contained in:
Justin Mitchell
2026-06-28 02:38:53 -04:00
parent 48aa3c8e02
commit 79f5657fb2
4 changed files with 28 additions and 3 deletions
+8
View File
@@ -217,6 +217,14 @@ Home `navigation` modes:
- `splitAxis`: front left/right move through launcher actions; side up/down move through recent-book actions. Bottom button hints show Left/Right. - `splitAxis`: front left/right move through launcher actions; side up/down move through recent-book actions. Bottom button hints show Left/Right.
- `carousel`: front left/right move through recent-book actions; side up/down move through launcher actions. Use this when left/right should stay inside a cover carousel and up/down should enter or leave the launcher menu. - `carousel`: front left/right move through recent-book actions; side up/down move through launcher actions. Use this when left/right should stay inside a cover carousel and up/down should enter or leave the launcher menu.
Home `initialAction` can optionally choose the default selected action when entering home normally:
```json
"initialAction": "reader:recent"
```
Supported values match launcher `action` values. Explicit firmware navigation, such as returning to Settings from a settings submenu, still overrides this default.
### Layouts vs widgets ### Layouts vs widgets
Layouts only create named rectangles. They do not choose whether a screen is a list, cover grid, carousel, or any other presentation. Layouts only create named rectangles. They do not choose whether a screen is a list, cover grid, carousel, or any other presentation.
+13 -3
View File
@@ -145,7 +145,9 @@ void HomeActivity::onEnter() {
metrics.homeRecentBooksCount); metrics.homeRecentBooksCount);
const auto& actions = refreshHomeActions(); const auto& actions = refreshHomeActions();
const ThemeHomeScreenSpec* homeSpec = UITheme::getInstance().getHomeScreenSpec();
selectorIndex = 0; selectorIndex = 0;
bool hasWantedAction = initialMenuItem != HomeMenuItem::NONE;
const auto wantedAction = [this]() { const auto wantedAction = [this]() {
switch (initialMenuItem) { switch (initialMenuItem) {
case HomeMenuItem::RECENTS: case HomeMenuItem::RECENTS:
@@ -162,15 +164,23 @@ void HomeActivity::onEnter() {
return ThemeHomeAction::FileBrowser; return ThemeHomeAction::FileBrowser;
} }
}(); }();
if (initialMenuItem != HomeMenuItem::NONE) { ThemeHomeAction selectedEntryAction = wantedAction;
if (!hasWantedAction && homeSpec != nullptr && homeSpec->hasInitialAction) {
hasWantedAction = true;
selectedEntryAction = homeSpec->initialAction;
}
if (hasWantedAction) {
for (int i = 0; i < static_cast<int>(actions.size()); ++i) { for (int i = 0; i < static_cast<int>(actions.size()); ++i) {
if (actions[i].action == wantedAction) { if (actions[i].action == selectedEntryAction) {
selectorIndex = i; selectorIndex = i;
break; break;
} }
} }
} }
coverSelectorIndex = recentBooks.empty() ? 0 : std::min(selectorIndex, static_cast<int>(recentBooks.size()) - 1); coverSelectorIndex = !recentBooks.empty() && selectorIndex < static_cast<int>(actions.size()) &&
actions[selectorIndex].action == ThemeHomeAction::RecentBook
? actions[selectorIndex].value
: 0;
// Trigger first update // Trigger first update
requestUpdate(); requestUpdate();
@@ -688,6 +688,11 @@ void parseHomeScreenSpec(JsonObjectConst obj, ThemeHomeScreenSpec& out) {
out.enabled = true; out.enabled = true;
out.navigation = parseHomeNavigationMode(obj["navigation"].as<const char*>(), out.navigation); out.navigation = parseHomeNavigationMode(obj["navigation"].as<const char*>(), out.navigation);
const char* initialAction = obj["initialAction"].as<const char*>();
if (initialAction != nullptr) {
out.hasInitialAction = true;
out.initialAction = parseHomeAction(initialAction);
}
out.layout = ThemeLayoutNode{}; out.layout = ThemeLayoutNode{};
out.layout.id = "root"; out.layout.id = "root";
out.layout.sizeType = ThemeLayoutSizeType::Flex; out.layout.sizeType = ThemeLayoutSizeType::Flex;
+2
View File
@@ -120,6 +120,8 @@ struct ThemeHomeWidgetSpec {
struct ThemeHomeScreenSpec { struct ThemeHomeScreenSpec {
bool enabled = false; bool enabled = false;
ThemeHomeNavigationMode navigation = ThemeHomeNavigationMode::Linear; ThemeHomeNavigationMode navigation = ThemeHomeNavigationMode::Linear;
bool hasInitialAction = false;
ThemeHomeAction initialAction = ThemeHomeAction::FileBrowser;
ThemeLayoutNode layout; ThemeLayoutNode layout;
std::vector<ThemeHomeWidgetSpec> widgets; std::vector<ThemeHomeWidgetSpec> widgets;
}; };