a11y: better voice over for voice messages

This commit is contained in:
Mauro Romito
2025-03-27 17:40:00 +01:00
committed by Mauro
parent a4eeb66527
commit f507709626
6 changed files with 45 additions and 14 deletions
+8
View File
@@ -34,6 +34,10 @@ internal enum L10n {
}
/// Pause
internal static var a11yPause: String { return L10n.tr("Localizable", "a11y_pause") }
/// Voice message, duration: %1$@, current position: %2$@
internal static func a11yPausedVoiceMessage(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "a11y_paused_voice_message", String(describing: p1), String(describing: p2))
}
/// PIN field
internal static var a11yPinField: String { return L10n.tr("Localizable", "a11y_pin_field") }
/// Play
@@ -76,6 +80,10 @@ internal enum L10n {
internal static var a11yStartCall: String { return L10n.tr("Localizable", "a11y_start_call") }
/// User menu
internal static var a11yUserMenu: String { return L10n.tr("Localizable", "a11y_user_menu") }
/// Voice message, duration: %1$@
internal static func a11yVoiceMessage(_ p1: Any) -> String {
return L10n.tr("Localizable", "a11y_voice_message", String(describing: p1))
}
/// Record voice message.
internal static var a11yVoiceMessageRecord: String { return L10n.tr("Localizable", "a11y_voice_message_record") }
/// Stop recording
@@ -14,7 +14,7 @@ private struct TimelineItemAccessibilityModifier: ViewModifier {
@ViewBuilder
func body(content: Content) -> some View {
switch timelineItem {
case is PollRoomTimelineItem, is VoiceMessageRoomTimelineItem:
case is PollRoomTimelineItem:
content
.accessibilityActions {
Button(L10n.commonMessageActions) {
@@ -16,7 +16,6 @@ struct VoiceMessageRoomTimelineView: View {
TimelineStyler(timelineItem: timelineItem) {
VoiceMessageRoomTimelineContent(timelineItem: timelineItem,
playerState: playerState)
.accessibilityLabel(L10n.commonVoiceMessage)
.frame(maxWidth: 400)
}
}
@@ -18,18 +18,6 @@ struct VoiceMessageRoomPlaybackView: View {
let onPlayPause: () -> Void
let onSeek: (Double) -> Void
let onScrubbing: (Bool) -> Void
var timeLabelContent: String {
// Display the duration if progress is 0.0
let percent = playerState.progress > 0.0 ? playerState.progress : 1.0
// If the duration is greater or equal 10 minutes, use the long format
let elapsed = Date(timeIntervalSinceReferenceDate: playerState.duration * percent)
if playerState.duration >= 600 {
return DateFormatter.longElapsedTimeFormatter.string(from: elapsed)
} else {
return DateFormatter.elapsedTimeFormatter.string(from: elapsed)
}
}
var body: some View {
HStack(spacing: 8) {
@@ -54,6 +42,38 @@ struct VoiceMessageRoomPlaybackView: View {
.onChange(of: isDragging) { _, newValue in
onScrubbing(newValue)
}
.accessibilityLabel(accessibilityLabel)
}
// MARK: - Private
private var durationString: String {
let duration = Date(timeIntervalSinceReferenceDate: playerState.duration)
return if playerState.duration >= 600 {
DateFormatter.longElapsedTimeFormatter.string(from: duration)
} else {
DateFormatter.elapsedTimeFormatter.string(from: duration)
}
}
private var timeLabelContent: String {
// Display the duration if progress is 0.0
let percent = playerState.progress > 0.0 ? playerState.progress : 1.0
// If the duration is greater or equal 10 minutes, use the long format
let elapsed = Date(timeIntervalSinceReferenceDate: playerState.duration * percent)
if playerState.duration >= 600 {
return DateFormatter.longElapsedTimeFormatter.string(from: elapsed)
} else {
return DateFormatter.elapsedTimeFormatter.string(from: elapsed)
}
}
private var accessibilityLabel: String {
if playerState.progress > 0.0 {
L10n.a11yPausedVoiceMessage(durationString, timeLabelContent)
} else {
L10n.a11yVoiceMessage(durationString)
}
}
@ViewBuilder