Accessibility on RRs (#2094)

* added accessibility on the read receipts but there is something wrong in the generation

* voice over implementation for RRs

* Update ElementX/Sources/Screens/RoomScreen/View/Supplementary/TimelineReadReceiptsView.swift

Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com>

* done

* changelog

---------

Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com>
This commit is contained in:
Mauro
2023-11-16 17:51:25 +01:00
committed by GitHub
parent 0831c898ef
commit 93c6aa684b
8 changed files with 87 additions and 2 deletions
+18
View File
@@ -10,6 +10,10 @@ import Foundation
// swiftlint:disable explicit_type_interface function_parameter_count identifier_name line_length
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
public enum L10n {
/// Read by %1$@ and %2$@
public static func a11ReadReceiptsMultiple(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "a11_read_receipts_multiple", String(describing: p1), String(describing: p2))
}
/// Delete
public static var a11yDelete: String { return L10n.tr("Localizable", "a11y_delete") }
/// Plural format key: "%#@COUNT@"
@@ -32,6 +36,14 @@ public enum L10n {
public static var a11yPoll: String { return L10n.tr("Localizable", "a11y_poll") }
/// Ended poll
public static var a11yPollEnd: String { return L10n.tr("Localizable", "a11y_poll_end") }
/// Plural format key: "%#@COUNT@"
public static func a11yReadReceiptsMultipleWithOthers(_ p1: Int) -> String {
return L10n.tr("Localizable", "a11y_read_receipts_multiple_with_others", p1)
}
/// Read by %1$@
public static func a11yReadReceiptsSingle(_ p1: Any) -> String {
return L10n.tr("Localizable", "a11y_read_receipts_single", String(describing: p1))
}
/// Send files
public static var a11ySendFiles: String { return L10n.tr("Localizable", "a11y_send_files") }
/// Show password
@@ -180,6 +192,8 @@ public enum L10n {
public static var actionStaticMapLoad: String { return L10n.tr("Localizable", "action_static_map_load") }
/// Take photo
public static var actionTakePhoto: String { return L10n.tr("Localizable", "action_take_photo") }
/// Tap for options
public static var actionTapForOptions: String { return L10n.tr("Localizable", "action_tap_for_options") }
/// Try again
public static var actionTryAgain: String { return L10n.tr("Localizable", "action_try_again") }
/// View source
@@ -338,6 +352,10 @@ public enum L10n {
public static var commonSecurity: String { return L10n.tr("Localizable", "common_security") }
/// Sending…
public static var commonSending: String { return L10n.tr("Localizable", "common_sending") }
/// Sending failed
public static var commonSendingFailed: String { return L10n.tr("Localizable", "common_sending_failed") }
/// Sent
public static var commonSent: String { return L10n.tr("Localizable", "common_sent") }
/// Server not supported
public static var commonServerNotSupported: String { return L10n.tr("Localizable", "common_server_not_supported") }
/// Server URL
@@ -100,7 +100,11 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
VStack(alignment: alignment, spacing: -3) {
messageBubble
.timelineItemAccessibility(timelineItem) {
context.send(viewAction: .timelineItemMenu(itemID: timelineItem.id))
if adjustedDeliveryStatus == .sendingFailed {
context.sendFailedConfirmationDialogInfo = .init(itemID: timelineItem.id)
} else {
context.send(viewAction: .timelineItemMenu(itemID: timelineItem.id))
}
}
if !timelineItem.properties.reactions.isEmpty {
@@ -206,6 +210,7 @@ struct TimelineItemBubbledStylerView<Content: View>: View {
if adjustedDeliveryStatus == .sendingFailed {
CompoundIcon(\.error, size: .xSmall, relativeTo: .compound.bodyXS)
.accessibilityLabel(L10n.commonSendingFailed)
}
}
.font(.compound.bodyXS)
@@ -37,6 +37,16 @@ struct TimelineDeliveryStatusView: View {
var body: some View {
icon
.foregroundColor(.compound.iconSecondary)
.accessibilityLabel(accessibilityLabel)
}
private var accessibilityLabel: String {
switch deliveryStatus {
case .sending:
return L10n.commonSending
case .sent:
return L10n.commonSent
}
}
}
@@ -59,6 +59,8 @@ struct TimelineItemStatusView: View {
.onTapGesture {
context.sendFailedConfirmationDialogInfo = .init(itemID: timelineItem.id)
}
.accessibilityLabel(L10n.commonSendingFailed)
.accessibilityHint(L10n.actionTapForOptions)
}
}
}
@@ -40,12 +40,40 @@ struct TimelineReadReceiptsView: View {
}
}
if timelineItem.properties.orderedReadReceipts.count > displayNumber {
let remaining = timelineItem.properties.orderedReadReceipts.count - displayNumber
Text("+\(remaining)")
.font(.compound.bodySM)
.foregroundColor(.compound.textPrimary)
}
}
.accessibilityElement(children: .ignore)
.accessibilityLabel(accessibilityLabel)
}
private var remaining: Int {
timelineItem.properties.orderedReadReceipts.count - displayNumber
}
private var accessibilityLabel: String {
if timelineItem.properties.orderedReadReceipts.count == 1 {
return L10n.a11yReadReceiptsSingle(displayName(at: 0))
} else if timelineItem.properties.orderedReadReceipts.count <= displayNumber {
let limit = timelineItem.properties.orderedReadReceipts.count - 1
let list = (0..<limit).map { displayName(at: $0) }.formatted(.list(type: .and, width: .narrow))
let last = displayName(at: limit)
return L10n.a11ReadReceiptsMultiple(list, last)
} else if timelineItem.properties.orderedReadReceipts.count > displayNumber {
let list = (0..<displayNumber).map { displayName(at: $0) }.formatted(.list(type: .and, width: .narrow))
// Plurals with string arguments aren't generated correctly so we need to use this
// https://github.com/SwiftGen/SwiftGen/issues/1089
return L10n.tr("Localizable", "a11y_read_receipts_multiple_with_others", list, remaining)
}
return ""
}
private func displayName(at index: Int) -> String {
let userID = timelineItem.properties.orderedReadReceipts[index].userID
return context.viewState.members[userID]?.displayName ?? userID
}
}