From b64ef21831afaa01a8d0000847fd56a07e7d62a7 Mon Sep 17 00:00:00 2001 From: Codex Date: Mon, 6 Jul 2026 07:14:01 +0000 Subject: [PATCH] Add Tailscale API probe action --- README.md | 2 + .../neatstudio/tmuxandroid/MainActivity.java | 72 ++++++++++++++----- 2 files changed, 55 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 2575466..b9ce7b7 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ APIs directly: - server URL management for Tailscale `100.x.y.z:3000` APIs - quick server selectors for `100.89.0.2`, `100.89.0.4`, `100.89.0.9`, `100.89.0.11`, and `100.89.0.116` +- one-tap probe for the preset Tailscale APIs, showing health/version and + session counts - native tmux session list - create, rename, send command, split pane, select pane, kill pane, pin, mute, and kill session through HTTP API diff --git a/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java b/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java index 777334b..7223a63 100644 --- a/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java +++ b/app/src/main/java/com/neatstudio/tmuxandroid/MainActivity.java @@ -447,6 +447,7 @@ public final class MainActivity extends Activity { private void showMainActions() { String[] items = { "Health", + "Probe Tailscale APIs", "Server status", "Timeline", "Preferences", @@ -476,63 +477,66 @@ public final class MainActivity extends Activity { showRaw("Health", () -> api.health()); break; case 1: - showRaw("Server status", () -> api.serverStatus()); + probeServerProfiles(); break; case 2: - showRaw("Timeline", () -> api.timeline(50)); + showRaw("Server status", () -> api.serverStatus()); break; case 3: - showRaw("Preferences", () -> api.preferences()); + showRaw("Timeline", () -> api.timeline(50)); break; case 4: - showRaw("All session details", () -> api.sessionsAll()); + showRaw("Preferences", () -> api.preferences()); break; case 5: - showRaw("Pane details", () -> api.sessionsPanes()); + showRaw("All session details", () -> api.sessionsAll()); break; case 6: - showRaw("Kanban projects", () -> api.kanbanProjects()); + showRaw("Pane details", () -> api.sessionsPanes()); break; case 7: - promptCreateKanbanProject(); + showRaw("Kanban projects", () -> api.kanbanProjects()); break; case 8: - promptDeleteKanbanProject(); + promptCreateKanbanProject(); break; case 9: - promptRemoveKanbanSession(); + promptDeleteKanbanProject(); break; case 10: - promptGroupMessages(); + promptRemoveKanbanSession(); break; case 11: - promptSendGroupMessage(); + promptGroupMessages(); break; case 12: - promptScanGroupMessage(); + promptSendGroupMessage(); break; case 13: - promptPostHookEvent(); + promptScanGroupMessage(); break; case 14: - promptUploadImageFile(); + promptPostHookEvent(); break; case 15: - promptUploadImageUrl(); + promptUploadImageFile(); break; case 16: - promptImagePreviewInfo(); + promptUploadImageUrl(); break; case 17: - promptOpenImagePreview(); + promptImagePreviewInfo(); break; case 18: - openExternalUrl(BuildConfig.DEFAULT_APK_URL); + promptOpenImagePreview(); break; case 19: - showUpdateSourcePicker(); + openExternalUrl(BuildConfig.DEFAULT_APK_URL); break; case 20: + showUpdateSourcePicker(); + break; + case 21: showPermissionsAndUpdateStatus(); break; default: @@ -1020,6 +1024,36 @@ public final class MainActivity extends Activity { showMessage("Update source: " + url); } + private void probeServerProfiles() { + progressBar.setVisibility(View.VISIBLE); + setStatus("Probing Tailscale APIs..."); + executor.execute(() -> { + StringBuilder text = new StringBuilder(); + for (String url : SERVER_PROFILES) { + text.append(url).append('\n'); + try { + SessionApiClient client = new SessionApiClient(url); + JSONObject health = new JSONObject(client.health()); + List sessions = client.getSessions(); + text.append(" ok: true\n"); + text.append(" version: ") + .append(health.optString("version", "unknown")) + .append(" ") + .append(health.optString("commit", "")) + .append('\n'); + text.append(" sessions: ").append(sessions.size()).append('\n'); + } catch (Exception error) { + text.append(" failed: ").append(error.getMessage()).append('\n'); + } + text.append('\n'); + } + runOnUiThread(() -> { + progressBar.setVisibility(View.GONE); + showTextDialog("Tailscale APIs", text.toString()); + }); + }); + } + private void openInstallPermissionSettings() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { showMessage("Install permission is allowed on this Android version");