mirror of
https://github.com/mastodon/mastodon-ios.git
synced 2025-01-30 00:55:25 +01:00
Merge branch 'develop' into IOS-37_Widgets
This commit is contained in:
commit
e88dea0034
@ -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",
|
||||
|
@ -62,6 +62,7 @@ extension HomeTimelineNavigationBarTitleView {
|
||||
button.addTarget(self, action: #selector(HomeTimelineNavigationBarTitleView.buttonDidPressed(_:)), for: .touchUpInside)
|
||||
|
||||
logoButton.accessibilityIdentifier = "TitleButton"
|
||||
logoButton.accessibilityTraits = [.header, .button]
|
||||
button.accessibilityIdentifier = "TitleButton"
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ final class SearchHistorySectionHeaderCollectionReusableView: UICollectionReusab
|
||||
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 22, weight: .bold))
|
||||
label.textColor = Asset.Colors.Label.primary.color
|
||||
label.text = L10n.Scene.Search.Searching.recentSearch
|
||||
label.accessibilityTraits.insert(.header)
|
||||
return label
|
||||
}()
|
||||
|
||||
@ -32,6 +33,8 @@ final class SearchHistorySectionHeaderCollectionReusableView: UICollectionReusab
|
||||
let button = UIButton(type: .system)
|
||||
button.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
|
||||
button.tintColor = Asset.Colors.Label.secondary.color
|
||||
button.accessibilityLabel = L10n.Scene.Search.Searching.clear
|
||||
|
||||
return button
|
||||
}()
|
||||
|
||||
|
@ -51,9 +51,11 @@ extension SearchHistoryUserCollectionViewCell {
|
||||
NSLayoutConstraint.activate([
|
||||
userView.topAnchor.constraint(equalTo: contentView.topAnchor),
|
||||
userView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
|
||||
userView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 16),
|
||||
contentView.trailingAnchor.constraint(equalTo: userView.trailingAnchor, constant: 16),
|
||||
userView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
|
||||
])
|
||||
|
||||
userView.accessibilityTraits.insert(.button)
|
||||
}
|
||||
|
||||
override func updateConfiguration(using state: UICellConfigurationState) {
|
||||
|
@ -108,6 +108,7 @@ extension StatusThreadRootTableViewCell {
|
||||
statusView.viewModel.isContentReveal
|
||||
? statusView.contentMetaText.textView
|
||||
: statusView.spoilerOverlayView,
|
||||
statusView.translatedInfoView,
|
||||
statusView.mediaGridContainerView,
|
||||
statusView.pollTableView,
|
||||
statusView.pollStatusStackView,
|
||||
|
@ -61,6 +61,8 @@ extension UserTableViewCell {
|
||||
separatorLine.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
|
||||
separatorLine.heightAnchor.constraint(equalToConstant: UIView.separatorLineHeight(of: contentView)).priority(.required - 1),
|
||||
])
|
||||
|
||||
userView.accessibilityTraits.insert(.button)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -36,6 +36,7 @@ open class AvatarButton: UIControl {
|
||||
|
||||
isAccessibilityElement = true
|
||||
accessibilityLabel = L10n.Common.Controls.Status.showUserProfile
|
||||
accessibilityTraits.insert(.image)
|
||||
}
|
||||
|
||||
public override func layoutSubviews() {
|
||||
|
@ -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) {
|
||||
|
@ -52,15 +52,27 @@ extension UserView.ViewModel {
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
// username
|
||||
$authorUsername
|
||||
let displayUsername = $authorUsername
|
||||
.map { text -> String in
|
||||
guard let text = text else { return "" }
|
||||
return "@\(text)"
|
||||
}
|
||||
|
||||
displayUsername
|
||||
.sink { username in
|
||||
let metaContent = PlaintextMetaContent(string: username)
|
||||
userView.authorUsernameLabel.configure(content: metaContent)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
Publishers.CombineLatest($authorName, displayUsername)
|
||||
.sink { name, username in
|
||||
if let name {
|
||||
userView.accessibilityLabel = "\(name.string), \(username)"
|
||||
} else {
|
||||
userView.accessibilityLabel = username
|
||||
}
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
}
|
||||
|
@ -90,6 +90,8 @@ extension UserView {
|
||||
avatarButton.isUserInteractionEnabled = false
|
||||
authorNameLabel.isUserInteractionEnabled = false
|
||||
authorUsernameLabel.isUserInteractionEnabled = false
|
||||
|
||||
isAccessibilityElement = true
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user