voice: fix waveform — pointerInput on Box, cursor + white bars stay on pause
- Canvas pointerInput moved to wrapping Box (state updates trigger recomposition) - showCursor = playing || paused (cursor and white bars visible on pause) - elapsed/dur stays visible on pause too
This commit is contained in:
1 parent
6980f34df9
commit
2e8aa89397
1 file changed
+32
-29
+32
-29
@@ -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)
|
||||
|
||||
Reference in new issue
Block a user