Merge pull request #917 from j-f1/translated-info-view-a11y
IOS-81: Make “Translated From” UI accessible
This commit is contained in:
commit
f4b3f7550a
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -108,6 +108,7 @@ extension StatusThreadRootTableViewCell {
|
|||
statusView.viewModel.isContentReveal
|
||||
? statusView.contentMetaText.textView
|
||||
: statusView.spoilerOverlayView,
|
||||
statusView.translatedInfoView,
|
||||
statusView.mediaGridContainerView,
|
||||
statusView.pollTableView,
|
||||
statusView.pollStatusStackView,
|
||||
|
|
|
@ -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 %@")
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue