diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt
index b06b97f491..8d94ba9d2e 100644
--- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt
+++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/local/player/MediaPlayerControllerView.kt
@@ -28,6 +28,9 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
@@ -100,36 +103,54 @@ fun MediaPlayerControllerView(
contentColor = ElementTheme.colors.iconOnSolidPrimary,
)
}
+ val a11yPause = stringResource(CommonStrings.a11y_pause)
+ val a11yPlay = stringResource(CommonStrings.a11y_play)
IconButton(
modifier = Modifier
- .size(36.dp),
+ .size(36.dp)
+ .semantics {
+ stateDescription = if (state.isPlaying) a11yPause else a11yPlay
+ },
onClick = onTogglePlay,
colors = colors,
) {
if (state.isPlaying) {
Icon(
imageVector = CompoundIcons.PauseSolid(),
- contentDescription = stringResource(CommonStrings.a11y_pause)
+ contentDescription = null,
)
} else {
Icon(
imageVector = CompoundIcons.PlaySolid(),
- contentDescription = stringResource(CommonStrings.a11y_play)
+ contentDescription = null,
)
}
}
+ val position = state.displayProgressInMillis.toHumanReadableDuration()
+ val a11yPosition = stringResource(CommonStrings.a11y_position, position)
Text(
modifier = Modifier
.widthIn(min = 48.dp)
- .padding(horizontal = 8.dp),
- text = state.displayProgressInMillis.toHumanReadableDuration(),
+ .padding(horizontal = 8.dp)
+ .semantics {
+ contentDescription = a11yPosition
+ },
+ text = position,
textAlign = TextAlign.Center,
color = ElementTheme.colors.textPrimary,
style = ElementTheme.typography.fontBodyXsMedium,
)
var lastSelectedValue by remember { mutableFloatStateOf(-1f) }
Slider(
- modifier = Modifier.weight(1f),
+ modifier = Modifier
+ .weight(1f)
+ .semantics {
+ // Speak out a progress percent instead of milliseconds
+ stateDescription = buildString {
+ append((state.progressAsFloat * 100).toInt())
+ append("%")
+ }
+ },
valueRange = 0f..state.durationInMillis.toFloat(),
value = lastSelectedValue.takeIf { it >= 0 }
?: state.seekingToMillis?.toFloat()
@@ -146,10 +167,14 @@ fun MediaPlayerControllerView(
val formattedDuration = remember(state.durationInMillis) {
state.durationInMillis.toHumanReadableDuration()
}
+ val a11yDuration = stringResource(CommonStrings.a11y_duration, formattedDuration)
Text(
modifier = Modifier
.widthIn(min = 48.dp)
- .padding(horizontal = 8.dp),
+ .padding(horizontal = 8.dp)
+ .semantics {
+ contentDescription = a11yDuration
+ },
text = formattedDuration,
textAlign = TextAlign.Center,
color = ElementTheme.colors.textPrimary,
diff --git a/libraries/ui-strings/src/main/res/values/localazy.xml b/libraries/ui-strings/src/main/res/values/localazy.xml
index ee0f51000a..fd3679a140 100644
--- a/libraries/ui-strings/src/main/res/values/localazy.xml
+++ b/libraries/ui-strings/src/main/res/values/localazy.xml
@@ -9,6 +9,7 @@
- "%1$d digit entered"
- "%1$d digits entered"
+ "Duration: %1$s"
"Edit avatar"
"The full address will be %1$s"
"Encryption details"
@@ -33,6 +34,7 @@
"Playback speed"
"Poll"
"Ended poll"
+ "Position: %1$s"
"QR Code"
"React with %1$s"
"React with other emojis"