diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt index b557d5b0..2534ef29 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/components/MessageBubble.kt @@ -129,36 +129,39 @@ private fun VoiceBubble(message: Message, textColor: Color, /* Waveform with seek on tap */ if (wfCount >= 2) { - Canvas(modifier = Modifier.weight(1f).height(28.dp) - .pointerInput(message.filePath) { - detectTapGestures { offset -> - if (message.filePath.isEmpty()) return@detectTapGestures - val seekFrac = (offset.x / size.width).coerceIn(0f, 1f) - val seekMs = (seekFrac * durMs).toInt() - playing = true; paused = false; elapsedMs = seekMs; progress = seekFrac - onSeek(message.filePath, seekMs, onDone) + Box( + modifier = Modifier.weight(1f).height(28.dp) + .pointerInput(message.filePath) { + detectTapGestures { offset -> + if (message.filePath.isEmpty()) return@detectTapGestures + val seekFrac = (offset.x / size.width).coerceIn(0f, 1f) + val seekMs = (seekFrac * durMs).toInt() + playing = true; paused = false; elapsedMs = seekMs; progress = seekFrac + onSeek(message.filePath, seekMs, onDone) + } } - } ) { - val barW = size.width / wfCount - val ph = size.height - val showCursor = playing && !paused - val playedIdx = if (showCursor && progress > 0f) (progress * wfCount).toInt() else 0 - for (i in 0 until wfCount) { - val level = wf[i].coerceIn(0f, 1f) - val barH = (2f + level * (ph - 2f)).coerceAtMost(ph) - val x = i.toFloat() * barW - val y = ph - barH - val played = showCursor && i < playedIdx - drawRect( - color = when { played -> Color.White; else -> Color(0xFFCCCCD4).copy(alpha = 0.8f) }, - topLeft = Offset(x, y), - size = Size(barW * 0.75f, barH) - ) - } - if (showCursor && progress > 0f && progress < 1f) { - val cursorX = progress * size.width - drawLine(Color(0xFFFFD600), Offset(cursorX, 0f), Offset(cursorX, ph), strokeWidth = 2.5f) + Canvas(modifier = Modifier.fillMaxSize()) { + val barW = size.width / wfCount + val ph = size.height + val showCursor = playing || paused + val playedIdx = if (showCursor && progress > 0f) (progress * wfCount).toInt() else 0 + for (i in 0 until wfCount) { + val level = wf[i].coerceIn(0f, 1f) + val barH = (2f + level * (ph - 2f)).coerceAtMost(ph) + val x = i.toFloat() * barW + val y = ph - barH + val played = showCursor && i < playedIdx + drawRect( + color = when { played -> Color.White; else -> Color(0xFFCCCCD4).copy(alpha = 0.8f) }, + topLeft = Offset(x, y), + size = Size(barW * 0.75f, barH) + ) + } + if (showCursor && progress > 0f && progress < 1f) { + val cursorX = progress * size.width + drawLine(Color(0xFFFFD600), Offset(cursorX, 0f), Offset(cursorX, ph), strokeWidth = 2.5f) + } } } } @@ -173,7 +176,7 @@ private fun VoiceBubble(message: Message, textColor: Color, verticalAlignment = Alignment.Bottom ) { Text( - if (playing && !paused) "${formatDurationMs(elapsedMs)} / ${formatDurationMs(durMs)}" + if (playing || paused) "${formatDurationMs(elapsedMs)} / ${formatDurationMs(durMs)}" else formatDurationMs(durMs), fontSize = 12.sp, color = textColor.copy(alpha = 0.55f)