mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-22 08:10:59 +00:00
VoiceOver wip
This commit is contained in:
parent
82a1813064
commit
29d8d609b5
3 changed files with 59 additions and 1 deletions
|
@ -11,6 +11,7 @@
|
||||||
"account.domain-block.confirm-%@" = "Block domain %@?";
|
"account.domain-block.confirm-%@" = "Block domain %@?";
|
||||||
"account.domain-unblock-%@" = "Unblock domain %@";
|
"account.domain-unblock-%@" = "Unblock domain %@";
|
||||||
"account.domain-unblock.confirm-%@" = "Unblock domain %@?";
|
"account.domain-unblock.confirm-%@" = "Unblock domain %@?";
|
||||||
|
"account.field.activate-link-accessibility-action-%@" = "Activate link: %@";
|
||||||
"account.field.verified" = "Verified %@";
|
"account.field.verified" = "Verified %@";
|
||||||
"account.follow" = "Follow";
|
"account.follow" = "Follow";
|
||||||
"account.following" = "Following";
|
"account.following" = "Following";
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
// Copyright © 2020 Metabolist. All rights reserved.
|
// Copyright © 2020 Metabolist. All rights reserved.
|
||||||
|
|
||||||
|
import Combine
|
||||||
import Mastodon
|
import Mastodon
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
final class AccountFieldView: UIView {
|
final class AccountFieldView: UIView {
|
||||||
let nameLabel = UILabel()
|
let nameLabel = UILabel()
|
||||||
let valueTextView = TouchFallthroughTextView()
|
let valueTextView = TouchFallthroughTextView()
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
// swiftlint:disable:next function_body_length
|
// swiftlint:disable:next function_body_length
|
||||||
init(name: String, value: NSAttributedString, verifiedAt: Date?, emojis: [Emoji]) {
|
init(name: String, value: NSAttributedString, verifiedAt: Date?, emojis: [Emoji]) {
|
||||||
super.init(frame: .zero)
|
super.init(frame: .zero)
|
||||||
|
|
||||||
|
NotificationCenter.default.publisher(for: UIAccessibility.voiceOverStatusDidChangeNotification)
|
||||||
|
.sink { [weak self] _ in self?.configureUserInteractionEnabledForAccessibility() }
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
backgroundColor = .systemBackground
|
backgroundColor = .systemBackground
|
||||||
|
|
||||||
let nameBackgroundView = UIView()
|
let nameBackgroundView = UIView()
|
||||||
|
@ -134,6 +140,51 @@ final class AccountFieldView: UIView {
|
||||||
valueBackgroundView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
valueBackgroundView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
||||||
valueBackgroundView.bottomAnchor.constraint(equalTo: bottomAnchor)
|
valueBackgroundView.bottomAnchor.constraint(equalTo: bottomAnchor)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// isAccessibilityElement = true
|
||||||
|
|
||||||
|
let accessibilityAttributedLabel = NSMutableAttributedString(attributedString: mutableName)
|
||||||
|
|
||||||
|
accessibilityAttributedLabel.appendWithSeparator(mutableValue)
|
||||||
|
|
||||||
|
if let verifiedAt = verifiedAt {
|
||||||
|
accessibilityAttributedLabel.appendWithSeparator(
|
||||||
|
String.localizedStringWithFormat(
|
||||||
|
NSLocalizedString("account.field.verified", comment: ""),
|
||||||
|
Self.dateFormatter.string(from: verifiedAt)))
|
||||||
|
}
|
||||||
|
|
||||||
|
isAccessibilityElement = true
|
||||||
|
|
||||||
|
var accessibilityCustomActions = [UIAccessibilityCustomAction]()
|
||||||
|
|
||||||
|
mutableValue.enumerateAttribute(
|
||||||
|
.link,
|
||||||
|
in: NSRange(location: 0, length: mutableValue.length),
|
||||||
|
options: []) { attribute, range, _ in
|
||||||
|
guard let url = attribute as? URL else { return }
|
||||||
|
|
||||||
|
accessibilityCustomActions.append(
|
||||||
|
UIAccessibilityCustomAction(
|
||||||
|
name: String.localizedStringWithFormat(
|
||||||
|
NSLocalizedString("account.field.activate-link-accessibility-action-%@", comment: ""),
|
||||||
|
mutableValue.attributedSubstring(from: range).string)) { [weak self] _ in
|
||||||
|
guard let valueTextView = self?.valueTextView else { return false }
|
||||||
|
|
||||||
|
_ = valueTextView.delegate?.textView?(
|
||||||
|
valueTextView,
|
||||||
|
shouldInteractWith: url,
|
||||||
|
in: range,
|
||||||
|
interaction: .invokeDefaultAction)
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
self.accessibilityAttributedLabel = accessibilityAttributedLabel
|
||||||
|
self.accessibilityCustomActions = accessibilityCustomActions
|
||||||
|
|
||||||
|
configureUserInteractionEnabledForAccessibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, unavailable)
|
@available(*, unavailable)
|
||||||
|
@ -150,4 +201,8 @@ private extension AccountFieldView {
|
||||||
|
|
||||||
return formatter
|
return formatter
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
func configureUserInteractionEnabledForAccessibility() {
|
||||||
|
valueTextView.isUserInteractionEnabled = !UIAccessibility.isVoiceOverRunning
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,9 @@ final class TouchFallthroughTextView: UITextView {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
||||||
shouldFallthrough ? urlAndRect(at: point) != nil : super.point(inside: point, with: event)
|
guard !UIAccessibility.isVoiceOverRunning else { return super.point(inside: point, with: event) }
|
||||||
|
|
||||||
|
return shouldFallthrough ? urlAndRect(at: point) != nil : super.point(inside: point, with: event)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
|
Loading…
Reference in a new issue