Merge pull request #917 from j-f1/translated-info-view-a11y

IOS-81: Make “Translated From” UI accessible
This commit is contained in:
Marcus Kida 2023-02-07 09:48:16 +01:00 committed by GitHub
commit f4b3f7550a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 49 deletions

View File

@ -186,7 +186,7 @@
"translated_from": "Translated from %s using %s",
"unknown_language": "Unknown",
"unknown_provider": "Unknown",
"show_original": "Shown Original"
"show_original": "Show Original"
},
"media": {
"accessibility_label": "%s, attachment %d of %d",

View File

@ -186,7 +186,7 @@
"translated_from": "Translated from %s using %s",
"unknown_language": "Unknown",
"unknown_provider": "Unknown",
"show_original": "Shown Original"
"show_original": "Show Original"
},
"media": {
"accessibility_label": "%s, attachment %d of %d",

View File

@ -108,6 +108,7 @@ extension StatusThreadRootTableViewCell {
statusView.viewModel.isContentReveal
? statusView.contentMetaText.textView
: statusView.spoilerOverlayView,
statusView.translatedInfoView,
statusView.mediaGridContainerView,
statusView.pollTableView,
statusView.pollStatusStackView,

View File

@ -391,8 +391,8 @@ public enum L10n {
public static let url = L10n.tr("Localizable", "Common.Controls.Status.Tag.Url", fallback: "URL")
}
public enum Translation {
/// Shown Original
public static let showOriginal = L10n.tr("Localizable", "Common.Controls.Status.Translation.ShowOriginal", fallback: "Shown Original")
/// Show Original
public static let showOriginal = L10n.tr("Localizable", "Common.Controls.Status.Translation.ShowOriginal", fallback: "Show Original")
/// Translated from %@ using %@
public static func translatedFrom(_ p1: Any, _ p2: Any) -> String {
return L10n.tr("Localizable", "Common.Controls.Status.Translation.TranslatedFrom", String(describing: p1), String(describing: p2), fallback: "Translated from %@ using %@")

View File

@ -137,7 +137,7 @@ Please check your internet connection.";
"Common.Controls.Status.Tag.Mention" = "Mention";
"Common.Controls.Status.Tag.Url" = "URL";
"Common.Controls.Status.TapToReveal" = "Tap to reveal";
"Common.Controls.Status.Translation.ShowOriginal" = "Shown Original";
"Common.Controls.Status.Translation.ShowOriginal" = "Show Original";
"Common.Controls.Status.Translation.TranslatedFrom" = "Translated from %@ using %@";
"Common.Controls.Status.Translation.UnknownLanguage" = "Unknown";
"Common.Controls.Status.Translation.UnknownProvider" = "Unknown";

View File

@ -356,6 +356,18 @@ extension StatusView.ViewModel {
statusView.authorView.contentSensitiveeToggleButton.setImage(image, for: .normal)
}
.store(in: &disposeBag)
$isCurrentlyTranslating
.receive(on: DispatchQueue.main)
.sink { isTranslating in
switch isTranslating {
case true:
statusView.isTranslatingLoadingView.startAnimating()
case false:
statusView.isTranslatingLoadingView.stopAnimating()
}
}
.store(in: &disposeBag)
}
private func bindMedia(statusView: StatusView) {
@ -820,14 +832,39 @@ extension StatusView.ViewModel {
}
.assign(to: \.toolbarActions, on: statusView)
.store(in: &disposeBag)
Publishers.CombineLatest3(
let translatedFromLabel = Publishers.CombineLatest($translatedFromLanguage, $translatedUsingProvider)
.map { (language, provider) -> String? in
if let language {
return L10n.Common.Controls.Status.Translation.translatedFrom(
Locale.current.localizedString(forIdentifier: language) ?? L10n.Common.Controls.Status.Translation.unknownLanguage,
provider ?? L10n.Common.Controls.Status.Translation.unknownProvider
)
}
return nil
}
translatedFromLabel
.receive(on: DispatchQueue.main)
.sink { label in
if let label {
statusView.translatedInfoLabel.text = label
statusView.translatedInfoView.accessibilityValue = label
statusView.translatedInfoView.isHidden = false
} else {
statusView.translatedInfoView.isHidden = true
}
}
.store(in: &disposeBag)
Publishers.CombineLatest4(
shortAuthorAccessibilityLabel,
contentAccessibilityLabel,
translatedFromLabel,
mediaAccessibilityLabel
)
.map { author, content, media in
var labels: [String?] = [content, media]
.map { author, content, translated, media in
var labels: [String?] = [content, translated, media]
if statusView.style != .notification {
labels.insert(author, at: 0)

View File

@ -190,15 +190,24 @@ public final class StatusView: UIView {
activityIndicatorView.stopAnimating()
return activityIndicatorView
}()
private let translatedInfoLabel: UILabel = {
let translatedInfoLabel: UILabel = {
let label = UILabel()
label.font = UIFontMetrics(forTextStyle: .footnote).scaledFont(for: .systemFont(ofSize: 13, weight: .regular))
label.textColor = Asset.Colors.Label.secondary.color
label.numberOfLines = 0
return label
}()
lazy var translatedInfoView: UIView = {
let containerView = UIView()
private class TranslatedInfoView: UIView {
var revertAction: (() -> Void)?
override func accessibilityActivate() -> Bool {
revertAction?()
return true
}
}
public private(set) lazy var translatedInfoView: UIView = {
let containerView = TranslatedInfoView()
let revertButton = UIButton()
revertButton.titleLabel?.font = UIFontMetrics(forTextStyle: .footnote).scaledFont(for: .systemFont(ofSize: 13, weight: .bold))
@ -230,7 +239,14 @@ public final class StatusView: UIView {
])
containerView.isHidden = true
containerView.isAccessibilityElement = true
containerView.accessibilityLabel = L10n.Common.Controls.Status.Translation.showOriginal
containerView.accessibilityTraits = [.button]
containerView.revertAction = { [weak self] in
self?.revertTranslation()
}
return containerView
}()
@ -270,7 +286,6 @@ public final class StatusView: UIView {
setPollDisplay(isDisplay: false)
setFilterHintLabelDisplay(isDisplay: false)
setStatusCardControlDisplay(isDisplay: false)
setupTranslationIndicator()
}
public override init(frame: CGRect) {
@ -612,10 +627,19 @@ extension StatusView {
get {
(contentMetaText.textView.accessibilityCustomActions ?? [])
+ toolbarActions
+ (hideTranslationAction.map { [$0] } ?? [])
+ (authorView.accessibilityCustomActions ?? [])
}
set { }
}
private var hideTranslationAction: UIAccessibilityCustomAction? {
guard viewModel.translatedFromLanguage != nil else { return nil }
return UIAccessibilityCustomAction(name: L10n.Common.Controls.Status.Translation.showOriginal) { [weak self] _ in
self?.revertTranslation()
return true
}
}
}
// MARK: - AdaptiveContainerView
@ -728,41 +752,6 @@ extension StatusView: MastodonMenuDelegate {
}
}
extension StatusView {
func setupTranslationIndicator() {
viewModel.$isCurrentlyTranslating
.receive(on: DispatchQueue.main)
.sink { [weak self] isTranslating in
switch isTranslating {
case true:
self?.isTranslatingLoadingView.startAnimating()
case false:
self?.isTranslatingLoadingView.stopAnimating()
}
}
.store(in: &disposeBag)
Publishers.CombineLatest(
viewModel.$translatedFromLanguage,
viewModel.$translatedUsingProvider
)
.receive(on: DispatchQueue.main)
.sink { [weak self] translatedFromLanguage, translatedUsingProvider in
guard let self = self else { return }
if let translatedFromLanguage = translatedFromLanguage {
self.translatedInfoLabel.text = L10n.Common.Controls.Status.Translation.translatedFrom(
Locale.current.localizedString(forIdentifier: translatedFromLanguage) ?? L10n.Common.Controls.Status.Translation.unknownLanguage,
translatedUsingProvider ?? L10n.Common.Controls.Status.Translation.unknownProvider
)
self.translatedInfoView.isHidden = false
} else {
self.translatedInfoView.isHidden = true
}
}
.store(in: &disposeBag)
}
}
// MARK: StatusCardControlDelegate
extension StatusView: StatusCardControlDelegate {
public func statusCardControl(_ statusCardControl: StatusCardControl, didTapURL url: URL) {