From 1ce756a84996e76a8ed53eb454e8afab15056e1f Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Thu, 3 Nov 2022 14:59:58 -0400 Subject: [PATCH 1/5] Add accessibility actions for links/mentions/hashtags in posts --- .../TableviewCell/StatusTableViewCell.swift | 4 +++ .../Extension/MetaEntity+Accessibility.swift | 26 +++++++++++++++++++ .../View/Content/StatusView+ViewModel.swift | 20 +++++++++++--- .../MastodonUI/View/Content/StatusView.swift | 7 +++++ 4 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift diff --git a/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift index a3315211e..c9850a0d3 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift @@ -99,6 +99,10 @@ extension StatusTableViewCell { return true } + override var accessibilityCustomActions: [UIAccessibilityCustomAction]? { + get { statusView.accessibilityCustomActions } + set { } + } } // MARK: - AdaptiveContainerMarginTableViewCell diff --git a/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift b/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift new file mode 100644 index 000000000..8c818e7d4 --- /dev/null +++ b/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift @@ -0,0 +1,26 @@ +// +// MetaEntity+Accessibility.swift +// +// +// Created by Jed Fox on 2022-11-03. +// + +import Meta + +extension Meta.Entity { + var accessibilityCustomActionLabel: String? { + switch meta { + case .url(_, trimmed: _, url: let url, userInfo: _): + return "Link: \(url)" + case .hashtag(_, hashtag: let hashtag, userInfo: _): + return "Hashtag \(hashtag)" + case .mention(_, mention: let mention, userInfo: _): + return "Show Profile: @\(mention)" + case .email(let email, userInfo: _): + return "Email address: \(email)" + // emoji are not actionable + case .emoji: + return nil + } + } +} diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift index d0b5daa6f..416226cbb 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift @@ -315,7 +315,6 @@ extension StatusView.ViewModel { statusView.contentMetaText.configure( content: content ) - statusView.contentMetaText.textView.accessibilityLabel = content.string statusView.contentMetaText.textView.accessibilityTraits = [.staticText] statusView.contentMetaText.textView.accessibilityElementsHidden = false } else { @@ -727,8 +726,23 @@ extension StatusView.ViewModel { statusView.accessibilityLabel = accessibilityLabel } .store(in: &disposeBag) + + Publishers.CombineLatest( + $content, + $isContentReveal.removeDuplicates() + ) + .map { content, isRevealed in + guard isRevealed, let entities = content?.entities else { return [] } + return entities.compactMap { entity in + guard let name = entity.accessibilityCustomActionLabel else { return nil } + return UIAccessibilityCustomAction(name: name) { action in + statusView.delegate?.statusView(statusView, metaText: statusView.contentMetaText, didSelectMeta: entity.meta) + return true + } + } + } + .assign(to: \.accessibilityCustomActions, on: statusView.contentMetaText.textView) + .store(in: &disposeBag) } } - - diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift index 8ab34ce4f..563bc7e3d 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift @@ -547,6 +547,13 @@ extension StatusView { } +extension StatusView { + public override var accessibilityCustomActions: [UIAccessibilityCustomAction]? { + get { contentMetaText.textView.accessibilityCustomActions } + set { } + } +} + // MARK: - AdaptiveContainerView extension StatusView: AdaptiveContainerView { public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) { From aa87340345080e3d5b004158a804473e36a34ee1 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Mon, 7 Nov 2022 18:21:19 -0500 Subject: [PATCH 2/5] set up translations for link labels --- Localization/app.json | 10 +++++++++- .../Extension/MetaEntity+Accessibility.swift | 6 +++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Localization/app.json b/Localization/app.json index a965b23ae..707faf3ef 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -685,5 +685,13 @@ "multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.", "accessibility_hint": "Double tap to dismiss this wizard" } + }, + "a11y": { + "meta_entity": { + "url": "Link: %s", + "hashtag": "Hastag %s", + "mention": "Show Profile: %s", + "email": "Email address: %s", + } } -} \ No newline at end of file +} diff --git a/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift b/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift index 8c818e7d4..9319617bb 100644 --- a/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift +++ b/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift @@ -11,12 +11,16 @@ extension Meta.Entity { var accessibilityCustomActionLabel: String? { switch meta { case .url(_, trimmed: _, url: let url, userInfo: _): + // TODO: i18n (a11y.meta_entity.url) return "Link: \(url)" case .hashtag(_, hashtag: let hashtag, userInfo: _): + // TODO: i18n (a11y.meta_entity.hashtag) return "Hashtag \(hashtag)" case .mention(_, mention: let mention, userInfo: _): - return "Show Profile: @\(mention)" + // TODO: i18n (a11y.meta_entity.mention) + return "Show Profile: \("@" + mention)" case .email(let email, userInfo: _): + // TODO: i18n (a11y.meta_entity.email) return "Email address: \(email)" // emoji are not actionable case .emoji: From d96f189980917992d9b832d5dd9251893792dc04 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Tue, 8 Nov 2022 10:28:49 -0500 Subject: [PATCH 3/5] =?UTF-8?q?Consistently=20handle=20=E2=80=9CA11y?= =?UTF-8?q?=E2=80=9D=20key?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StringsConvertor/Sources/StringsConvertor/Parser.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift b/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift index ba9750cd4..c355493fe 100644 --- a/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift +++ b/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift @@ -43,7 +43,12 @@ extension Parser { .map { switch keyStyle { case .infoPlist: return $0 - case .swiftgen: return $0.capitalized + case .swiftgen: + if $0 == "a11y" { + return "A11y" + } else { + return $0.capitalized + } } } .joined() From 24c426f7f3260052dc34d301a5510827ccc70ab9 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Tue, 8 Nov 2022 13:30:17 -0500 Subject: [PATCH 4/5] Add localization info --- .../StringsConvertor/input/en.lproj/app.json | 6 ++++++ Localization/app.json | 14 ++++++-------- .../Generated/Strings.swift | 18 ++++++++++++++++++ .../Resources/en.lproj/Localizable.strings | 4 ++++ .../Extension/MetaEntity+Accessibility.swift | 13 +++++-------- 5 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Localization/StringsConvertor/input/en.lproj/app.json b/Localization/StringsConvertor/input/en.lproj/app.json index a965b23ae..702811c14 100644 --- a/Localization/StringsConvertor/input/en.lproj/app.json +++ b/Localization/StringsConvertor/input/en.lproj/app.json @@ -136,6 +136,12 @@ "vote": "Vote", "closed": "Closed" }, + "meta_entity": { + "url": "Link: %s", + "hashtag": "Hastag %s", + "mention": "Show Profile: %s", + "email": "Email address: %s" + }, "actions": { "reply": "Reply", "reblog": "Reblog", diff --git a/Localization/app.json b/Localization/app.json index 707faf3ef..31972b075 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -136,6 +136,12 @@ "vote": "Vote", "closed": "Closed" }, + "meta_entity": { + "url": "Link: %s", + "hashtag": "Hastag %s", + "mention": "Show Profile: %s", + "email": "Email address: %s" + }, "actions": { "reply": "Reply", "reblog": "Reblog", @@ -685,13 +691,5 @@ "multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.", "accessibility_hint": "Double tap to dismiss this wizard" } - }, - "a11y": { - "meta_entity": { - "url": "Link: %s", - "hashtag": "Hastag %s", - "mention": "Show Profile: %s", - "email": "Email address: %s", - } } } diff --git a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift index c64a50fa2..1bf067226 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift +++ b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift @@ -314,6 +314,24 @@ public enum L10n { /// Undo reblog public static let unreblog = L10n.tr("Localizable", "Common.Controls.Status.Actions.Unreblog") } + public enum MetaEntity { + /// Email address: %@ + public static func email(_ p1: Any) -> String { + return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Email", String(describing: p1)) + } + /// Hastag %@ + public static func hashtag(_ p1: Any) -> String { + return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Hashtag", String(describing: p1)) + } + /// Show Profile: %@ + public static func mention(_ p1: Any) -> String { + return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Mention", String(describing: p1)) + } + /// Link: %@ + public static func url(_ p1: Any) -> String { + return L10n.tr("Localizable", "Common.Controls.Status.MetaEntity.Url", String(describing: p1)) + } + } public enum Poll { /// Closed public static let closed = L10n.tr("Localizable", "Common.Controls.Status.Poll.Closed") diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings index 1c40bf855..6b7d2348f 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings @@ -108,6 +108,10 @@ Please check your internet connection."; "Common.Controls.Status.Actions.Unbookmark" = "Unbookmark"; "Common.Controls.Status.ContentWarning" = "Content Warning"; "Common.Controls.Status.MediaContentWarning" = "Tap anywhere to reveal"; +"Common.Controls.Status.MetaEntity.Email" = "Email address: %@"; +"Common.Controls.Status.MetaEntity.Hashtag" = "Hastag %@"; +"Common.Controls.Status.MetaEntity.Mention" = "Show Profile: %@"; +"Common.Controls.Status.MetaEntity.Url" = "Link: %@"; "Common.Controls.Status.Poll.Closed" = "Closed"; "Common.Controls.Status.Poll.Vote" = "Vote"; "Common.Controls.Status.SensitiveContent" = "Sensitive Content"; diff --git a/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift b/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift index 9319617bb..b604a3870 100644 --- a/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift +++ b/MastodonSDK/Sources/MastodonUI/Extension/MetaEntity+Accessibility.swift @@ -6,22 +6,19 @@ // import Meta +import MastodonLocalization extension Meta.Entity { var accessibilityCustomActionLabel: String? { switch meta { case .url(_, trimmed: _, url: let url, userInfo: _): - // TODO: i18n (a11y.meta_entity.url) - return "Link: \(url)" + return L10n.Common.Controls.Status.MetaEntity.url(url) case .hashtag(_, hashtag: let hashtag, userInfo: _): - // TODO: i18n (a11y.meta_entity.hashtag) - return "Hashtag \(hashtag)" + return L10n.Common.Controls.Status.MetaEntity.hashtag(hashtag) case .mention(_, mention: let mention, userInfo: _): - // TODO: i18n (a11y.meta_entity.mention) - return "Show Profile: \("@" + mention)" + return L10n.Common.Controls.Status.MetaEntity.mention(mention) case .email(let email, userInfo: _): - // TODO: i18n (a11y.meta_entity.email) - return "Email address: \(email)" + return L10n.Common.Controls.Status.MetaEntity.email(email) // emoji are not actionable case .emoji: return nil From fcf38a15d69a7659882eb823a5257806109db0bd Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Wed, 9 Nov 2022 07:35:06 -0500 Subject: [PATCH 5/5] =?UTF-8?q?Revert=20"Consistently=20handle=20=E2=80=9C?= =?UTF-8?q?A11y=E2=80=9D=20key"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d96f189980917992d9b832d5dd9251893792dc04. --- .../StringsConvertor/Sources/StringsConvertor/Parser.swift | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift b/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift index c355493fe..ba9750cd4 100644 --- a/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift +++ b/Localization/StringsConvertor/Sources/StringsConvertor/Parser.swift @@ -43,12 +43,7 @@ extension Parser { .map { switch keyStyle { case .infoPlist: return $0 - case .swiftgen: - if $0 == "a11y" { - return "A11y" - } else { - return $0.capitalized - } + case .swiftgen: return $0.capitalized } } .joined()