@@ -27,6 +27,11 @@ import androidx.compose.foundation.layout.width
2727import androidx.compose.foundation.shape.CircleShape
2828import androidx.compose.material3.IconButtonDefaults
2929import androidx.compose.runtime.Composable
30+ import androidx.compose.runtime.LaunchedEffect
31+ import androidx.compose.runtime.getValue
32+ import androidx.compose.runtime.mutableStateOf
33+ import androidx.compose.runtime.remember
34+ import androidx.compose.runtime.setValue
3035import androidx.compose.ui.Alignment
3136import androidx.compose.ui.Modifier
3237import androidx.compose.ui.platform.LocalContext
@@ -53,6 +58,7 @@ import io.element.android.libraries.designsystem.theme.components.IconButton
5358import io.element.android.libraries.designsystem.theme.components.Text
5459import io.element.android.libraries.theme.ElementTheme
5560import io.element.android.libraries.ui.strings.CommonStrings
61+ import kotlinx.coroutines.delay
5662
5763@Composable
5864fun TimelineItemVoiceView (
@@ -147,19 +153,40 @@ private fun RetryButton(
147153 }
148154}
149155
156+ /* *
157+ * Progress button is shown when the voice message is being downloaded.
158+ *
159+ * The progress indicator is optimistic and displays a pause button (which
160+ * indicates the audio is playing) for 2 seconds before revealing the
161+ * actual progress indicator.
162+ */
150163@Composable
151- private fun ProgressButton () {
164+ private fun ProgressButton (
165+ displayImmediately : Boolean = false,
166+ ) {
167+ var canDisplay by remember { mutableStateOf(displayImmediately) }
168+ LaunchedEffect (Unit ) {
169+ delay(2000L )
170+ canDisplay = true
171+ }
152172 CustomIconButton (
153173 onClick = {},
154174 enabled = false ,
155175 ) {
156- CircularProgressIndicator (
157- modifier = Modifier
158- .padding(2 .dp)
159- .size(16 .dp),
160- color = ElementTheme .colors.iconSecondary,
161- strokeWidth = 2 .dp,
162- )
176+ if (canDisplay) {
177+ CircularProgressIndicator (
178+ modifier = Modifier
179+ .padding(2 .dp)
180+ .size(16 .dp),
181+ color = ElementTheme .colors.iconSecondary,
182+ strokeWidth = 2 .dp,
183+ )
184+ } else {
185+ Icon (
186+ resourceId = R .drawable.pause,
187+ contentDescription = stringResource(id = CommonStrings .a11y_pause),
188+ )
189+ }
163190 }
164191}
165192
@@ -228,3 +255,12 @@ internal fun TimelineItemVoiceViewUnifiedPreview() = ElementPreview {
228255 }
229256 }
230257}
258+
259+ @PreviewsDayNight
260+ @Composable
261+ internal fun ProgressButtonPreview () = ElementPreview {
262+ Row {
263+ ProgressButton (displayImmediately = true )
264+ ProgressButton (displayImmediately = false )
265+ }
266+ }
0 commit comments