mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-08 19:10:53 +00:00
Refine context menu appearance
This commit is contained in:
parent
781ff5f843
commit
0f72e95e24
@ -5,7 +5,7 @@ import TelegramPresentationData
|
||||
|
||||
private let textFont = Font.regular(17.0)
|
||||
|
||||
enum ContextActionNext {
|
||||
enum ContextActionSibling {
|
||||
case none
|
||||
case item
|
||||
case separator
|
||||
@ -18,7 +18,6 @@ final class ContextActionNode: ASDisplayNode {
|
||||
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let highlightedBackgroundNode: ASDisplayNode
|
||||
private let separatorNode: ASDisplayNode
|
||||
private let textNode: ImmediateTextNode
|
||||
private let statusNode: ImmediateTextNode?
|
||||
private let iconNode: ASImageNode
|
||||
@ -31,24 +30,12 @@ final class ContextActionNode: ASDisplayNode {
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isAccessibilityElement = false
|
||||
if theme.chatList.searchBarKeyboardColor == .dark {
|
||||
self.backgroundNode.backgroundColor = theme.actionSheet.itemBackgroundColor.withAlphaComponent(0.8)
|
||||
} else {
|
||||
self.backgroundNode.backgroundColor = UIColor(white: 1.0, alpha: 0.6)
|
||||
}
|
||||
self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isAccessibilityElement = false
|
||||
if theme.chatList.searchBarKeyboardColor == .dark {
|
||||
self.highlightedBackgroundNode.backgroundColor = theme.actionSheet.opaqueItemHighlightedBackgroundColor
|
||||
} else {
|
||||
self.highlightedBackgroundNode.backgroundColor = UIColor(white: 0.8, alpha: 0.6)
|
||||
}
|
||||
self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor
|
||||
self.highlightedBackgroundNode.alpha = 0.0
|
||||
|
||||
self.separatorNode = ASDisplayNode()
|
||||
self.separatorNode.isAccessibilityElement = false
|
||||
self.separatorNode.backgroundColor = UIColor(white: 0.0, alpha: 0.1)
|
||||
|
||||
self.textNode = ImmediateTextNode()
|
||||
self.textNode.isAccessibilityElement = false
|
||||
self.textNode.isUserInteractionEnabled = false
|
||||
@ -56,9 +43,9 @@ final class ContextActionNode: ASDisplayNode {
|
||||
let textColor: UIColor
|
||||
switch action.textColor {
|
||||
case .primary:
|
||||
textColor = theme.actionSheet.primaryTextColor
|
||||
textColor = theme.contextMenu.primaryColor
|
||||
case .destructive:
|
||||
textColor = theme.actionSheet.destructiveActionTextColor
|
||||
textColor = theme.contextMenu.destructiveColor
|
||||
}
|
||||
self.textNode.attributedText = NSAttributedString(string: action.text, font: textFont, textColor: textColor)
|
||||
|
||||
@ -75,7 +62,7 @@ final class ContextActionNode: ASDisplayNode {
|
||||
statusNode.isAccessibilityElement = false
|
||||
statusNode.isUserInteractionEnabled = false
|
||||
statusNode.displaysAsynchronously = false
|
||||
statusNode.attributedText = NSAttributedString(string: value, font: textFont, textColor: theme.actionSheet.secondaryTextColor)
|
||||
statusNode.attributedText = NSAttributedString(string: value, font: textFont, textColor: theme.contextMenu.secondaryColor)
|
||||
statusNode.maximumNumberOfLines = 1
|
||||
self.statusNode = statusNode
|
||||
}
|
||||
@ -98,7 +85,6 @@ final class ContextActionNode: ASDisplayNode {
|
||||
self.addSubnode(self.textNode)
|
||||
self.statusNode.flatMap(self.addSubnode)
|
||||
self.addSubnode(self.iconNode)
|
||||
self.addSubnode(self.separatorNode)
|
||||
self.addSubnode(self.buttonNode)
|
||||
|
||||
self.buttonNode.highligthedChanged = { [weak self] highligted in
|
||||
@ -115,28 +101,22 @@ final class ContextActionNode: ASDisplayNode {
|
||||
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
|
||||
func updateLayout(constrainedWidth: CGFloat, next: ContextActionNext) -> (CGSize, (CGSize, ContainedViewLayoutTransition) -> Void) {
|
||||
func updateLayout(constrainedWidth: CGFloat, previous: ContextActionSibling, next: ContextActionSibling) -> (CGSize, (CGSize, ContainedViewLayoutTransition) -> Void) {
|
||||
let sideInset: CGFloat = 16.0
|
||||
let iconSideInset: CGFloat = 8.0
|
||||
let verticalInset: CGFloat = 12.0
|
||||
|
||||
let iconSize = self.iconNode.image.flatMap({ $0.size }) ?? CGSize()
|
||||
|
||||
let standardIconWidth: CGFloat = 28.0
|
||||
var rightTextInset: CGFloat = 0.0
|
||||
let standardIconWidth: CGFloat = 32.0
|
||||
var rightTextInset: CGFloat = sideInset
|
||||
if !iconSize.width.isZero {
|
||||
rightTextInset = max(iconSize.width, standardIconWidth) + sideInset
|
||||
rightTextInset = max(iconSize.width, standardIconWidth) + iconSideInset + sideInset
|
||||
}
|
||||
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: constrainedWidth - sideInset - rightTextInset, height: .greatestFiniteMagnitude))
|
||||
let statusSize = self.statusNode?.updateLayout(CGSize(width: constrainedWidth - sideInset - rightTextInset, height: .greatestFiniteMagnitude)) ?? CGSize()
|
||||
|
||||
switch next {
|
||||
case .item:
|
||||
self.separatorNode.alpha = 1.0
|
||||
case .none, .separator:
|
||||
self.separatorNode.alpha = 0.0
|
||||
}
|
||||
|
||||
if !statusSize.width.isZero, let statusNode = self.statusNode {
|
||||
let verticalSpacing: CGFloat = 2.0
|
||||
let combinedTextHeight = textSize.height + verticalSpacing + statusSize.height
|
||||
@ -146,12 +126,11 @@ final class ContextActionNode: ASDisplayNode {
|
||||
transition.updateFrameAdditive(node: statusNode, frame: CGRect(origin: CGPoint(x: sideInset, y: verticalOrigin + verticalSpacing + textSize.height), size: textSize))
|
||||
|
||||
if !iconSize.width.isZero {
|
||||
transition.updateFrameAdditive(node: self.iconNode, frame: CGRect(origin: CGPoint(x: size.width - standardIconWidth + floor((standardIconWidth - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize))
|
||||
transition.updateFrameAdditive(node: self.iconNode, frame: CGRect(origin: CGPoint(x: size.width - standardIconWidth - iconSideInset + floor((standardIconWidth - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize))
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
transition.updateFrame(node: self.highlightedBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel)))
|
||||
transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
})
|
||||
} else {
|
||||
@ -160,18 +139,21 @@ final class ContextActionNode: ASDisplayNode {
|
||||
transition.updateFrameAdditive(node: self.textNode, frame: CGRect(origin: CGPoint(x: sideInset, y: verticalOrigin), size: textSize))
|
||||
|
||||
if !iconSize.width.isZero {
|
||||
transition.updateFrameAdditive(node: self.iconNode, frame: CGRect(origin: CGPoint(x: size.width - sideInset - standardIconWidth + floor((standardIconWidth - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize))
|
||||
transition.updateFrameAdditive(node: self.iconNode, frame: CGRect(origin: CGPoint(x: size.width - standardIconWidth - iconSideInset + floor((standardIconWidth - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize))
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
transition.updateFrame(node: self.highlightedBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: size.height - UIScreenPixel), size: CGSize(width: size.width, height: UIScreenPixel)))
|
||||
transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func buttonPressed() {
|
||||
self.performAction()
|
||||
}
|
||||
|
||||
func performAction() {
|
||||
guard let controller = self.getController() else {
|
||||
return
|
||||
}
|
||||
@ -179,4 +161,12 @@ final class ContextActionNode: ASDisplayNode {
|
||||
self?.actionSelected(result)
|
||||
})
|
||||
}
|
||||
|
||||
func setIsHighlighted(_ value: Bool) {
|
||||
if value {
|
||||
self.highlightedBackgroundNode.alpha = 1.0
|
||||
} else {
|
||||
self.highlightedBackgroundNode.alpha = 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import TelegramPresentationData
|
||||
|
||||
private enum ContextItemNode {
|
||||
case action(ContextActionNode)
|
||||
case itemSeparator(ASDisplayNode)
|
||||
case separator(ASDisplayNode)
|
||||
}
|
||||
|
||||
@ -12,30 +13,38 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
private var itemNodes: [ContextItemNode]
|
||||
|
||||
init(theme: PresentationTheme, items: [ContextMenuItem], getController: @escaping () -> ContextController?, actionSelected: @escaping (ContextMenuActionResult) -> Void) {
|
||||
self.itemNodes = items.map { item in
|
||||
switch item {
|
||||
var itemNodes: [ContextItemNode] = []
|
||||
for i in 0 ..< items.count {
|
||||
switch items[i] {
|
||||
case let .action(action):
|
||||
return .action(ContextActionNode(theme: theme, action: action, getController: getController, actionSelected: actionSelected))
|
||||
itemNodes.append(.action(ContextActionNode(theme: theme, action: action, getController: getController, actionSelected: actionSelected)))
|
||||
if i != items.count - 1, case .action = items[i + 1] {
|
||||
let separatorNode = ASDisplayNode()
|
||||
separatorNode.backgroundColor = theme.contextMenu.itemSeparatorColor
|
||||
itemNodes.append(.itemSeparator(separatorNode))
|
||||
}
|
||||
case .separator:
|
||||
let separatorNode = ASDisplayNode()
|
||||
if theme.chatList.searchBarKeyboardColor == .dark {
|
||||
separatorNode.backgroundColor = theme.actionSheet.opaqueItemHighlightedBackgroundColor.withAlphaComponent(0.8)
|
||||
} else {
|
||||
separatorNode.backgroundColor = UIColor(white: 0.8, alpha: 0.6)
|
||||
}
|
||||
return .separator(separatorNode)
|
||||
separatorNode.backgroundColor = theme.contextMenu.sectionSeparatorColor
|
||||
itemNodes.append(.separator(separatorNode))
|
||||
}
|
||||
}
|
||||
|
||||
self.itemNodes = itemNodes
|
||||
|
||||
super.init()
|
||||
|
||||
self.clipsToBounds = true
|
||||
self.cornerRadius = 14.0
|
||||
|
||||
self.backgroundColor = theme.contextMenu.backgroundColor
|
||||
|
||||
self.itemNodes.forEach({ itemNode in
|
||||
switch itemNode {
|
||||
case let .action(actionNode):
|
||||
self.addSubnode(actionNode)
|
||||
case let .itemSeparator(separatorNode):
|
||||
self.addSubnode(separatorNode)
|
||||
case let .separator(separatorNode):
|
||||
self.addSubnode(separatorNode)
|
||||
}
|
||||
@ -52,7 +61,15 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
for i in 0 ..< self.itemNodes.count {
|
||||
switch self.itemNodes[i] {
|
||||
case let .action(itemNode):
|
||||
let next: ContextActionNext
|
||||
let previous: ContextActionSibling
|
||||
let next: ContextActionSibling
|
||||
if i == 0 {
|
||||
previous = .none
|
||||
} else if case .separator = self.itemNodes[i - 1] {
|
||||
previous = .separator
|
||||
} else {
|
||||
previous = .item
|
||||
}
|
||||
if i == self.itemNodes.count - 1 {
|
||||
next = .none
|
||||
} else if case .separator = self.itemNodes[i + 1] {
|
||||
@ -60,10 +77,13 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
} else {
|
||||
next = .item
|
||||
}
|
||||
let (minSize, complete) = itemNode.updateLayout(constrainedWidth: constrainedWidth, next: next)
|
||||
let (minSize, complete) = itemNode.updateLayout(constrainedWidth: constrainedWidth, previous: previous, next: next)
|
||||
maxWidth = max(maxWidth, minSize.width)
|
||||
heightsAndCompletions.append((minSize.height, complete))
|
||||
contentHeight += minSize.height
|
||||
case .itemSeparator:
|
||||
heightsAndCompletions.append(nil)
|
||||
contentHeight += UIScreenPixel
|
||||
case .separator:
|
||||
heightsAndCompletions.append(nil)
|
||||
contentHeight += separatorHeight
|
||||
@ -82,6 +102,9 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
itemCompletion(itemSize, transition)
|
||||
verticalOffset += itemHeight
|
||||
}
|
||||
case let .itemSeparator(separatorNode):
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: verticalOffset), size: CGSize(width: maxWidth, height: UIScreenPixel)))
|
||||
verticalOffset += UIScreenPixel
|
||||
case let .separator(separatorNode):
|
||||
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: verticalOffset), size: CGSize(width: maxWidth, height: separatorHeight)))
|
||||
verticalOffset += separatorHeight
|
||||
@ -90,4 +113,18 @@ final class ContextActionsContainerNode: ASDisplayNode {
|
||||
|
||||
return CGSize(width: maxWidth, height: verticalOffset)
|
||||
}
|
||||
|
||||
func actionNode(at point: CGPoint) -> ContextActionNode? {
|
||||
for itemNode in self.itemNodes {
|
||||
switch itemNode {
|
||||
case let .action(actionNode):
|
||||
if actionNode.frame.contains(point) {
|
||||
return actionNode
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ public final class ContextContentContainingNode: ASDisplayNode {
|
||||
public var updateAbsoluteRect: ((CGRect, CGSize) -> Void)?
|
||||
public var applyAbsoluteOffset: ((CGFloat, ContainedViewLayoutTransitionCurve, Double) -> Void)?
|
||||
public var applyAbsoluteOffsetSpring: ((CGFloat, Double, CGFloat) -> Void)?
|
||||
public var layoutUpdated: ((CGSize) -> Void)?
|
||||
|
||||
public override init() {
|
||||
self.contentNode = ContextContentNode()
|
||||
|
@ -51,17 +51,27 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
private let effectView: UIVisualEffectView
|
||||
private var propertyAnimator: AnyObject?
|
||||
private var displayLinkAnimator: DisplayLinkAnimator?
|
||||
private let dimNode: ASDisplayNode
|
||||
|
||||
private let clippingNode: ASDisplayNode
|
||||
private let scrollNode: ASScrollNode
|
||||
|
||||
private var originalProjectedContentViewFrame: (CGRect, CGRect)?
|
||||
private var contentAreaInScreenSpace: CGRect?
|
||||
private var contentParentNode: ContextContentContainingNode?
|
||||
private let contentContainerNode: ContextContentContainerNode
|
||||
private var actionsContainerNode: ContextActionsContainerNode
|
||||
|
||||
init(controller: ContextController, theme: PresentationTheme, strings: PresentationStrings, source: ContextControllerContentSource, items: [ContextMenuItem], beginDismiss: @escaping (ContextMenuActionResult) -> Void) {
|
||||
private var didCompleteAnimationIn = false
|
||||
private var initialContinueGesturePoint: CGPoint?
|
||||
private var didMoveFromInitialGesturePoint = false
|
||||
private var highlightedActionNode: ContextActionNode?
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
init(controller: ContextController, theme: PresentationTheme, strings: PresentationStrings, source: ContextControllerContentSource, items: [ContextMenuItem], beginDismiss: @escaping (ContextMenuActionResult) -> Void, recognizer: TapLongTapOrDoubleTapGestureRecognizer?) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.source = source
|
||||
@ -80,11 +90,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
}
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
if theme.chatList.searchBarKeyboardColor == .dark {
|
||||
self.dimNode.backgroundColor = theme.chatList.backgroundColor.withAlphaComponent(0.2)
|
||||
} else {
|
||||
self.dimNode.backgroundColor = UIColor(rgb: 0xb8bbc1, alpha: 0.5)
|
||||
}
|
||||
self.dimNode.backgroundColor = theme.contextMenu.dimColor
|
||||
self.dimNode.alpha = 0.0
|
||||
|
||||
self.clippingNode = ASDisplayNode()
|
||||
@ -109,6 +115,15 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
|
||||
super.init()
|
||||
|
||||
if #available(iOS 10.0, *) {
|
||||
let propertyAnimator = UIViewPropertyAnimator(duration: 0.4, curve: .linear)
|
||||
propertyAnimator.isInterruptible = true
|
||||
propertyAnimator.addAnimations {
|
||||
self.effectView.effect = makeCustomZoomBlurEffect()
|
||||
}
|
||||
self.propertyAnimator = propertyAnimator
|
||||
}
|
||||
|
||||
self.scrollNode.view.delegate = self
|
||||
|
||||
self.view.addSubview(self.effectView)
|
||||
@ -124,6 +139,71 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
getController = { [weak controller] in
|
||||
return controller
|
||||
}
|
||||
|
||||
if let recognizer = recognizer {
|
||||
recognizer.externalUpdated = { [weak self, weak recognizer] view, point in
|
||||
guard let strongSelf = self, let _ = recognizer else {
|
||||
return
|
||||
}
|
||||
let localPoint = strongSelf.view.convert(point, from: view)
|
||||
let initialPoint: CGPoint
|
||||
if let current = strongSelf.initialContinueGesturePoint {
|
||||
initialPoint = current
|
||||
} else {
|
||||
initialPoint = localPoint
|
||||
strongSelf.initialContinueGesturePoint = localPoint
|
||||
}
|
||||
if strongSelf.didCompleteAnimationIn {
|
||||
if !strongSelf.didMoveFromInitialGesturePoint {
|
||||
let distance = abs(localPoint.y - initialPoint.y)
|
||||
if distance > 4.0 {
|
||||
strongSelf.didMoveFromInitialGesturePoint = true
|
||||
}
|
||||
}
|
||||
if strongSelf.didMoveFromInitialGesturePoint {
|
||||
let actionPoint = strongSelf.view.convert(localPoint, to: strongSelf.actionsContainerNode.view)
|
||||
let actionNode = strongSelf.actionsContainerNode.actionNode(at: actionPoint)
|
||||
if strongSelf.highlightedActionNode !== actionNode {
|
||||
strongSelf.highlightedActionNode?.setIsHighlighted(false)
|
||||
strongSelf.highlightedActionNode = actionNode
|
||||
if let actionNode = actionNode {
|
||||
actionNode.setIsHighlighted(true)
|
||||
strongSelf.hapticFeedback.tap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
recognizer.externalEnded = { [weak self, weak recognizer] viewAndPoint in
|
||||
guard let strongSelf = self, let recognizer = recognizer else {
|
||||
return
|
||||
}
|
||||
recognizer.externalUpdated = nil
|
||||
if strongSelf.didMoveFromInitialGesturePoint {
|
||||
if let (view, point) = viewAndPoint {
|
||||
let _ = strongSelf.view.convert(point, from: view)
|
||||
if let highlightedActionNode = strongSelf.highlightedActionNode {
|
||||
strongSelf.highlightedActionNode = nil
|
||||
highlightedActionNode.performAction()
|
||||
}
|
||||
} else {
|
||||
if let highlightedActionNode = strongSelf.highlightedActionNode {
|
||||
strongSelf.highlightedActionNode = nil
|
||||
highlightedActionNode.setIsHighlighted(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
if let propertyAnimator = self.propertyAnimator {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
let propertyAnimator = propertyAnimator as? UIViewPropertyAnimator
|
||||
propertyAnimator?.stopAnimation(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
@ -137,11 +217,24 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
}
|
||||
|
||||
func animateIn() {
|
||||
self.hapticFeedback.impact()
|
||||
|
||||
let takenViewInfo = self.source.takeView()
|
||||
|
||||
if let takenViewInfo = takenViewInfo, let parentSupernode = takenViewInfo.contentContainingNode.supernode {
|
||||
self.contentParentNode = takenViewInfo.contentContainingNode
|
||||
let contentParentNode = takenViewInfo.contentContainingNode
|
||||
takenViewInfo.contentContainingNode.layoutUpdated = { [weak contentParentNode, weak self] size in
|
||||
guard let strongSelf = self, let contentParentNode = contentParentNode, let parentSupernode = contentParentNode.supernode else {
|
||||
return
|
||||
}
|
||||
strongSelf.originalProjectedContentViewFrame = (parentSupernode.view.convert(contentParentNode.frame, to: strongSelf.view), contentParentNode.view.convert(contentParentNode.contentRect, to: strongSelf.view))
|
||||
if let validLayout = strongSelf.validLayout {
|
||||
strongSelf.updateLayout(layout: validLayout, transition: .animated(duration: 0.2, curve: .easeInOut), previousActionsContainerNode: nil)
|
||||
}
|
||||
}
|
||||
self.contentContainerNode.contentNode = takenViewInfo.contentContainingNode.contentNode
|
||||
self.contentAreaInScreenSpace = takenViewInfo.contentAreaInScreenSpace
|
||||
self.contentContainerNode.addSubnode(takenViewInfo.contentContainingNode.contentNode)
|
||||
takenViewInfo.contentContainingNode.isExtractedToContextPreview = true
|
||||
takenViewInfo.contentContainingNode.isExtractedToContextPreviewUpdated?(true)
|
||||
@ -158,45 +251,59 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
|
||||
self.dimNode.alpha = 1.0
|
||||
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
UIView.animate(withDuration: 0.25, animations: {
|
||||
if #available(iOS 9.0, *) {
|
||||
if self.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .regular)
|
||||
if self.effectView.subviews.count == 2 {
|
||||
self.effectView.subviews[1].isHidden = true
|
||||
if let _ = self.propertyAnimator {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.displayLinkAnimator = DisplayLinkAnimator(duration: 0.25, from: 0.0, to: 1.0, update: { [weak self] value in
|
||||
(self?.propertyAnimator as? UIViewPropertyAnimator)?.fractionComplete = value
|
||||
}, completion: { [weak self] in
|
||||
self?.didCompleteAnimationIn = true
|
||||
self?.hapticFeedback.prepareTap()
|
||||
})
|
||||
}
|
||||
} else {
|
||||
UIView.animate(withDuration: 0.25, animations: {
|
||||
if #available(iOS 9.0, *) {
|
||||
if self.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .regular)
|
||||
if self.effectView.subviews.count == 2 {
|
||||
self.effectView.subviews[1].isHidden = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
}
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .dark)
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.effectView.effect = UIBlurEffect(style: .regular)
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.effectView.effect = UIBlurEffect(style: .regular)
|
||||
self.effectView.alpha = 1.0
|
||||
}
|
||||
}, completion: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
||||
} else {
|
||||
self.effectView.effect = UIBlurEffect(style: .light)
|
||||
if strongSelf.effectView.subviews.count == 2 {
|
||||
strongSelf.effectView.subviews[1].isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.effectView.alpha = 1.0
|
||||
}
|
||||
}, completion: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if strongSelf.theme.chatList.searchBarKeyboardColor == .dark {
|
||||
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
||||
} else {
|
||||
if strongSelf.effectView.subviews.count == 2 {
|
||||
strongSelf.effectView.subviews[1].isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
//self.effectView.subviews[1].layer.removeAnimation(forKey: "backgroundColor")
|
||||
})
|
||||
}
|
||||
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
||||
} else {
|
||||
//self.effectView.subviews[1].layer.removeAnimation(forKey: "backgroundColor")
|
||||
}
|
||||
|
||||
self.actionsContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
|
||||
@ -247,16 +354,28 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
}
|
||||
}
|
||||
|
||||
UIView.animate(withDuration: 0.3, animations: {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.effectView.effect = nil
|
||||
} else {
|
||||
self.effectView.alpha = 0.0
|
||||
if let propertyAnimator = self.propertyAnimator {
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
self.displayLinkAnimator = DisplayLinkAnimator(duration: 0.22, from: (propertyAnimator as? UIViewPropertyAnimator)?.fractionComplete ?? 0.2, to: 0.0, update: { [weak self] value in
|
||||
(self?.propertyAnimator as? UIViewPropertyAnimator)?.fractionComplete = value
|
||||
}, completion: { [weak self] in
|
||||
self?.effectView.isHidden = true
|
||||
completedEffect = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
}
|
||||
}, completion: { _ in
|
||||
completedEffect = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
} else {
|
||||
UIView.animate(withDuration: 0.3, animations: {
|
||||
if #available(iOS 9.0, *) {
|
||||
self.effectView.effect = nil
|
||||
} else {
|
||||
self.effectView.alpha = 0.0
|
||||
}
|
||||
}, completion: { _ in
|
||||
completedEffect = true
|
||||
intermediateCompletion()
|
||||
})
|
||||
}
|
||||
|
||||
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.actionsContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { _ in
|
||||
@ -337,13 +456,20 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
||||
self.contentContainerNode.updateLayout(size: contentSize, transition: transition)
|
||||
|
||||
let maximumActionsFrameOrigin = max(60.0, layout.size.height - layout.intrinsicInsets.bottom - actionsBottomInset - actionsSize.height)
|
||||
let originalActionsFrame = CGRect(origin: CGPoint(x: max(actionsSideInset, min(layout.size.width - actionsSize.width - actionsSideInset, originalProjectedContentViewFrame.1.minX)), y: min(originalProjectedContentViewFrame.1.maxY + contentActionsSpacing, maximumActionsFrameOrigin)), size: actionsSize)
|
||||
let originalContentFrame = CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalActionsFrame.minY - contentActionsSpacing - originalProjectedContentViewFrame.1.size.height), size: originalProjectedContentViewFrame.1.size)
|
||||
var originalActionsFrame = CGRect(origin: CGPoint(x: max(actionsSideInset, min(layout.size.width - actionsSize.width - actionsSideInset, originalProjectedContentViewFrame.1.minX)), y: min(originalProjectedContentViewFrame.1.maxY + contentActionsSpacing, maximumActionsFrameOrigin)), size: actionsSize)
|
||||
var originalContentFrame = CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalActionsFrame.minY - contentActionsSpacing - originalProjectedContentViewFrame.1.size.height), size: originalProjectedContentViewFrame.1.size)
|
||||
let topEdge = max(contentTopInset, self.contentAreaInScreenSpace?.minY ?? 0.0)
|
||||
if originalContentFrame.minY < topEdge {
|
||||
let requiredOffset = topEdge - originalContentFrame.minY
|
||||
let availableOffset = max(0.0, layout.size.height - layout.intrinsicInsets.bottom - actionsBottomInset - originalActionsFrame.maxY)
|
||||
let offset = min(requiredOffset, availableOffset)
|
||||
originalActionsFrame = originalActionsFrame.offsetBy(dx: 0.0, dy: offset)
|
||||
originalContentFrame = originalContentFrame.offsetBy(dx: 0.0, dy: offset)
|
||||
}
|
||||
|
||||
let contentHeight = max(layout.size.height, max(layout.size.height, originalActionsFrame.maxY + actionsBottomInset) - originalContentFrame.minY + contentTopInset)
|
||||
|
||||
let scrollContentSize = CGSize(width: layout.size.width, height: contentHeight)
|
||||
let initialContentOffset = self.scrollNode.view.contentOffset
|
||||
if self.scrollNode.view.contentSize != scrollContentSize {
|
||||
self.scrollNode.view.contentSize = scrollContentSize
|
||||
}
|
||||
@ -434,24 +560,25 @@ public final class ContextController: ViewController {
|
||||
private let source: ContextControllerContentSource
|
||||
private var items: [ContextMenuItem]
|
||||
|
||||
private weak var recognizer: TapLongTapOrDoubleTapGestureRecognizer?
|
||||
|
||||
private var animatedDidAppear = false
|
||||
private var wasDismissed = false
|
||||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
private var controllerNode: ContextControllerNode {
|
||||
return self.displayNode as! ContextControllerNode
|
||||
}
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, source: ContextControllerContentSource, items: [ContextMenuItem]) {
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, source: ContextControllerContentSource, items: [ContextMenuItem], recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.source = source
|
||||
self.items = items
|
||||
self.recognizer = recognizer
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
||||
self.statusBar.statusBarStyle = .Ignore
|
||||
self.statusBar.statusBarStyle = .Hide
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
@ -461,7 +588,7 @@ public final class ContextController: ViewController {
|
||||
override public func loadDisplayNode() {
|
||||
self.displayNode = ContextControllerNode(controller: self, theme: self.theme, strings: self.strings, source: self.source, items: self.items, beginDismiss: { [weak self] result in
|
||||
self?.dismiss(result: result)
|
||||
})
|
||||
}, recognizer: self.recognizer)
|
||||
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
@ -473,12 +600,14 @@ public final class ContextController: ViewController {
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
if self.ignoreAppearanceMethodInvocations() {
|
||||
return
|
||||
}
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
if !self.wasDismissed && !self.animatedDidAppear {
|
||||
self.animatedDidAppear = true
|
||||
self.controllerNode.animateIn()
|
||||
self.hapticFeedback.impact()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ public func childWindowHostView(parent: UIView) -> WindowHostView {
|
||||
let view = ChildWindowHostView()
|
||||
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
||||
|
||||
let hostView = WindowHostView(containerView: view, eventView: view, isRotating: {
|
||||
let hostView = WindowHostView(containerView: view, eventView: view, aboveStatusBarView: view, isRotating: {
|
||||
return false
|
||||
}, updateSupportedInterfaceOrientations: { orientations in
|
||||
}, updateDeferScreenEdgeGestures: { edges in
|
||||
|
@ -28,7 +28,6 @@ FOUNDATION_EXPORT const unsigned char DisplayVersionString[];
|
||||
#import <Display/NavigationBarProxy.h>
|
||||
#import <UIKit/UIGestureRecognizerSubclass.h>
|
||||
#import <Display/NSWeakReference.h>
|
||||
#import <Display/FBAnimationPerformanceTracker.h>
|
||||
#import <Display/CATracingLayer.h>
|
||||
#import <Display/CASeeThroughTracingLayer.h>
|
||||
#import <Display/UIMenuItem+Icons.h>
|
||||
|
@ -65,7 +65,7 @@ final class GlobalOverlayPresentationContext {
|
||||
|
||||
var underStatusBar = false
|
||||
if let controller = controller as? ViewController {
|
||||
if case .Ignore = controller.statusBar.statusBarStyle {
|
||||
if case .Hide = controller.statusBar.statusBarStyle {
|
||||
underStatusBar = true
|
||||
}
|
||||
}
|
||||
@ -145,7 +145,7 @@ final class GlobalOverlayPresentationContext {
|
||||
for controller in self.controllers {
|
||||
var underStatusBar = false
|
||||
if let controller = controller as? ViewController {
|
||||
if case .Ignore = controller.statusBar.statusBarStyle {
|
||||
if case .Hide = controller.statusBar.statusBarStyle {
|
||||
underStatusBar = true
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,9 @@ private final class HapticFeedbackImpl {
|
||||
if number == "1" {
|
||||
return generator
|
||||
} else {
|
||||
if #available(iOSApplicationExtension 13.0, iOS 13.0, *) {
|
||||
return generator
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
|
@ -3462,6 +3462,8 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
let updatedApparentHeight = itemNode.apparentHeight
|
||||
let apparentHeightDelta = updatedApparentHeight - previousApparentHeight
|
||||
if abs(apparentHeightDelta) > CGFloat.ulpOfOne {
|
||||
itemNode.updateFrame(itemNode.frame, within: self.visibleSize)
|
||||
|
||||
let visualInsets = self.visualInsets ?? self.insets
|
||||
|
||||
if itemNode.apparentFrame.maxY <= visualInsets.top {
|
||||
|
@ -337,7 +337,7 @@ private final class NativeWindow: UIWindow, WindowHost {
|
||||
}
|
||||
}
|
||||
|
||||
public func nativeWindowHostView() -> (UIWindow & WindowHost, WindowHostView) {
|
||||
public func nativeWindowHostView() -> (UIWindow & WindowHost, WindowHostView, UIWindow) {
|
||||
let window = NativeWindow(frame: UIScreen.main.bounds)
|
||||
|
||||
let rootViewController = WindowRootViewController()
|
||||
@ -346,7 +346,9 @@ public func nativeWindowHostView() -> (UIWindow & WindowHost, WindowHostView) {
|
||||
rootViewController.view.frame = CGRect(origin: CGPoint(), size: window.bounds.size)
|
||||
rootViewController.viewDidAppear(false)
|
||||
|
||||
let hostView = WindowHostView(containerView: rootViewController.view, eventView: window, isRotating: {
|
||||
let aboveStatusbarWindow = AboveStatusBarWindow(frame: UIScreen.main.bounds)
|
||||
|
||||
let hostView = WindowHostView(containerView: rootViewController.view, eventView: window, aboveStatusBarView: rootViewController.view, isRotating: {
|
||||
return window.isRotating()
|
||||
}, updateSupportedInterfaceOrientations: { orientations in
|
||||
rootViewController.orientations = orientations
|
||||
@ -422,5 +424,5 @@ public func nativeWindowHostView() -> (UIWindow & WindowHost, WindowHostView) {
|
||||
}
|
||||
}
|
||||
|
||||
return (window, hostView)
|
||||
return (window, hostView, aboveStatusbarWindow)
|
||||
}
|
||||
|
@ -1,6 +1,25 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import UIKit.UIGestureRecognizerSubclass
|
||||
import AsyncDisplayKit
|
||||
|
||||
private func cancelScrollViewGestures(view: UIView?) {
|
||||
if let view = view {
|
||||
if let gestureRecognizers = view.gestureRecognizers {
|
||||
for recognizer in gestureRecognizers {
|
||||
if let recognizer = recognizer as? UIPanGestureRecognizer {
|
||||
switch recognizer.state {
|
||||
case .began, .possible:
|
||||
recognizer.state = .ended
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
cancelScrollViewGestures(view: view.superview)
|
||||
}
|
||||
}
|
||||
|
||||
private class TapLongTapOrDoubleTapGestureRecognizerTimerTarget: NSObject {
|
||||
weak var target: TapLongTapOrDoubleTapGestureRecognizer?
|
||||
@ -47,6 +66,10 @@ public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer,
|
||||
public private(set) var lastRecognizedGestureAndLocation: (TapLongTapOrDoubleTapGesture, CGPoint)?
|
||||
|
||||
public var tapActionAtPoint: ((CGPoint) -> TapLongTapOrDoubleTapGestureRecognizerAction)?
|
||||
public var longTap: ((CGPoint, TapLongTapOrDoubleTapGestureRecognizer) -> Void)?
|
||||
private var recognizedLongTap: Bool = false
|
||||
public var externalUpdated: ((UIView?, CGPoint) -> Void)?
|
||||
public var externalEnded: (((UIView?, CGPoint)?) -> Void)?
|
||||
public var highlight: ((CGPoint?) -> Void)?
|
||||
|
||||
public var hapticFeedback: HapticFeedback?
|
||||
@ -73,20 +96,35 @@ public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer,
|
||||
self.tapCount = 0
|
||||
self.touchCount = 0
|
||||
self.hapticFeedback = nil
|
||||
self.recognizedLongTap = false
|
||||
|
||||
if self.highlightPoint != nil {
|
||||
self.highlightPoint = nil
|
||||
self.highlight?(nil)
|
||||
}
|
||||
|
||||
self.externalUpdated = nil
|
||||
self.externalEnded = nil
|
||||
|
||||
super.reset()
|
||||
}
|
||||
|
||||
public func cancel() {
|
||||
self.state = .cancelled
|
||||
}
|
||||
|
||||
fileprivate func longTapEvent() {
|
||||
self.timer?.invalidate()
|
||||
self.timer = nil
|
||||
if let (location, _) = self.touchLocationAndTimestamp {
|
||||
self.lastRecognizedGestureAndLocation = (.longTap, location)
|
||||
if let longTap = self.longTap {
|
||||
self.recognizedLongTap = true
|
||||
longTap(location, self)
|
||||
cancelScrollViewGestures(view: self.view?.superview)
|
||||
self.state = .began
|
||||
return
|
||||
}
|
||||
} else {
|
||||
self.lastRecognizedGestureAndLocation = nil
|
||||
}
|
||||
@ -184,6 +222,12 @@ public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer,
|
||||
return
|
||||
}
|
||||
|
||||
if self.recognizedLongTap, let externalUpdated = self.externalUpdated {
|
||||
let location = touch.location(in: self.view)
|
||||
externalUpdated(self.view, location)
|
||||
return
|
||||
}
|
||||
|
||||
if let touch = touches.first, let (touchLocation, _) = self.touchLocationAndTimestamp {
|
||||
let location = touch.location(in: self.view)
|
||||
let distance = CGPoint(x: location.x - touchLocation.x, y: location.y - touchLocation.y)
|
||||
@ -211,6 +255,12 @@ public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer,
|
||||
return
|
||||
}
|
||||
|
||||
if let (gesture, location) = self.lastRecognizedGestureAndLocation, case .longTap = gesture, self.recognizedLongTap {
|
||||
self.externalEnded?((self.view, location))
|
||||
self.state = .cancelled
|
||||
return
|
||||
}
|
||||
|
||||
if self.tapCount == 1 {
|
||||
var tapAction: TapLongTapOrDoubleTapGestureRecognizerAction = .waitForDoubleTap
|
||||
if let tapActionAtPoint = self.tapActionAtPoint, let (touchLocation, _) = self.touchLocationAndTimestamp {
|
||||
@ -252,6 +302,8 @@ public final class TapLongTapOrDoubleTapGestureRecognizer: UIGestureRecognizer,
|
||||
self.highlight?(nil)
|
||||
}
|
||||
|
||||
self.externalEnded?(nil)
|
||||
|
||||
self.state = .cancelled
|
||||
}
|
||||
}
|
||||
|
@ -11,3 +11,5 @@ CABasicAnimation * _Nonnull makeSpringAnimation(NSString * _Nonnull keyPath);
|
||||
CABasicAnimation * _Nonnull makeSpringBounceAnimation(NSString * _Nonnull keyPath, CGFloat initialVelocity, CGFloat damping);
|
||||
CGFloat springAnimationValueAt(CABasicAnimation * _Nonnull animation, CGFloat t);
|
||||
|
||||
void testZoomBlurEffect(UIVisualEffect *effect);
|
||||
UIBlurEffect *makeCustomZoomBlurEffect();
|
||||
|
@ -87,3 +87,43 @@ CABasicAnimation * _Nonnull makeSpringBounceAnimation(NSString * _Nonnull keyPat
|
||||
CGFloat springAnimationValueAt(CABasicAnimation * _Nonnull animation, CGFloat t) {
|
||||
return [(CASpringAnimation *)animation valueAt:t];
|
||||
}
|
||||
|
||||
@interface CustomBlurEffect : UIBlurEffect
|
||||
|
||||
@property (nonatomic) double blurRadius;
|
||||
@property (nonatomic) double colorBurnTintAlpha;
|
||||
@property (nonatomic) double colorBurnTintLevel;
|
||||
@property (nonatomic, retain) UIColor *colorTint;
|
||||
@property (nonatomic) double colorTintAlpha;
|
||||
@property (nonatomic) bool darkenWithSourceOver;
|
||||
@property (nonatomic) double darkeningTintAlpha;
|
||||
@property (nonatomic) double darkeningTintHue;
|
||||
@property (nonatomic) double darkeningTintSaturation;
|
||||
@property (nonatomic) double grayscaleTintAlpha;
|
||||
@property (nonatomic) double grayscaleTintLevel;
|
||||
@property (nonatomic) bool lightenGrayscaleWithSourceOver;
|
||||
@property (nonatomic) double saturationDeltaFactor;
|
||||
@property (nonatomic) double scale;
|
||||
@property (nonatomic) double zoom;
|
||||
|
||||
+ (id)effectWithStyle:(long long)arg1;
|
||||
|
||||
@end
|
||||
|
||||
void testZoomBlurEffect(UIVisualEffect *effect) {
|
||||
}
|
||||
|
||||
UIBlurEffect *makeCustomZoomBlurEffect() {
|
||||
NSString *string = [@[@"_", @"UI", @"Custom", @"BlurEffect"] componentsJoinedByString:@""];
|
||||
CustomBlurEffect *result = (CustomBlurEffect *)[NSClassFromString(string) effectWithStyle:0];
|
||||
result.blurRadius = 7.0;
|
||||
result.zoom = 0.015;
|
||||
result.colorTint = nil;
|
||||
result.colorTintAlpha = 0.0;
|
||||
result.darkeningTintAlpha = 0.0;
|
||||
result.grayscaleTintAlpha = 0.0;
|
||||
result.saturationDeltaFactor = 1.0;
|
||||
result.scale = 0.5;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -33,3 +33,7 @@ typedef NS_OPTIONS(NSUInteger, UIResponderDisableAutomaticKeyboardHandling) {
|
||||
@end
|
||||
|
||||
void applyKeyboardAutocorrection();
|
||||
|
||||
@interface AboveStatusBarWindow : UIWindow
|
||||
|
||||
@end
|
||||
|
@ -308,3 +308,74 @@ void applyKeyboardAutocorrection() {
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
}
|
||||
|
||||
@interface AboveStatusBarWindowController : UIViewController
|
||||
|
||||
@end
|
||||
|
||||
@implementation AboveStatusBarWindowController
|
||||
|
||||
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
|
||||
self = [super initWithNibName:nil bundle:nil];
|
||||
if (self != nil) {
|
||||
self.extendedLayoutIncludesOpaqueBars = true;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)loadView {
|
||||
self.view = [[UIView alloc] initWithFrame:CGRectZero];
|
||||
self.view.opaque = false;
|
||||
self.view.backgroundColor = nil;
|
||||
[self viewDidLoad];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation AboveStatusBarWindow
|
||||
|
||||
- (instancetype)initWithFrame:(CGRect)frame {
|
||||
self = [super initWithFrame:frame];
|
||||
if (self != nil) {
|
||||
self.windowLevel = UIWindowLevelStatusBar + 1.0f;
|
||||
self.rootViewController = [[AboveStatusBarWindowController alloc] initWithNibName:nil bundle:nil];
|
||||
if (self.gestureRecognizers != nil) {
|
||||
for (UIGestureRecognizer *recognizer in self.gestureRecognizers) {
|
||||
recognizer.delaysTouchesBegan = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)shouldAffectStatusBarAppearance {
|
||||
return false;
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeKeyWindow {
|
||||
return false;
|
||||
}
|
||||
|
||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
||||
UIView *result = [super hitTest:point withEvent:event];
|
||||
if (result == self || result == self.rootViewController.view) {
|
||||
return nil;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (void)initialize {
|
||||
NSString *canAffectSelectorString = [@[@"_can", @"Affect", @"Status", @"Bar", @"Appearance"] componentsJoinedByString:@""];
|
||||
SEL canAffectSelector = NSSelectorFromString(canAffectSelectorString);
|
||||
Method shouldAffectMethod = class_getInstanceMethod(self, @selector(shouldAffectStatusBarAppearance));
|
||||
IMP canAffectImplementation = method_getImplementation(shouldAffectMethod);
|
||||
class_addMethod(self, canAffectSelector, canAffectImplementation, method_getTypeEncoding(shouldAffectMethod));
|
||||
|
||||
NSString *canBecomeKeySelectorString = [NSString stringWithFormat:@"_%@", NSStringFromSelector(@selector(canBecomeKeyWindow))];
|
||||
SEL canBecomeKeySelector = NSSelectorFromString(canBecomeKeySelectorString);
|
||||
Method canBecomeKeyMethod = class_getInstanceMethod(self, @selector(canBecomeKeyWindow));
|
||||
IMP canBecomeKeyImplementation = method_getImplementation(canBecomeKeyMethod);
|
||||
class_addMethod(self, canBecomeKeySelector, canBecomeKeyImplementation, method_getTypeEncoding(canBecomeKeyMethod));
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -170,6 +170,7 @@ private func checkIsPreviewingView(_ view: UIView) -> Bool {
|
||||
private func applyThemeToPreviewingView(_ view: UIView, accentColor: UIColor, darkBlur: Bool) {
|
||||
if let previewingActionGroupClass = previewingActionGroupClass, view.isKind(of: previewingActionGroupClass) {
|
||||
view.tintColor = accentColor
|
||||
testZoomBlurEffect((view.superview?.superview?.subviews[1] as? UIVisualEffectView)?.effect)
|
||||
if darkBlur {
|
||||
applyThemeToPreviewingEffectView(view)
|
||||
}
|
||||
@ -214,6 +215,7 @@ public func getFirstResponderAndAccessoryHeight(_ view: UIView, _ accessoryHeigh
|
||||
public final class WindowHostView {
|
||||
public let containerView: UIView
|
||||
public let eventView: UIView
|
||||
public let aboveStatusBarView: UIView
|
||||
public let isRotating: () -> Bool
|
||||
|
||||
let updateSupportedInterfaceOrientations: (UIInterfaceOrientationMask) -> Void
|
||||
@ -235,9 +237,10 @@ public final class WindowHostView {
|
||||
var forEachController: (((ContainableController) -> Void) -> Void)?
|
||||
var getAccessibilityElements: (() -> [Any]?)?
|
||||
|
||||
init(containerView: UIView, eventView: UIView, isRotating: @escaping () -> Bool, updateSupportedInterfaceOrientations: @escaping (UIInterfaceOrientationMask) -> Void, updateDeferScreenEdgeGestures: @escaping (UIRectEdge) -> Void, updatePreferNavigationUIHidden: @escaping (Bool) -> Void) {
|
||||
init(containerView: UIView, eventView: UIView, aboveStatusBarView: UIView, isRotating: @escaping () -> Bool, updateSupportedInterfaceOrientations: @escaping (UIInterfaceOrientationMask) -> Void, updateDeferScreenEdgeGestures: @escaping (UIRectEdge) -> Void, updatePreferNavigationUIHidden: @escaping (Bool) -> Void) {
|
||||
self.containerView = containerView
|
||||
self.eventView = eventView
|
||||
self.aboveStatusBarView = aboveStatusBarView
|
||||
self.isRotating = isRotating
|
||||
self.updateSupportedInterfaceOrientations = updateSupportedInterfaceOrientations
|
||||
self.updateDeferScreenEdgeGestures = updateDeferScreenEdgeGestures
|
||||
@ -372,7 +375,7 @@ public class Window1 {
|
||||
self.windowLayout = WindowLayout(size: boundsSize, metrics: layoutMetricsForScreenSize(boundsSize), statusBarHeight: statusBarHeight, forceInCallStatusBarText: self.forceInCallStatusBarText, inputHeight: 0.0, safeInsets: safeInsetsForScreenSize(boundsSize, hasOnScreenNavigation: self.hostView.hasOnScreenNavigation), onScreenNavigationHeight: onScreenNavigationHeight, upperKeyboardInputPositionBound: nil, inVoiceOver: UIAccessibility.isVoiceOverRunning)
|
||||
self.updatingLayout = UpdatingLayout(layout: self.windowLayout, transition: .immediate)
|
||||
self.presentationContext = PresentationContext()
|
||||
self.overlayPresentationContext = GlobalOverlayPresentationContext(statusBarHost: statusBarHost, parentView: self.hostView.containerView)
|
||||
self.overlayPresentationContext = GlobalOverlayPresentationContext(statusBarHost: statusBarHost, parentView: self.hostView.aboveStatusBarView)
|
||||
|
||||
self.presentationContext.updateIsInteractionBlocked = { [weak self] value in
|
||||
self?.isInteractionBlocked = value
|
||||
|
@ -36,6 +36,7 @@
|
||||
D02958001D6F096000360E5E /* ContextMenuContainerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02957FF1D6F096000360E5E /* ContextMenuContainerNode.swift */; };
|
||||
D02BDB021B6AC703008AFAD2 /* RuntimeUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02BDB011B6AC703008AFAD2 /* RuntimeUtils.swift */; };
|
||||
D02C61F322A94BD600D4EC86 /* Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02C61F222A94BD600D4EC86 /* Keyboard.swift */; };
|
||||
D0329EA822FC8E7600F9F071 /* DisplayLinkAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0329EA722FC8E7600F9F071 /* DisplayLinkAnimator.swift */; };
|
||||
D03310B3213F232600FC83CD /* ListViewTapGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03310B2213F232600FC83CD /* ListViewTapGestureRecognizer.swift */; };
|
||||
D033874E223D3E86007A2CE4 /* AccessibilityAreaNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033874D223D3E86007A2CE4 /* AccessibilityAreaNode.swift */; };
|
||||
D0338750223EE5A4007A2CE4 /* ActionSheetSwitchItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D033874F223EE5A4007A2CE4 /* ActionSheetSwitchItem.swift */; };
|
||||
@ -131,8 +132,6 @@
|
||||
D0BE93191E8ED71100DCC1E6 /* NativeWindowHostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BE93181E8ED71100DCC1E6 /* NativeWindowHostView.swift */; };
|
||||
D0C0B5991EDF3BC9000F4D2C /* ActionSheetTextItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B5981EDF3BC9000F4D2C /* ActionSheetTextItem.swift */; };
|
||||
D0C0B59D1EE022CC000F4D2C /* NavigationBarContentNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C0B59C1EE022CC000F4D2C /* NavigationBarContentNode.swift */; };
|
||||
D0C0D28F1C997110001D2851 /* FBAnimationPerformanceTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = D0C0D28D1C997110001D2851 /* FBAnimationPerformanceTracker.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D0C0D2901C997110001D2851 /* FBAnimationPerformanceTracker.mm in Sources */ = {isa = PBXBuildFile; fileRef = D0C0D28E1C997110001D2851 /* FBAnimationPerformanceTracker.mm */; };
|
||||
D0C12A1A1F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C12A191F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift */; };
|
||||
D0C2DFC61CC4431D0044FF83 /* ASTransformLayerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C2DFBB1CC4431D0044FF83 /* ASTransformLayerNode.swift */; };
|
||||
D0C2DFC71CC4431D0044FF83 /* ListViewItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C2DFBC1CC4431D0044FF83 /* ListViewItemNode.swift */; };
|
||||
@ -213,6 +212,7 @@
|
||||
D02957FF1D6F096000360E5E /* ContextMenuContainerNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextMenuContainerNode.swift; sourceTree = "<group>"; };
|
||||
D02BDB011B6AC703008AFAD2 /* RuntimeUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RuntimeUtils.swift; sourceTree = "<group>"; };
|
||||
D02C61F222A94BD600D4EC86 /* Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keyboard.swift; sourceTree = "<group>"; };
|
||||
D0329EA722FC8E7600F9F071 /* DisplayLinkAnimator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayLinkAnimator.swift; sourceTree = "<group>"; };
|
||||
D03310B2213F232600FC83CD /* ListViewTapGestureRecognizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListViewTapGestureRecognizer.swift; sourceTree = "<group>"; };
|
||||
D033874D223D3E86007A2CE4 /* AccessibilityAreaNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityAreaNode.swift; sourceTree = "<group>"; };
|
||||
D033874F223EE5A4007A2CE4 /* ActionSheetSwitchItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionSheetSwitchItem.swift; sourceTree = "<group>"; };
|
||||
@ -311,8 +311,6 @@
|
||||
D0BE93181E8ED71100DCC1E6 /* NativeWindowHostView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeWindowHostView.swift; sourceTree = "<group>"; };
|
||||
D0C0B5981EDF3BC9000F4D2C /* ActionSheetTextItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionSheetTextItem.swift; sourceTree = "<group>"; };
|
||||
D0C0B59C1EE022CC000F4D2C /* NavigationBarContentNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBarContentNode.swift; sourceTree = "<group>"; };
|
||||
D0C0D28D1C997110001D2851 /* FBAnimationPerformanceTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBAnimationPerformanceTracker.h; sourceTree = "<group>"; };
|
||||
D0C0D28E1C997110001D2851 /* FBAnimationPerformanceTracker.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FBAnimationPerformanceTracker.mm; sourceTree = "<group>"; };
|
||||
D0C12A191F3375B400B3F66D /* NavigationBarTitleTransitionNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationBarTitleTransitionNode.swift; sourceTree = "<group>"; };
|
||||
D0C2DFBB1CC4431D0044FF83 /* ASTransformLayerNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ASTransformLayerNode.swift; sourceTree = "<group>"; };
|
||||
D0C2DFBC1CC4431D0044FF83 /* ListViewItemNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListViewItemNode.swift; sourceTree = "<group>"; };
|
||||
@ -620,13 +618,12 @@
|
||||
D03E7DF61C96C5F200C07816 /* NSWeakReference.h */,
|
||||
D03E7DF71C96C5F200C07816 /* NSWeakReference.m */,
|
||||
D03E7E001C974AB300C07816 /* DisplayLinkDispatcher.swift */,
|
||||
D0C0D28D1C997110001D2851 /* FBAnimationPerformanceTracker.h */,
|
||||
D0C0D28E1C997110001D2851 /* FBAnimationPerformanceTracker.mm */,
|
||||
D0D94A161D3814F900740E02 /* UniversalTapRecognizer.swift */,
|
||||
D01F728121F13891006AB634 /* Accessibility.swift */,
|
||||
09167E1E229803DC005734A7 /* UIMenuItem+Icons.h */,
|
||||
09167E1F229803DC005734A7 /* UIMenuItem+Icons.m */,
|
||||
D02C61F222A94BD600D4EC86 /* Keyboard.swift */,
|
||||
D0329EA722FC8E7600F9F071 /* DisplayLinkAnimator.swift */,
|
||||
);
|
||||
name = Utils;
|
||||
sourceTree = "<group>";
|
||||
@ -768,7 +765,6 @@
|
||||
D05174B31EAA833200A1BF36 /* CASeeThroughTracingLayer.h in Headers */,
|
||||
D05CC3081B69575900E235A3 /* NSBag.h in Headers */,
|
||||
09167E20229803DC005734A7 /* UIMenuItem+Icons.h in Headers */,
|
||||
D0C0D28F1C997110001D2851 /* FBAnimationPerformanceTracker.h in Headers */,
|
||||
D05CC2671B69316F00E235A3 /* Display.h in Headers */,
|
||||
D05CC2F91B6955D000E235A3 /* UIViewController+Navigation.h in Headers */,
|
||||
);
|
||||
@ -993,7 +989,6 @@
|
||||
D0CE67921F7DA11700FFB557 /* ActionSheetTheme.swift in Sources */,
|
||||
D0A134642034DE580059716A /* TabBarTapRecognizer.swift in Sources */,
|
||||
D03AA4E3202DD52E0056C405 /* PeekControllerMenuItemNode.swift in Sources */,
|
||||
D0C0D2901C997110001D2851 /* FBAnimationPerformanceTracker.mm in Sources */,
|
||||
D015F7521D1AE08D00E269B5 /* ContainableController.swift in Sources */,
|
||||
D036574B1E71C44D00BB1EE4 /* MinimizeKeyboardGestureRecognizer.swift in Sources */,
|
||||
D0CB78901F9822F8004AB79B /* WindowPanRecognizer.swift in Sources */,
|
||||
@ -1006,6 +1001,7 @@
|
||||
D02383861DE0E3B4004018B6 /* ListViewIntermediateState.swift in Sources */,
|
||||
D0DA444E1E4DCA6E005FDCA7 /* AlertControllerNode.swift in Sources */,
|
||||
D0B367201C94A53A00346D2E /* StatusBarProxyNode.swift in Sources */,
|
||||
D0329EA822FC8E7600F9F071 /* DisplayLinkAnimator.swift in Sources */,
|
||||
09DD88EB21BCA5E0000766BC /* EditableTextNode.swift in Sources */,
|
||||
D05CC2A21B69326C00E235A3 /* WindowContent.swift in Sources */,
|
||||
D05CC3151B695A9600E235A3 /* NavigationTransitionCoordinator.swift in Sources */,
|
||||
|
@ -291,6 +291,18 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
inputClearButtonColor: UIColor(rgb: 0x8f8f8f),
|
||||
checkContentColor: .white
|
||||
)
|
||||
|
||||
let contextMenu = PresentationThemeContextMenu(
|
||||
dimColor: UIColor(rgb: 0x000000, alpha: 0.6),
|
||||
backgroundColor: UIColor(rgb: 0x252525, alpha: 0.78),
|
||||
itemSeparatorColor: UIColor(rgb: 0xFFFFFF, alpha: 0.15),
|
||||
sectionSeparatorColor: UIColor(rgb: 0x000000, alpha: 0.2),
|
||||
itemBackgroundColor: UIColor(rgb: 0x000000, alpha: 0.0),
|
||||
itemHighlightedBackgroundColor: UIColor(rgb: 0xFFFFFF, alpha: 0.15),
|
||||
primaryColor: UIColor(rgb: 0xffffff, alpha: 1.0),
|
||||
secondaryColor: UIColor(rgb: 0xffffff, alpha: 0.8),
|
||||
destructiveColor: destructiveColor
|
||||
)
|
||||
|
||||
let inAppNotification = PresentationThemeInAppNotification(
|
||||
fillColor: UIColor(rgb: 0x1c1c1d),
|
||||
@ -318,6 +330,7 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
chatList: chatList,
|
||||
chat: chat,
|
||||
actionSheet: actionSheet,
|
||||
contextMenu: contextMenu,
|
||||
inAppNotification: inAppNotification,
|
||||
preview: preview
|
||||
)
|
||||
|
@ -292,6 +292,18 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
inputClearButtonColor: mainSecondaryColor,
|
||||
checkContentColor: .white
|
||||
)
|
||||
|
||||
let contextMenu = PresentationThemeContextMenu(
|
||||
dimColor: UIColor(rgb: 0x000000, alpha: 0.6),
|
||||
backgroundColor: rootNavigationBar.backgroundColor.withAlphaComponent(0.78),
|
||||
itemSeparatorColor: UIColor(rgb: 0xFFFFFF, alpha: 0.15),
|
||||
sectionSeparatorColor: UIColor(rgb: 0x000000, alpha: 0.2),
|
||||
itemBackgroundColor: UIColor(rgb: 0x000000, alpha: 0.0),
|
||||
itemHighlightedBackgroundColor: UIColor(rgb: 0xFFFFFF, alpha: 0.15),
|
||||
primaryColor: UIColor(rgb: 0xffffff, alpha: 1.0),
|
||||
secondaryColor: UIColor(rgb: 0xffffff, alpha: 0.8),
|
||||
destructiveColor: destructiveColor
|
||||
)
|
||||
|
||||
let inAppNotification = PresentationThemeInAppNotification(
|
||||
fillColor: mainBackgroundColor,
|
||||
@ -319,6 +331,7 @@ private func makeDarkPresentationTheme(accentColor: UIColor, baseColor: Presenta
|
||||
chatList: chatList,
|
||||
chat: chat,
|
||||
actionSheet: actionSheet,
|
||||
contextMenu: contextMenu,
|
||||
inAppNotification: inAppNotification,
|
||||
preview: preview
|
||||
)
|
||||
|
@ -299,6 +299,18 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
|
||||
checkContentColor: .white
|
||||
)
|
||||
|
||||
let contextMenu = PresentationThemeContextMenu(
|
||||
dimColor: UIColor(rgb: 0x000A26, alpha: 0.2),
|
||||
backgroundColor: UIColor(rgb: 0xF9F9F9, alpha: 0.78),
|
||||
itemSeparatorColor: UIColor(rgb: 0x3C3C43, alpha: 0.2),
|
||||
sectionSeparatorColor: UIColor(rgb: 0x8A8A8A, alpha: 0.2),
|
||||
itemBackgroundColor: UIColor(rgb: 0x000000, alpha: 0.0),
|
||||
itemHighlightedBackgroundColor: UIColor(rgb: 0x3C3C43, alpha: 0.2),
|
||||
primaryColor: UIColor(rgb: 0x000000, alpha: 1.0),
|
||||
secondaryColor: UIColor(rgb: 0x000000, alpha: 0.8),
|
||||
destructiveColor: destructiveColor
|
||||
)
|
||||
|
||||
let inAppNotification = PresentationThemeInAppNotification(
|
||||
fillColor: .white,
|
||||
primaryTextColor: .black,
|
||||
@ -325,6 +337,7 @@ private func makeDefaultDayPresentationTheme(accentColor: UIColor, serviceBackgr
|
||||
chatList: chatList,
|
||||
chat: chat,
|
||||
actionSheet: actionSheet,
|
||||
contextMenu: contextMenu,
|
||||
inAppNotification: inAppNotification,
|
||||
preview: preview
|
||||
)
|
||||
|
@ -200,6 +200,30 @@ public final class PresentationThemeActionSheet {
|
||||
}
|
||||
}
|
||||
|
||||
public final class PresentationThemeContextMenu {
|
||||
public let dimColor: UIColor
|
||||
public let backgroundColor: UIColor
|
||||
public let itemSeparatorColor: UIColor
|
||||
public let sectionSeparatorColor: UIColor
|
||||
public let itemBackgroundColor: UIColor
|
||||
public let itemHighlightedBackgroundColor: UIColor
|
||||
public let primaryColor: UIColor
|
||||
public let secondaryColor: UIColor
|
||||
public let destructiveColor: UIColor
|
||||
|
||||
init(dimColor: UIColor, backgroundColor: UIColor, itemSeparatorColor: UIColor, sectionSeparatorColor: UIColor, itemBackgroundColor: UIColor, itemHighlightedBackgroundColor: UIColor, primaryColor: UIColor, secondaryColor: UIColor, destructiveColor: UIColor) {
|
||||
self.dimColor = dimColor
|
||||
self.backgroundColor = backgroundColor
|
||||
self.itemSeparatorColor = itemSeparatorColor
|
||||
self.sectionSeparatorColor = sectionSeparatorColor
|
||||
self.itemBackgroundColor = itemBackgroundColor
|
||||
self.itemHighlightedBackgroundColor = itemHighlightedBackgroundColor
|
||||
self.primaryColor = primaryColor
|
||||
self.secondaryColor = secondaryColor
|
||||
self.destructiveColor = destructiveColor
|
||||
}
|
||||
}
|
||||
|
||||
public final class PresentationThemeSwitch {
|
||||
public let frameColor: UIColor
|
||||
public let handleColor: UIColor
|
||||
@ -914,12 +938,13 @@ public final class PresentationTheme: Equatable {
|
||||
public let chatList: PresentationThemeChatList
|
||||
public let chat: PresentationThemeChat
|
||||
public let actionSheet: PresentationThemeActionSheet
|
||||
public let contextMenu: PresentationThemeContextMenu
|
||||
public let inAppNotification: PresentationThemeInAppNotification
|
||||
public let preview: Bool
|
||||
|
||||
public let resourceCache: PresentationsResourceCache = PresentationsResourceCache()
|
||||
|
||||
public init(name: PresentationThemeName, author: String?, overallDarkAppearance: Bool, baseColor: PresentationThemeBaseColor?, intro: PresentationThemeIntro, passcode: PresentationThemePasscode, rootController: PresentationThemeRootController, list: PresentationThemeList, chatList: PresentationThemeChatList, chat: PresentationThemeChat, actionSheet: PresentationThemeActionSheet, inAppNotification: PresentationThemeInAppNotification, preview: Bool = false) {
|
||||
public init(name: PresentationThemeName, author: String?, overallDarkAppearance: Bool, baseColor: PresentationThemeBaseColor?, intro: PresentationThemeIntro, passcode: PresentationThemePasscode, rootController: PresentationThemeRootController, list: PresentationThemeList, chatList: PresentationThemeChatList, chat: PresentationThemeChat, actionSheet: PresentationThemeActionSheet, contextMenu: PresentationThemeContextMenu, inAppNotification: PresentationThemeInAppNotification, preview: Bool = false) {
|
||||
self.name = name
|
||||
self.author = author
|
||||
self.overallDarkAppearance = overallDarkAppearance
|
||||
@ -931,6 +956,7 @@ public final class PresentationTheme: Equatable {
|
||||
self.chatList = chatList
|
||||
self.chat = chat
|
||||
self.actionSheet = actionSheet
|
||||
self.contextMenu = contextMenu
|
||||
self.inAppNotification = inAppNotification
|
||||
self.preview = preview
|
||||
}
|
||||
|
@ -431,6 +431,48 @@ extension PresentationThemeActionSheet: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
extension PresentationThemeContextMenu: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case dim
|
||||
case background
|
||||
case itemSeparator
|
||||
case sectionSeparator
|
||||
case itemBackground
|
||||
case itemHighlightedBackground
|
||||
case primary
|
||||
case secondary
|
||||
case destructive
|
||||
}
|
||||
|
||||
public convenience init(from decoder: Decoder) throws {
|
||||
let values = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.init(
|
||||
dimColor: try decodeColor(values, .dim),
|
||||
backgroundColor: try decodeColor(values, .background),
|
||||
itemSeparatorColor: try decodeColor(values, .itemSeparator),
|
||||
sectionSeparatorColor: try decodeColor(values, .sectionSeparator),
|
||||
itemBackgroundColor: try decodeColor(values, .itemBackground),
|
||||
itemHighlightedBackgroundColor: try decodeColor(values, .itemHighlightedBackground),
|
||||
primaryColor: try decodeColor(values, .primary),
|
||||
secondaryColor: try decodeColor(values, .secondary),
|
||||
destructiveColor: try decodeColor(values, .destructive)
|
||||
)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var values = encoder.container(keyedBy: CodingKeys.self)
|
||||
try encodeColor(&values, self.dimColor, .dim)
|
||||
try encodeColor(&values, self.backgroundColor, .background)
|
||||
try encodeColor(&values, self.itemSeparatorColor, .itemSeparator)
|
||||
try encodeColor(&values, self.sectionSeparatorColor, .sectionSeparator)
|
||||
try encodeColor(&values, self.itemBackgroundColor, .itemBackground)
|
||||
try encodeColor(&values, self.itemHighlightedBackgroundColor, .itemHighlightedBackground)
|
||||
try encodeColor(&values, self.primaryColor, .primary)
|
||||
try encodeColor(&values, self.secondaryColor, .secondary)
|
||||
try encodeColor(&values, self.destructiveColor, .destructive)
|
||||
}
|
||||
}
|
||||
|
||||
extension PresentationThemeSwitch: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case frame
|
||||
@ -1423,6 +1465,7 @@ extension PresentationTheme: Codable {
|
||||
case chatList
|
||||
case chat
|
||||
case actionSheet
|
||||
case contextMenu
|
||||
case notification
|
||||
}
|
||||
|
||||
@ -1440,6 +1483,7 @@ extension PresentationTheme: Codable {
|
||||
chatList: try values.decode(PresentationThemeChatList.self, forKey: .chatList),
|
||||
chat: try values.decode(PresentationThemeChat.self, forKey: .chat),
|
||||
actionSheet: try values.decode(PresentationThemeActionSheet.self, forKey: .actionSheet),
|
||||
contextMenu: try values.decode(PresentationThemeContextMenu.self, forKey: .contextMenu),
|
||||
inAppNotification: try values.decode(PresentationThemeInAppNotification.self, forKey: .notification)
|
||||
)
|
||||
}
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Add.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Add.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_add.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Add.imageset/ic_lt_add.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Add.imageset/ic_lt_add.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Archive.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Archive.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_archive.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Archive.imageset/ic_lt_archive.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Archive.imageset/ic_lt_archive.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Browser.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Browser.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_browser.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Browser.imageset/ic_lt_browser.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Browser.imageset/ic_lt_browser.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Call.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Call.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_call.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Call.imageset/ic_lt_call.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Call.imageset/ic_lt_call.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Clear.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Clear.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_clear.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Clear.imageset/ic_lt_clear.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Clear.imageset/ic_lt_clear.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Copy.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Copy.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_copy.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Copy.imageset/ic_lt_copy.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Copy.imageset/ic_lt_copy.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/DarkMode.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/DarkMode.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_darkmode.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/DarkMode.imageset/ic_lt_darkmode.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/DarkMode.imageset/ic_lt_darkmode.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Delete.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Delete.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_delete.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Delete.imageset/ic_lt_delete.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Delete.imageset/ic_lt_delete.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Edit.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Edit.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_edit.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Edit.imageset/ic_lt_edit.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Edit.imageset/ic_lt_edit.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Forward.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Forward.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_forward.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Forward.imageset/ic_lt_forward.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Forward.imageset/ic_lt_forward.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/HideArchive.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/HideArchive.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_hidechat.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/HideArchive.imageset/ic_lt_hidechat.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/HideArchive.imageset/ic_lt_hidechat.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Info.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Info.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_info.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Info.imageset/ic_lt_info.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Info.imageset/ic_lt_info.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Link.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Link.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_link.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Link.imageset/ic_lt_link.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Link.imageset/ic_lt_link.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Logout.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Logout.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_logout.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Logout.imageset/ic_lt_logout.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Logout.imageset/ic_lt_logout.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsRead.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsRead.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_markasread.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsRead.imageset/ic_lt_markasread.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsRead.imageset/ic_lt_markasread.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsUnread.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsUnread.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_markasunread.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsUnread.imageset/ic_lt_markasunread.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/MarkAsUnread.imageset/ic_lt_markasunread.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Message.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Message.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_message.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Message.imageset/ic_lt_message.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Message.imageset/ic_lt_message.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/More.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/More.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_more.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/More.imageset/ic_lt_more.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/More.imageset/ic_lt_more.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Muted.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Muted.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_muted.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Muted.imageset/ic_lt_muted.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Muted.imageset/ic_lt_muted.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/NightMode.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/NightMode.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_daymode.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/NightMode.imageset/ic_lt_daymode.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/NightMode.imageset/ic_lt_daymode.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Pin.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Pin.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_pin.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Pin.imageset/ic_lt_pin.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Pin.imageset/ic_lt_pin.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Promote.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Promote.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_promote.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Promote.imageset/ic_lt_promote.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Promote.imageset/ic_lt_promote.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Rate.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Rate.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_rate.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Rate.imageset/ic_lt_rate.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Rate.imageset/ic_lt_rate.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Reply.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Reply.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_reply.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Reply.imageset/ic_lt_reply.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Reply.imageset/ic_lt_reply.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Report.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Report.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_report.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Report.imageset/ic_lt_report.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Report.imageset/ic_lt_report.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Resend.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Resend.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_resend.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Resend.imageset/ic_lt_resend.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Resend.imageset/ic_lt_resend.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Restrict.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Restrict.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_restrict.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Restrict.imageset/ic_lt_restrict.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Restrict.imageset/ic_lt_restrict.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Save.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Save.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_save.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Save.imageset/ic_lt_save.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Save.imageset/ic_lt_save.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Schedule.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Schedule.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_schedule.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Schedule.imageset/ic_lt_schedule.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Schedule.imageset/ic_lt_schedule.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Share.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Share.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_share.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Share.imageset/ic_lt_share.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Share.imageset/ic_lt_share.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/StopPoll.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/StopPoll.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_stoppoll.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/StopPoll.imageset/ic_lt_stoppoll.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/StopPoll.imageset/ic_lt_stoppoll.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Timer.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Timer.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_timer.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Timer.imageset/ic_lt_timer.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Timer.imageset/ic_lt_timer.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unarchive.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unarchive.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_unarchive.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unarchive.imageset/ic_lt_unarchive.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unarchive.imageset/ic_lt_unarchive.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unmute.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unmute.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_unmuted.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unmute.imageset/ic_lt_unmuted.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unmute.imageset/ic_lt_unmuted.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unpin.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unpin.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_unpin.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unpin.imageset/ic_lt_unpin.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unpin.imageset/ic_lt_unpin.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unvote.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unvote.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_unvote.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unvote.imageset/ic_lt_unvote.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Unvote.imageset/ic_lt_unvote.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/User.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/User.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_lt_user.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/User.imageset/ic_lt_user.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/User.imageset/ic_lt_user.pdf
vendored
Normal file
Binary file not shown.
@ -154,6 +154,7 @@ final class SharedApplicationContext {
|
||||
@objc var window: UIWindow?
|
||||
var nativeWindow: (UIWindow & WindowHost)?
|
||||
var mainWindow: Window1!
|
||||
var aboveStatusbarWindow: UIWindow?
|
||||
private var dataImportSplash: LegacyDataImportSplash?
|
||||
|
||||
let episodeId = arc4random()
|
||||
@ -227,8 +228,9 @@ final class SharedApplicationContext {
|
||||
let launchStartTime = CFAbsoluteTimeGetCurrent()
|
||||
|
||||
let statusBarHost = ApplicationStatusBarHost()
|
||||
let (window, hostView) = nativeWindowHostView()
|
||||
let (window, hostView, aboveStatusbarWindow) = nativeWindowHostView()
|
||||
self.mainWindow = Window1(hostView: hostView, statusBarHost: statusBarHost)
|
||||
self.aboveStatusbarWindow = aboveStatusbarWindow
|
||||
window.backgroundColor = UIColor.white
|
||||
self.window = window
|
||||
self.nativeWindow = window
|
||||
@ -434,6 +436,7 @@ final class SharedApplicationContext {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
self.aboveStatusbarWindow?.isHidden = false
|
||||
self.window?.makeKeyAndVisible()
|
||||
|
||||
self.hasActiveAudioSession.set(MediaManagerImpl.globalAudioSession.isActive())
|
||||
|
@ -484,7 +484,7 @@ public final class ChatController: TelegramBaseController, GalleryHiddenMediaTar
|
||||
self?.openPeer(peerId: id, navigation: navigation, fromMessage: fromMessage)
|
||||
}, openPeerMention: { [weak self] name in
|
||||
self?.openPeerMention(name)
|
||||
}, openMessageContextMenu: { [weak self] message, selectAll, node, frame in
|
||||
}, openMessageContextMenu: { [weak self] message, selectAll, node, frame, recognizer in
|
||||
guard let strongSelf = self, strongSelf.isNodeLoaded else {
|
||||
return
|
||||
}
|
||||
@ -502,7 +502,33 @@ public final class ChatController: TelegramBaseController, GalleryHiddenMediaTar
|
||||
guard let strongSelf = self, !actions.isEmpty else {
|
||||
return
|
||||
}
|
||||
strongSelf.window?.presentInGlobalOverlay(ContextController(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextControllerContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions))
|
||||
var actions = actions
|
||||
actions.insert(.action(ContextMenuActionItem(text: "Reaction", icon: { _ in nil }, action: { _, f in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let actionSheet = ActionSheetController(presentationTheme: strongSelf.presentationData.theme)
|
||||
var items: [ActionSheetItem] = []
|
||||
let emojis = ["👍", "😊", "🤔", "😔", "❤️"]
|
||||
for emoji in emojis {
|
||||
items.append(ActionSheetButtonItem(title: "\(emoji)", color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
let _ = updateMessageReactionsInteractively(postbox: strongSelf.context.account.postbox, messageId: updatedMessages[0].id, reactions: [emoji]).start()
|
||||
}))
|
||||
}
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
})
|
||||
])])
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
f(.dismissWithoutContent)
|
||||
})), at: 0)
|
||||
strongSelf.window?.presentInGlobalOverlay(ContextController(theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, source: ChatMessageContextControllerContentSource(chatNode: strongSelf.chatDisplayNode, message: message), items: actions, recognizer: recognizer))
|
||||
})
|
||||
}
|
||||
}, navigateToMessage: { [weak self] fromId, id in
|
||||
@ -2620,12 +2646,9 @@ public final class ChatController: TelegramBaseController, GalleryHiddenMediaTar
|
||||
self?.present(c, in: .window(.root), with: a)
|
||||
}, completion: { _ in }), in: .window(.root))
|
||||
}
|
||||
}, reportMessages: { [weak self] messages in
|
||||
}, reportMessages: { [weak self] messages, contextController in
|
||||
if let strongSelf = self, !messages.isEmpty {
|
||||
strongSelf.chatDisplayNode.dismissInput()
|
||||
strongSelf.present(peerReportOptionsController(context: strongSelf.context, subject: .messages(messages.map({ $0.id }).sorted()), present: { c, a in
|
||||
self?.present(c, in: .window(.root), with: a)
|
||||
}, completion: { _ in }), in: .window(.root))
|
||||
presentPeerReportOptions(context: strongSelf.context, parent: strongSelf, contextController: contextController, subject: .messages(messages.map({ $0.id }).sorted()), completion: { _ in })
|
||||
}
|
||||
}, deleteMessages: { [weak self] messages, contextController, completion in
|
||||
if let strongSelf = self, !messages.isEmpty {
|
||||
|
@ -48,7 +48,7 @@ public final class ChatControllerInteraction {
|
||||
let openMessage: (Message, ChatControllerInteractionOpenMessageMode) -> Bool
|
||||
let openPeer: (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void
|
||||
let openPeerMention: (String) -> Void
|
||||
let openMessageContextMenu: (Message, Bool, ASDisplayNode, CGRect) -> Void
|
||||
let openMessageContextMenu: (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void
|
||||
let navigateToMessage: (MessageId, MessageId) -> Void
|
||||
let clickThroughMessage: () -> Void
|
||||
let toggleMessagesSelection: ([MessageId], Bool) -> Void
|
||||
@ -100,7 +100,7 @@ public final class ChatControllerInteraction {
|
||||
var searchTextHighightState: String?
|
||||
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
||||
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
self.openMessage = openMessage
|
||||
self.openPeer = openPeer
|
||||
self.openPeerMention = openPeerMention
|
||||
@ -154,7 +154,7 @@ public final class ChatControllerInteraction {
|
||||
|
||||
static var `default`: ChatControllerInteraction {
|
||||
return ChatControllerInteraction(openMessage: { _, _ in
|
||||
return false }, openPeer: { _, _, _ in }, openPeerMention: { _ in }, openMessageContextMenu: { _, _, _, _ in }, navigateToMessage: { _, _ in }, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in return false }, sendGif: { _, _, _ in return false }, requestMessageActionCallback: { _, _, _ in }, requestMessageActionUrlAuth: { _, _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in
|
||||
return false }, openPeer: { _, _, _ in }, openPeerMention: { _ in }, openMessageContextMenu: { _, _, _, _, _ in }, navigateToMessage: { _, _ in }, clickThroughMessage: { }, toggleMessagesSelection: { _, _ in }, sendCurrentMessage: { _ in }, sendMessage: { _ in }, sendSticker: { _, _, _, _ in return false }, sendGif: { _, _, _ in return false }, requestMessageActionCallback: { _, _, _ in }, requestMessageActionUrlAuth: { _, _, _ in }, activateSwitchInline: { _, _ in }, openUrl: { _, _, _ in }, shareCurrentLocation: {}, shareAccountContact: {}, sendBotCommand: { _, _ in }, openInstantPage: { _, _ in }, openWallpaper: { _ in }, openHashtag: { _, _ in }, updateInputState: { _ in }, updateInputMode: { _ in }, openMessageShareMenu: { _ in
|
||||
}, presentController: { _, _ in }, navigationController: {
|
||||
return nil
|
||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
||||
|
@ -850,7 +850,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
let visibleAreaInset = UIEdgeInsets(top: containerInsets.top, left: 0.0, bottom: containerInsets.bottom + contentBottomInset, right: 0.0)
|
||||
let visibleAreaInset = UIEdgeInsets(top: containerInsets.top, left: 0.0, bottom: containerInsets.bottom + inputPanelsHeight, right: 0.0)
|
||||
self.visibleAreaInset = visibleAreaInset
|
||||
self.loadingNode.updateLayout(size: contentBounds.size, insets: visibleAreaInset, transition: transition)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user