Make main toolbar page contextual
Some checks failed
Gitea Smoke / smoke (push) Successful in 0s
Gitea Android APK / build (push) Has been cancelled

This commit is contained in:
Codex 2026-07-06 12:50:09 +00:00
parent 147cec7c6b
commit 79fd148511
3 changed files with 39 additions and 119 deletions

View File

@ -17,7 +17,7 @@ APIs directly:
- open one live terminal viewer through `/ws/terminal`
- native `/ws/events` listener for session invalidation and hook notifications
- selectable GitHub or Gitea update manifest source
- native API action center for health, server status, timeline, preferences,
- native Tools page for health, server status, timeline, preferences,
kanban projects, group messages, hook events, image file/URL upload, image
preview info, and native image preview display
- mobile soft-key row for tmux-oriented input, including tmux prefix, detach,
@ -177,10 +177,10 @@ In the app:
- If Android sends you to the unknown-app install permission screen, return to
the app after allowing it; the app continues installing the already downloaded
APK without another update check or download.
- Open `More` -> `Open APK download` to download the current public APK in a
- Open the `Update` page and tap `APK` to download the current public APK in a
browser.
- Open the `Update` page or `More` -> `Permissions / update status` to see the
installed version, selected update source, APK URL, install permission state,
and a `Check update` button.
- Open the `Update` page and tap `Details` to see the installed version,
selected update source, APK URL, install permission state, and a `Check
update` button.
- Open the `About` page to see the app version, package name, API/protocol
summary, and update policy.

View File

@ -228,7 +228,8 @@ public final class MainActivity extends Activity {
content.addView(actionPanel(
actionButton("Health", view -> showRaw("Health", () -> api.health())),
actionButton("Probe Tailscale", view -> probeServerProfiles()),
actionButton("Status", view -> showRaw("Server status", () -> api.serverStatus()))
actionButton("Status", view -> showRaw("Server status", () -> api.serverStatus())),
actionButton("Preferences", view -> showRaw("Preferences", () -> api.preferences()))
));
content.addView(sectionTitle("Sessions"));
content.addView(actionPanel(
@ -240,9 +241,11 @@ public final class MainActivity extends Activity {
content.addView(actionPanel(
actionButton("Projects", view -> showRaw("Kanban projects", () -> api.kanbanProjects())),
actionButton("New project", view -> promptCreateKanbanProject()),
actionButton("Messages", view -> promptGroupMessages())
actionButton("Delete project", view -> promptDeleteKanbanProject()),
actionButton("Remove session", view -> promptRemoveKanbanSession())
));
content.addView(actionPanel(
actionButton("Messages", view -> promptGroupMessages()),
actionButton("Send message", view -> promptSendGroupMessage()),
actionButton("Scan message", view -> promptScanGroupMessage()),
actionButton("Post hook", view -> promptPostHookEvent())
@ -251,6 +254,7 @@ public final class MainActivity extends Activity {
content.addView(actionPanel(
actionButton("Upload file", view -> promptUploadImageFile()),
actionButton("Upload URL", view -> promptUploadImageUrl()),
actionButton("Preview info", view -> promptImagePreviewInfo()),
actionButton("Preview", view -> promptOpenImagePreview())
));
scroll.addView(content);
@ -398,16 +402,38 @@ public final class MainActivity extends Activity {
actionRow.setOrientation(LinearLayout.HORIZONTAL);
actionRow.setGravity(Gravity.CENTER_VERTICAL);
actionRow.setPadding(0, dp(6), 0, 0);
actionRow.addView(toolbarButton("New", view -> promptCreateSession()));
actionRow.addView(toolbarButton("Refresh", view -> refreshSessions()));
actionRow.addView(toolbarButton("Update", view -> updateManager.check(true)));
actionRow.addView(toolbarButton("More", view -> showMainActions()));
addContextActions(actionRow);
toolbar.addView(urlRow, matchWrap());
toolbar.addView(actionRow, matchWrap());
if (actionRow.getChildCount() > 0) {
toolbar.addView(actionRow, matchWrap());
}
return toolbar;
}
private void addContextActions(LinearLayout actionRow) {
if (PAGE_SESSIONS.equals(activeMainPage)) {
actionRow.addView(toolbarButton("New", view -> promptCreateSession()));
actionRow.addView(toolbarButton("Refresh", view -> refreshSessions()));
actionRow.addView(toolbarButton("Probe", view -> probeServerProfiles()));
return;
}
if (PAGE_TOOLS.equals(activeMainPage)) {
actionRow.addView(toolbarButton("Health", view -> showRaw("Health", () -> api.health())));
actionRow.addView(toolbarButton("Probe", view -> probeServerProfiles()));
return;
}
if (PAGE_UPDATE.equals(activeMainPage)) {
actionRow.addView(toolbarButton("Check now", view -> updateManager.check(true)));
actionRow.addView(toolbarButton("Source", view -> showUpdateSourcePicker()));
return;
}
if (PAGE_ABOUT.equals(activeMainPage)) {
actionRow.addView(toolbarButton("Release", view -> openExternalUrl(BuildConfig.DEFAULT_RELEASE_PAGE_URL)));
actionRow.addView(toolbarButton("Permissions", view -> showPermissionsAndUpdateStatus()));
}
}
private HorizontalScrollView createServerProfileBar() {
HorizontalScrollView scroller = new HorizontalScrollView(this);
scroller.setHorizontalScrollBarEnabled(false);
@ -750,112 +776,6 @@ public final class MainActivity extends Activity {
return bar;
}
private void showMainActions() {
String[] items = {
"Health",
"Probe Tailscale APIs",
"Server status",
"Timeline",
"Preferences",
"All session details",
"Pane details",
"Kanban projects",
"Create kanban project",
"Delete kanban project",
"Remove kanban session",
"Group messages",
"Send group message",
"Scan group message",
"Post hook event",
"Upload image file",
"Upload image URL",
"Image preview info",
"Open image preview",
"Open APK download",
"Update source",
"Permissions / update status",
"About"
};
new AlertDialog.Builder(this)
.setTitle("Native API actions")
.setItems(items, (dialog, which) -> {
switch (which) {
case 0:
showRaw("Health", () -> api.health());
break;
case 1:
probeServerProfiles();
break;
case 2:
showRaw("Server status", () -> api.serverStatus());
break;
case 3:
showRaw("Timeline", () -> api.timeline(50));
break;
case 4:
showRaw("Preferences", () -> api.preferences());
break;
case 5:
showRaw("All session details", () -> api.sessionsAll());
break;
case 6:
showRaw("Pane details", () -> api.sessionsPanes());
break;
case 7:
showRaw("Kanban projects", () -> api.kanbanProjects());
break;
case 8:
promptCreateKanbanProject();
break;
case 9:
promptDeleteKanbanProject();
break;
case 10:
promptRemoveKanbanSession();
break;
case 11:
promptGroupMessages();
break;
case 12:
promptSendGroupMessage();
break;
case 13:
promptScanGroupMessage();
break;
case 14:
promptPostHookEvent();
break;
case 15:
promptUploadImageFile();
break;
case 16:
promptUploadImageUrl();
break;
case 17:
promptImagePreviewInfo();
break;
case 18:
promptOpenImagePreview();
break;
case 19:
openExternalUrl(BuildConfig.DEFAULT_APK_URL);
break;
case 20:
showUpdateSourcePicker();
break;
case 21:
showPermissionsAndUpdateStatus();
break;
case 22:
renderAboutScreen();
break;
default:
break;
}
})
.show();
}
private void showSessionActions(String sessionName) {
String[] items = {
"Status",

View File

@ -79,7 +79,7 @@ Implemented now:
- bottom shortcut bar for `Esc`, `Tab`, `Ctrl+C`, `Ctrl+V`, arrows, page keys,
tmux prefix actions, and paste
- shortcut delivery through the terminal WebSocket `input` message
- native action center for health, server status, timeline, preferences, kanban
- native Tools page for health, server status, timeline, preferences, kanban
projects, group messages, hook events, image file/URL upload, image preview
metadata, and native image preview display
- GitHub Actions APK build