diff --git a/submodules/Display/Source/ImmediateTextNode.swift b/submodules/Display/Source/ImmediateTextNode.swift index 3ac2dec4bc..af2ffc8f57 100644 --- a/submodules/Display/Source/ImmediateTextNode.swift +++ b/submodules/Display/Source/ImmediateTextNode.swift @@ -9,6 +9,7 @@ public struct ImmediateTextNodeLayoutInfo { public class ImmediateTextNode: TextNode { public var attributedText: NSAttributedString? public var textAlignment: NSTextAlignment = .natural + public var verticalAlignment: TextVerticalAlignment = .top public var truncationType: CTLineTruncationType = .end public var maximumNumberOfLines: Int = 1 public var lineSpacing: CGFloat = 0.0 @@ -88,7 +89,7 @@ public class ImmediateTextNode: TextNode { self.constrainedSize = constrainedSize let makeLayout = TextNode.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke)) let _ = apply() if layout.numberOfLines > 1 { self.trailingLineWidth = layout.trailingLineWidth @@ -102,7 +103,7 @@ public class ImmediateTextNode: TextNode { self.constrainedSize = constrainedSize let makeLayout = TextNode.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets)) let _ = apply() return ImmediateTextNodeLayoutInfo(size: layout.size, truncated: layout.truncated) } @@ -111,7 +112,7 @@ public class ImmediateTextNode: TextNode { self.constrainedSize = constrainedSize let makeLayout = TextNode.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets)) let _ = apply() return layout } diff --git a/submodules/Display/Source/NavigationButtonNode.swift b/submodules/Display/Source/NavigationButtonNode.swift index 01af9c910e..1d614e0202 100644 --- a/submodules/Display/Source/NavigationButtonNode.swift +++ b/submodules/Display/Source/NavigationButtonNode.swift @@ -32,6 +32,7 @@ private final class NavigationButtonItemNode: ImmediateTextNode { self?.isEnabled = value } self.accessibilityHint = item.accessibilityHint + self.accessibilityLabel = item.accessibilityLabel } } } @@ -194,6 +195,8 @@ private final class NavigationButtonItemNode: ImmediateTextNode { self.hitTestSlop = UIEdgeInsets(top: -16.0, left: -10.0, bottom: -16.0, right: -10.0) self.displaysAsynchronously = false + self.verticalAlignment = .middle + self.accessibilityTraits = .button } @@ -213,7 +216,8 @@ private final class NavigationButtonItemNode: ImmediateTextNode { } override func updateLayout(_ constrainedSize: CGSize) -> CGSize { - let superSize = super.updateLayout(constrainedSize) + var superSize = super.updateLayout(constrainedSize) + superSize.height = max(44.0, superSize.height) if let node = self.node { let nodeSize = node.measure(constrainedSize) diff --git a/submodules/Display/Source/TextNode.swift b/submodules/Display/Source/TextNode.swift index 508a177271..e010783205 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -94,6 +94,12 @@ private func displayLineFrame(frame: CGRect, isRTL: Bool, boundingRect: CGRect, return lineFrame } +public enum TextVerticalAlignment { + case top + case middle + case bottom +} + public final class TextNodeLayoutArguments { public let attributedString: NSAttributedString? public let backgroundColor: UIColor? @@ -102,6 +108,7 @@ public final class TextNodeLayoutArguments { public let truncationType: CTLineTruncationType public let constrainedSize: CGSize public let alignment: NSTextAlignment + public let verticalAlignment: TextVerticalAlignment public let lineSpacing: CGFloat public let cutout: TextNodeCutout? public let insets: UIEdgeInsets @@ -109,7 +116,7 @@ public final class TextNodeLayoutArguments { public let textShadowColor: UIColor? public let textStroke: (UIColor, CGFloat)? - public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil, textStroke: (UIColor, CGFloat)? = nil) { + public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, verticalAlignment: TextVerticalAlignment = .top, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil, textStroke: (UIColor, CGFloat)? = nil) { self.attributedString = attributedString self.backgroundColor = backgroundColor self.minimumNumberOfLines = minimumNumberOfLines @@ -117,6 +124,7 @@ public final class TextNodeLayoutArguments { self.truncationType = truncationType self.constrainedSize = constrainedSize self.alignment = alignment + self.verticalAlignment = verticalAlignment self.lineSpacing = lineSpacing self.cutout = cutout self.insets = insets @@ -134,6 +142,7 @@ public final class TextNodeLayout: NSObject { fileprivate let constrainedSize: CGSize fileprivate let explicitAlignment: NSTextAlignment fileprivate let resolvedAlignment: NSTextAlignment + fileprivate let verticalAlignment: TextVerticalAlignment fileprivate let lineSpacing: CGFloat fileprivate let cutout: TextNodeCutout? fileprivate let insets: UIEdgeInsets @@ -148,13 +157,14 @@ public final class TextNodeLayout: NSObject { fileprivate let textStroke: (UIColor, CGFloat)? public let hasRTL: Bool - fileprivate init(attributedString: NSAttributedString?, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, explicitAlignment: NSTextAlignment, resolvedAlignment: NSTextAlignment, lineSpacing: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, size: CGSize, rawTextSize: CGSize, truncated: Bool, firstLineOffset: CGFloat, lines: [TextNodeLine], blockQuotes: [TextNodeBlockQuote], backgroundColor: UIColor?, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?) { + fileprivate init(attributedString: NSAttributedString?, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, explicitAlignment: NSTextAlignment, resolvedAlignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacing: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, size: CGSize, rawTextSize: CGSize, truncated: Bool, firstLineOffset: CGFloat, lines: [TextNodeLine], blockQuotes: [TextNodeBlockQuote], backgroundColor: UIColor?, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?) { self.attributedString = attributedString self.maximumNumberOfLines = maximumNumberOfLines self.truncationType = truncationType self.constrainedSize = constrainedSize self.explicitAlignment = explicitAlignment self.resolvedAlignment = resolvedAlignment + self.verticalAlignment = verticalAlignment self.lineSpacing = lineSpacing self.cutout = cutout self.insets = insets @@ -823,7 +833,7 @@ public class TextNode: ASDisplayNode { } } - private class func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?) -> TextNodeLayout { + private class func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?) -> TextNodeLayout { if let attributedString = attributedString { let stringLength = attributedString.length @@ -862,7 +872,7 @@ public class TextNode: ASDisplayNode { var maybeTypesetter: CTTypesetter? maybeTypesetter = CTTypesetterCreateWithAttributedString(attributedString as CFAttributedString) if maybeTypesetter == nil { - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke) } let typesetter = maybeTypesetter! @@ -1074,9 +1084,9 @@ public class TextNode: ASDisplayNode { } } - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke) } else { - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: alignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke) } } @@ -1129,7 +1139,15 @@ public class TextNode: ASDisplayNode { context.textMatrix = CGAffineTransform(scaleX: 1.0, y: -1.0) let alignment = layout.resolvedAlignment - let offset = CGPoint(x: layout.insets.left, y: layout.insets.top) + var offset = CGPoint(x: layout.insets.left, y: layout.insets.top) + switch layout.verticalAlignment { + case .top: + break + case .middle: + offset.y = floor((bounds.height - layout.size.height) / 2.0) + layout.insets.top + case .bottom: + offset.y = floor(bounds.height - layout.size.height) + layout.insets.top + } for i in 0 ..< layout.lines.count { let line = layout.lines[i] @@ -1230,11 +1248,11 @@ public class TextNode: ASDisplayNode { if stringMatch { layout = existingLayout } else { - layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke) + layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke) updated = true } } else { - layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke) + layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, verticalAlignment: arguments.verticalAlignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor, textStroke: arguments.textStroke) updated = true } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift index e04413f547..f5d2d61013 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/Recent Sessions/ItemListRecentSessionItem.swift @@ -294,6 +294,7 @@ class ItemListRecentSessionItemNode: ItemListRevealOptionsItemNode { } value += string } + strongSelf.activateArea.accessibilityValue = value if item.enabled { strongSelf.activateArea.accessibilityTraits = [] diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 195e618fe5..ac19261fe8 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -2646,7 +2646,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } chatInfoButtonItem.target = self chatInfoButtonItem.action = #selector(self.rightNavigationButtonAction) - chatInfoButtonItem.accessibilityLabel = self.presentationData.strings.Conversation_Info self.chatInfoNavigationButton = ChatNavigationButton(action: .openChatInfo(expandAvatar: true), buttonItem: chatInfoButtonItem) self.navigationItem.titleView = self.chatTitleView @@ -2801,6 +2800,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.avatarNode.setPeer(context: strongSelf.context, theme: strongSelf.presentationData.theme, peer: peer, overrideImage: imageOverride) (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.contextActionIsEnabled = peer.restrictionText(platform: "ios", contentSettings: strongSelf.context.currentContentSettings.with { $0 }) == nil + strongSelf.chatInfoNavigationButton?.buttonItem.accessibilityLabel = presentationInterfaceState.strings.Conversation_ContextMenuOpenProfile } } } @@ -8465,6 +8465,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G legacyController?.dismiss() } + legacyController.blocksBackgroundWhenInOverlay = true strongSelf.present(legacyController, in: .window(.root)) controller.present(in: emptyController, sourceView: nil, animated: true) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift index a3384dabd9..42acaf62f7 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateNavigationButtons.swift @@ -78,7 +78,9 @@ func rightNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Ch if let currentButton = currentButton, currentButton.action == .cancelMessageSelection { return currentButton } else { - return ChatNavigationButton(action: .cancelMessageSelection, buttonItem: UIBarButtonItem(title: strings.Common_Cancel, style: .plain, target: target, action: selector)) + let buttonItem = UIBarButtonItem(title: strings.Common_Cancel, style: .plain, target: target, action: selector) + buttonItem.accessibilityLabel = strings.Common_Cancel + return ChatNavigationButton(action: .cancelMessageSelection, buttonItem: buttonItem) } } diff --git a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift index ac26274088..6e8abf40c7 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift @@ -135,8 +135,8 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { } func updateAccessibility() { + self.accessibilityTraits = .button if !self.micButton.alpha.isZero { - self.accessibilityTraits = .button switch self.micButton.mode { case .audio: self.accessibilityLabel = self.strings.VoiceOver_Chat_RecordModeVoiceMessage @@ -146,7 +146,6 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { self.accessibilityHint = self.strings.VoiceOver_Chat_RecordModeVideoMessageInfo } } else { - self.accessibilityTraits = .button self.accessibilityLabel = self.strings.MediaPicker_Send self.accessibilityHint = nil } diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 87449c1cba..fba0e54d0a 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -401,6 +401,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.textPlaceholderNode.isUserInteractionEnabled = false self.attachmentButton = HighlightableButtonNode(pointerStyle: .circle) self.attachmentButton.accessibilityLabel = presentationInterfaceState.strings.VoiceOver_AttachMedia + self.attachmentButton.accessibilityTraits = [.button] self.attachmentButton.isAccessibilityElement = true self.attachmentButtonDisabledNode = HighlightableButtonNode() self.searchLayoutClearButton = HighlightableButton() @@ -716,6 +717,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } transition.updateAlpha(layer: self.attachmentButton.layer, alpha: isMediaEnabled ? 1.0 : 0.4) self.attachmentButton.isEnabled = isMediaEnabled + self.attachmentButton.accessibilityTraits = (!isSlowmodeActive || isMediaEnabled) ? [.button] : [.button, .notEnabled] self.attachmentButtonDisabledNode.isHidden = !isSlowmodeActive || isMediaEnabled if self.presentationInterfaceState != interfaceState {