feat(aiturk): say when AITURK IDE is closed in the chat banner
Merge Conflict Detector / detect-and-label (push) Successful in 2s
Android CI/CD / Detect Changes (push) Successful in 4s
Android CI/CD / Build Debug APK (push) Failing after 2m50s
Android CI/CD / ktlint — Code Style (push) Failing after 3m9s
CodeQL Analysis / Analyze (java-kotlin) (push) Failing after 3m20s
Android CI/CD / Instrumented Tests (push) Failing after 3m11s
Android CI/CD / Release Compile Check (push) Failing after 1m22s
Android CI/CD / Android Lint — Static Analysis (push) Failing after 2m46s
Android CI/CD / Unit & Integration Tests (push) Failing after 2m50s
Android CI/CD / CI Summary (push) Failing after 1s

When the tunnel reports that no computer is attached (close 4503) the
reconnect banner now says that AITURK IDE is not open or Phone
connection is off, instead of an endless 'reconnecting'.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B8ppceaR5s6cvMnm7uGRnf
This commit is contained in:
2026-10-05 04:18:53 +03:00
co-authored by Claude Opus 5.5
parent cbe716300c
commit c2d828b90a
2 changed files with 17 additions and 2 deletions
@@ -730,6 +730,8 @@ internal class WsTransport(
// Do NOT log [reason] — it may carry server-side context. The // Do NOT log [reason] — it may carry server-side context. The
// reason is still inspected internally to detect auth failures. // reason is still inspected internally to detect auth failures.
Log.i(TAG, "WebSocket closed: $code") Log.i(TAG, "WebSocket closed: $code")
com.m57.hermescontrol.data.aiturk.AiturkRelayStatus
.onSocketEnded(null)
connected.set(false) connected.set(false)
ActiveSessionHolder.clear() ActiveSessionHolder.clear()
connectionHealth.stop() connectionHealth.stop()
@@ -764,6 +766,10 @@ internal class WsTransport(
connectionHealth.stop() connectionHealth.stop()
rpcChannel.clearCapabilityRequests() rpcChannel.clearCapabilityRequests()
val code = response?.code ?: 0 val code = response?.code ?: 0
// AITURK: lets the chat banner say "AITURK IDE is not open on the
// computer" when the tunnel reports that no host is attached.
com.m57.hermescontrol.data.aiturk.AiturkRelayStatus
.onSocketEnded(t)
if (code == 401 || code == 4401 || code == 4403 || if (code == 401 || code == 4401 || code == 4403 ||
t.message?.contains("401") == true || t.message?.contains("401") == true ||
t.message?.contains("4401") == true || t.message?.contains("4401") == true ||
@@ -17,6 +17,8 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@@ -70,13 +72,20 @@ fun ChatConnectionBanner(
color = LocalHermesStatusColors.current.error, color = LocalHermesStatusColors.current.error,
) )
} }
// AITURK: over the relay, say why the reconnect keeps failing.
val aiturkHostOffline by com.m57.hermescontrol.data.aiturk.AiturkRelayStatus.hostOffline
.collectAsState()
val hostOffline = aiturkHostOffline && connectionStatus == ConnectionStatus.RECONNECTING
Text( Text(
modifier = Modifier.weight(1f, fill = false), modifier = Modifier.weight(1f, fill = false),
maxLines = 1, maxLines = if (hostOffline) 3 else 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
text = text =
when (connectionStatus) { when (connectionStatus) {
ConnectionStatus.RECONNECTING -> stringResource(R.string.chat_status_reconnecting) ConnectionStatus.RECONNECTING ->
stringResource(
if (hostOffline) R.string.aiturk_status_host_offline else R.string.chat_status_reconnecting,
)
ConnectionStatus.DISCONNECTED -> stringResource(R.string.chat_status_disconnected) ConnectionStatus.DISCONNECTED -> stringResource(R.string.chat_status_disconnected)
ConnectionStatus.NO_NETWORK -> stringResource(R.string.chat_status_no_network) ConnectionStatus.NO_NETWORK -> stringResource(R.string.chat_status_no_network)
ConnectionStatus.AUTH_EXPIRED -> stringResource(R.string.chat_status_auth_expired) ConnectionStatus.AUTH_EXPIRED -> stringResource(R.string.chat_status_auth_expired)