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` - open one live terminal viewer through `/ws/terminal`
- native `/ws/events` listener for session invalidation and hook notifications - native `/ws/events` listener for session invalidation and hook notifications
- selectable GitHub or Gitea update manifest source - 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 kanban projects, group messages, hook events, image file/URL upload, image
preview info, and native image preview display preview info, and native image preview display
- mobile soft-key row for tmux-oriented input, including tmux prefix, detach, - 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 - 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 the app after allowing it; the app continues installing the already downloaded
APK without another update check or download. 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. browser.
- Open the `Update` page or `More` -> `Permissions / update status` to see the - Open the `Update` page and tap `Details` to see the installed version,
installed version, selected update source, APK URL, install permission state, selected update source, APK URL, install permission state, and a `Check
and a `Check update` button. update` button.
- Open the `About` page to see the app version, package name, API/protocol - Open the `About` page to see the app version, package name, API/protocol
summary, and update policy. summary, and update policy.

View File

@ -228,7 +228,8 @@ public final class MainActivity extends Activity {
content.addView(actionPanel( content.addView(actionPanel(
actionButton("Health", view -> showRaw("Health", () -> api.health())), actionButton("Health", view -> showRaw("Health", () -> api.health())),
actionButton("Probe Tailscale", view -> probeServerProfiles()), 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(sectionTitle("Sessions"));
content.addView(actionPanel( content.addView(actionPanel(
@ -240,9 +241,11 @@ public final class MainActivity extends Activity {
content.addView(actionPanel( content.addView(actionPanel(
actionButton("Projects", view -> showRaw("Kanban projects", () -> api.kanbanProjects())), actionButton("Projects", view -> showRaw("Kanban projects", () -> api.kanbanProjects())),
actionButton("New project", view -> promptCreateKanbanProject()), actionButton("New project", view -> promptCreateKanbanProject()),
actionButton("Messages", view -> promptGroupMessages()) actionButton("Delete project", view -> promptDeleteKanbanProject()),
actionButton("Remove session", view -> promptRemoveKanbanSession())
)); ));
content.addView(actionPanel( content.addView(actionPanel(
actionButton("Messages", view -> promptGroupMessages()),
actionButton("Send message", view -> promptSendGroupMessage()), actionButton("Send message", view -> promptSendGroupMessage()),
actionButton("Scan message", view -> promptScanGroupMessage()), actionButton("Scan message", view -> promptScanGroupMessage()),
actionButton("Post hook", view -> promptPostHookEvent()) actionButton("Post hook", view -> promptPostHookEvent())
@ -251,6 +254,7 @@ public final class MainActivity extends Activity {
content.addView(actionPanel( content.addView(actionPanel(
actionButton("Upload file", view -> promptUploadImageFile()), actionButton("Upload file", view -> promptUploadImageFile()),
actionButton("Upload URL", view -> promptUploadImageUrl()), actionButton("Upload URL", view -> promptUploadImageUrl()),
actionButton("Preview info", view -> promptImagePreviewInfo()),
actionButton("Preview", view -> promptOpenImagePreview()) actionButton("Preview", view -> promptOpenImagePreview())
)); ));
scroll.addView(content); scroll.addView(content);
@ -398,16 +402,38 @@ public final class MainActivity extends Activity {
actionRow.setOrientation(LinearLayout.HORIZONTAL); actionRow.setOrientation(LinearLayout.HORIZONTAL);
actionRow.setGravity(Gravity.CENTER_VERTICAL); actionRow.setGravity(Gravity.CENTER_VERTICAL);
actionRow.setPadding(0, dp(6), 0, 0); actionRow.setPadding(0, dp(6), 0, 0);
actionRow.addView(toolbarButton("New", view -> promptCreateSession())); addContextActions(actionRow);
actionRow.addView(toolbarButton("Refresh", view -> refreshSessions()));
actionRow.addView(toolbarButton("Update", view -> updateManager.check(true)));
actionRow.addView(toolbarButton("More", view -> showMainActions()));
toolbar.addView(urlRow, matchWrap()); toolbar.addView(urlRow, matchWrap());
toolbar.addView(actionRow, matchWrap()); if (actionRow.getChildCount() > 0) {
toolbar.addView(actionRow, matchWrap());
}
return toolbar; 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() { private HorizontalScrollView createServerProfileBar() {
HorizontalScrollView scroller = new HorizontalScrollView(this); HorizontalScrollView scroller = new HorizontalScrollView(this);
scroller.setHorizontalScrollBarEnabled(false); scroller.setHorizontalScrollBarEnabled(false);
@ -750,112 +776,6 @@ public final class MainActivity extends Activity {
return bar; 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) { private void showSessionActions(String sessionName) {
String[] items = { String[] items = {
"Status", "Status",

View File

@ -79,7 +79,7 @@ Implemented now:
- bottom shortcut bar for `Esc`, `Tab`, `Ctrl+C`, `Ctrl+V`, arrows, page keys, - bottom shortcut bar for `Esc`, `Tab`, `Ctrl+C`, `Ctrl+V`, arrows, page keys,
tmux prefix actions, and paste tmux prefix actions, and paste
- shortcut delivery through the terminal WebSocket `input` message - 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 projects, group messages, hook events, image file/URL upload, image preview
metadata, and native image preview display metadata, and native image preview display
- GitHub Actions APK build - GitHub Actions APK build