Browse Source

android: fix PTT — one Box across all states, release now works; 1s min duration

- PTT Box: same composable identity in idle/recording states (just changes bg color)
  Gesture coroutine survives recomposition → onPttReleased() fires on finger lift.
  When locked, Box is replaced by cancel/send IconButtons.
- Min voice duration: 500→1000ms (C and ViewModel)
topo_upd
evgeny 2 months ago
parent
commit
00afc5c80a
  1. 26
      tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt
  2. 2
      tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt
  3. 2
      tools/chatgui-android/libutun_lite/voice_recorder.c

26
tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt

@ -167,27 +167,20 @@ fun InputBar(
Spacer(Modifier.width(4.dp))
if (isRecording && isRecordingLocked) {
/* Locked: cancel + send voice */
/* Locked: cancel + send voice — PTT box replaced by action buttons */
IconButton(onClick = onVoiceCancel) {
Text("\u2715", fontSize = 20.sp, color = Color(0xFFE53935))
}
IconButton(onClick = onVoiceSend) {
Text("\u25B6", fontSize = 20.sp, color = Color(0xFF4CAF50))
}
} else if (isRecording) {
/* Holding: only PTT active */
IconButton(
onClick = {},
enabled = true,
modifier = Modifier.background(Color(0xFFE53935), RoundedCornerShape(4.dp))
) {
Text("\uD83C\uDFA4", fontSize = 20.sp)
}
} else {
/* Idle: PTT + send */
/* PTT Box — always present (same identity), just changes appearance */
val pttBg = if (isRecording) Color(0xFFE53935) else Color.Transparent
Box(
modifier = Modifier
.size(48.dp)
.background(pttBg, RoundedCornerShape(4.dp))
.pointerInput(hasMicPerm) {
awaitPointerEventScope {
val down = awaitPointerEvent()
@ -223,13 +216,14 @@ fun InputBar(
},
contentAlignment = Alignment.Center
) {
Text("\uD83C\uDFA4", fontSize = 20.sp)
Text("\uD83C\uDFA4", fontSize = 20.sp, color = if (isRecording) Color.White else Color.Unspecified)
}
Spacer(Modifier.width(4.dp))
Button(onClick = onSend, enabled = enabled && text.isNotBlank()) {
Text("Send")
if (!isRecording) {
Spacer(Modifier.width(4.dp))
Button(onClick = onSend, enabled = enabled && text.isNotBlank()) {
Text("Send")
}
}
}
}

2
tools/chatgui-android/app/src/main/java/com/utun/chat/viewmodel/ChatViewModel.kt

@ -239,7 +239,7 @@ class ChatViewModel : ViewModel() {
fun sendVoiceMessage() {
val duration = stopVoiceRecording()
if (duration < 500) {
if (duration < 1000) {
LogManager.addLog("INFO", "VM", "voice too short (${duration}ms), discarded")
}
}

2
tools/chatgui-android/libutun_lite/voice_recorder.c

@ -221,7 +221,7 @@ int voice_recorder_stop(int* out_duration_ms) {
return -1;
}
if (elapsed_ms < 500) {
if (elapsed_ms < 1000) {
DEBUG_INFO(DEBUG_CATEGORY_GENERAL, "voice_recorder_stop: too short %lldms, discarding", (long long)elapsed_ms);
voice_cleanup_locked(g_rec);
pthread_mutex_unlock(&g_rec->mtx);

Loading…
Cancel
Save