Skip to content

Commit cec52bd

Browse files
committed
fix(android): route offline voice to gateway setup
1 parent 581c8a6 commit cec52bd

2 files changed

Lines changed: 61 additions & 12 deletions

File tree

apps/android/app/src/main/java/ai/openclaw/app/ui/ShellScreen.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ fun ShellScreen(
151151
VoiceShellScreen(
152152
viewModel = viewModel,
153153
onOpenCommand = { commandOpen = true },
154+
onOpenGatewaySettings = {
155+
settingsRoute = SettingsRoute.Gateway
156+
returnToOverviewFromSettings = false
157+
activeTab = Tab.Settings
158+
},
154159
onOpenVoiceSettings = {
155160
settingsRoute = SettingsRoute.Voice
156161
returnToOverviewFromSettings = false
@@ -637,10 +642,16 @@ private fun ChatShellScreen(
637642
private fun VoiceShellScreen(
638643
viewModel: MainViewModel,
639644
onOpenCommand: () -> Unit,
645+
onOpenGatewaySettings: () -> Unit,
640646
onOpenVoiceSettings: () -> Unit,
641647
) {
642648
ClawScaffold(contentPadding = PaddingValues(start = 0.dp, top = 8.dp, end = 0.dp, bottom = 8.dp)) {
643-
VoiceScreen(viewModel = viewModel, onOpenCommand = onOpenCommand, onOpenVoiceSettings = onOpenVoiceSettings)
649+
VoiceScreen(
650+
viewModel = viewModel,
651+
onOpenCommand = onOpenCommand,
652+
onOpenGatewaySettings = onOpenGatewaySettings,
653+
onOpenVoiceSettings = onOpenVoiceSettings,
654+
)
644655
}
645656
}
646657

apps/android/app/src/main/java/ai/openclaw/app/ui/VoiceScreen.kt

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import androidx.compose.material.icons.automirrored.filled.Send
4242
import androidx.compose.material.icons.automirrored.filled.VolumeOff
4343
import androidx.compose.material.icons.automirrored.filled.VolumeUp
4444
import androidx.compose.material.icons.filled.Close
45+
import androidx.compose.material.icons.filled.Cloud
4546
import androidx.compose.material.icons.filled.GraphicEq
4647
import androidx.compose.material.icons.filled.Info
4748
import androidx.compose.material.icons.filled.Mic
@@ -78,6 +79,7 @@ import androidx.core.content.ContextCompat
7879
fun VoiceScreen(
7980
viewModel: MainViewModel,
8081
onOpenCommand: () -> Unit,
82+
onOpenGatewaySettings: () -> Unit,
8183
onOpenVoiceSettings: () -> Unit,
8284
) {
8385
val context = LocalContext.current
@@ -113,6 +115,7 @@ fun VoiceScreen(
113115

114116
val activeConversation = if (voiceCaptureMode == VoiceCaptureMode.TalkMode) talkModeConversation else micConversation
115117
val voiceActive = micEnabled || micIsSending || talkModeEnabled
118+
val gatewayReady = gatewayStatus.isVoiceGatewayReady()
116119
val activeStatus =
117120
voiceStatusLabel(
118121
gatewayStatus = gatewayStatus,
@@ -161,7 +164,7 @@ fun VoiceScreen(
161164
verticalArrangement = Arrangement.spacedBy(8.dp),
162165
) {
163166
VoiceHeader(
164-
statusText = if (voiceActive) activeStatus else "Your voice command center.",
167+
statusText = if (voiceActive || !gatewayReady) activeStatus else "Your voice command center.",
165168
speakerEnabled = speakerEnabled,
166169
onToggleSpeaker = { viewModel.setSpeakerEnabled(!speakerEnabled) },
167170
onOpenCommand = onOpenCommand,
@@ -175,6 +178,7 @@ fun VoiceScreen(
175178
talkModeListening = talkModeListening,
176179
talkModeSpeaking = talkModeSpeaking,
177180
micLiveTranscript = micLiveTranscript,
181+
gatewayReady = gatewayReady,
178182
onStartTalk = {
179183
runVoiceAction(
180184
action = VoiceAction.Talk,
@@ -198,6 +202,7 @@ fun VoiceScreen(
198202
run = { viewModel.setMicEnabled(!micEnabled) },
199203
)
200204
},
205+
onConnectGateway = onOpenGatewaySettings,
201206
)
202207

203208
if (!hasMicPermission) {
@@ -582,8 +587,10 @@ private fun VoiceHero(
582587
talkModeListening: Boolean,
583588
talkModeSpeaking: Boolean,
584589
micLiveTranscript: String?,
590+
gatewayReady: Boolean,
585591
onStartTalk: () -> Unit,
586592
onStartDictation: () -> Unit,
593+
onConnectGateway: () -> Unit,
587594
) {
588595
Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(10.dp)) {
589596
VoiceOrb(
@@ -607,6 +614,7 @@ private fun VoiceHero(
607614
talkModeListening -> "Listening"
608615
talkModeEnabled -> "Talk is live"
609616
micEnabled -> "Dictation is listening"
617+
!gatewayReady -> "Gateway offline"
610618
else -> "Ready to talk"
611619
},
612620
style = ClawTheme.type.body,
@@ -634,24 +642,46 @@ private fun VoiceHero(
634642
ClawPanel(contentPadding = PaddingValues(horizontal = 0.dp, vertical = 0.dp)) {
635643
VoiceModeRow(
636644
title = if (talkModeEnabled) "End Talk" else "Realtime Talk",
637-
subtitle = if (talkModeEnabled) "Conversation is live" else "Natural conversation in real time",
645+
subtitle =
646+
when {
647+
talkModeEnabled -> "Conversation is live"
648+
gatewayReady -> "Natural conversation in real time"
649+
else -> "Connect gateway to start"
650+
},
638651
icon = if (talkModeEnabled) Icons.Default.PhoneDisabled else Icons.Default.RecordVoiceOver,
639652
onClick = onStartTalk,
653+
enabled = gatewayReady || talkModeEnabled,
640654
)
641655
VoiceModeRow(
642656
title = if (micEnabled) "Stop Dictation" else "Dictation",
643-
subtitle = if (micEnabled) "Listening for one turn" else "Convert speech to text",
657+
subtitle =
658+
when {
659+
micEnabled -> "Listening for one turn"
660+
gatewayReady -> "Convert speech to text"
661+
else -> "Connect gateway to start"
662+
},
644663
icon = if (micEnabled) Icons.Default.MicOff else Icons.Default.TextFields,
645664
onClick = onStartDictation,
665+
enabled = gatewayReady || micEnabled,
646666
)
647667
}
648668

649669
VoiceProviderCard(gatewayStatus = gatewayStatus)
650670

651671
VoicePrimaryAction(
652-
text = if (talkModeEnabled) "End Talk" else "Start Talk",
653-
icon = if (talkModeEnabled) Icons.Default.PhoneDisabled else Icons.Default.Phone,
654-
onClick = onStartTalk,
672+
text =
673+
when {
674+
talkModeEnabled -> "End Talk"
675+
gatewayReady -> "Start Talk"
676+
else -> "Connect Gateway"
677+
},
678+
icon =
679+
when {
680+
talkModeEnabled -> Icons.Default.PhoneDisabled
681+
gatewayReady -> Icons.Default.Phone
682+
else -> Icons.Default.Cloud
683+
},
684+
onClick = if (gatewayReady || talkModeEnabled) onStartTalk else onConnectGateway,
655685
)
656686
}
657687
}
@@ -662,8 +692,9 @@ private fun VoiceModeRow(
662692
subtitle: String,
663693
icon: androidx.compose.ui.graphics.vector.ImageVector,
664694
onClick: () -> Unit,
695+
enabled: Boolean = true,
665696
) {
666-
Surface(onClick = onClick, color = Color.Transparent, contentColor = ClawTheme.colors.text) {
697+
Surface(onClick = onClick, enabled = enabled, color = Color.Transparent, contentColor = ClawTheme.colors.text) {
667698
Row(
668699
modifier = Modifier.fillMaxWidth().heightIn(min = 60.dp).padding(horizontal = 10.dp, vertical = 6.dp),
669700
verticalAlignment = Alignment.CenterVertically,
@@ -672,19 +703,26 @@ private fun VoiceModeRow(
672703
Surface(
673704
modifier = Modifier.size(34.dp),
674705
shape = CircleShape,
675-
color = ClawTheme.colors.surface,
676-
contentColor = ClawTheme.colors.text,
706+
color = if (enabled) ClawTheme.colors.surface else ClawTheme.colors.canvas,
707+
contentColor = if (enabled) ClawTheme.colors.text else ClawTheme.colors.textSubtle,
677708
border = BorderStroke(1.dp, ClawTheme.colors.border),
678709
) {
679710
Box(contentAlignment = Alignment.Center) {
680711
Icon(imageVector = icon, contentDescription = null, modifier = Modifier.size(16.dp))
681712
}
682713
}
683714
Column(modifier = Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(2.dp)) {
684-
Text(text = title, style = ClawTheme.type.body, color = ClawTheme.colors.text, maxLines = 1)
715+
Text(text = title, style = ClawTheme.type.body, color = if (enabled) ClawTheme.colors.text else ClawTheme.colors.textMuted, maxLines = 1)
685716
Text(text = subtitle, style = ClawTheme.type.caption.copy(fontSize = 12.5.sp, lineHeight = 16.sp), color = ClawTheme.colors.textMuted, maxLines = 1)
686717
}
687-
Icon(imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight, contentDescription = null, modifier = Modifier.size(21.dp), tint = ClawTheme.colors.textMuted)
718+
if (enabled) {
719+
Icon(
720+
imageVector = Icons.AutoMirrored.Filled.KeyboardArrowRight,
721+
contentDescription = null,
722+
modifier = Modifier.size(21.dp),
723+
tint = ClawTheme.colors.textMuted,
724+
)
725+
}
688726
}
689727
}
690728
}

0 commit comments

Comments
 (0)