VoiceOver improvements

This commit is contained in:
Ilya Laktyushin 2023-02-18 00:52:55 +04:00
parent ef96be345c
commit fa0130bf8c
4 changed files with 33 additions and 2 deletions

View File

@ -8928,3 +8928,5 @@ Sorry for the inconvenience.";
"VoiceOver.Chat.NotPlayedByRecipient" = "Not played by recipient"; "VoiceOver.Chat.NotPlayedByRecipient" = "Not played by recipient";
"VoiceOver.Chat.NotPlayedByRecipients" = "Not played by recipients"; "VoiceOver.Chat.NotPlayedByRecipients" = "Not played by recipients";
"VoiceOver.Chat.ReplyingToMessage" = "In reply to message: %@";

View File

@ -87,6 +87,8 @@ final class MediaPickerGridItemNode: GridItemNode {
private let typeIconNode: ASImageNode private let typeIconNode: ASImageNode
private let durationNode: ImmediateTextNode private let durationNode: ImmediateTextNode
private let activateAreaNode: AccessibilityAreaNode
private var interaction: MediaPickerInteraction? private var interaction: MediaPickerInteraction?
private var theme: PresentationTheme? private var theme: PresentationTheme?
@ -114,10 +116,14 @@ final class MediaPickerGridItemNode: GridItemNode {
self.typeIconNode.displayWithoutProcessing = true self.typeIconNode.displayWithoutProcessing = true
self.durationNode = ImmediateTextNode() self.durationNode = ImmediateTextNode()
self.activateAreaNode = AccessibilityAreaNode()
self.activateAreaNode.accessibilityTraits = [.image]
super.init() super.init()
self.addSubnode(self.imageNode) self.addSubnode(self.imageNode)
self.addSubnode(self.activateAreaNode)
self.imageNode.contentUpdated = { [weak self] image in self.imageNode.contentUpdated = { [weak self] image in
self?.spoilerNode?.setImage(image) self?.spoilerNode?.setImage(image)
@ -285,6 +291,10 @@ final class MediaPickerGridItemNode: GridItemNode {
let editingContext = interaction.editingState let editingContext = interaction.editingState
let asset = fetchResult.object(at: index) let asset = fetchResult.object(at: index)
if #available(iOS 15.0, *) {
self.activateAreaNode.accessibilityLabel = "Photo \(asset.creationDate?.formatted(date: .abbreviated, time: .standard) ?? "")"
}
let editedSignal = Signal<UIImage?, NoError> { subscriber in let editedSignal = Signal<UIImage?, NoError> { subscriber in
if let signal = editingContext.thumbnailImageSignal(forIdentifier: asset.localIdentifier) { if let signal = editingContext.thumbnailImageSignal(forIdentifier: asset.localIdentifier) {
let disposable = signal.start(next: { next in let disposable = signal.start(next: { next in
@ -411,6 +421,7 @@ final class MediaPickerGridItemNode: GridItemNode {
self.imageNode.frame = self.bounds self.imageNode.frame = self.bounds
self.gradientNode.frame = CGRect(x: 0.0, y: self.bounds.height - 24.0, width: self.bounds.width, height: 24.0) self.gradientNode.frame = CGRect(x: 0.0, y: self.bounds.height - 24.0, width: self.bounds.width, height: 24.0)
self.typeIconNode.frame = CGRect(x: 0.0, y: self.bounds.height - 20.0, width: 19.0, height: 19.0) self.typeIconNode.frame = CGRect(x: 0.0, y: self.bounds.height - 20.0, width: 19.0, height: 19.0)
self.activateAreaNode.frame = self.bounds
if self.durationNode.supernode != nil { if self.durationNode.supernode != nil {
let durationSize = self.durationNode.updateLayout(self.bounds.size) let durationSize = self.durationNode.updateLayout(self.bounds.size)

View File

@ -192,6 +192,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
private let backgroundNode: NavigationBackgroundNode private let backgroundNode: NavigationBackgroundNode
private let gridNode: GridNode private let gridNode: GridNode
fileprivate var cameraView: TGAttachmentCameraView? fileprivate var cameraView: TGAttachmentCameraView?
private var cameraActivateAreaNode: AccessibilityAreaNode
private var placeholderNode: MediaPickerPlaceholderNode? private var placeholderNode: MediaPickerPlaceholderNode?
private var manageNode: MediaPickerManageNode? private var manageNode: MediaPickerManageNode?
private var scrollingArea: SparseItemGridScrollingArea private var scrollingArea: SparseItemGridScrollingArea
@ -233,6 +234,10 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
self.gridNode = GridNode() self.gridNode = GridNode()
self.scrollingArea = SparseItemGridScrollingArea() self.scrollingArea = SparseItemGridScrollingArea()
self.cameraActivateAreaNode = AccessibilityAreaNode()
self.cameraActivateAreaNode.accessibilityLabel = "Camera"
self.cameraActivateAreaNode.accessibilityTraits = [.button]
super.init() super.init()
if case .assets(nil) = controller.subject { if case .assets(nil) = controller.subject {
@ -416,6 +421,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
cameraView.startPreview() cameraView.startPreview()
self.gridNode.scrollView.addSubview(cameraView) self.gridNode.scrollView.addSubview(cameraView)
self.gridNode.addSubnode(self.cameraActivateAreaNode)
} else { } else {
self.containerNode.clipsToBounds = true self.containerNode.clipsToBounds = true
} }
@ -1067,6 +1073,7 @@ public final class MediaPickerScreen: ViewController, AttachmentContainable {
if let cameraView = self.cameraView { if let cameraView = self.cameraView {
if let cameraRect = cameraRect { if let cameraRect = cameraRect {
transition.updateFrame(view: cameraView, frame: cameraRect) transition.updateFrame(view: cameraView, frame: cameraRect)
self.cameraActivateAreaNode.frame = cameraRect
cameraView.isHidden = false cameraView.isHidden = false
} else { } else {
cameraView.isHidden = true cameraView.isHidden = true

View File

@ -232,6 +232,9 @@ final class ChatMessageAccessibilityData {
} }
} else if let file = media as? TelegramMediaFile { } else if let file = media as? TelegramMediaFile {
var isSpecialFile = false var isSpecialFile = false
let isVideo = file.isInstantVideo
for attribute in file.attributes { for attribute in file.attributes {
switch attribute { switch attribute {
case let .Sticker(displayText, _, _): case let .Sticker(displayText, _, _):
@ -259,6 +262,9 @@ final class ChatMessageAccessibilityData {
} }
} }
case let .Audio(isVoice, duration, title, performer, _): case let .Audio(isVoice, duration, title, performer, _):
if isVideo {
continue
}
isSpecialFile = true isSpecialFile = true
if isSelected == nil { if isSelected == nil {
hint = item.presentationData.strings.VoiceOver_Chat_PlayHint hint = item.presentationData.strings.VoiceOver_Chat_PlayHint
@ -598,6 +604,7 @@ final class ChatMessageAccessibilityData {
} }
var (label, value) = dataForMessage(item.message, false) var (label, value) = dataForMessage(item.message, false)
var replyValue: String?
for attribute in item.message.attributes { for attribute in item.message.attributes {
if let attribute = attribute as? TextEntitiesMessageAttribute { if let attribute = attribute as? TextEntitiesMessageAttribute {
@ -638,8 +645,8 @@ final class ChatMessageAccessibilityData {
replyLabel = item.presentationData.strings.VoiceOver_Chat_ReplyToYourMessage replyLabel = item.presentationData.strings.VoiceOver_Chat_ReplyToYourMessage
} }
// let (replyMessageLabel, replyMessageValue) = dataForMessage(replyMessage, true) let (_, replyMessageValue) = dataForMessage(replyMessage, true)
// replyLabel += "\(replyLabel): \(replyMessageLabel), \(replyMessageValue)" replyValue = replyMessageValue
label = "\(replyLabel) . \(label)" label = "\(replyLabel) . \(label)"
} }
@ -691,6 +698,10 @@ final class ChatMessageAccessibilityData {
customActions.append(ChatMessageAccessibilityCustomAction(name: item.presentationData.strings.VoiceOver_MessageContextOpenMessageMenu, target: nil, selector: #selector(self.noop), action: .options)) customActions.append(ChatMessageAccessibilityCustomAction(name: item.presentationData.strings.VoiceOver_MessageContextOpenMessageMenu, target: nil, selector: #selector(self.noop), action: .options))
} }
if let replyValue {
value = "\(value). \(item.presentationData.strings.VoiceOver_Chat_ReplyingToMessage(replyValue).string)"
}
self.label = label self.label = label
self.value = value self.value = value
self.hint = hint self.hint = hint