From 5e9afc1e661b36789e1f3f730dd4dbed82cd2d79 Mon Sep 17 00:00:00 2001 From: Jason Pearson Date: Sun, 8 Feb 2026 21:45:00 -0600 Subject: [PATCH] fix: make daemon-down socket check reactive via polling state Replace the one-off ObservationStreamClient.socketExists() call during composition with a polled mutableStateOf that checks every 2 seconds while disconnected/connecting. This ensures the UI transitions between "Device Disconnected" and "Restart MCP Daemon" when the daemon socket appears or disappears after the initial disconnect. Co-Authored-By: Claude Opus 4.6 --- .../ide/layout/LayoutInspectorDashboard.kt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/android/ide-plugin/src/main/kotlin/dev/jasonpearson/automobile/ide/layout/LayoutInspectorDashboard.kt b/android/ide-plugin/src/main/kotlin/dev/jasonpearson/automobile/ide/layout/LayoutInspectorDashboard.kt index 5ea687a01..d5052b280 100644 --- a/android/ide-plugin/src/main/kotlin/dev/jasonpearson/automobile/ide/layout/LayoutInspectorDashboard.kt +++ b/android/ide-plugin/src/main/kotlin/dev/jasonpearson/automobile/ide/layout/LayoutInspectorDashboard.kt @@ -105,6 +105,22 @@ fun LayoutInspectorDashboard( } } + // Poll socket existence so the UI reacts when the daemon starts or stops. + // Only active when disconnected/connecting — connected state doesn't need this. + var socketExists by remember { mutableStateOf(ObservationStreamClient.socketExists()) } + val isDisconnectedOrConnecting = state.connectionStatus == ConnectionStatus.Disconnected || + state.connectionStatus == ConnectionStatus.Connecting + LaunchedEffect(isDisconnectedOrConnecting) { + if (isDisconnectedOrConnecting) { + while (true) { + socketExists = ObservationStreamClient.socketExists() + kotlinx.coroutines.delay(2000) + } + } else { + socketExists = true + } + } + // Initial fetch as fallback (in case stream hasn't pushed yet) LaunchedEffect(dataSourceMode, clientProvider) { kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.IO) { @@ -189,7 +205,7 @@ fun LayoutInspectorDashboard( showTapTargetIssues = state.showTapTargetIssues, onToggleTapTargetIssues = { state.toggleTapTargetIssues() }, connectionStatus = state.connectionStatus, - socketExists = ObservationStreamClient.socketExists(), + socketExists = socketExists, onRestartDaemon = onRestartDaemon, modifier = Modifier.fillMaxSize(), refitTrigger = refitTrigger, // Trigger refit when panels toggle