mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-24 07:01:49 +00:00
fix(android): auto-resume pairing approval
This commit is contained in:
@@ -38,6 +38,7 @@ import androidx.compose.material3.SwitchDefaults
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -55,12 +56,15 @@ import androidx.compose.ui.unit.dp
|
||||
import ai.openclaw.app.MainViewModel
|
||||
import ai.openclaw.app.gateway.GatewayEndpoint
|
||||
import ai.openclaw.app.ui.mobileCardSurface
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
private enum class ConnectInputMode {
|
||||
SetupCode,
|
||||
Manual,
|
||||
}
|
||||
|
||||
private const val PAIRING_AUTO_RETRY_MS = 6_000L
|
||||
|
||||
@Composable
|
||||
fun ConnectTabScreen(viewModel: MainViewModel) {
|
||||
val context = LocalContext.current
|
||||
@@ -140,8 +144,19 @@ fun ConnectTabScreen(viewModel: MainViewModel) {
|
||||
}
|
||||
|
||||
val showDiagnostics = !isConnected && gatewayStatusHasDiagnostics(statusText)
|
||||
val pairingRequired = !isConnected && gatewayStatusLooksLikePairing(statusText)
|
||||
val statusLabel = gatewayStatusForDisplay(statusText)
|
||||
|
||||
LaunchedEffect(pairingRequired) {
|
||||
if (!pairingRequired) {
|
||||
return@LaunchedEffect
|
||||
}
|
||||
while (true) {
|
||||
delay(PAIRING_AUTO_RETRY_MS)
|
||||
viewModel.refreshGatewayConnection()
|
||||
}
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState()).padding(horizontal = 20.dp, vertical = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(14.dp),
|
||||
@@ -319,8 +334,17 @@ fun ConnectTabScreen(viewModel: MainViewModel) {
|
||||
modifier = Modifier.fillMaxWidth().padding(horizontal = 14.dp, vertical = 14.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
) {
|
||||
Text("Last gateway error", style = mobileHeadline, color = mobileWarning)
|
||||
Text(if (pairingRequired) "Pairing required" else "Last gateway error", style = mobileHeadline, color = mobileWarning)
|
||||
Text(statusLabel, style = mobileBody.copy(fontFamily = FontFamily.Monospace), color = mobileText)
|
||||
if (pairingRequired) {
|
||||
Text(
|
||||
"Approve this phone on the gateway. OpenClaw retries automatically while this screen stays open.",
|
||||
style = mobileCallout,
|
||||
color = mobileTextSecondary,
|
||||
)
|
||||
CommandBlock("openclaw devices list")
|
||||
CommandBlock("openclaw devices approve <requestId>")
|
||||
}
|
||||
Text("OpenClaw Android ${openClawAndroidVersionLabel()}", style = mobileCaption1, color = mobileTextSecondary)
|
||||
Button(
|
||||
onClick = {
|
||||
|
||||
@@ -71,6 +71,7 @@ import androidx.compose.material.icons.filled.Wifi
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -101,6 +102,7 @@ import ai.openclaw.app.node.DeviceNotificationListenerService
|
||||
import com.google.mlkit.vision.barcode.common.Barcode
|
||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions
|
||||
import com.google.mlkit.vision.codescanner.GmsBarcodeScanning
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
private enum class OnboardingStep(val index: Int, val label: String) {
|
||||
Welcome(1, "Welcome"),
|
||||
@@ -132,6 +134,8 @@ private enum class SpecialAccessToggle {
|
||||
NotificationListener,
|
||||
}
|
||||
|
||||
private const val PAIRING_AUTO_RETRY_MS = 6_000L
|
||||
|
||||
private val onboardingBackgroundGradient: Brush
|
||||
@Composable get() = mobileBackgroundGradient
|
||||
|
||||
@@ -737,6 +741,7 @@ fun OnboardingFlow(viewModel: MainViewModel, modifier: Modifier = Modifier) {
|
||||
)
|
||||
OnboardingStep.FinalCheck ->
|
||||
FinalStep(
|
||||
viewModel = viewModel,
|
||||
parsedGateway = parseGatewayEndpoint(gatewayUrl),
|
||||
statusText = statusText,
|
||||
isConnected = canFinishOnboarding,
|
||||
@@ -1566,6 +1571,7 @@ private fun PermissionToggleRow(
|
||||
|
||||
@Composable
|
||||
private fun FinalStep(
|
||||
viewModel: MainViewModel,
|
||||
parsedGateway: GatewayEndpointConfig?,
|
||||
statusText: String,
|
||||
isConnected: Boolean,
|
||||
@@ -1581,6 +1587,16 @@ private fun FinalStep(
|
||||
val showDiagnostics = gatewayStatusHasDiagnostics(statusText)
|
||||
val pairingRequired = gatewayStatusLooksLikePairing(statusText)
|
||||
|
||||
LaunchedEffect(pairingRequired, attemptedConnect) {
|
||||
if (!pairingRequired || !attemptedConnect) {
|
||||
return@LaunchedEffect
|
||||
}
|
||||
while (true) {
|
||||
delay(PAIRING_AUTO_RETRY_MS)
|
||||
viewModel.refreshGatewayConnection()
|
||||
}
|
||||
}
|
||||
|
||||
Column(verticalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
Text("Review", style = onboardingTitle1Style, color = onboardingText)
|
||||
|
||||
@@ -1761,7 +1777,11 @@ private fun FinalStep(
|
||||
if (pairingRequired) {
|
||||
CommandBlock("openclaw devices list")
|
||||
CommandBlock("openclaw devices approve <requestId>")
|
||||
Text("Then tap Connect again.", style = onboardingCalloutStyle, color = onboardingTextSecondary)
|
||||
Text(
|
||||
"OpenClaw retries automatically while this screen stays open.",
|
||||
style = onboardingCalloutStyle,
|
||||
color = onboardingTextSecondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user