diff --git a/apps/android/app/src/main/java/com/clawdbot/android/ui/RootScreen.kt b/apps/android/app/src/main/java/com/clawdbot/android/ui/RootScreen.kt index 96d2543a7..994989cca 100644 --- a/apps/android/app/src/main/java/com/clawdbot/android/ui/RootScreen.kt +++ b/apps/android/app/src/main/java/com/clawdbot/android/ui/RootScreen.kt @@ -271,6 +271,7 @@ fun RootScreen(viewModel: MainViewModel) { statusText = talkStatusText, isListening = talkIsListening, isSpeaking = talkIsSpeaking, + onDismiss = { viewModel.setTalkEnabled(false) }, ) } } diff --git a/apps/android/app/src/main/java/com/clawdbot/android/ui/TalkOrbOverlay.kt b/apps/android/app/src/main/java/com/clawdbot/android/ui/TalkOrbOverlay.kt index 32225b486..3c5b052fc 100644 --- a/apps/android/app/src/main/java/com/clawdbot/android/ui/TalkOrbOverlay.kt +++ b/apps/android/app/src/main/java/com/clawdbot/android/ui/TalkOrbOverlay.kt @@ -7,6 +7,8 @@ import androidx.compose.animation.core.infiniteRepeatable import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween import androidx.compose.foundation.Canvas +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -18,11 +20,14 @@ import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.platform.LocalHapticFeedback import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp @@ -33,7 +38,9 @@ fun TalkOrbOverlay( isListening: Boolean, isSpeaking: Boolean, modifier: Modifier = Modifier, + onDismiss: (() -> Unit)? = null, ) { + val haptic = LocalHapticFeedback.current val transition = rememberInfiniteTransition(label = "talk-orb") val t by transition.animateFloat( @@ -62,7 +69,19 @@ fun TalkOrbOverlay( verticalArrangement = Arrangement.spacedBy(12.dp), ) { Box(contentAlignment = Alignment.Center) { - Canvas(modifier = Modifier.size(360.dp)) { + Canvas( + modifier = Modifier + .size(360.dp) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, // No ripple - the orb itself is the feedback + enabled = onDismiss != null, + onClick = { + haptic.performHapticFeedback(HapticFeedbackType.LongPress) + onDismiss?.invoke() + } + ) + ) { val center = this.center val baseRadius = size.minDimension * 0.30f