mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Accessibility improvements
This commit is contained in:
parent
f1f4eefcbf
commit
050418b0b8
@ -8895,3 +8895,14 @@ Sorry for the inconvenience.";
|
||||
"Premium.Purchase.OnlyOneSubscriptionAllowed" = "You have already purchased Telegram Premium for another account. You can only have one Telegram Premium subscription on one Apple ID.";
|
||||
|
||||
"Call.VoiceOver.Minimize" = "Minimize Call";
|
||||
|
||||
"Login.VoiceOver.PhoneCountryCode" = "Phone country code";
|
||||
"Login.VoiceOver.PhoneNumber" = "Phone number";
|
||||
"Login.VoiceOver.Password" = "Password";
|
||||
|
||||
"Gallery.VoiceOver.Delete" = "Delete";
|
||||
"Gallery.VoiceOver.Fullscreen" = "Fullscreen";
|
||||
"Gallery.VoiceOver.Share" = "Share";
|
||||
"Gallery.VoiceOver.Edit" = "Edit";
|
||||
"Gallery.VoiceOver.Stickers" = "Stickers";
|
||||
"Gallery.VoiceOver.PictureInPicture" = "Picture-in-Picture";
|
||||
|
@ -894,6 +894,26 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
||||
containerSize: CGSize(width: buttonWidth, height: buttonSize.height)
|
||||
)
|
||||
buttonTransition.setFrame(view: buttonView, frame: buttonFrame)
|
||||
var accessibilityTitle = ""
|
||||
switch type {
|
||||
case .gallery:
|
||||
accessibilityTitle = self.presentationData.strings.Attachment_Gallery
|
||||
case .file:
|
||||
accessibilityTitle = self.presentationData.strings.Attachment_File
|
||||
case .location:
|
||||
accessibilityTitle = self.presentationData.strings.Attachment_Location
|
||||
case .contact:
|
||||
accessibilityTitle = self.presentationData.strings.Attachment_Contact
|
||||
case .poll:
|
||||
accessibilityTitle = self.presentationData.strings.Attachment_Poll
|
||||
case let .app(_, appName, _):
|
||||
accessibilityTitle = appName
|
||||
case .standalone:
|
||||
accessibilityTitle = ""
|
||||
}
|
||||
buttonView.isAccessibilityElement = true
|
||||
buttonView.accessibilityLabel = accessibilityTitle
|
||||
buttonView.accessibilityTraits = [.button]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,14 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
|
||||
private let animationNode: AnimatedStickerNode
|
||||
private let titleNode: ImmediateTextNode
|
||||
private let titleActivateAreaNode: AccessibilityAreaNode
|
||||
private let titleIconNode: ASImageNode
|
||||
private let currentOptionNode: ImmediateTextNode
|
||||
private let currentOptionActivateAreaNode: AccessibilityAreaNode
|
||||
private var dustNode: InvisibleInkDustNode?
|
||||
|
||||
private let currentOptionInfoNode: ASTextNode
|
||||
private let currentOptionInfoActivateAreaNode: AccessibilityAreaNode
|
||||
private let nextOptionTitleNode: ImmediateTextNode
|
||||
private let nextOptionButtonNode: HighlightableButtonNode
|
||||
|
||||
@ -91,6 +94,9 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
|
||||
self.titleActivateAreaNode = AccessibilityAreaNode()
|
||||
self.titleActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.titleIconNode = ASImageNode()
|
||||
self.titleIconNode.isLayerBacked = true
|
||||
self.titleIconNode.displayWithoutProcessing = true
|
||||
@ -102,10 +108,16 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
self.currentOptionNode.lineSpacing = 0.1
|
||||
self.currentOptionNode.maximumNumberOfLines = 0
|
||||
|
||||
self.currentOptionActivateAreaNode = AccessibilityAreaNode()
|
||||
self.currentOptionActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.currentOptionInfoNode = ASTextNode()
|
||||
self.currentOptionInfoNode.isUserInteractionEnabled = false
|
||||
self.currentOptionInfoNode.displaysAsynchronously = false
|
||||
|
||||
self.currentOptionInfoActivateAreaNode = AccessibilityAreaNode()
|
||||
self.currentOptionInfoActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.nextOptionTitleNode = ImmediateTextNode()
|
||||
|
||||
self.nextOptionButtonNode = HighlightableButtonNode()
|
||||
@ -113,6 +125,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: .sms(length: 5), nextType: .call, timeout: 60, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
|
||||
self.nextOptionTitleNode.attributedText = nextOptionText
|
||||
self.nextOptionButtonNode.isUserInteractionEnabled = nextOptionActive
|
||||
self.nextOptionButtonNode.accessibilityLabel = nextOptionText.string
|
||||
if nextOptionActive {
|
||||
self.nextOptionButtonNode.accessibilityTraits = [.button]
|
||||
} else {
|
||||
self.nextOptionButtonNode.accessibilityTraits = [.button, .notEnabled]
|
||||
}
|
||||
self.nextOptionButtonNode.addSubnode(self.nextOptionTitleNode)
|
||||
|
||||
self.codeInputView = CodeInputView()
|
||||
@ -156,8 +174,10 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
|
||||
self.addSubnode(self.codeInputView)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.titleActivateAreaNode)
|
||||
self.addSubnode(self.titleIconNode)
|
||||
self.addSubnode(self.currentOptionNode)
|
||||
self.addSubnode(self.currentOptionActivateAreaNode)
|
||||
self.addSubnode(self.currentOptionInfoNode)
|
||||
self.addSubnode(self.nextOptionButtonNode)
|
||||
self.addSubnode(self.animationNode)
|
||||
@ -266,10 +286,18 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
self.appleSignInAllowed = appleSignInAllowed
|
||||
|
||||
self.currentOptionNode.attributedText = authorizationCurrentOptionText(codeType, phoneNumber: self.phoneNumber, email: self.email, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
|
||||
self.currentOptionActivateAreaNode.accessibilityLabel = self.currentOptionNode.attributedText?.string ?? ""
|
||||
if case .missedCall = codeType {
|
||||
self.currentOptionInfoNode.attributedText = NSAttributedString(string: self.strings.Login_CodePhonePatternInfoText, font: Font.regular(17.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
|
||||
self.currentOptionInfoActivateAreaNode.accessibilityLabel = self.currentOptionInfoNode.attributedText?.string ?? ""
|
||||
if self.currentOptionInfoActivateAreaNode.supernode == nil {
|
||||
self.addSubnode(self.currentOptionInfoActivateAreaNode)
|
||||
}
|
||||
} else {
|
||||
self.currentOptionInfoNode.attributedText = NSAttributedString(string: "", font: Font.regular(17.0), textColor: self.theme.list.itemPrimaryTextColor)
|
||||
if self.currentOptionInfoActivateAreaNode.supernode != nil {
|
||||
self.currentOptionInfoActivateAreaNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
if let timeout = timeout {
|
||||
#if DEBUG
|
||||
@ -283,7 +311,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: codeType, nextType: nextType, timeout: strongSelf.currentTimeoutTime, strings: strongSelf.strings, primaryColor: strongSelf.theme.list.itemPrimaryTextColor, accentColor: strongSelf.theme.list.itemAccentColor)
|
||||
strongSelf.nextOptionTitleNode.attributedText = nextOptionText
|
||||
strongSelf.nextOptionButtonNode.isUserInteractionEnabled = nextOptionActive
|
||||
|
||||
strongSelf.nextOptionButtonNode.accessibilityLabel = nextOptionText.string
|
||||
if nextOptionActive {
|
||||
strongSelf.nextOptionButtonNode.accessibilityTraits = [.button]
|
||||
} else {
|
||||
strongSelf.nextOptionButtonNode.accessibilityTraits = [.button, .notEnabled]
|
||||
}
|
||||
if let layoutArguments = strongSelf.layoutArguments {
|
||||
strongSelf.containerLayoutUpdated(layoutArguments.0, navigationBarHeight: layoutArguments.1, transition: .immediate)
|
||||
}
|
||||
@ -301,7 +334,12 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
let (nextOptionText, nextOptionActive) = authorizationNextOptionText(currentType: codeType, nextType: nextType, timeout: self.currentTimeoutTime, strings: self.strings, primaryColor: self.theme.list.itemPrimaryTextColor, accentColor: self.theme.list.itemAccentColor)
|
||||
self.nextOptionTitleNode.attributedText = nextOptionText
|
||||
self.nextOptionButtonNode.isUserInteractionEnabled = nextOptionActive
|
||||
|
||||
self.nextOptionButtonNode.accessibilityLabel = nextOptionText.string
|
||||
if nextOptionActive {
|
||||
self.nextOptionButtonNode.accessibilityTraits = [.button]
|
||||
} else {
|
||||
self.nextOptionButtonNode.accessibilityTraits = [.button, .notEnabled]
|
||||
}
|
||||
if let layoutArguments = self.layoutArguments {
|
||||
self.containerLayoutUpdated(layoutArguments.0, navigationBarHeight: layoutArguments.1, transition: .immediate)
|
||||
}
|
||||
@ -347,6 +385,8 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.strings.Login_EnterCodeTelegramTitle, font: Font.semibold(40.0), textColor: self.theme.list.itemPrimaryTextColor)
|
||||
}
|
||||
|
||||
self.titleActivateAreaNode.accessibilityLabel = self.titleNode.attributedText?.string ?? ""
|
||||
|
||||
if let inputHeight = layout.inputHeight {
|
||||
if let codeType = self.codeType, case .email = codeType {
|
||||
insets.bottom = max(inputHeight, insets.bottom)
|
||||
@ -525,6 +565,10 @@ final class AuthorizationSequenceCodeEntryControllerNode: ASDisplayNode, UITextF
|
||||
}
|
||||
|
||||
self.nextOptionTitleNode.frame = self.nextOptionButtonNode.bounds
|
||||
|
||||
self.titleActivateAreaNode.frame = self.titleNode.frame
|
||||
self.currentOptionActivateAreaNode.frame = self.currentOptionNode.frame
|
||||
self.currentOptionInfoActivateAreaNode.frame = self.currentOptionInfoNode.frame
|
||||
}
|
||||
|
||||
func activateInput() {
|
||||
|
@ -15,7 +15,9 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
|
||||
|
||||
private let animationNode: AnimatedStickerNode
|
||||
private let titleNode: ASTextNode
|
||||
private let titleActivateAreaNode: AccessibilityAreaNode
|
||||
private let noticeNode: ASTextNode
|
||||
private let noticeActivateAreaNode: AccessibilityAreaNode
|
||||
private let forgotNode: HighlightableButtonNode
|
||||
private let resetNode: HighlightableButtonNode
|
||||
private let proceedNode: SolidRoundedButtonNode
|
||||
@ -68,15 +70,23 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.LoginPassword_Title, font: Font.semibold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
|
||||
|
||||
self.titleActivateAreaNode = AccessibilityAreaNode()
|
||||
self.titleActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.noticeNode = ASTextNode()
|
||||
self.noticeNode.isUserInteractionEnabled = false
|
||||
self.noticeNode.displaysAsynchronously = false
|
||||
self.noticeNode.lineSpacing = 0.1
|
||||
self.noticeNode.attributedText = NSAttributedString(string: strings.TwoStepAuth_EnterPasswordHelp, font: Font.regular(17.0), textColor: self.theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
|
||||
|
||||
self.noticeActivateAreaNode = AccessibilityAreaNode()
|
||||
self.noticeActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.forgotNode = HighlightableButtonNode()
|
||||
self.forgotNode.displaysAsynchronously = false
|
||||
self.forgotNode.setAttributedTitle(NSAttributedString(string: self.strings.TwoStepAuth_EnterPasswordForgot, font: Font.regular(16.0), textColor: self.theme.list.itemAccentColor, paragraphAlignment: .center), for: [])
|
||||
self.forgotNode.accessibilityLabel = self.strings.TwoStepAuth_EnterPasswordForgot
|
||||
self.forgotNode.accessibilityTraits = [.button]
|
||||
|
||||
self.resetNode = HighlightableButtonNode()
|
||||
self.resetNode.displaysAsynchronously = false
|
||||
@ -95,6 +105,7 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
|
||||
self.codeField.textField.keyboardAppearance = self.theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.codeField.textField.disableAutomaticKeyboardHandling = [.forward, .backward]
|
||||
self.codeField.textField.tintColor = self.theme.list.itemAccentColor
|
||||
self.codeField.textField.accessibilityHint = self.strings.Login_VoiceOver_Password
|
||||
|
||||
self.proceedNode = SolidRoundedButtonNode(title: self.strings.Login_Continue, theme: SolidRoundedButtonTheme(theme: self.theme), height: 50.0, cornerRadius: 11.0, gloss: false)
|
||||
self.proceedNode.progressType = .embedded
|
||||
@ -114,9 +125,11 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
|
||||
self.addSubnode(self.codeSeparatorNode)
|
||||
self.addSubnode(self.codeField)
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.titleActivateAreaNode)
|
||||
self.addSubnode(self.forgotNode)
|
||||
self.addSubnode(self.resetNode)
|
||||
self.addSubnode(self.noticeNode)
|
||||
self.addSubnode(self.noticeActivateAreaNode)
|
||||
self.addSubnode(self.animationNode)
|
||||
self.addSubnode(self.proceedNode)
|
||||
|
||||
@ -214,6 +227,12 @@ final class AuthorizationSequencePasswordEntryControllerNode: ASDisplayNode, UIT
|
||||
self.animationNode.updateLayout(size: animationSize)
|
||||
|
||||
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - additionalBottomInset)), items: items, transition: transition, failIfDoesNotFit: false)
|
||||
|
||||
self.titleActivateAreaNode.accessibilityLabel = self.titleNode.attributedText?.string ?? ""
|
||||
self.noticeActivateAreaNode.accessibilityLabel = self.noticeNode.attributedText?.string ?? ""
|
||||
|
||||
self.titleActivateAreaNode.frame = self.titleNode.frame
|
||||
self.noticeActivateAreaNode.frame = self.noticeNode.frame
|
||||
}
|
||||
|
||||
func activateInput() {
|
||||
|
@ -110,6 +110,8 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
self.phoneInputNode.numberField.textField.textColor = theme.list.itemPrimaryTextColor
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
|
||||
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
|
||||
self.phoneInputNode.countryCodeField.accessibilityHint = strings.Login_VoiceOver_PhoneCountryCode
|
||||
self.phoneInputNode.numberField.accessibilityHint = strings.Login_VoiceOver_PhoneNumber
|
||||
|
||||
self.phoneInputNode.countryCodeField.textField.tintColor = theme.list.itemAccentColor
|
||||
self.phoneInputNode.numberField.textField.tintColor = theme.list.itemAccentColor
|
||||
@ -172,6 +174,9 @@ private final class PhoneAndCountryNode: ASDisplayNode {
|
||||
strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: theme.list.itemPlaceholderTextColor)
|
||||
}
|
||||
|
||||
strongSelf.countryButton.accessibilityLabel = strongSelf.countryButton.attributedTitle(for: .normal)?.string ?? ""
|
||||
strongSelf.countryButton.accessibilityTraits = [.button]
|
||||
|
||||
if strongSelf.hasCountry {
|
||||
strongSelf.hasNumberUpdated?(!strongSelf.phoneInputNode.codeAndNumber.2.isEmpty)
|
||||
} else {
|
||||
@ -289,7 +294,9 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
private let animationNode: AnimatedStickerNode
|
||||
private let managedAnimationNode: ManagedPhoneAnimationNode
|
||||
private let titleNode: ASTextNode
|
||||
private let titleActivateAreaNode: AccessibilityAreaNode
|
||||
private let noticeNode: ASTextNode
|
||||
private let noticeActivateAreaNode: AccessibilityAreaNode
|
||||
private let phoneAndCountryNode: PhoneAndCountryNode
|
||||
private let contactSyncNode: ContactSyncNode
|
||||
private let proceedNode: SolidRoundedButtonNode
|
||||
@ -378,12 +385,18 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.attributedText = NSAttributedString(string: account == nil ? strings.Login_NewNumber : strings.Login_PhoneTitle, font: Font.light(30.0), textColor: theme.list.itemPrimaryTextColor)
|
||||
|
||||
self.titleActivateAreaNode = AccessibilityAreaNode()
|
||||
self.titleActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.noticeNode = ASTextNode()
|
||||
self.noticeNode.maximumNumberOfLines = 0
|
||||
self.noticeNode.isUserInteractionEnabled = true
|
||||
self.noticeNode.displaysAsynchronously = false
|
||||
self.noticeNode.lineSpacing = 0.1
|
||||
|
||||
self.noticeActivateAreaNode = AccessibilityAreaNode()
|
||||
self.noticeActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.noticeNode.attributedText = NSAttributedString(string: account == nil ? strings.ChangePhoneNumberNumber_Help : strings.Login_PhoneAndCountryHelp, font: Font.regular(17.0), textColor: theme.list.itemPrimaryTextColor, paragraphAlignment: .center)
|
||||
|
||||
self.contactSyncNode = ContactSyncNode(theme: theme, strings: strings)
|
||||
@ -404,6 +417,8 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.noticeNode)
|
||||
self.addSubnode(self.titleActivateAreaNode)
|
||||
self.addSubnode(self.noticeActivateAreaNode)
|
||||
self.addSubnode(self.phoneAndCountryNode)
|
||||
self.addSubnode(self.contactSyncNode)
|
||||
self.addSubnode(self.proceedNode)
|
||||
@ -534,6 +549,7 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
let additionalBottomInset: CGFloat = layout.size.width > 320.0 ? 80.0 : 10.0
|
||||
|
||||
self.titleNode.attributedText = NSAttributedString(string: self.account == nil ? strings.Login_NewNumber : strings.Login_PhoneTitle, font: Font.bold(28.0), textColor: self.theme.list.itemPrimaryTextColor)
|
||||
self.titleActivateAreaNode.accessibilityLabel = self.titleNode.attributedText?.string ?? ""
|
||||
|
||||
let inset: CGFloat = 24.0
|
||||
let maximumWidth: CGFloat = min(430.0, layout.size.width)
|
||||
@ -587,6 +603,10 @@ final class AuthorizationSequencePhoneEntryControllerNode: ASDisplayNode {
|
||||
let _ = layoutAuthorizationItems(bounds: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: layout.size.height - insets.top - insets.bottom - additionalBottomInset)), items: items, transition: transition, failIfDoesNotFit: false)
|
||||
|
||||
transition.updateFrame(node: self.managedAnimationNode, frame: self.animationNode.frame)
|
||||
|
||||
self.titleActivateAreaNode.frame = self.titleNode.frame
|
||||
self.noticeActivateAreaNode.accessibilityLabel = self.noticeNode.attributedText?.string ?? ""
|
||||
self.noticeActivateAreaNode.frame = self.noticeNode.frame
|
||||
}
|
||||
|
||||
func activateInput() {
|
||||
@ -726,6 +746,7 @@ final class PhoneConfirmationController: ViewController {
|
||||
|
||||
class Node: ASDisplayNode {
|
||||
private let theme: PresentationTheme
|
||||
private let strings: PresentationStrings
|
||||
|
||||
private let code: String
|
||||
private let number: String
|
||||
@ -740,6 +761,7 @@ final class PhoneConfirmationController: ViewController {
|
||||
private let phoneTargetNode: ImmediateTextNode
|
||||
|
||||
private let textNode: ImmediateTextNode
|
||||
private let textActivateAreaNode: AccessibilityAreaNode
|
||||
|
||||
private let cancelButton: HighlightableButtonNode
|
||||
fileprivate let proceedNode: SolidRoundedButtonNode
|
||||
@ -751,6 +773,7 @@ final class PhoneConfirmationController: ViewController {
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, code: String, number: String) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
|
||||
self.code = code
|
||||
self.number = number
|
||||
@ -767,8 +790,13 @@ final class PhoneConfirmationController: ViewController {
|
||||
self.textNode.attributedText = NSAttributedString(string: strings.Login_PhoneNumberConfirmation, font: Font.regular(17.0), textColor: theme.list.itemPrimaryTextColor)
|
||||
self.textNode.textAlignment = .center
|
||||
|
||||
self.textActivateAreaNode = AccessibilityAreaNode()
|
||||
self.textActivateAreaNode.accessibilityTraits = .staticText
|
||||
|
||||
self.cancelButton = HighlightableButtonNode()
|
||||
self.cancelButton.setTitle(strings.Login_Edit, with: Font.regular(19.0), with: theme.list.itemAccentColor, for: .normal)
|
||||
self.cancelButton.accessibilityTraits = [.button]
|
||||
self.cancelButton.accessibilityLabel = strings.Login_Edit
|
||||
|
||||
self.proceedNode = SolidRoundedButtonNode(title: strings.Login_Continue, theme: SolidRoundedButtonTheme(theme: theme), height: 50.0, cornerRadius: 11.0, gloss: false)
|
||||
self.proceedNode.progressType = .embedded
|
||||
@ -814,6 +842,7 @@ final class PhoneConfirmationController: ViewController {
|
||||
self.addSubnode(self.phoneTargetNode)
|
||||
|
||||
self.addSubnode(self.textNode)
|
||||
self.addSubnode(self.textActivateAreaNode)
|
||||
|
||||
self.addSubnode(self.cancelButton)
|
||||
self.addSubnode(self.proceedNode)
|
||||
@ -1009,6 +1038,8 @@ final class PhoneConfirmationController: ViewController {
|
||||
|
||||
let textSize = self.textNode.updateLayout(backgroundSize)
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - textSize.width) / 2.0), y: 88.0), size: textSize).offsetBy(dx: backgroundFrame.minX, dy: backgroundFrame.minY))
|
||||
self.textActivateAreaNode.frame = self.textNode.frame
|
||||
self.textActivateAreaNode.accessibilityLabel = "\(self.code) \(self.number). \(self.strings.Login_PhoneNumberConfirmation)"
|
||||
|
||||
let proceedWidth = backgroundSize.width - 16.0 * 2.0
|
||||
let proceedHeight = self.proceedNode.updateLayout(width: proceedWidth, transition: transition)
|
||||
|
@ -196,7 +196,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
|
||||
}
|
||||
|
||||
return ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
sortOrder: nameSortOrder,
|
||||
displayOrder: nameDisplayOrder,
|
||||
context: context,
|
||||
|
@ -319,7 +319,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
}
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListAdditionalCategoryItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
context: context,
|
||||
title: title,
|
||||
image: image,
|
||||
@ -525,7 +525,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -564,7 +564,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
let status: ContactsPeerItemStatus = .none
|
||||
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -778,7 +778,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -817,7 +817,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
let status: ContactsPeerItemStatus = .none
|
||||
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
@ -887,7 +887,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
}
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ChatListAdditionalCategoryItem(
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings),
|
||||
presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder),
|
||||
context: context,
|
||||
title: title,
|
||||
image: image,
|
||||
|
@ -64,7 +64,7 @@ func localizedCountryNamesAndCodes(strings: PresentationStrings) -> [((String, S
|
||||
let locale = localeWithStrings(strings)
|
||||
var result: [((String, String), String, [Int])] = []
|
||||
for country in AuthorizationSequenceCountrySelectionController.countries() {
|
||||
if country.hidden {
|
||||
if country.hidden || country.id == "FT" {
|
||||
continue
|
||||
}
|
||||
if let englishCountryName = usEnglishLocale.localizedString(forRegionCode: country.id), let countryName = locale.localizedString(forRegionCode: country.id) {
|
||||
@ -362,20 +362,24 @@ final class AuthorizationSequenceCountrySelectionControllerNode: ASDisplayNode,
|
||||
}
|
||||
|
||||
var countryName: String
|
||||
var cleanCountryName: String
|
||||
let originalCountryName: String
|
||||
let code: String
|
||||
if tableView === self.tableView {
|
||||
countryName = self.sections[indexPath.section].1[indexPath.row].0.1
|
||||
countryName = "\(emojiFlagForISOCountryCode(self.sections[indexPath.section].1[indexPath.row].1)) \(countryName)"
|
||||
cleanCountryName = self.sections[indexPath.section].1[indexPath.row].0.1
|
||||
countryName = "\(emojiFlagForISOCountryCode(self.sections[indexPath.section].1[indexPath.row].1)) \(cleanCountryName)"
|
||||
originalCountryName = self.sections[indexPath.section].1[indexPath.row].0.0
|
||||
code = "+\(self.sections[indexPath.section].1[indexPath.row].2)"
|
||||
} else {
|
||||
countryName = self.searchResults[indexPath.row].0.1
|
||||
countryName = "\(emojiFlagForISOCountryCode(self.searchResults[indexPath.row].1)) \(countryName)"
|
||||
cleanCountryName = self.searchResults[indexPath.row].0.1
|
||||
countryName = "\(emojiFlagForISOCountryCode(self.searchResults[indexPath.row].1)) \(cleanCountryName)"
|
||||
originalCountryName = self.searchResults[indexPath.row].0.0
|
||||
code = "+\(self.searchResults[indexPath.row].2)"
|
||||
}
|
||||
|
||||
cell.accessibilityLabel = cleanCountryName
|
||||
cell.accessibilityValue = code
|
||||
|
||||
cell.textLabel?.text = countryName
|
||||
cell.detailTextLabel?.text = originalCountryName
|
||||
if self.displayCodes, let label = cell.accessoryView as? UILabel {
|
||||
|
@ -48,7 +48,9 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
|
||||
|
||||
self.attributedText = NSAttributedString(string: text, attributes: self.attributesForCurrentState())
|
||||
if _image == nil {
|
||||
self.item?.accessibilityLabel = value
|
||||
if self.item?.accessibilityLabel == nil {
|
||||
self.item?.accessibilityLabel = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -341,6 +341,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
self.authorNameNode.maximumNumberOfLines = 1
|
||||
self.authorNameNode.isUserInteractionEnabled = false
|
||||
self.authorNameNode.displaysAsynchronously = false
|
||||
|
||||
self.dateNode = ASTextNode()
|
||||
self.dateNode.maximumNumberOfLines = 1
|
||||
self.dateNode.isUserInteractionEnabled = false
|
||||
@ -428,9 +429,20 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
self.contentNode.addSubnode(self.statusButtonNode)
|
||||
|
||||
self.deleteButton.addTarget(self, action: #selector(self.deleteButtonPressed), for: [.touchUpInside])
|
||||
self.deleteButton.accessibilityTraits = [.button]
|
||||
self.deleteButton.accessibilityLabel = presentationData.strings.Gallery_VoiceOver_Delete
|
||||
|
||||
self.fullscreenButton.addTarget(self, action: #selector(self.fullscreenButtonPressed), for: [.touchUpInside])
|
||||
self.fullscreenButton.accessibilityTraits = [.button]
|
||||
self.fullscreenButton.accessibilityLabel = presentationData.strings.Gallery_VoiceOver_Fullscreen
|
||||
|
||||
self.actionButton.addTarget(self, action: #selector(self.actionButtonPressed), for: [.touchUpInside])
|
||||
self.actionButton.accessibilityTraits = [.button]
|
||||
self.actionButton.accessibilityLabel = presentationData.strings.Gallery_VoiceOver_Share
|
||||
|
||||
self.editButton.addTarget(self, action: #selector(self.editButtonPressed), for: [.touchUpInside])
|
||||
self.editButton.accessibilityTraits = [.button]
|
||||
self.editButton.accessibilityLabel = presentationData.strings.Gallery_VoiceOver_Edit
|
||||
|
||||
self.backwardButton.addTarget(self, action: #selector(self.backwardButtonPressed), forControlEvents: .touchUpInside)
|
||||
self.forwardButton.addTarget(self, action: #selector(self.forwardButtonPressed), forControlEvents: .touchUpInside)
|
||||
@ -595,12 +607,15 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
} else {
|
||||
self.authorNameNode.attributedText = nil
|
||||
}
|
||||
self.authorNameNode.accessibilityLabel = self.authorNameNode.attributedText?.string
|
||||
|
||||
if let dateText = dateText {
|
||||
self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: .white)
|
||||
} else {
|
||||
self.dateNode.attributedText = nil
|
||||
}
|
||||
|
||||
self.dateNode.accessibilityLabel = self.dateNode.attributedText?.string
|
||||
|
||||
self.requestLayout?(.immediate)
|
||||
}
|
||||
|
||||
@ -763,8 +778,11 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll
|
||||
} else {
|
||||
self.authorNameNode.attributedText = nil
|
||||
}
|
||||
self.authorNameNode.accessibilityLabel = self.authorNameNode.attributedText?.string
|
||||
|
||||
self.dateNode.attributedText = NSAttributedString(string: dateText, font: dateFont, textColor: .white)
|
||||
|
||||
self.dateNode.accessibilityLabel = self.dateNode.attributedText?.string
|
||||
|
||||
if canFullscreen {
|
||||
self.fullscreenButton.isHidden = false
|
||||
self.deleteButton.isHidden = true
|
||||
|
@ -443,10 +443,12 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
var barButtonItems: [UIBarButtonItem] = []
|
||||
if imageReference.media.flags.contains(.hasStickers) {
|
||||
let rightBarButtonItem = UIBarButtonItem(image: generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/Stickers"), color: .white), style: .plain, target: self, action: #selector(self.openStickersButtonPressed))
|
||||
rightBarButtonItem.accessibilityLabel = self.presentationData.strings.Gallery_VoiceOver_Stickers
|
||||
barButtonItems.append(rightBarButtonItem)
|
||||
}
|
||||
if self.message != nil {
|
||||
let moreMenuItem = UIBarButtonItem(customDisplayNode: self.moreBarButton)!
|
||||
moreMenuItem.accessibilityLabel = self.presentationData.strings.Common_More
|
||||
barButtonItems.append(moreMenuItem)
|
||||
}
|
||||
self._rightBarButtonItems.set(.single(barButtonItems))
|
||||
@ -646,6 +648,7 @@ final class ChatImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
var barButtonItems: [UIBarButtonItem] = []
|
||||
if self.message != nil {
|
||||
let moreMenuItem = UIBarButtonItem(customDisplayNode: self.moreBarButton)!
|
||||
moreMenuItem.accessibilityLabel = self.presentationData.strings.Common_More
|
||||
barButtonItems.append(moreMenuItem)
|
||||
}
|
||||
self._rightBarButtonItems.set(.single(barButtonItems))
|
||||
|
@ -1420,10 +1420,12 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
var barButtonItems: [UIBarButtonItem] = []
|
||||
if hasLinkedStickers {
|
||||
let rightBarButtonItem = UIBarButtonItem(image: generateTintedImage(image: UIImage(bundleImageName: "Media Gallery/Stickers"), color: .white), style: .plain, target: self, action: #selector(self.openStickersButtonPressed))
|
||||
rightBarButtonItem.accessibilityLabel = self.presentationData.strings.Gallery_VoiceOver_Stickers
|
||||
barButtonItems.append(rightBarButtonItem)
|
||||
}
|
||||
if forceEnablePiP || (!isAnimated && !disablePlayerControls && !disablePictureInPicture) {
|
||||
let rightBarButtonItem = UIBarButtonItem(image: pictureInPictureButtonImage, style: .plain, target: self, action: #selector(self.pictureInPictureButtonPressed))
|
||||
rightBarButtonItem.accessibilityLabel = self.presentationData.strings.Gallery_VoiceOver_PictureInPicture
|
||||
self.pictureInPictureButton = rightBarButtonItem
|
||||
barButtonItems.append(rightBarButtonItem)
|
||||
self.hasPictureInPicture = true
|
||||
@ -1452,6 +1454,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
|
||||
if hasMoreButton {
|
||||
let moreMenuItem = UIBarButtonItem(customDisplayNode: self.moreBarButton)!
|
||||
moreMenuItem.accessibilityLabel = self.presentationData.strings.Common_More
|
||||
barButtonItems.append(moreMenuItem)
|
||||
}
|
||||
}
|
||||
|
@ -159,11 +159,13 @@ public final class ItemListPresentationData: Equatable {
|
||||
public let theme: PresentationTheme
|
||||
public let fontSize: PresentationFontSize
|
||||
public let strings: PresentationStrings
|
||||
public let nameDisplayOrder: PresentationPersonNameOrder
|
||||
|
||||
public init(theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings) {
|
||||
public init(theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder) {
|
||||
self.theme = theme
|
||||
self.fontSize = fontSize
|
||||
self.strings = strings
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
}
|
||||
|
||||
public static func ==(lhs: ItemListPresentationData, rhs: ItemListPresentationData) -> Bool {
|
||||
@ -176,6 +178,9 @@ public final class ItemListPresentationData: Equatable {
|
||||
if lhs.fontSize != rhs.fontSize {
|
||||
return false
|
||||
}
|
||||
if lhs.nameDisplayOrder != rhs.nameDisplayOrder {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -226,6 +231,6 @@ public extension PresentationFontSize {
|
||||
|
||||
public extension ItemListPresentationData {
|
||||
convenience init(_ presentationData: PresentationData) {
|
||||
self.init(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings)
|
||||
self.init(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder)
|
||||
}
|
||||
}
|
||||
|
@ -232,15 +232,20 @@ public class ItemListCallListItemNode: ListViewItemNode {
|
||||
insets = UIEdgeInsets()
|
||||
}
|
||||
|
||||
var accessibilityText = ""
|
||||
|
||||
let earliestMessage = item.messages.sorted(by: {$0.timestamp < $1.timestamp}).first!
|
||||
let titleText = stringForDate(timestamp: earliestMessage.timestamp, strings: item.presentationData.strings)
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: titleText, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
accessibilityText.append(titleText)
|
||||
accessibilityText.append(". ")
|
||||
|
||||
contentHeight += titleLayout.size.height + 18.0
|
||||
|
||||
var index = 0
|
||||
var nodesLayout: [(TextNodeLayout, TextNodeLayout)] = []
|
||||
var nodesApply: [(() -> TextNode, () -> TextNode)] = []
|
||||
|
||||
for message in item.messages {
|
||||
let makeTimeLayout = makeNodesLayout[index].0
|
||||
let time = stringForMessageTimestamp(timestamp: message.timestamp, dateTimeFormat: item.dateTimeFormat)
|
||||
@ -250,6 +255,8 @@ public class ItemListCallListItemNode: ListViewItemNode {
|
||||
let type = stringForCallType(message: message, strings: item.presentationData.strings)
|
||||
let (typeLayout, typeApply) = makeTypeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: type, font: typeFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
accessibilityText.append("\(time) - \(type)")
|
||||
|
||||
nodesLayout.append((timeLayout, typeLayout))
|
||||
nodesApply.append((timeApply, typeApply))
|
||||
|
||||
@ -336,6 +343,8 @@ public class ItemListCallListItemNode: ListViewItemNode {
|
||||
index += 1
|
||||
}
|
||||
|
||||
strongSelf.accessibilityArea.accessibilityLabel = accessibilityText
|
||||
strongSelf.accessibilityArea.accessibilityTraits = .staticText
|
||||
strongSelf.accessibilityArea.frame = CGRect(origin: CGPoint(), size: layout.contentSize)
|
||||
}
|
||||
})
|
||||
|
@ -101,6 +101,7 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
if self.isEnabled != oldValue {
|
||||
self.updateColors(animated: true)
|
||||
}
|
||||
self.updateAccessibilityLabels()
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,6 +131,11 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
|
||||
private func updateAccessibilityLabels() {
|
||||
self.accessibilityLabel = (self.title ?? "") + " " + (self.subtitle ?? "")
|
||||
if !self.isEnabled {
|
||||
self.accessibilityTraits = [.button, .notEnabled]
|
||||
} else {
|
||||
self.accessibilityTraits = [.button]
|
||||
}
|
||||
}
|
||||
|
||||
private var animationTimer: SwiftSignalKit.Timer?
|
||||
@ -289,6 +295,8 @@ public final class SolidRoundedButtonNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.updateAccessibilityLabels()
|
||||
}
|
||||
|
||||
public override func didLoad() {
|
||||
@ -795,6 +803,11 @@ public final class SolidRoundedButtonView: UIView {
|
||||
private func updateAccessibilityLabels() {
|
||||
self.accessibilityLabel = (self.title ?? "") + " " + (self.subtitle ?? "")
|
||||
self.accessibilityValue = self.label
|
||||
if !self.isEnabled {
|
||||
self.accessibilityTraits = [.button, .notEnabled]
|
||||
} else {
|
||||
self.accessibilityTraits = [.button]
|
||||
}
|
||||
}
|
||||
|
||||
public var icon: UIImage? {
|
||||
@ -808,6 +821,7 @@ public final class SolidRoundedButtonView: UIView {
|
||||
if self.isEnabled != oldValue {
|
||||
self.titleNode.alpha = self.isEnabled ? 1.0 : 0.6
|
||||
}
|
||||
self.updateAccessibilityLabels()
|
||||
}
|
||||
}
|
||||
|
||||
@ -976,6 +990,8 @@ public final class SolidRoundedButtonView: UIView {
|
||||
if #available(iOS 13.0, *) {
|
||||
self.buttonBackgroundNode.layer.cornerCurve = .continuous
|
||||
}
|
||||
|
||||
self.updateAccessibilityLabels()
|
||||
}
|
||||
|
||||
required public init(coder: NSCoder) {
|
||||
|
@ -214,6 +214,7 @@ final class ChatMessageAccessibilityData {
|
||||
|
||||
loop: for media in message.media {
|
||||
if let _ = media as? TelegramMediaImage {
|
||||
traits.insert(.image)
|
||||
if isIncoming {
|
||||
if announceIncomingAuthors, let authorName = authorName {
|
||||
label = item.presentationData.strings.VoiceOver_Chat_PhotoFrom(authorName).string
|
||||
|
@ -32,6 +32,8 @@ final class ChatTextInputAudioRecordingCancelIndicator: ASDisplayNode {
|
||||
self.cancelButton = HighlightableButtonNode()
|
||||
self.cancelButton.setTitle(strings.Common_Cancel, with: cancelFont, with: theme.chat.inputPanel.panelControlAccentColor, for: [])
|
||||
self.cancelButton.alpha = 0.0
|
||||
self.cancelButton.accessibilityLabel = strings.Common_Cancel
|
||||
self.cancelButton.accessibilityTraits = [.button]
|
||||
|
||||
self.strings = strings
|
||||
|
||||
|
@ -10,6 +10,7 @@ import MergeLists
|
||||
import AccountContext
|
||||
import ChatPresentationInterfaceState
|
||||
import ChatControllerInteraction
|
||||
import ItemListUI
|
||||
|
||||
private struct CommandChatInputContextPanelEntryStableId: Hashable {
|
||||
let command: PeerCommand
|
||||
@ -36,8 +37,8 @@ private struct CommandChatInputContextPanelEntry: Comparable, Identifiable {
|
||||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
func item(context: AccountContext, fontSize: PresentationFontSize, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> ListViewItem {
|
||||
return CommandChatInputPanelItem(context: context, theme: self.theme, fontSize: fontSize, command: self.command, commandSelected: commandSelected)
|
||||
func item(context: AccountContext, presentationData: PresentationData, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> ListViewItem {
|
||||
return CommandChatInputPanelItem(context: context, presentationData: ItemListPresentationData(presentationData), command: self.command, commandSelected: commandSelected)
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,12 +48,12 @@ private struct CommandChatInputContextPanelTransition {
|
||||
let updates: [ListViewUpdateItem]
|
||||
}
|
||||
|
||||
private func preparedTransition(from fromEntries: [CommandChatInputContextPanelEntry], to toEntries: [CommandChatInputContextPanelEntry], context: AccountContext, fontSize: PresentationFontSize, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> CommandChatInputContextPanelTransition {
|
||||
private func preparedTransition(from fromEntries: [CommandChatInputContextPanelEntry], to toEntries: [CommandChatInputContextPanelEntry], context: AccountContext, presentationData: PresentationData, commandSelected: @escaping (PeerCommand, Bool) -> Void) -> CommandChatInputContextPanelTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, fontSize: fontSize, commandSelected: commandSelected), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, fontSize: fontSize, commandSelected: commandSelected), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, commandSelected: commandSelected), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, commandSelected: commandSelected), directionHint: nil) }
|
||||
|
||||
return CommandChatInputContextPanelTransition(deletions: deletions, insertions: insertions, updates: updates)
|
||||
}
|
||||
@ -101,7 +102,8 @@ final class CommandChatInputContextPanelNode: ChatInputContextPanelNode {
|
||||
|
||||
private func prepareTransition(from: [CommandChatInputContextPanelEntry]? , to: [CommandChatInputContextPanelEntry]) {
|
||||
let firstTime = self.currentEntries == nil
|
||||
let transition = preparedTransition(from: from ?? [], to: to, context: self.context, fontSize: self.fontSize, commandSelected: { [weak self] command, sendImmediately in
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let transition = preparedTransition(from: from ?? [], to: to, context: self.context, presentationData: presentationData, commandSelected: { [weak self] command, sendImmediately in
|
||||
if let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction {
|
||||
if sendImmediately {
|
||||
interfaceInteraction.sendBotCommand(command.peer, "/" + command.command.text)
|
||||
|
@ -9,20 +9,19 @@ import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
import AvatarNode
|
||||
import AccountContext
|
||||
import ItemListUI
|
||||
|
||||
final class CommandChatInputPanelItem: ListViewItem {
|
||||
fileprivate let context: AccountContext
|
||||
fileprivate let theme: PresentationTheme
|
||||
fileprivate let fontSize: PresentationFontSize
|
||||
fileprivate let presentationData: ItemListPresentationData
|
||||
fileprivate let command: PeerCommand
|
||||
fileprivate let commandSelected: (PeerCommand, Bool) -> Void
|
||||
|
||||
let selectable: Bool = true
|
||||
|
||||
public init(context: AccountContext, theme: PresentationTheme, fontSize: PresentationFontSize, command: PeerCommand, commandSelected: @escaping (PeerCommand, Bool) -> Void) {
|
||||
public init(context: AccountContext, presentationData: ItemListPresentationData, command: PeerCommand, commandSelected: @escaping (PeerCommand, Bool) -> Void) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.fontSize = fontSize
|
||||
self.presentationData = presentationData
|
||||
self.command = command
|
||||
self.commandSelected = commandSelected
|
||||
}
|
||||
@ -92,6 +91,8 @@ final class CommandChatInputPanelItemNode: ListViewItemNode {
|
||||
private let highlightedBackgroundNode: ASDisplayNode
|
||||
private let arrowNode: ASButtonNode
|
||||
|
||||
private let activateAreaNode: AccessibilityAreaNode
|
||||
|
||||
init() {
|
||||
self.avatarNode = AvatarNode(font: avatarFont)
|
||||
self.textNode = TextNode()
|
||||
@ -107,6 +108,9 @@ final class CommandChatInputPanelItemNode: ListViewItemNode {
|
||||
|
||||
self.arrowNode = HighlightableButtonNode()
|
||||
|
||||
self.activateAreaNode = AccessibilityAreaNode()
|
||||
self.activateAreaNode.accessibilityTraits = [.button]
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
|
||||
self.addSubnode(self.topSeparatorNode)
|
||||
@ -117,6 +121,8 @@ final class CommandChatInputPanelItemNode: ListViewItemNode {
|
||||
self.addSubnode(self.arrowNode)
|
||||
|
||||
self.arrowNode.addTarget(self, action: #selector(self.arrowButtonPressed), forControlEvents: [.touchUpInside])
|
||||
|
||||
self.addSubnode(self.activateAreaNode)
|
||||
}
|
||||
|
||||
override public func layoutForParams(_ params: ListViewItemLayoutParams, item: ListViewItem, previousItem: ListViewItem?, nextItem: ListViewItem?) {
|
||||
@ -134,37 +140,40 @@ final class CommandChatInputPanelItemNode: ListViewItemNode {
|
||||
let makeTextLayout = TextNode.asyncLayout(self.textNode)
|
||||
|
||||
return { [weak self] item, params, mergedTop, mergedBottom in
|
||||
let textFont = Font.medium(floor(item.fontSize.baseDisplaySize * 14.0 / 17.0))
|
||||
let descriptionFont = Font.regular(floor(item.fontSize.baseDisplaySize * 14.0 / 17.0))
|
||||
let textFont = Font.medium(floor(item.presentationData.fontSize.baseDisplaySize * 14.0 / 17.0))
|
||||
let descriptionFont = Font.regular(floor(item.presentationData.fontSize.baseDisplaySize * 14.0 / 17.0))
|
||||
|
||||
let leftInset: CGFloat = 55.0 + params.leftInset
|
||||
let rightInset: CGFloat = 10.0 + params.rightInset
|
||||
|
||||
let peerName = EnginePeer(item.command.peer).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
|
||||
|
||||
let commandString = NSMutableAttributedString()
|
||||
commandString.append(NSAttributedString(string: "/" + item.command.command.text, font: textFont, textColor: item.theme.list.itemPrimaryTextColor))
|
||||
commandString.append(NSAttributedString(string: "/" + item.command.command.text, font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor))
|
||||
let command = commandString.string
|
||||
|
||||
if !item.command.command.description.isEmpty {
|
||||
commandString.append(NSAttributedString(string: " " + item.command.command.description, font: descriptionFont, textColor: item.theme.list.itemSecondaryTextColor))
|
||||
commandString.append(NSAttributedString(string: " " + item.command.command.description, font: descriptionFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor))
|
||||
}
|
||||
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: commandString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 40.0, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: HashtagChatInputPanelItemNode.itemHeight), insets: UIEdgeInsets())
|
||||
|
||||
let iconImage = PresentationResourcesChat.chatCommandPanelArrowImage(item.theme)
|
||||
let iconImage = PresentationResourcesChat.chatCommandPanelArrowImage(item.presentationData.theme)
|
||||
|
||||
return (nodeLayout, { _ in
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
|
||||
strongSelf.separatorNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.topSeparatorNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundColor = item.theme.list.plainBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.separatorNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.topSeparatorNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
|
||||
strongSelf.arrowNode.setImage(iconImage, for: [])
|
||||
|
||||
strongSelf.avatarNode.setPeer(context: item.context, theme: item.theme, peer: EnginePeer(item.command.peer), emptyColor: item.theme.list.mediaPlaceholderColor)
|
||||
strongSelf.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: EnginePeer(item.command.peer), emptyColor: item.presentationData.theme.list.mediaPlaceholderColor)
|
||||
|
||||
let _ = textApply()
|
||||
|
||||
@ -181,6 +190,10 @@ final class CommandChatInputPanelItemNode: ListViewItemNode {
|
||||
strongSelf.separatorNode.frame = CGRect(origin: CGPoint(x: leftInset, y: nodeLayout.contentSize.height - UIScreenPixel), size: CGSize(width: params.width - leftInset, height: UIScreenPixel))
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: nodeLayout.size.height + UIScreenPixel))
|
||||
|
||||
strongSelf.activateAreaNode.accessibilityLabel = "\(peerName), \(command)"
|
||||
strongSelf.activateAreaNode.accessibilityValue = item.command.command.description
|
||||
strongSelf.activateAreaNode.frame = CGRect(origin: .zero, size: nodeLayout.size)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ final class CommandMenuChatInputContextPanelNode: ChatInputContextPanelNode {
|
||||
self.listView.clipsToBounds = false
|
||||
self.listView.isOpaque = false
|
||||
self.listView.stackFromBottom = true
|
||||
self.listView.keepBottomItemOverscrollBackground = theme.list.plainBackgroundColor
|
||||
self.listView.limitHitTestToNodes = true
|
||||
self.listView.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
self.listView.accessibilityPageScrolledString = { row, count in
|
||||
@ -234,7 +235,7 @@ final class CommandMenuChatInputContextPanelNode: ChatInputContextPanelNode {
|
||||
self.listView.keepBottomItemOverscrollBackground = self.theme.list.plainBackgroundColor
|
||||
|
||||
let new = self.currentEntries?.map({$0.withUpdatedTheme(interfaceState.theme)}) ?? []
|
||||
prepareTransition(from: self.currentEntries, to: new)
|
||||
self.prepareTransition(from: self.currentEntries, to: new)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,8 @@ final class CommandMenuChatInputPanelItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let highlightedBackgroundNode: ASDisplayNode
|
||||
|
||||
private let activateAreaNode: AccessibilityAreaNode
|
||||
|
||||
init() {
|
||||
self.textNode = TextNode()
|
||||
self.commandNode = TextNode()
|
||||
@ -139,6 +141,9 @@ final class CommandMenuChatInputPanelItemNode: ListViewItemNode {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.clipsToBounds = true
|
||||
|
||||
self.activateAreaNode = AccessibilityAreaNode()
|
||||
self.activateAreaNode.accessibilityTraits = [.button]
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
|
||||
self.addSubnode(self.clippingNode)
|
||||
@ -148,6 +153,8 @@ final class CommandMenuChatInputPanelItemNode: ListViewItemNode {
|
||||
self.backgroundNode.addSubnode(self.textNode)
|
||||
self.backgroundNode.addSubnode(self.commandNode)
|
||||
self.backgroundNode.addSubnode(self.separatorNode)
|
||||
|
||||
self.addSubnode(self.activateAreaNode)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -227,6 +234,10 @@ final class CommandMenuChatInputPanelItemNode: ListViewItemNode {
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: nodeLayout.size.height + UIScreenPixel))
|
||||
|
||||
strongSelf.activateAreaNode.accessibilityLabel = textString.string
|
||||
strongSelf.activateAreaNode.accessibilityValue = commandString.string
|
||||
strongSelf.activateAreaNode.frame = CGRect(origin: .zero, size: nodeLayout.size)
|
||||
|
||||
if !mergedTop {
|
||||
strongSelf.shadowNode.isHidden = false
|
||||
strongSelf.shadowNode.frame = CGRect(origin: CGPoint(x: -shadowBlur, y: 0.0), size: CGSize(width: nodeLayout.size.width + shadowBlur * 2.0, height: backgroundCornerRadius + shadowBlur))
|
||||
|
@ -98,6 +98,8 @@ final class HashtagChatInputPanelItemNode: ListViewItemNode {
|
||||
private var recognizer: ItemListRevealOptionsGestureRecognizer?
|
||||
private var hapticFeedback: HapticFeedback?
|
||||
|
||||
private let activateAreaNode: AccessibilityAreaNode
|
||||
|
||||
private var item: HashtagChatInputPanelItem?
|
||||
|
||||
private var validLayout: (CGSize, CGFloat, CGFloat)?
|
||||
@ -114,11 +116,16 @@ final class HashtagChatInputPanelItemNode: ListViewItemNode {
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
|
||||
self.activateAreaNode = AccessibilityAreaNode()
|
||||
self.activateAreaNode.accessibilityTraits = [.button]
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
|
||||
self.addSubnode(self.topSeparatorNode)
|
||||
self.addSubnode(self.separatorNode)
|
||||
self.addSubnode(self.textNode)
|
||||
|
||||
self.addSubnode(self.activateAreaNode)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -150,7 +157,8 @@ final class HashtagChatInputPanelItemNode: ListViewItemNode {
|
||||
|
||||
let leftInset: CGFloat = 15.0 + params.leftInset
|
||||
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "#\(item.text)", font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: baseWidth, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let title = "#\(item.text)"
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: title, font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: baseWidth, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: HashtagChatInputPanelItemNode.itemHeight), insets: UIEdgeInsets())
|
||||
|
||||
@ -177,6 +185,9 @@ final class HashtagChatInputPanelItemNode: ListViewItemNode {
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: nodeLayout.size.height + UIScreenPixel))
|
||||
|
||||
strongSelf.activateAreaNode.accessibilityLabel = title
|
||||
strongSelf.activateAreaNode.frame = CGRect(origin: .zero, size: nodeLayout.size)
|
||||
|
||||
strongSelf.setRevealOptions([ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)])
|
||||
strongSelf.setRevealOptionsOpened(item.revealed, animated: animation.isAnimated)
|
||||
}
|
||||
|
@ -108,6 +108,8 @@ final class MentionChatInputPanelItemNode: ListViewItemNode {
|
||||
private var recognizer: ItemListRevealOptionsGestureRecognizer?
|
||||
private var hapticFeedback: HapticFeedback?
|
||||
|
||||
private let activateAreaNode: AccessibilityAreaNode
|
||||
|
||||
private var item: MentionChatInputPanelItem?
|
||||
|
||||
private var validLayout: (CGSize, CGFloat, CGFloat)?
|
||||
@ -125,6 +127,9 @@ final class MentionChatInputPanelItemNode: ListViewItemNode {
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
|
||||
self.activateAreaNode = AccessibilityAreaNode()
|
||||
self.activateAreaNode.accessibilityTraits = [.button]
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
|
||||
self.addSubnode(self.topSeparatorNode)
|
||||
@ -132,6 +137,8 @@ final class MentionChatInputPanelItemNode: ListViewItemNode {
|
||||
|
||||
self.addSubnode(self.avatarNode)
|
||||
self.addSubnode(self.textNode)
|
||||
|
||||
self.addSubnode(self.activateAreaNode)
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -171,10 +178,14 @@ final class MentionChatInputPanelItemNode: ListViewItemNode {
|
||||
updatedInverted = item.inverted
|
||||
}
|
||||
|
||||
|
||||
let title = EnginePeer(item.peer).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
|
||||
var username: String?
|
||||
let string = NSMutableAttributedString()
|
||||
string.append(NSAttributedString(string: item.peer.debugDisplayTitle, font: primaryFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor))
|
||||
string.append(NSAttributedString(string: title, font: primaryFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor))
|
||||
if let addressName = item.peer.addressName, !addressName.isEmpty {
|
||||
string.append(NSAttributedString(string: " @\(addressName)", font: secondaryFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor))
|
||||
username = "@\(addressName)"
|
||||
}
|
||||
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: 100.0), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
@ -215,6 +226,10 @@ final class MentionChatInputPanelItemNode: ListViewItemNode {
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: nodeLayout.size.height + UIScreenPixel))
|
||||
|
||||
strongSelf.activateAreaNode.accessibilityLabel = title
|
||||
strongSelf.activateAreaNode.accessibilityValue = username
|
||||
strongSelf.activateAreaNode.frame = CGRect(origin: .zero, size: nodeLayout.size)
|
||||
|
||||
if let peer = item.peer as? TelegramUser, let _ = peer.botInfo {
|
||||
strongSelf.setRevealOptions([ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)])
|
||||
strongSelf.setRevealOptionsOpened(item.revealed, animated: animation.isAnimated)
|
||||
|
@ -63,6 +63,8 @@ final class MultiScaleTextNode: ASDisplayNode {
|
||||
for (key, state) in states {
|
||||
if let node = self.stateNodes[key] {
|
||||
node.textNode.attributedText = NSAttributedString(string: text, font: state.attributes.font, textColor: state.attributes.color)
|
||||
node.textNode.isAccessibilityElement = true
|
||||
node.textNode.accessibilityLabel = text
|
||||
let nodeSize = node.textNode.updateLayout(state.constrainedSize)
|
||||
let nodeLayout = MultiScaleTextLayout(size: nodeSize)
|
||||
if key == mainState {
|
||||
|
@ -30,6 +30,7 @@ final class PeerInfoScreenCallListItem: PeerInfoScreenItem {
|
||||
private final class PeerInfoScreenCallListItemNode: PeerInfoScreenItemNode {
|
||||
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
|
||||
private let bottomSeparatorNode: ASDisplayNode
|
||||
private let maskNode: ASImageNode
|
||||
|
||||
private var item: PeerInfoScreenCallListItem?
|
||||
private var itemNode: ItemListCallListItemNode?
|
||||
@ -42,6 +43,9 @@ private final class PeerInfoScreenCallListItemNode: PeerInfoScreenItemNode {
|
||||
self.bottomSeparatorNode = ASDisplayNode()
|
||||
self.bottomSeparatorNode.isLayerBacked = true
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
self.maskNode.isUserInteractionEnabled = false
|
||||
|
||||
super.init()
|
||||
|
||||
bringToFrontForHighlightImpl = { [weak self] in
|
||||
@ -50,6 +54,7 @@ private final class PeerInfoScreenCallListItemNode: PeerInfoScreenItemNode {
|
||||
|
||||
self.addSubnode(self.bottomSeparatorNode)
|
||||
self.addSubnode(self.selectionNode)
|
||||
self.addSubnode(self.maskNode)
|
||||
}
|
||||
|
||||
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
@ -106,6 +111,14 @@ private final class PeerInfoScreenCallListItemNode: PeerInfoScreenItemNode {
|
||||
transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel)))
|
||||
transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0)
|
||||
|
||||
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
|
||||
let hasTopCorners = hasCorners && topItem == nil
|
||||
let hasBottomCorners = hasCorners && bottomItem == nil
|
||||
|
||||
self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
self.maskNode.frame = CGRect(origin: CGPoint(x: safeInsets.left, y: 0.0), size: CGSize(width: width - safeInsets.left - safeInsets.right, height: height))
|
||||
self.bottomSeparatorNode.isHidden = hasBottomCorners
|
||||
|
||||
return height
|
||||
}
|
||||
}
|
||||
|
@ -527,7 +527,6 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
||||
self.activateArea.accessibilityLabel = item.label
|
||||
self.activateArea.accessibilityValue = item.text
|
||||
|
||||
|
||||
let contentSize = CGSize(width: width, height: height)
|
||||
self.containerNode.frame = CGRect(origin: CGPoint(), size: contentSize)
|
||||
self.contextSourceNode.frame = CGRect(origin: CGPoint(), size: contentSize)
|
||||
|
@ -2918,7 +2918,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
TitleNodeStateRegular: MultiScaleTextState(attributes: titleAttributes, constrainedSize: titleConstrainedSize),
|
||||
TitleNodeStateExpanded: MultiScaleTextState(attributes: smallTitleAttributes, constrainedSize: titleConstrainedSize)
|
||||
], mainState: TitleNodeStateRegular)
|
||||
self.titleNode.accessibilityLabel = titleStringText
|
||||
|
||||
let subtitleNodeLayout = self.subtitleNode.updateLayout(text: subtitleStringText, states: [
|
||||
TitleNodeStateRegular: MultiScaleTextState(attributes: subtitleAttributes, constrainedSize: titleConstrainedSize),
|
||||
|
Loading…
x
Reference in New Issue
Block a user