From f728ea652e17e3984d03628082d5c7a45b229a1b Mon Sep 17 00:00:00 2001 From: Chris Kolbu Date: Mon, 3 Apr 2023 19:14:44 +1000 Subject: [PATCH] Accessibility bug fixes (#1348) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix bug affecting accessibillityRepresentation of type Toggle Previously, the action on the button would not get executed. This is a SwiftUI bug, as views passed into `accessibilityRepresentation` should not have any behaviour. Now, we set an equivalent `accessibilityValue` on|off to emulate the same functionality. * Remove conditional ViewModifier in favour of inlined modifier Since this view is part of the `StatusRowView` it’s better to err on the side of less branching with ModifiedContent<> * Avoid combining StatusRowMediaPreviewView accessibility children By combining the elements, the end result was that the intended action (opening QuickLook) was swallowed in favour of displaying the alt text alert of images. --- .../Localization/be.lproj/Localizable.strings | 2 ++ .../Localization/ca.lproj/Localizable.strings | 2 ++ .../Localization/de.lproj/Localizable.strings | 2 ++ .../en-GB.lproj/Localizable.strings | 2 ++ .../Localization/en.lproj/Localizable.strings | 2 ++ .../Localization/es.lproj/Localizable.strings | 2 ++ .../Localization/eu.lproj/Localizable.strings | 2 ++ .../Localization/fr.lproj/Localizable.strings | 2 ++ .../Localization/it.lproj/Localizable.strings | 2 ++ .../Localization/ja.lproj/Localizable.strings | 2 ++ .../Localization/ko.lproj/Localizable.strings | 2 ++ .../Localization/nb.lproj/Localizable.strings | 2 ++ .../Localization/nl.lproj/Localizable.strings | 2 ++ .../Localization/pl.lproj/Localizable.strings | 2 ++ .../pt-BR.lproj/Localizable.strings | 2 ++ .../Localization/tr.lproj/Localizable.strings | 2 ++ .../Localization/uk.lproj/Localizable.strings | 2 ++ .../zh-Hans.lproj/Localizable.strings | 2 ++ .../zh-Hant.lproj/Localizable.strings | 2 ++ .../Sources/Account/Follow/FollowButton.swift | 13 +++++----- .../Subviews/StatusRowMediaPreviewView.swift | 26 +++++++------------ 21 files changed, 53 insertions(+), 24 deletions(-) diff --git a/IceCubesApp/Resources/Localization/be.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/be.lproj/Localizable.strings index ebcd9725..d82ae5ab 100644 --- a/IceCubesApp/Resources/Localization/be.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/be.lproj/Localizable.strings @@ -517,6 +517,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Далучыць фота"; "accessibility.editor.button.poll" = "Апытанне"; "accessibility.editor.button.spoiler" = "Папярэджанне пра спойлер"; diff --git a/IceCubesApp/Resources/Localization/ca.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/ca.lproj/Localizable.strings index 7ab39e50..971e7c61 100644 --- a/IceCubesApp/Resources/Localization/ca.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/ca.lproj/Localizable.strings @@ -511,6 +511,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Attach photo"; "accessibility.editor.button.poll" = "Poll"; "accessibility.editor.button.spoiler" = "Spoiler warning"; diff --git a/IceCubesApp/Resources/Localization/de.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/de.lproj/Localizable.strings index 206a6bf5..1341a2af 100644 --- a/IceCubesApp/Resources/Localization/de.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/de.lproj/Localizable.strings @@ -500,6 +500,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Foto anhängen"; "accessibility.editor.button.poll" = "Umfrage"; "accessibility.editor.button.spoiler" = "Inhaltswarnung"; diff --git a/IceCubesApp/Resources/Localization/en-GB.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/en-GB.lproj/Localizable.strings index 043f85ae..0f83d290 100644 --- a/IceCubesApp/Resources/Localization/en-GB.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/en-GB.lproj/Localizable.strings @@ -512,6 +512,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Attach photo"; "accessibility.editor.button.poll" = "Poll"; "accessibility.editor.button.spoiler" = "Spoiler warning"; diff --git a/IceCubesApp/Resources/Localization/en.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/en.lproj/Localizable.strings index 20c80242..f7b984d4 100644 --- a/IceCubesApp/Resources/Localization/en.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/en.lproj/Localizable.strings @@ -513,6 +513,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Attach photo"; "accessibility.editor.button.poll" = "Poll"; "accessibility.editor.button.spoiler" = "Spoiler warning"; diff --git a/IceCubesApp/Resources/Localization/es.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/es.lproj/Localizable.strings index fe55c8a2..198518d1 100644 --- a/IceCubesApp/Resources/Localization/es.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/es.lproj/Localizable.strings @@ -513,6 +513,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Añadir foto"; "accessibility.editor.button.poll" = "Encuesta"; "accessibility.editor.button.spoiler" = "Advertencia"; diff --git a/IceCubesApp/Resources/Localization/eu.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/eu.lproj/Localizable.strings index 11e5c85d..ea80e9c7 100644 --- a/IceCubesApp/Resources/Localization/eu.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/eu.lproj/Localizable.strings @@ -501,6 +501,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Erantsi irudia"; "accessibility.editor.button.poll" = "Bozketa"; "accessibility.editor.button.spoiler" = "Edukiari buruzko oharra"; diff --git a/IceCubesApp/Resources/Localization/fr.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/fr.lproj/Localizable.strings index 7cdfa322..d8a118c4 100644 --- a/IceCubesApp/Resources/Localization/fr.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/fr.lproj/Localizable.strings @@ -508,6 +508,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Attacher la photo"; "accessibility.editor.button.poll" = "Sondage"; "accessibility.editor.button.spoiler" = "Alerte spoiler"; diff --git a/IceCubesApp/Resources/Localization/it.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/it.lproj/Localizable.strings index 4c99133c..faf8ac89 100644 --- a/IceCubesApp/Resources/Localization/it.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/it.lproj/Localizable.strings @@ -512,6 +512,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Allega foto"; "accessibility.editor.button.poll" = "Sondaggio"; "accessibility.editor.button.spoiler" = "Avviso di Spoiler"; diff --git a/IceCubesApp/Resources/Localization/ja.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/ja.lproj/Localizable.strings index f29dba37..ba09b3b8 100644 --- a/IceCubesApp/Resources/Localization/ja.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/ja.lproj/Localizable.strings @@ -512,6 +512,8 @@ "filter.expiry-%@" = "有効期限: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "画像を添付"; "accessibility.editor.button.poll" = "投票"; "accessibility.editor.button.spoiler" = "ネタバレを警告"; diff --git a/IceCubesApp/Resources/Localization/ko.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/ko.lproj/Localizable.strings index 89e5db58..efd81d4c 100644 --- a/IceCubesApp/Resources/Localization/ko.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/ko.lproj/Localizable.strings @@ -514,6 +514,8 @@ "filter.expiry-%@" = "%@까지 가림"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "미디어 첨부"; "accessibility.editor.button.poll" = "투표"; "accessibility.editor.button.spoiler" = "열람 주의 문구"; diff --git a/IceCubesApp/Resources/Localization/nb.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/nb.lproj/Localizable.strings index 99e51db8..1b8dd9a6 100644 --- a/IceCubesApp/Resources/Localization/nb.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/nb.lproj/Localizable.strings @@ -512,6 +512,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Attach photo"; "accessibility.editor.button.poll" = "Poll"; "accessibility.editor.button.spoiler" = "Spoiler warning"; diff --git a/IceCubesApp/Resources/Localization/nl.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/nl.lproj/Localizable.strings index 079f1e2a..f4e5e003 100644 --- a/IceCubesApp/Resources/Localization/nl.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/nl.lproj/Localizable.strings @@ -509,6 +509,8 @@ "enum.expand-media.hide-sensitive" = "Verberg gevoelige"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Voeg foto toe"; "accessibility.editor.button.poll" = "Poll"; "accessibility.editor.button.spoiler" = "Spoilerwaarschuwing"; diff --git a/IceCubesApp/Resources/Localization/pl.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/pl.lproj/Localizable.strings index a638676e..94cf1f90 100644 --- a/IceCubesApp/Resources/Localization/pl.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/pl.lproj/Localizable.strings @@ -503,6 +503,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Dołącz zdjęcie"; "accessibility.editor.button.poll" = "Sondaż"; "accessibility.editor.button.spoiler" = "Ostrzeżenie o spoilerze"; diff --git a/IceCubesApp/Resources/Localization/pt-BR.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/pt-BR.lproj/Localizable.strings index e1047a85..8c8489a5 100644 --- a/IceCubesApp/Resources/Localization/pt-BR.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/pt-BR.lproj/Localizable.strings @@ -512,6 +512,8 @@ "filter.expiry-%@" = "Expiração: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Anexar foto"; "accessibility.editor.button.poll" = "Enquete"; "accessibility.editor.button.spoiler" = "Aviso de spoiler"; diff --git a/IceCubesApp/Resources/Localization/tr.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/tr.lproj/Localizable.strings index 9249fcbf..13a69351 100644 --- a/IceCubesApp/Resources/Localization/tr.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/tr.lproj/Localizable.strings @@ -512,6 +512,8 @@ "enum.expand-media.hide-sensitive" = "Hide Sensitive"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Attach photo"; "accessibility.editor.button.poll" = "Poll"; "accessibility.editor.button.spoiler" = "Spoiler warning"; diff --git a/IceCubesApp/Resources/Localization/uk.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/uk.lproj/Localizable.strings index 2600ad16..fd03e762 100644 --- a/IceCubesApp/Resources/Localization/uk.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/uk.lproj/Localizable.strings @@ -513,6 +513,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "Додати світлину"; "accessibility.editor.button.poll" = "Опитування"; "accessibility.editor.button.spoiler" = "Увага! Спойлер."; diff --git a/IceCubesApp/Resources/Localization/zh-Hans.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/zh-Hans.lproj/Localizable.strings index b0c5c8d8..26968aca 100644 --- a/IceCubesApp/Resources/Localization/zh-Hans.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/zh-Hans.lproj/Localizable.strings @@ -514,6 +514,8 @@ "enum.expand-media.hide-sensitive" = "隐藏敏感内容"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "添加图片"; "accessibility.editor.button.poll" = "投票"; "accessibility.editor.button.spoiler" = "剧透警告"; diff --git a/IceCubesApp/Resources/Localization/zh-Hant.lproj/Localizable.strings b/IceCubesApp/Resources/Localization/zh-Hant.lproj/Localizable.strings index 452589c8..6b39d0fa 100644 --- a/IceCubesApp/Resources/Localization/zh-Hant.lproj/Localizable.strings +++ b/IceCubesApp/Resources/Localization/zh-Hant.lproj/Localizable.strings @@ -513,6 +513,8 @@ "filter.expiry-%@" = "Expiry: %@"; // MARK: Accessibility +"accessibility.general.toggle.on" = "On"; +"accessibility.general.toggle.off" = "Off"; "accessibility.editor.button.attach-photo" = "附上相片"; "accessibility.editor.button.poll" = "投票"; "accessibility.editor.button.spoiler" = "劇透警告"; diff --git a/Packages/Account/Sources/Account/Follow/FollowButton.swift b/Packages/Account/Sources/Account/Follow/FollowButton.swift index 54c23fcd..9795f43f 100644 --- a/Packages/Account/Sources/Account/Follow/FollowButton.swift +++ b/Packages/Account/Sources/Account/Follow/FollowButton.swift @@ -97,9 +97,8 @@ public struct FollowButton: View { Text("account.follow.requested") } else { Text(viewModel.relationship.following ? "account.follow.following" : "account.follow.follow") - .accessibilityRepresentation { - Toggle("account.follow.following", isOn: .constant(viewModel.relationship.following)) - } + .accessibilityLabel("account.follow.following") + .accessibilityValue(viewModel.relationship.following ? "accessibility.general.toggle.on" : "accessibility.general.toggle.off") } } if viewModel.relationship.following, @@ -112,18 +111,18 @@ public struct FollowButton: View { } } label: { Image(systemName: viewModel.relationship.notifying ? "bell.fill" : "bell") - }.accessibilityRepresentation { - Toggle("accessibility.tabs.profile.user-notifications.label", isOn: .constant(viewModel.relationship.notifying)) } + .accessibilityLabel("accessibility.tabs.profile.user-notifications.label") + .accessibilityValue(viewModel.relationship.notifying ? "accessibility.general.toggle.on" : "accessibility.general.toggle.off") Button { Task { await viewModel.toggleReboosts() } } label: { Image(viewModel.relationship.showingReblogs ? "Rocket.Fill" : "Rocket") - }.accessibilityRepresentation { - Toggle("accessibility.tabs.profile.user-reblogs.label", isOn: .constant(viewModel.relationship.showingReblogs)) } + .accessibilityLabel("accessibility.tabs.profile.user-reblogs.label") + .accessibilityValue(viewModel.relationship.showingReblogs ? "accessibility.general.toggle.on" : "accessibility.general.toggle.off") } } } diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift index 1abedd06..5140e19f 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift @@ -90,8 +90,8 @@ public struct StatusRowMediaPreviewView: View { await quickLook.prepareFor(urls: attachments.compactMap { $0.url }, selectedURL: attachment.url!) } } - .accessibilityElement(children: .combine) - .modifier(ConditionalAccessibilityLabelAltTextModifier(attachment: attachment)) + .accessibilityElement(children: .ignore) + .accessibilityLabel(Self.accessibilityLabel(for: attachment)) .accessibilityAddTraits([.isButton, .isImage]) } else { if isCompact || theme.statusDisplayStyle == .compact { @@ -254,7 +254,6 @@ public struct StatusRowMediaPreviewView: View { .cornerRadius(4) } } - .accessibilityAddTraits(.isImage) case .gifv, .video, .audio: if let url = attachment.url { VideoPlayerView(viewModel: .init(url: url)) @@ -274,9 +273,9 @@ public struct StatusRowMediaPreviewView: View { await quickLook.prepareFor(urls: attachments.compactMap { $0.url }, selectedURL: attachment.url!) } } - .accessibilityElement(children: .combine) - .modifier(ConditionalAccessibilityLabelAltTextModifier(attachment: attachment)) - .accessibilityAddTraits(.isButton) + .accessibilityElement(children: .ignore) + .accessibilityLabel(Self.accessibilityLabel(for: attachment)) + .accessibilityAddTraits(attachment.supportedType == .image ? [.isImage, .isButton] : .isButton) } } @@ -335,21 +334,14 @@ public struct StatusRowMediaPreviewView: View { Spacer() } } -} -/// A ``ViewModifier`` that creates a suitable accessibility label for an image that may or may not have alt text -private struct ConditionalAccessibilityLabelAltTextModifier: ViewModifier { - let attachment: MediaAttachment - - func body(content: Content) -> some View { + private static func accessibilityLabel(for attachment: MediaAttachment) -> Text { if let altText = attachment.description { - content - .accessibilityLabel("accessibility.image.alt-text-\(altText)") + return Text("accessibility.image.alt-text-\(altText)") } else if let typeDescription = attachment.localizedTypeDescription { - content - .accessibilityLabel(typeDescription) + return Text(typeDescription) } else { - content + return Text("accessibility.tabs.profile.picker.media") } } }