Android: tap orb to dismiss talk mode with haptic feedback

Makes the talk orb tappable to disable voice mode - much easier to hit
than the small button. Includes haptic feedback on tap.
This commit is contained in:
yishai 2026-01-28 21:31:46 +02:00
parent e5198b8f31
commit 32cf8c3290
2 changed files with 21 additions and 1 deletions

View File

@ -271,6 +271,7 @@ fun RootScreen(viewModel: MainViewModel) {
statusText = talkStatusText,
isListening = talkIsListening,
isSpeaking = talkIsSpeaking,
onDismiss = { viewModel.setTalkEnabled(false) },
)
}
}

View File

@ -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