VoiceOver wip

This commit is contained in:
Justin Mazzocchi 2021-02-02 12:18:15 -08:00
parent e4b4e0eaff
commit 783b88b54a
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
4 changed files with 53 additions and 3 deletions

View file

@ -3,6 +3,7 @@
"about" = "About"; "about" = "About";
"about.acknowledgments" = "Acknowledgments"; "about.acknowledgments" = "Acknowledgments";
"account.%@-followers" = "%@'s Followers"; "account.%@-followers" = "%@'s Followers";
"account.avatar.accessibility-label-%@" = "Avatar: %@";
"account.block" = "Block"; "account.block" = "Block";
"account.block.confirm-%@" = "Block %@?"; "account.block.confirm-%@" = "Block %@?";
"account.domain-block-%@" = "Block domain %@"; "account.domain-block-%@" = "Block domain %@";
@ -15,6 +16,7 @@
"account.following-count" = "%ld Following"; "account.following-count" = "%ld Following";
"account.followed-by-%@" = "Followed by %@"; "account.followed-by-%@" = "Followed by %@";
"account.follows-you" = "Follows you"; "account.follows-you" = "Follows you";
"account.header.accessibility-label-%@" = "Header image: %@";
"account.hide-reblogs" = "Hide boosts"; "account.hide-reblogs" = "Hide boosts";
"account.mute" = "Mute"; "account.mute" = "Mute";
"account.request" = "Request"; "account.request" = "Request";

View file

@ -89,10 +89,20 @@ public extension StatusViewModel {
var time: String? { statusService.status.displayStatus.createdAt.timeAgo } var time: String? { statusService.status.displayStatus.createdAt.timeAgo }
var accessibilityTime: String {
Self.accessiblityTimeFormatter.localizedString(
for: statusService.status.displayStatus.createdAt,
relativeTo: Date())
}
var contextParentTime: String { var contextParentTime: String {
Self.contextParentDateFormatter.string(from: statusService.status.displayStatus.createdAt) Self.contextParentDateFormatter.string(from: statusService.status.displayStatus.createdAt)
} }
var accessibilityContextParentTime: String {
Self.contextParentAccessibilityDateFormatter.string(from: statusService.status.displayStatus.createdAt)
}
var applicationName: String? { statusService.status.displayStatus.application?.name } var applicationName: String? { statusService.status.displayStatus.application?.name }
var applicationURL: URL? { var applicationURL: URL? {
@ -335,6 +345,14 @@ public extension StatusViewModel {
} }
private extension StatusViewModel { private extension StatusViewModel {
private static let accessiblityTimeFormatter: RelativeDateTimeFormatter = {
let dateFormatter = RelativeDateTimeFormatter()
dateFormatter.unitsStyle = .full
return dateFormatter
}()
private static let contextParentDateFormatter: DateFormatter = { private static let contextParentDateFormatter: DateFormatter = {
let dateFormatter = DateFormatter() let dateFormatter = DateFormatter()
@ -343,4 +361,13 @@ private extension StatusViewModel {
return dateFormatter return dateFormatter
}() }()
private static let contextParentAccessibilityDateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .long
dateFormatter.timeStyle = .short
return dateFormatter
}()
} }

View file

@ -36,8 +36,14 @@ final class AccountHeaderView: UIView {
} }
} }
headerImageView.tag = accountViewModel.headerURL.hashValue headerImageView.tag = accountViewModel.headerURL.hashValue
headerButton.accessibilityLabel = String.localizedStringWithFormat(
NSLocalizedString("account.header.accessibility-label-%@", comment: ""),
accountViewModel.displayName)
avatarImageView.kf.setImage(with: accountViewModel.avatarURL(profile: true)) avatarImageView.kf.setImage(with: accountViewModel.avatarURL(profile: true))
avatarImageView.tag = accountViewModel.avatarURL(profile: true).hashValue avatarImageView.tag = accountViewModel.avatarURL(profile: true).hashValue
avatarButton.accessibilityLabel = String.localizedStringWithFormat(
NSLocalizedString("account.avatar.accessibility-label-%@", comment: ""),
accountViewModel.displayName)
if !accountViewModel.isSelf, let relationship = accountViewModel.relationship { if !accountViewModel.isSelf, let relationship = accountViewModel.relationship {
followsYouLabel.isHidden = !relationship.followedBy followsYouLabel.isHidden = !relationship.followedBy

View file

@ -190,6 +190,7 @@ private extension StatusView {
label.textColor = .secondaryLabel label.textColor = .secondaryLabel
label.text = "" label.text = ""
label.setContentHuggingPriority(.required, for: .horizontal) label.setContentHuggingPriority(.required, for: .horizontal)
label.isAccessibilityElement = false
} }
contextParentTimeApplicationStackView.addArrangedSubview(timeVisibilityDividerLabel) contextParentTimeApplicationStackView.addArrangedSubview(timeVisibilityDividerLabel)
@ -197,6 +198,7 @@ private extension StatusView {
contextParentTimeApplicationStackView.addArrangedSubview(visibilityImageView) contextParentTimeApplicationStackView.addArrangedSubview(visibilityImageView)
visibilityImageView.contentMode = .scaleAspectFit visibilityImageView.contentMode = .scaleAspectFit
visibilityImageView.tintColor = .secondaryLabel visibilityImageView.tintColor = .secondaryLabel
visibilityImageView.isAccessibilityElement = true
contextParentTimeApplicationStackView.addArrangedSubview(visibilityApplicationDividerLabel) contextParentTimeApplicationStackView.addArrangedSubview(visibilityApplicationDividerLabel)
@ -330,13 +332,12 @@ private extension StatusView {
interactionsStackView.heightAnchor.constraint(greaterThanOrEqualToConstant: .minimumButtonDimension) interactionsStackView.heightAnchor.constraint(greaterThanOrEqualToConstant: .minimumButtonDimension)
]) ])
NotificationCenter.default.publisher(for: UIAccessibility.voiceOverStatusDidChangeNotification) NotificationCenter.default.publisher(for: UIAccessibility.voiceOverStatusDidChangeNotification)
.sink { [weak self] _ in self?.configureUserInteractionEnabledForAccessibility() } .sink { [weak self] _ in self?.configureUserInteractionEnabledForAccessibility() }
.store(in: &cancellables) .store(in: &cancellables)
} }
// swiftlint:disable:next cyclomatic_complexity
func applyStatusConfiguration() { func applyStatusConfiguration() {
let viewModel = statusConfiguration.viewModel let viewModel = statusConfiguration.viewModel
let isContextParent = viewModel.configuration.isContextParent let isContextParent = viewModel.configuration.isContextParent
@ -347,6 +348,9 @@ private extension StatusView {
menuButton.menu = menu(viewModel: viewModel) menuButton.menu = menu(viewModel: viewModel)
avatarImageView.kf.setImage(with: viewModel.avatarURL) avatarImageView.kf.setImage(with: viewModel.avatarURL)
avatarButton.accessibilityLabel = String.localizedStringWithFormat(
NSLocalizedString("account.avatar.accessibility-label-%@", comment: ""),
viewModel.displayName)
sideStackView.isHidden = isContextParent sideStackView.isHidden = isContextParent
avatarImageView.removeFromSuperview() avatarImageView.removeFromSuperview()
@ -420,12 +424,15 @@ private extension StatusView {
accountLabel.text = viewModel.accountName accountLabel.text = viewModel.accountName
timeLabel.text = viewModel.time timeLabel.text = viewModel.time
timeLabel.accessibilityLabel = viewModel.accessibilityTime
timeLabel.isHidden = isContextParent timeLabel.isHidden = isContextParent
bodyView.viewModel = viewModel bodyView.viewModel = viewModel
contextParentTimeLabel.text = viewModel.contextParentTime contextParentTimeLabel.text = viewModel.contextParentTime
contextParentTimeLabel.accessibilityLabel = viewModel.accessibilityContextParentTime
visibilityImageView.image = UIImage(systemName: viewModel.visibility.systemImageName) visibilityImageView.image = UIImage(systemName: viewModel.visibility.systemImageName)
visibilityImageView.accessibilityLabel = viewModel.visibility.title
visibilityApplicationDividerLabel.isHidden = viewModel.applicationName == nil visibilityApplicationDividerLabel.isHidden = viewModel.applicationName == nil
applicationButton.isHidden = viewModel.applicationName == nil applicationButton.isHidden = viewModel.applicationName == nil
applicationButton.setTitle(viewModel.applicationName, for: .normal) applicationButton.setTitle(viewModel.applicationName, for: .normal)
@ -485,12 +492,20 @@ private extension StatusView {
isAccessibilityElement = !viewModel.configuration.isContextParent isAccessibilityElement = !viewModel.configuration.isContextParent
let accessibilityAttributedLabel = NSMutableAttributedString(attributedString: mutableDisplayName) let accessibilityAttributedLabel = NSMutableAttributedString(string: "")
if let infoText = infoLabel.attributedText {
accessibilityAttributedLabel.appendWithSeparator(infoText)
}
accessibilityAttributedLabel.append(mutableDisplayName)
if let bodyAccessibilityAttributedLabel = bodyView.accessibilityAttributedLabel { if let bodyAccessibilityAttributedLabel = bodyView.accessibilityAttributedLabel {
accessibilityAttributedLabel.appendWithSeparator(bodyAccessibilityAttributedLabel) accessibilityAttributedLabel.appendWithSeparator(bodyAccessibilityAttributedLabel)
} }
accessibilityAttributedLabel.appendWithSeparator(viewModel.accessibilityTime)
self.accessibilityAttributedLabel = accessibilityAttributedLabel self.accessibilityAttributedLabel = accessibilityAttributedLabel
configureUserInteractionEnabledForAccessibility() configureUserInteractionEnabledForAccessibility()