88package com.nextcloud.talk.ui.chat
99
1010import android.text.format.DateUtils
11- import android.widget.SeekBar
11+ import androidx.compose.animation.core.animateIntAsState
1212import androidx.compose.foundation.layout.Column
1313import androidx.compose.foundation.layout.Row
1414import androidx.compose.foundation.layout.fillMaxWidth
@@ -19,26 +19,34 @@ import androidx.compose.material.icons.Icons
1919import androidx.compose.material.icons.filled.Pause
2020import androidx.compose.material.icons.filled.PlayArrow
2121import androidx.compose.material3.CircularProgressIndicator
22+ import androidx.compose.material3.ExperimentalMaterial3Api
2223import androidx.compose.material3.Icon
2324import androidx.compose.material3.IconButton
2425import androidx.compose.material3.MaterialTheme.colorScheme
2526import androidx.compose.material3.Text
2627import androidx.compose.material3.TextButton
2728import androidx.compose.runtime.Composable
29+ import androidx.compose.runtime.getValue
30+ import androidx.compose.runtime.mutableFloatStateOf
2831import androidx.compose.runtime.remember
32+ import androidx.compose.runtime.setValue
2933import androidx.compose.ui.Alignment
3034import androidx.compose.ui.Modifier
3135import androidx.compose.ui.graphics.toArgb
3236import androidx.compose.ui.res.stringResource
3337import androidx.compose.ui.unit.dp
34- import androidx.compose.ui.viewinterop.AndroidView
3538import com.nextcloud.talk.R
3639import com.nextcloud.talk.chat.ui.model.ChatMessageUi
3740import com.nextcloud.talk.chat.ui.model.MessageTypeContent
38- import com.nextcloud.talk.ui.WaveformSeekBar
41+ import com.nextcloud.talk.ui.ComposeWaveformSeekBar
42+ import com.nextcloud.talk.ui.WAVEFORM_SIZE
43+ import com.nextcloud.talk.utils.AudioUtils
3944
4045private const val SEEKBAR_MAX = 100
46+ private const val START_WAVE_FORM_HEIGHT = 10
47+ private const val END_WAVE_FORM_HEIGHT = 56
4148
49+ @OptIn(ExperimentalMaterial3Api ::class )
4250@Suppress(" Detekt.LongMethod" , " LongParameterList" )
4351@Composable
4452fun VoiceMessage (
@@ -57,12 +65,23 @@ fun VoiceMessage(
5765 forceTimeBelow = true ,
5866 content = {
5967 val inversePrimaryColor = colorScheme.inversePrimary
60- val inversePrimary = remember(inversePrimaryColor) { inversePrimaryColor.toArgb() }
68+ remember(inversePrimaryColor) { inversePrimaryColor.toArgb() }
6169 val onPrimaryContainerColor = colorScheme.onPrimaryContainer
62- val onPrimaryContainer = remember(onPrimaryContainerColor) { onPrimaryContainerColor.toArgb() }
70+ remember(onPrimaryContainerColor) { onPrimaryContainerColor.toArgb() }
6371 val remainingSeconds = (typeContent.durationSeconds - typeContent.playedSeconds).coerceAtLeast(0 )
64- val waveformData = remember(typeContent.waveform) { typeContent.waveform.toFloatArray() }
65- val lastWaveformData = remember { mutableListOf<Float >() }
72+ val waveformData = remember(typeContent.waveform) {
73+ val floatArr = typeContent.waveform.toFloatArray()
74+ if (floatArr.size < WAVEFORM_SIZE ) {
75+ FloatArray (WAVEFORM_SIZE )
76+ } else {
77+ AudioUtils .shrinkFloatArray(floatArr, WAVEFORM_SIZE )
78+ }
79+ }
80+
81+ val animValue by animateIntAsState(
82+ if (waveformData.average() > 0 ) END_WAVE_FORM_HEIGHT else START_WAVE_FORM_HEIGHT ,
83+ label = " size"
84+ )
6685
6786 Column {
6887 Row (
@@ -84,49 +103,20 @@ fun VoiceMessage(
84103 }
85104 }
86105
87- AndroidView (
88- factory = { ctx ->
89- WaveformSeekBar (ctx).apply {
90- max = SEEKBAR_MAX
91- setWaveData(waveformData)
92- setColors(
93- inversePrimary,
94- onPrimaryContainer
95- )
96- setOnSeekBarChangeListener(object : SeekBar .OnSeekBarChangeListener {
97- override fun onProgressChanged (
98- seekBar : SeekBar ? ,
99- progress : Int ,
100- fromUser : Boolean
101- ) {
102- if (fromUser) {
103- onSeek(message.id, progress)
104- }
105- }
106+ var sliderValue by remember { mutableFloatStateOf(0f ) }
107+ sliderValue = typeContent.seekbarProgress * 1f / SEEKBAR_MAX
106108
107- override fun onStartTrackingTouch (seekBar : SeekBar ? ) = Unit
108-
109- override fun onStopTrackingTouch (seekBar : SeekBar ? ) = Unit
110- })
111- }
112- },
113- update = { seekBar ->
114- seekBar.max = SEEKBAR_MAX
115- val waveformChanged = typeContent.waveform != lastWaveformData
116- if (waveformChanged) {
117- lastWaveformData.clear()
118- lastWaveformData.addAll(typeContent.waveform)
119- seekBar.setWaveData(waveformData)
120- seekBar.requestLayout()
121- }
122- seekBar.setColors(inversePrimary, onPrimaryContainer)
123- seekBar.progress = typeContent.seekbarProgress
124- seekBar.isEnabled = ! typeContent.isDownloading
125- seekBar.invalidate()
109+ ComposeWaveformSeekBar (
110+ sliderValue,
111+ {
112+ val progressI = (it * SEEKBAR_MAX ).toInt()
113+ onSeek(message.id, progressI)
126114 },
127115 modifier = Modifier
128- .weight(1f )
129- .height(56 .dp)
116+ .height(animValue.dp)
117+ .fillMaxWidth()
118+ .padding(8 .dp), // or weight(1f),
119+ waveformData
130120 )
131121
132122 TextButton (
0 commit comments