diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 292c5878d8..5aaded99a0 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8893,3 +8893,7 @@ Sorry for the inconvenience."; "Login.CodeSentCallText" = "Calling **%@** to dictate the code."; "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"; + +"VoiceOver.Tab" = "Tab"; diff --git a/submodules/ContactListUI/Sources/ContactsController.swift b/submodules/ContactListUI/Sources/ContactsController.swift index e3f975a779..d1cb89b843 100644 --- a/submodules/ContactListUI/Sources/ContactsController.swift +++ b/submodules/ContactListUI/Sources/ContactsController.swift @@ -203,6 +203,7 @@ public class ContactsController: ViewController { self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) self.navigationItem.leftBarButtonItem = UIBarButtonItem(customDisplayNode: self.sortButton) + self.navigationItem.leftBarButtonItem?.accessibilityLabel = self.presentationData.strings.Contacts_Sort self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: PresentationResourcesRootController.navigationAddIcon(self.presentationData.theme), style: .plain, target: self, action: #selector(self.addPressed)) self.navigationItem.rightBarButtonItem?.accessibilityLabel = self.presentationData.strings.Contacts_VoiceOver_AddContact diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 7752442d25..a3b935c357 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -93,10 +93,12 @@ public final class NavigationBarTheme { public final class NavigationBarStrings { public let back: String public let close: String + public let tab: String - public init(back: String, close: String) { + public init(back: String, close: String, tab: String) { self.back = back self.close = close + self.tab = tab } } diff --git a/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift b/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift index 57dca9563a..6ca0d5fc0f 100644 --- a/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift +++ b/submodules/PasscodeUI/Sources/PasscodeEntryControllerNode.swift @@ -125,8 +125,12 @@ final class PasscodeEntryControllerNode: ASDisplayNode { } self.cancelButtonNode.setTitle(strings.Common_Cancel, with: buttonFont, with: .white, for: .normal) + self.cancelButtonNode.accessibilityLabel = strings.Common_Cancel + self.cancelButtonNode.accessibilityTraits = [.button] self.deleteButtonNode.setTitle(strings.Common_Delete, with: buttonFont, with: .white, for: .normal) - + self.deleteButtonNode.accessibilityLabel = strings.Common_Delete + self.deleteButtonNode.accessibilityTraits = [.button] + if let biometricsType = self.biometricsType { switch biometricsType { case .touchId: diff --git a/submodules/PasscodeUI/Sources/PasscodeEntryKeyboardNode.swift b/submodules/PasscodeUI/Sources/PasscodeEntryKeyboardNode.swift index 649b98978d..5ccd1b07d3 100644 --- a/submodules/PasscodeUI/Sources/PasscodeEntryKeyboardNode.swift +++ b/submodules/PasscodeUI/Sources/PasscodeEntryKeyboardNode.swift @@ -128,6 +128,9 @@ final class PasscodeEntryButtonNode: HighlightTrackingButtonNode { super.init() + self.accessibilityLabel = title + self.accessibilityTraits = .keyboardKey + if let gradientBackgroundNode = self.gradientBackgroundNode { self.addSubnode(gradientBackgroundNode) } diff --git a/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift index 5a23069496..54c4115572 100644 --- a/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift +++ b/submodules/PasswordSetupUI/Sources/TwoFactorAuthDataInputScreen.swift @@ -73,7 +73,7 @@ public final class TwoFactorDataInputScreen: ViewController { let defaultTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme) let navigationBarTheme = NavigationBarTheme(buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor) - super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close))) + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close, tab: self.presentationData.strings.VoiceOver_Tab))) self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style self.navigationPresentation = presentation diff --git a/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift b/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift index 5d2912da32..0c986951c2 100644 --- a/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift +++ b/submodules/PasswordSetupUI/Sources/TwoFactorAuthSplashScreen.swift @@ -56,7 +56,7 @@ public final class TwoFactorAuthSplashScreen: ViewController { let defaultTheme = NavigationBarTheme(rootControllerTheme: self.presentationData.theme) let navigationBarTheme = NavigationBarTheme(buttonColor: defaultTheme.buttonColor, disabledButtonColor: defaultTheme.disabledButtonColor, primaryTextColor: defaultTheme.primaryTextColor, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: defaultTheme.badgeBackgroundColor, badgeStrokeColor: defaultTheme.badgeStrokeColor, badgeTextColor: defaultTheme.badgeTextColor) - super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close))) + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close, tab: self.presentationData.strings.VoiceOver_Tab))) self.navigationPresentation = presentation diff --git a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift index d38c8efc06..c944446ab5 100644 --- a/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift +++ b/submodules/QrCodeUI/Sources/QrCodeScanScreen.swift @@ -112,7 +112,7 @@ public final class QrCodeScanScreen: ViewController { let navigationBarTheme = NavigationBarTheme(buttonColor: .white, disabledButtonColor: .white, primaryTextColor: .white, backgroundColor: .clear, enableBackgroundBlur: false, separatorColor: .clear, badgeBackgroundColor: .clear, badgeStrokeColor: .clear, badgeTextColor: .clear) - super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close))) + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: navigationBarTheme, strings: NavigationBarStrings(back: self.presentationData.strings.Common_Back, close: self.presentationData.strings.Common_Close, tab: self.presentationData.strings.VoiceOver_Tab))) self.statusBar.statusBarStyle = .White diff --git a/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceController.swift b/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceController.swift index 4e4db063d1..651c862ae7 100644 --- a/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceController.swift +++ b/submodules/SettingsUI/Sources/Terms of Service/TermsOfServiceController.swift @@ -78,7 +78,7 @@ public class TermsOfServiceController: ViewController, StandalonePresentableCont self.decline = decline self.openUrl = openUrl - super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(back: presentationData.strings.Common_Back, close: presentationData.strings.Common_Close))) + super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(back: presentationData.strings.Common_Back, close: presentationData.strings.Common_Close, tab: presentationData.strings.VoiceOver_Tab))) self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style diff --git a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift index 7e56eb8946..d34ac8b555 100644 --- a/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift +++ b/submodules/SolidRoundedButtonNode/Sources/SolidRoundedButtonNode.swift @@ -251,6 +251,8 @@ public final class SolidRoundedButtonNode: ASDisplayNode { super.init() + self.isAccessibilityElement = true + self.addSubnode(self.buttonBackgroundNode) self.addSubnode(self.buttonNode) self.addSubnode(self.titleNode) @@ -931,6 +933,8 @@ public final class SolidRoundedButtonView: UIView { super.init(frame: CGRect()) + self.isAccessibilityElement = true + self.addSubview(self.buttonBackgroundNode) self.addSubview(self.buttonNode) self.addSubview(self.titleNode) diff --git a/submodules/TabBarUI/Sources/TabBarContollerNode.swift b/submodules/TabBarUI/Sources/TabBarContollerNode.swift index 39a56e395a..8d26ba1f6c 100644 --- a/submodules/TabBarUI/Sources/TabBarContollerNode.swift +++ b/submodules/TabBarUI/Sources/TabBarContollerNode.swift @@ -10,6 +10,7 @@ private extension ToolbarTheme { } final class TabBarControllerNode: ASDisplayNode { + private var navigationBarPresentationData: NavigationBarPresentationData private var theme: TabBarControllerTheme let tabBarNode: TabBarNode private let disabledOverlayNode: ASDisplayNode @@ -27,9 +28,10 @@ final class TabBarControllerNode: ASDisplayNode { } } - init(theme: TabBarControllerTheme, itemSelected: @escaping (Int, Bool, [ASDisplayNode]) -> Void, contextAction: @escaping (Int, ContextExtractedContentContainingNode, ContextGesture) -> Void, swipeAction: @escaping (Int, TabBarItemSwipeDirection) -> Void, toolbarActionSelected: @escaping (ToolbarActionOption) -> Void, disabledPressed: @escaping () -> Void) { + init(theme: TabBarControllerTheme, navigationBarPresentationData: NavigationBarPresentationData, itemSelected: @escaping (Int, Bool, [ASDisplayNode]) -> Void, contextAction: @escaping (Int, ContextExtractedContentContainingNode, ContextGesture) -> Void, swipeAction: @escaping (Int, TabBarItemSwipeDirection) -> Void, toolbarActionSelected: @escaping (ToolbarActionOption) -> Void, disabledPressed: @escaping () -> Void) { self.theme = theme - self.tabBarNode = TabBarNode(theme: theme, itemSelected: itemSelected, contextAction: contextAction, swipeAction: swipeAction) + self.navigationBarPresentationData = navigationBarPresentationData + self.tabBarNode = TabBarNode(theme: theme, tabString: navigationBarPresentationData.strings.tab, itemSelected: itemSelected, contextAction: contextAction, swipeAction: swipeAction) self.disabledOverlayNode = ASDisplayNode() self.disabledOverlayNode.backgroundColor = theme.backgroundColor.withAlphaComponent(0.5) self.disabledOverlayNode.alpha = 0.0 @@ -60,11 +62,12 @@ final class TabBarControllerNode: ASDisplayNode { } } - func updateTheme(_ theme: TabBarControllerTheme) { + func updateTheme(_ theme: TabBarControllerTheme, navigationBarPresentationData: NavigationBarPresentationData) { self.theme = theme + self.navigationBarPresentationData = navigationBarPresentationData self.backgroundColor = theme.backgroundColor - self.tabBarNode.updateTheme(theme) + self.tabBarNode.updateTheme(theme, tabString: navigationBarPresentationData.strings.tab) self.disabledOverlayNode.backgroundColor = theme.backgroundColor.withAlphaComponent(0.5) self.toolbarNode?.updateTheme(ToolbarTheme(tabBarTheme: theme)) } diff --git a/submodules/TabBarUI/Sources/TabBarController.swift b/submodules/TabBarUI/Sources/TabBarController.swift index b5381d47ca..5fdefb0a3a 100644 --- a/submodules/TabBarUI/Sources/TabBarController.swift +++ b/submodules/TabBarUI/Sources/TabBarController.swift @@ -127,9 +127,11 @@ open class TabBarControllerImpl: ViewController, TabBarController { private let pendingControllerDisposable = MetaDisposable() + private var navigationBarPresentationData: NavigationBarPresentationData private var theme: TabBarControllerTheme public init(navigationBarPresentationData: NavigationBarPresentationData, theme: TabBarControllerTheme) { + self.navigationBarPresentationData = navigationBarPresentationData self.theme = theme super.init(navigationBarPresentationData: nil) @@ -155,8 +157,9 @@ open class TabBarControllerImpl: ViewController, TabBarController { public func updateTheme(navigationBarPresentationData: NavigationBarPresentationData, theme: TabBarControllerTheme) { if self.theme !== theme { self.theme = theme + self.navigationBarPresentationData = navigationBarPresentationData if self.isNodeLoaded { - self.tabBarControllerNode.updateTheme(theme) + self.tabBarControllerNode.updateTheme(theme, navigationBarPresentationData: navigationBarPresentationData) } } } @@ -194,7 +197,7 @@ open class TabBarControllerImpl: ViewController, TabBarController { } override open func loadDisplayNode() { - self.displayNode = TabBarControllerNode(theme: self.theme, itemSelected: { [weak self] index, longTap, itemNodes in + self.displayNode = TabBarControllerNode(theme: self.theme, navigationBarPresentationData: self.navigationBarPresentationData, itemSelected: { [weak self] index, longTap, itemNodes in if let strongSelf = self { if longTap, let controller = strongSelf.controllers[index] as? TabBarContainedController { controller.presentTabBarPreviewingController(sourceNodes: itemNodes) diff --git a/submodules/TabBarUI/Sources/TabBarNode.swift b/submodules/TabBarUI/Sources/TabBarNode.swift index 5867b6b865..428a189c85 100644 --- a/submodules/TabBarUI/Sources/TabBarNode.swift +++ b/submodules/TabBarUI/Sources/TabBarNode.swift @@ -344,6 +344,7 @@ class TabBarNode: ASDisplayNode { private let swipeAction: (Int, TabBarItemSwipeDirection) -> Void private var theme: TabBarControllerTheme + private var tabString: String private var validLayout: (CGSize, CGFloat, CGFloat, UIEdgeInsets, CGFloat)? private var horizontal: Bool = false private var centered: Bool = false @@ -356,11 +357,12 @@ class TabBarNode: ASDisplayNode { private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer? - init(theme: TabBarControllerTheme, itemSelected: @escaping (Int, Bool, [ASDisplayNode]) -> Void, contextAction: @escaping (Int, ContextExtractedContentContainingNode, ContextGesture) -> Void, swipeAction: @escaping (Int, TabBarItemSwipeDirection) -> Void) { + init(theme: TabBarControllerTheme, tabString: String, itemSelected: @escaping (Int, Bool, [ASDisplayNode]) -> Void, contextAction: @escaping (Int, ContextExtractedContentContainingNode, ContextGesture) -> Void, swipeAction: @escaping (Int, TabBarItemSwipeDirection) -> Void) { self.itemSelected = itemSelected self.contextAction = contextAction self.swipeAction = swipeAction self.theme = theme + self.tabString = tabString self.backgroundNode = NavigationBackgroundNode(color: theme.tabBarBackgroundColor) @@ -374,6 +376,7 @@ class TabBarNode: ASDisplayNode { super.init() self.isAccessibilityContainer = false + self.accessibilityTraits = [.tabBar] self.isOpaque = false self.backgroundColor = nil @@ -406,9 +409,10 @@ class TabBarNode: ASDisplayNode { } } - func updateTheme(_ theme: TabBarControllerTheme) { + func updateTheme(_ theme: TabBarControllerTheme, tabString: String) { if self.theme !== theme { self.theme = theme + self.tabString = tabString self.separatorNode.backgroundColor = theme.tabBarSeparatorColor self.backgroundNode.updateColor(color: theme.tabBarBackgroundColor, transition: .immediate) @@ -502,6 +506,8 @@ class TabBarNode: ASDisplayNode { node.contextTextImageNode.image = contextTextImage node.contextImageNode.image = contextImage node.accessibilityLabel = item.item.title + node.accessibilityTraits = [.button, .selected] + node.accessibilityHint = self.tabString node.contentWidth = max(contentWidth, imageContentWidth) node.isSelected = true } else { @@ -515,6 +521,8 @@ class TabBarNode: ASDisplayNode { node.textImageNode.image = textImage node.accessibilityLabel = item.item.title + node.accessibilityTraits = [.button] + node.accessibilityHint = self.tabString node.imageNode.image = image node.contextTextImageNode.image = contextTextImage node.contextImageNode.image = contextImage @@ -576,6 +584,8 @@ class TabBarNode: ASDisplayNode { let (contextImage, _) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarExtractedIconColor, horizontal: self.horizontal, imageMode: true, centered: self.centered) node.textImageNode.image = textImage node.accessibilityLabel = item.item.title + node.accessibilityTraits = [.button, .selected] + node.accessibilityHint = self.tabString node.imageNode.image = image node.contextTextImageNode.image = contextTextImage node.contextImageNode.image = contextImage @@ -608,6 +618,8 @@ class TabBarNode: ASDisplayNode { node.textImageNode.image = textImage node.accessibilityLabel = item.item.title + node.accessibilityTraits = [.button] + node.accessibilityHint = self.tabString node.imageNode.image = image node.contextTextImageNode.image = contextTextImage node.contextImageNode.image = contextImage @@ -706,6 +718,7 @@ class TabBarNode: ASDisplayNode { node.containerNode.frame = CGRect(origin: CGPoint(), size: nodeFrame.size) node.hitTestSlop = UIEdgeInsets(top: -3.0, left: -horizontalHitTestInset, bottom: -3.0, right: -horizontalHitTestInset) node.containerNode.hitTestSlop = UIEdgeInsets(top: -3.0, left: -horizontalHitTestInset, bottom: -3.0, right: -horizontalHitTestInset) + node.accessibilityFrame = nodeFrame.insetBy(dx: -horizontalHitTestInset, dy: 0.0).offsetBy(dx: 0.0, dy: size.height - nodeSize.height - bottomInset) if node.ringColor == nil { node.imageNode.frame = CGRect(origin: CGPoint(), size: nodeFrame.size) } diff --git a/submodules/TelegramCallsUI/Sources/CallControllerButtonsNode.swift b/submodules/TelegramCallsUI/Sources/CallControllerButtonsNode.swift index ad5346ffc7..4f8fec1299 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerButtonsNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerButtonsNode.swift @@ -436,6 +436,9 @@ final class CallControllerButtonsNode: ASDisplayNode { } let buttonContent: CallControllerButtonItemNode.Content let buttonText: String + var buttonAccessibilityLabel = "" + var buttonAccessibilityValue = "" + var buttonAccessibilityTraits: UIAccessibilityTraits = [.button] switch button.button { case .accept: buttonContent = CallControllerButtonItemNode.Content( @@ -443,6 +446,7 @@ final class CallControllerButtonsNode: ASDisplayNode { image: .accept ) buttonText = strings.Call_Accept + buttonAccessibilityLabel = buttonText case let .end(type): buttonContent = CallControllerButtonItemNode.Content( appearance: .color(.red), @@ -456,6 +460,11 @@ final class CallControllerButtonsNode: ASDisplayNode { case .end: buttonText = strings.Call_End } + if !buttonText.isEmpty { + buttonAccessibilityLabel = buttonText + } else { + buttonAccessibilityLabel = strings.Call_End + } case let .enableCamera(isActivated, isEnabled, isInitializing, isScreencastActive): buttonContent = CallControllerButtonItemNode.Content( appearance: .blurred(isFilled: isActivated), @@ -464,6 +473,13 @@ final class CallControllerButtonsNode: ASDisplayNode { hasProgress: isInitializing ) buttonText = strings.Call_Camera + buttonAccessibilityLabel = buttonText + if !isEnabled { + buttonAccessibilityTraits.insert(.notEnabled) + } + if isActivated { + buttonAccessibilityTraits.insert(.selected) + } case let .switchCamera(isEnabled): buttonContent = CallControllerButtonItemNode.Content( appearance: .blurred(isFilled: false), @@ -471,6 +487,10 @@ final class CallControllerButtonsNode: ASDisplayNode { isEnabled: isEnabled ) buttonText = strings.Call_Flip + buttonAccessibilityLabel = buttonText + if !isEnabled { + buttonAccessibilityTraits.insert(.notEnabled) + } case let .soundOutput(value): let image: CallControllerButtonItemNode.Content.Image var isFilled = false @@ -484,30 +504,43 @@ final class CallControllerButtonsNode: ASDisplayNode { case .bluetooth: image = .bluetooth title = strings.Call_Audio + buttonAccessibilityValue = "Bluetooth" case .airpods: image = .airpods title = strings.Call_Audio + buttonAccessibilityValue = "Airpods" case .airpodsPro: image = .airpodsPro title = strings.Call_Audio + buttonAccessibilityValue = "Airpods Pro" case .airpodsMax: image = .airpodsMax title = strings.Call_Audio + buttonAccessibilityValue = "Airpods Max" case .headphones: image = .headphones title = strings.Call_Audio + buttonAccessibilityValue = strings.Call_AudioRouteHeadphones } buttonContent = CallControllerButtonItemNode.Content( appearance: .blurred(isFilled: isFilled), image: image ) buttonText = title + buttonAccessibilityLabel = buttonText + if isFilled { + buttonAccessibilityTraits.insert(.selected) + } case let .mute(isMuted): buttonContent = CallControllerButtonItemNode.Content( appearance: .blurred(isFilled: isMuted), image: .mute ) buttonText = strings.Call_Mute + buttonAccessibilityLabel = buttonText + if isMuted { + buttonAccessibilityTraits.insert(.selected) + } } var buttonDelay = 0.0 if animatePositionsWithDelay { @@ -526,6 +559,10 @@ final class CallControllerButtonsNode: ASDisplayNode { } buttonTransition.updateFrame(node: buttonNode, frame: button.frame, delay: buttonDelay) buttonNode.update(size: button.frame.size, content: buttonContent, text: buttonText, transition: buttonTransition) + buttonNode.accessibilityLabel = buttonAccessibilityLabel + buttonNode.accessibilityValue = buttonAccessibilityValue + buttonNode.accessibilityTraits = buttonAccessibilityTraits + if animateButtonIn { buttonNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } diff --git a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift index e1818f74e9..f1d8d74b9c 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift @@ -501,6 +501,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro self.buttonsNode = CallControllerButtonsNode(strings: self.presentationData.strings) self.toastNode = CallControllerToastContainerNode(strings: self.presentationData.strings) self.keyButtonNode = CallControllerKeyButton() + self.keyButtonNode.accessibilityElementsHidden = false super.init() @@ -510,6 +511,8 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro self.containerTransformationNode.addSubnode(self.containerNode) self.backButtonNode.setTitle(presentationData.strings.Common_Back, with: Font.regular(17.0), with: .white, for: []) + self.backButtonNode.accessibilityLabel = presentationData.strings.Call_VoiceOver_Minimize + self.backButtonNode.accessibilityTraits = [.button] self.backButtonNode.hitTestSlop = UIEdgeInsets(top: -8.0, left: -20.0, bottom: -8.0, right: -8.0) self.backButtonNode.highligthedChanged = { [weak self] highlighted in if let strongSelf = self { diff --git a/submodules/TelegramCallsUI/Sources/CallControllerStatusNode.swift b/submodules/TelegramCallsUI/Sources/CallControllerStatusNode.swift index 9e84d73aaa..dc1ebe58d9 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerStatusNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerStatusNode.swift @@ -40,6 +40,9 @@ final class CallControllerStatusNode: ASDisplayNode { private let receptionNode: CallControllerReceptionNode private let logoNode: ASImageNode + private let titleActivateAreaNode: AccessibilityAreaNode + private let statusActivateAreaNode: AccessibilityAreaNode + var title: String = "" var subtitle: String = "" var status: CallControllerStatusValue = .text(string: "", displayLogo: false) { @@ -118,6 +121,12 @@ final class CallControllerStatusNode: ASDisplayNode { self.logoNode.image = generateTintedImage(image: UIImage(bundleImageName: "Call/CallTitleLogo"), color: .white) self.logoNode.isHidden = true + self.titleActivateAreaNode = AccessibilityAreaNode() + self.titleActivateAreaNode.accessibilityTraits = .staticText + + self.statusActivateAreaNode = AccessibilityAreaNode() + self.statusActivateAreaNode.accessibilityTraits = [.staticText, .updatesFrequently] + super.init() self.isUserInteractionEnabled = false @@ -127,6 +136,9 @@ final class CallControllerStatusNode: ASDisplayNode { self.statusContainerNode.addSubnode(self.statusNode) self.statusContainerNode.addSubnode(self.receptionNode) self.statusContainerNode.addSubnode(self.logoNode) + + self.addSubnode(self.titleActivateAreaNode) + self.addSubnode(self.statusActivateAreaNode) } deinit { @@ -191,6 +203,9 @@ final class CallControllerStatusNode: ASDisplayNode { let _ = statusApply() let _ = statusMeasureApply() + self.titleActivateAreaNode.accessibilityLabel = self.title + self.statusActivateAreaNode.accessibilityLabel = statusText + self.titleNode.frame = CGRect(origin: CGPoint(x: floor((constrainedWidth - titleLayout.size.width) / 2.0), y: 0.0), size: titleLayout.size) self.statusContainerNode.frame = CGRect(origin: CGPoint(x: 0.0, y: titleLayout.size.height + spacing), size: CGSize(width: constrainedWidth, height: statusLayout.size.height)) self.statusNode.frame = CGRect(origin: CGPoint(x: floor((constrainedWidth - statusMeasureLayout.size.width) / 2.0) + statusOffset, y: 0.0), size: statusLayout.size) @@ -201,6 +216,9 @@ final class CallControllerStatusNode: ASDisplayNode { self.logoNode.frame = CGRect(origin: CGPoint(x: self.statusNode.frame.minX + firstLineOffset - image.size.width - 7.0, y: 5.0), size: image.size) } + self.titleActivateAreaNode.frame = self.titleNode.frame + self.statusActivateAreaNode.frame = self.statusContainerNode.frame + return titleLayout.size.height + spacing + statusLayout.size.height } } diff --git a/submodules/TelegramPresentationData/Sources/ComponentsThemes.swift b/submodules/TelegramPresentationData/Sources/ComponentsThemes.swift index f47d7ea5fc..569dce889c 100644 --- a/submodules/TelegramPresentationData/Sources/ComponentsThemes.swift +++ b/submodules/TelegramPresentationData/Sources/ComponentsThemes.swift @@ -54,7 +54,7 @@ public extension NavigationBarTheme { public extension NavigationBarStrings { convenience init(presentationStrings: PresentationStrings) { - self.init(back: presentationStrings.Common_Back, close: presentationStrings.Common_Close) + self.init(back: presentationStrings.Common_Back, close: presentationStrings.Common_Close, tab: presentationStrings.VoiceOver_Tab) } } diff --git a/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift index 2921481394..728a4c8214 100644 --- a/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatButtonKeyboardInputNode.swift @@ -65,6 +65,8 @@ private final class ChatButtonKeyboardInputButtonNode: HighlightTrackingButtonNo super.init() + self.accessibilityTraits = [.button] + self.addSubnode(self.backgroundContainerNode) self.backgroundContainerNode.addSubnode(self.backgroundColorNode) @@ -94,6 +96,7 @@ private final class ChatButtonKeyboardInputButtonNode: HighlightTrackingButtonNo override func setAttributedTitle(_ title: NSAttributedString, for state: UIControl.State) { self.textNode.attributedText = title + self.accessibilityLabel = title.string } private var absoluteRect: (CGRect, CGSize)? diff --git a/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift b/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift index ca44feaeb0..c510117192 100644 --- a/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift +++ b/submodules/TelegramUI/Sources/ChatQrCodeScreen.swift @@ -860,6 +860,7 @@ private class ChatQrCodeScreenNode: ViewControllerTracingNode, UIScrollViewDeleg self.cancelButton = HighlightableButtonNode() self.cancelButton.setImage(closeButtonImage(theme: self.presentationData.theme), for: .normal) self.cancelButton.accessibilityLabel = self.presentationData.strings.Common_Close + self.cancelButton.accessibilityTraits = [.button] self.switchThemeButton = HighlightTrackingButtonNode() self.animationContainerNode = ASDisplayNode() diff --git a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift index ca88b0dd34..788cdfb4a1 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift @@ -373,9 +373,11 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { self.iconNode.image = generateTintedImage(image: iconImage, color: presentationData.theme.list.itemAccentColor) self.iconNode.isHidden = false self.iconButtonNode.isHidden = false + self.iconButtonNode.accessibilityLabel = presentationData.strings.InviteLink_QRCode_Share } else { self.iconNode.isHidden = true self.iconButtonNode.isHidden = true + self.iconButtonNode.accessibilityLabel = nil } let additionalSideInset: CGFloat = !self.iconNode.isHidden ? 32.0 : 0.0 diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index bdda287c7d..ebca5e5cee 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -1713,6 +1713,7 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader self.clearButtonNode = HighlightableButtonNode() self.clearButtonNode.isHidden = true + self.clearButtonNode.isAccessibilityElement = false self.topSeparator = ASDisplayNode() @@ -1873,6 +1874,7 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT self.clearButtonNode = HighlightableButtonNode() self.clearButtonNode.isHidden = true + self.clearButtonNode.isAccessibilityElement = false self.maskNode = ASImageNode() self.maskNode.isUserInteractionEnabled = false diff --git a/submodules/TelegramUI/Sources/PeerSelectionController.swift b/submodules/TelegramUI/Sources/PeerSelectionController.swift index d8767a7419..eaad689acc 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionController.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionController.swift @@ -240,7 +240,31 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon strongSelf.openMessageFromSearchDisposable.set((strongSelf.context.engine.peers.ensurePeerIsLocallyAvailable(peer: EnginePeer(peer)) |> deliverOnMainQueue).start(completed: { [weak strongSelf] in if let strongSelf = strongSelf, let peerSelected = strongSelf.peerSelected { - peerSelected(peer, threadId) + if let peer = peer as? TelegramChannel, peer.flags.contains(.isForum), threadId == nil, strongSelf.selectForumThreads { + let controller = PeerSelectionControllerImpl( + PeerSelectionControllerParams( + context: strongSelf.context, + updatedPresentationData: nil, + filter: strongSelf.filter, + forumPeerId: peer.id, + hasChatListSelector: false, + hasContactSelector: false, + hasGlobalSearch: false, + title: EnginePeer(peer).compactDisplayTitle, + attemptSelection: strongSelf.attemptSelection, + createNewGroup: nil, + pretendPresentedInModal: false, + multipleSelection: false, + forwardedMessageIds: [], + hasTypeHeaders: false, + selectForumThreads: false + ) + ) + controller.peerSelected = strongSelf.peerSelected + strongSelf.push(controller) + } else { + peerSelected(peer, threadId) + } } })) } diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 7d7b62fcea..50501b0dad 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -1056,7 +1056,7 @@ public final class WebAppController: ViewController, AttachmentContainable { self.moreButtonNode = MoreButtonNode(theme: self.presentationData.theme) self.moreButtonNode.iconNode.enqueueState(.more, animated: false) - let navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), strings: NavigationBarStrings(back: "", close: "")) + let navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: self.presentationData.theme), strings: NavigationBarStrings(back: "", close: "", tab: "")) super.init(navigationBarPresentationData: navigationBarPresentationData) self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style @@ -1087,7 +1087,7 @@ public final class WebAppController: ViewController, AttachmentContainable { if let strongSelf = self { strongSelf.presentationData = presentationData - let navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(back: "", close: "")) + let navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(back: "", close: "", tab: "")) strongSelf.navigationBar?.updatePresentationData(navigationBarPresentationData) strongSelf.titleView?.theme = presentationData.theme