mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 09:20:08 +00:00
Saved message search
This commit is contained in:
parent
960d968e0f
commit
ca4eb2cb69
@ -912,6 +912,24 @@ public extension Peer {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ChatControllerCustomNavigationPanelNodeLayoutResult {
|
||||
public var backgroundHeight: CGFloat
|
||||
public var insetHeight: CGFloat
|
||||
public var hitTestSlop: CGFloat
|
||||
|
||||
public init(backgroundHeight: CGFloat, insetHeight: CGFloat, hitTestSlop: CGFloat) {
|
||||
self.backgroundHeight = backgroundHeight
|
||||
self.insetHeight = insetHeight
|
||||
self.hitTestSlop = hitTestSlop
|
||||
}
|
||||
}
|
||||
|
||||
public protocol ChatControllerCustomNavigationPanelNode: ASDisplayNode {
|
||||
typealias LayoutResult = ChatControllerCustomNavigationPanelNodeLayoutResult
|
||||
|
||||
func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, chatController: ChatController) -> LayoutResult
|
||||
}
|
||||
|
||||
public protocol ChatController: ViewController {
|
||||
var chatLocation: ChatLocation { get }
|
||||
var canReadHistory: ValuePromise<Bool> { get }
|
||||
@ -919,9 +937,14 @@ public protocol ChatController: ViewController {
|
||||
|
||||
var purposefulAction: (() -> Void)? { get set }
|
||||
|
||||
var stateUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set }
|
||||
|
||||
var selectedMessageIds: Set<EngineMessage.Id>? { get }
|
||||
var presentationInterfaceStateSignal: Signal<Any, NoError> { get }
|
||||
|
||||
var customNavigationBarContentNode: NavigationBarContentNode? { get }
|
||||
var customNavigationPanelNode: ChatControllerCustomNavigationPanelNode? { get }
|
||||
|
||||
func updatePresentationMode(_ mode: ChatControllerPresentationMode)
|
||||
func beginMessageSearch(_ query: String)
|
||||
func displayPromoAnnouncement(text: String)
|
||||
|
||||
@ -994,6 +994,35 @@ public extension ContainedViewLayoutTransition {
|
||||
}
|
||||
}
|
||||
|
||||
func updateTintColor(view: UIView, color: UIColor, completion: ((Bool) -> Void)? = nil) {
|
||||
if let current = view.tintColor, current == color {
|
||||
completion?(true)
|
||||
return
|
||||
}
|
||||
|
||||
switch self {
|
||||
case .immediate:
|
||||
view.tintColor = color
|
||||
completion?(true)
|
||||
case let .animated(duration, curve):
|
||||
let previousColor: CGColor = view.layer.layerTintColor ?? UIColor.clear.cgColor
|
||||
view.tintColor = color
|
||||
|
||||
view.layer.animate(
|
||||
from: previousColor,
|
||||
to: color.cgColor,
|
||||
keyPath: "contentsMultiplyColor",
|
||||
timingFunction: curve.timingFunction,
|
||||
duration: duration,
|
||||
delay: 0.0,
|
||||
mediaTimingFunction: curve.mediaTimingFunction,
|
||||
removeOnCompletion: true,
|
||||
additive: false,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func updateContentsRect(layer: CALayer, contentsRect: CGRect, completion: ((Bool) -> Void)? = nil) {
|
||||
if layer.contentsRect == contentsRect {
|
||||
if let completion = completion {
|
||||
|
||||
@ -493,6 +493,8 @@ open class NavigationBar: ASDisplayNode {
|
||||
public var makeCustomTransitionNode: ((NavigationBar, Bool) -> CustomNavigationTransitionNode?)?
|
||||
public var allowsCustomTransition: (() -> Bool)?
|
||||
|
||||
public var customSetContentNode: ((NavigationBarContentNode?, Bool) -> Void)?
|
||||
|
||||
private var collapsed: Bool {
|
||||
get {
|
||||
return self.frame.size.height.isLess(than: 44.0)
|
||||
@ -1649,6 +1651,11 @@ open class NavigationBar: ASDisplayNode {
|
||||
}
|
||||
|
||||
public func setContentNode(_ contentNode: NavigationBarContentNode?, animated: Bool) {
|
||||
if let customSetContentNode = self.customSetContentNode {
|
||||
customSetContentNode(contentNode, animated)
|
||||
return
|
||||
}
|
||||
|
||||
if self.contentNode !== contentNode {
|
||||
if let previous = self.contentNode {
|
||||
if animated {
|
||||
|
||||
@ -110,7 +110,7 @@ private extension MessageHistoryInput {
|
||||
assert(Set(items.map({ $0.stableId })).count == items.count)
|
||||
|
||||
if items.count > limit {
|
||||
let overLimit = limit - items.count
|
||||
let overLimit = items.count - limit
|
||||
switch direction {
|
||||
case .lowToHigh:
|
||||
items.removeFirst(overLimit)
|
||||
|
||||
@ -21,6 +21,7 @@ public enum PresentationResourceKey: Int32 {
|
||||
case navigationSearchIcon
|
||||
case navigationCompactSearchIcon
|
||||
case navigationCompactTagsSearchIcon
|
||||
case navigationCompactTagsSearchWhiteIcon
|
||||
case navigationCalendarIcon
|
||||
case navigationMoreIcon
|
||||
case navigationMoreCircledIcon
|
||||
|
||||
@ -80,6 +80,12 @@ public struct PresentationResourcesRootController {
|
||||
})
|
||||
}
|
||||
|
||||
public static func navigationCompactTagsSearchWhiteIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.navigationCompactTagsSearchIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/NavigationSearchTagsIcon"), color: .white)
|
||||
})
|
||||
}
|
||||
|
||||
public static func navigationCalendarIcon(_ theme: PresentationTheme) -> UIImage? {
|
||||
return theme.image(PresentationResourceKey.navigationCalendarIcon.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Search/Calendar"), color: theme.rootController.navigationBar.accentTextColor)
|
||||
|
||||
@ -427,15 +427,15 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
|
||||
if let tagButton {
|
||||
buttons = [
|
||||
self.deleteButton,
|
||||
self.forwardButton,
|
||||
tagButton,
|
||||
self.forwardButton,
|
||||
self.shareButton
|
||||
]
|
||||
} else {
|
||||
buttons = [
|
||||
self.deleteButton,
|
||||
self.forwardButton,
|
||||
self.shareButton
|
||||
self.shareButton,
|
||||
self.forwardButton
|
||||
]
|
||||
}
|
||||
} else if !self.deleteButton.isHidden {
|
||||
@ -459,17 +459,17 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
|
||||
if let tagButton {
|
||||
buttons = [
|
||||
self.deleteButton,
|
||||
self.forwardButton,
|
||||
self.reportButton,
|
||||
tagButton,
|
||||
self.shareButton
|
||||
self.shareButton,
|
||||
self.forwardButton
|
||||
]
|
||||
} else {
|
||||
buttons = [
|
||||
self.deleteButton,
|
||||
self.forwardButton,
|
||||
self.reportButton,
|
||||
self.shareButton
|
||||
self.shareButton,
|
||||
self.forwardButton
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,83 @@ import TelegramUIPreferences
|
||||
import AppBundle
|
||||
import PeerInfoPaneNode
|
||||
|
||||
private final class SearchNavigationContentNode: ASDisplayNode, PeerInfoPanelNodeNavigationContentNode {
|
||||
private struct Params: Equatable {
|
||||
var width: CGFloat
|
||||
var defaultHeight: CGFloat
|
||||
var insets: UIEdgeInsets
|
||||
|
||||
init(width: CGFloat, defaultHeight: CGFloat, insets: UIEdgeInsets) {
|
||||
self.width = width
|
||||
self.defaultHeight = defaultHeight
|
||||
self.insets = insets
|
||||
}
|
||||
}
|
||||
|
||||
weak var chatController: ChatController?
|
||||
let contentNode: NavigationBarContentNode
|
||||
|
||||
var panelNode: ChatControllerCustomNavigationPanelNode?
|
||||
private var appliedPanelNode: ChatControllerCustomNavigationPanelNode?
|
||||
|
||||
private var params: Params?
|
||||
|
||||
init(chatController: ChatController, contentNode: NavigationBarContentNode) {
|
||||
self.chatController = chatController
|
||||
self.contentNode = contentNode
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.contentNode)
|
||||
}
|
||||
|
||||
func update(transition: ContainedViewLayoutTransition) {
|
||||
if let params = self.params {
|
||||
let _ = self.update(width: params.width, defaultHeight: params.defaultHeight, insets: params.insets, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
func update(width: CGFloat, defaultHeight: CGFloat, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
self.params = Params(width: width, defaultHeight: defaultHeight, insets: insets)
|
||||
|
||||
let size = CGSize(width: width, height: defaultHeight)
|
||||
transition.updateFrame(node: self.contentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 10.0), size: size))
|
||||
self.contentNode.updateLayout(size: size, leftInset: insets.left, rightInset: insets.right, transition: transition)
|
||||
|
||||
var contentHeight: CGFloat = size.height + 10.0
|
||||
|
||||
if self.appliedPanelNode !== self.panelNode {
|
||||
if let previous = self.appliedPanelNode {
|
||||
transition.updateAlpha(node: previous, alpha: 0.0, completion: { [weak previous] _ in
|
||||
previous?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
|
||||
self.appliedPanelNode = self.panelNode
|
||||
if let panelNode = self.panelNode, let chatController = self.chatController {
|
||||
self.addSubnode(panelNode)
|
||||
let panelLayout = panelNode.updateLayout(width: width, leftInset: insets.left, rightInset: insets.right, transition: .immediate, chatController: chatController)
|
||||
let panelHeight = panelLayout.backgroundHeight
|
||||
let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: panelHeight))
|
||||
panelNode.frame = panelFrame
|
||||
panelNode.alpha = 0.0
|
||||
transition.updateAlpha(node: panelNode, alpha: 1.0)
|
||||
|
||||
contentHeight += panelHeight - 1.0
|
||||
}
|
||||
} else if let panelNode = self.panelNode, let chatController = self.chatController {
|
||||
let panelLayout = panelNode.updateLayout(width: width, leftInset: insets.left, rightInset: insets.right, transition: transition, chatController: chatController)
|
||||
let panelHeight = panelLayout.backgroundHeight
|
||||
let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: panelHeight))
|
||||
transition.updateFrame(node: panelNode, frame: panelFrame)
|
||||
|
||||
contentHeight += panelHeight - 1.0
|
||||
}
|
||||
|
||||
return contentHeight
|
||||
}
|
||||
}
|
||||
|
||||
public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate {
|
||||
private let context: AccountContext
|
||||
private let peerId: EnginePeer.Id
|
||||
@ -52,6 +129,12 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
return 0.0
|
||||
}
|
||||
|
||||
private var searchNavigationContentNode: SearchNavigationContentNode?
|
||||
public var navigationContentNode: PeerInfoPanelNodeNavigationContentNode? {
|
||||
return self.searchNavigationContentNode
|
||||
}
|
||||
public var externalDataUpdated: ((ContainedViewLayoutTransition) -> Void)?
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
@ -77,6 +160,29 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
|
||||
self.addSubnode(self.chatController.displayNode)
|
||||
self.chatController.displayNode.clipsToBounds = true
|
||||
|
||||
self.chatController.stateUpdated = { [weak self] transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let contentNode = self.chatController.customNavigationBarContentNode {
|
||||
if self.searchNavigationContentNode?.contentNode !== contentNode {
|
||||
self.searchNavigationContentNode = SearchNavigationContentNode(chatController: self.chatController, contentNode: contentNode)
|
||||
self.searchNavigationContentNode?.panelNode = self.chatController.customNavigationPanelNode
|
||||
self.externalDataUpdated?(transition)
|
||||
} else if self.searchNavigationContentNode?.panelNode !== self.chatController.customNavigationPanelNode {
|
||||
self.searchNavigationContentNode?.panelNode = self.chatController.customNavigationPanelNode
|
||||
self.externalDataUpdated?(transition)
|
||||
} else {
|
||||
self.searchNavigationContentNode?.update(transition: transition)
|
||||
}
|
||||
} else {
|
||||
if self.searchNavigationContentNode !== nil {
|
||||
self.searchNavigationContentNode = nil
|
||||
self.externalDataUpdated?(transition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -124,6 +230,9 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
super.didLoad()
|
||||
}
|
||||
|
||||
public func activateSearch() {
|
||||
self.chatController.activateSearch(domain: .everything, query: "")
|
||||
}
|
||||
|
||||
override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
return true
|
||||
|
||||
@ -39,6 +39,10 @@ public struct PeerInfoStatusData: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public protocol PeerInfoPanelNodeNavigationContentNode: ASDisplayNode {
|
||||
func update(width: CGFloat, defaultHeight: CGFloat, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) -> CGFloat
|
||||
}
|
||||
|
||||
public protocol PeerInfoPaneNode: ASDisplayNode {
|
||||
var isReady: Signal<Bool, NoError> { get }
|
||||
|
||||
@ -48,6 +52,9 @@ public protocol PeerInfoPaneNode: ASDisplayNode {
|
||||
var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set }
|
||||
var tabBarOffset: CGFloat { get }
|
||||
|
||||
var navigationContentNode: PeerInfoPanelNodeNavigationContentNode? { get }
|
||||
var externalDataUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set }
|
||||
|
||||
func update(size: CGSize, topInset: CGFloat, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, isScrollingLockedAtTop: Bool, expandProgress: CGFloat, presentationData: PresentationData, synchronous: Bool, transition: ContainedViewLayoutTransition)
|
||||
func scrollToTop() -> Bool
|
||||
func transferVelocity(_ velocity: CGFloat)
|
||||
@ -59,3 +66,15 @@ public protocol PeerInfoPaneNode: ASDisplayNode {
|
||||
func updateSelectedMessages(animated: Bool)
|
||||
func ensureMessageIsVisible(id: MessageId)
|
||||
}
|
||||
|
||||
public extension PeerInfoPaneNode {
|
||||
var navigationContentNode: PeerInfoPanelNodeNavigationContentNode? {
|
||||
return nil
|
||||
}
|
||||
var externalDataUpdated: ((ContainedViewLayoutTransition) -> Void)? {
|
||||
get {
|
||||
return nil
|
||||
} set(value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,6 +207,7 @@ final class PeerInfoScreenData {
|
||||
let appConfiguration: AppConfiguration?
|
||||
let isPowerSavingEnabled: Bool?
|
||||
let accountIsPremium: Bool
|
||||
let hasSavedMessageTags: Bool
|
||||
|
||||
let _isContact: Bool
|
||||
var forceIsContact: Bool = false
|
||||
@ -242,7 +243,8 @@ final class PeerInfoScreenData {
|
||||
threadData: MessageHistoryThreadData?,
|
||||
appConfiguration: AppConfiguration?,
|
||||
isPowerSavingEnabled: Bool?,
|
||||
accountIsPremium: Bool
|
||||
accountIsPremium: Bool,
|
||||
hasSavedMessageTags: Bool
|
||||
) {
|
||||
self.peer = peer
|
||||
self.chatPeer = chatPeer
|
||||
@ -267,6 +269,7 @@ final class PeerInfoScreenData {
|
||||
self.appConfiguration = appConfiguration
|
||||
self.isPowerSavingEnabled = isPowerSavingEnabled
|
||||
self.accountIsPremium = accountIsPremium
|
||||
self.hasSavedMessageTags = hasSavedMessageTags
|
||||
}
|
||||
}
|
||||
|
||||
@ -662,7 +665,8 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
|
||||
threadData: nil,
|
||||
appConfiguration: appConfiguration,
|
||||
isPowerSavingEnabled: isPowerSavingEnabled,
|
||||
accountIsPremium: peer?.isPremium ?? false
|
||||
accountIsPremium: peer?.isPremium ?? false,
|
||||
hasSavedMessageTags: false
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -697,7 +701,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
threadData: nil,
|
||||
appConfiguration: nil,
|
||||
isPowerSavingEnabled: nil,
|
||||
accountIsPremium: false
|
||||
accountIsPremium: false,
|
||||
hasSavedMessageTags: false
|
||||
))
|
||||
case let .user(userPeerId, secretChatId, kind):
|
||||
let groupsInCommon: GroupsInCommonContext?
|
||||
@ -853,6 +858,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
hasSavedMessagesChats = .single(false)
|
||||
}
|
||||
|
||||
let hasSavedMessageTags: Signal<Bool, NoError>
|
||||
if let peerId = chatLocation.peerId {
|
||||
hasSavedMessageTags = context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId, threadId: peerId.toInt64())
|
||||
)
|
||||
|> map { tags -> Bool in
|
||||
return !tags.isEmpty
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
} else {
|
||||
hasSavedMessageTags = .single(false)
|
||||
}
|
||||
|
||||
return combineLatest(
|
||||
context.account.viewTracker.peerView(peerId, updateData: true),
|
||||
peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder),
|
||||
@ -863,9 +881,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
accountIsPremium,
|
||||
savedMessagesPeer,
|
||||
hasSavedMessagesChats,
|
||||
hasSavedMessages
|
||||
hasSavedMessages,
|
||||
hasSavedMessageTags
|
||||
)
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages -> PeerInfoScreenData in
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags -> PeerInfoScreenData in
|
||||
var availablePanes = availablePanes
|
||||
|
||||
if let hasStories {
|
||||
@ -924,7 +943,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
threadData: nil,
|
||||
appConfiguration: nil,
|
||||
isPowerSavingEnabled: nil,
|
||||
accountIsPremium: accountIsPremium
|
||||
accountIsPremium: accountIsPremium,
|
||||
hasSavedMessageTags: hasSavedMessageTags
|
||||
)
|
||||
}
|
||||
case .channel:
|
||||
@ -985,6 +1005,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
hasSavedMessagesChats = .single(false)
|
||||
}
|
||||
|
||||
let hasSavedMessageTags: Signal<Bool, NoError>
|
||||
if let peerId = chatLocation.peerId {
|
||||
hasSavedMessageTags = context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId, threadId: peerId.toInt64())
|
||||
)
|
||||
|> map { tags -> Bool in
|
||||
return !tags.isEmpty
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
} else {
|
||||
hasSavedMessageTags = .single(false)
|
||||
}
|
||||
|
||||
return combineLatest(
|
||||
context.account.viewTracker.peerView(peerId, updateData: true),
|
||||
peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder),
|
||||
@ -998,9 +1031,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
accountIsPremium,
|
||||
context.engine.peers.recommendedChannels(peerId: peerId),
|
||||
hasSavedMessages,
|
||||
hasSavedMessagesChats
|
||||
hasSavedMessagesChats,
|
||||
hasSavedMessageTags
|
||||
)
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, status, currentInvitationsContext, invitations, currentRequestsContext, requests, hasStories, accountIsPremium, recommendedChannels, hasSavedMessages, hasSavedMessagesChats -> PeerInfoScreenData in
|
||||
|> map { peerView, availablePanes, globalNotificationSettings, status, currentInvitationsContext, invitations, currentRequestsContext, requests, hasStories, accountIsPremium, recommendedChannels, hasSavedMessages, hasSavedMessagesChats, hasSavedMessageTags -> PeerInfoScreenData in
|
||||
var availablePanes = availablePanes
|
||||
if let hasStories {
|
||||
if hasStories {
|
||||
@ -1072,7 +1106,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
threadData: nil,
|
||||
appConfiguration: nil,
|
||||
isPowerSavingEnabled: nil,
|
||||
accountIsPremium: accountIsPremium
|
||||
accountIsPremium: accountIsPremium,
|
||||
hasSavedMessageTags: hasSavedMessageTags
|
||||
)
|
||||
}
|
||||
case let .group(groupId):
|
||||
@ -1219,6 +1254,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
hasSavedMessagesChats = .single(false)
|
||||
}
|
||||
|
||||
let hasSavedMessageTags: Signal<Bool, NoError>
|
||||
if let peerId = chatLocation.peerId {
|
||||
hasSavedMessageTags = context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Messages.SavedMessageTagStats(peerId: context.account.peerId, threadId: peerId.toInt64())
|
||||
)
|
||||
|> map { tags -> Bool in
|
||||
return !tags.isEmpty
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
} else {
|
||||
hasSavedMessageTags = .single(false)
|
||||
}
|
||||
|
||||
return combineLatest(queue: .mainQueue(),
|
||||
context.account.viewTracker.peerView(groupId, updateData: true),
|
||||
peerInfoAvailableMediaPanes(context: context, peerId: groupId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder),
|
||||
@ -1233,9 +1281,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration]),
|
||||
accountIsPremium,
|
||||
hasSavedMessages,
|
||||
hasSavedMessagesChats
|
||||
hasSavedMessagesChats,
|
||||
hasSavedMessageTags
|
||||
)
|
||||
|> mapToSignal { peerView, availablePanes, globalNotificationSettings, status, membersData, currentInvitationsContext, invitations, currentRequestsContext, requests, threadData, preferencesView, accountIsPremium, hasSavedMessages, hasSavedMessagesChats -> Signal<PeerInfoScreenData, NoError> in
|
||||
|> mapToSignal { peerView, availablePanes, globalNotificationSettings, status, membersData, currentInvitationsContext, invitations, currentRequestsContext, requests, threadData, preferencesView, accountIsPremium, hasSavedMessages, hasSavedMessagesChats, hasSavedMessageTags -> Signal<PeerInfoScreenData, NoError> in
|
||||
var discussionPeer: Peer?
|
||||
if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] {
|
||||
discussionPeer = peer
|
||||
@ -1320,7 +1369,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
||||
threadData: threadData,
|
||||
appConfiguration: appConfiguration,
|
||||
isPowerSavingEnabled: nil,
|
||||
accountIsPremium: accountIsPremium
|
||||
accountIsPremium: accountIsPremium,
|
||||
hasSavedMessageTags: hasSavedMessageTags
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,7 +178,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
self.backgroundNode.updateColor(color: backgroundColor, transition: transition)
|
||||
|
||||
transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor)
|
||||
transition.updateTintColor(layer: self.iconNode.layer, color: self.contentsColor)
|
||||
transition.updateTintColor(view: self.iconNode.view, color: self.contentsColor)
|
||||
transition.updateStrokeColor(layer: self.backIconLayer, strokeColor: self.contentsColor)
|
||||
|
||||
switch self.key {
|
||||
@ -247,9 +247,13 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
case .search:
|
||||
text = ""
|
||||
accessibilityText = presentationData.strings.Common_Search
|
||||
icon = nil// PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme)
|
||||
icon = nil
|
||||
isAnimation = true
|
||||
animationState = .search
|
||||
case .searchWithTags:
|
||||
text = ""
|
||||
accessibilityText = presentationData.strings.Common_Search
|
||||
icon = PresentationResourcesRootController.navigationCompactTagsSearchWhiteIcon(presentationData.theme)
|
||||
case .editPhoto:
|
||||
text = presentationData.strings.Settings_EditPhoto
|
||||
accessibilityText = text
|
||||
|
||||
@ -13,6 +13,7 @@ enum PeerInfoHeaderNavigationButtonKey {
|
||||
case select
|
||||
case selectionDone
|
||||
case search
|
||||
case searchWithTags
|
||||
case editPhoto
|
||||
case editVideo
|
||||
case more
|
||||
@ -210,7 +211,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
||||
if wasAdded {
|
||||
buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: self.canBeExpanded, transition: .immediate)
|
||||
|
||||
if key == .moreToSearch {
|
||||
if key == .moreToSearch || key == .searchWithTags {
|
||||
buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
@ -236,7 +237,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
|
||||
}
|
||||
for key in removeKeys {
|
||||
if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) {
|
||||
if key == .moreToSearch {
|
||||
if key == .moreToSearch || key == .searchWithTags {
|
||||
buttonNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonNode] _ in
|
||||
buttonNode?.removeFromSupernode()
|
||||
})
|
||||
|
||||
@ -169,6 +169,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
var emojiStatusPackDisposable = MetaDisposable()
|
||||
var emojiStatusFileAndPackTitle = Promise<(TelegramMediaFile, LoadedStickerPack)?>()
|
||||
|
||||
var customNavigationContentNode: PeerInfoPanelNodeNavigationContentNode?
|
||||
private var appliedCustomNavigationContentNode: PeerInfoPanelNodeNavigationContentNode?
|
||||
|
||||
private var validLayout: (width: CGFloat, deviceMetrics: DeviceMetrics)?
|
||||
|
||||
init(context: AccountContext, controller: PeerInfoScreenImpl, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool, forumTopicThreadId: Int64?, chatLocation: ChatLocation) {
|
||||
@ -451,6 +454,24 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
|
||||
private var currentPanelStatusData: PeerInfoStatusData?
|
||||
func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, paneContainerY: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, threadData: MessageHistoryThreadData?, peerNotificationSettings: TelegramPeerNotificationSettings?, threadNotificationSettings: TelegramPeerNotificationSettings?, globalNotificationSettings: EngineGlobalNotificationSettings?, statusData: PeerInfoStatusData?, panelStatusData: (PeerInfoStatusData?, PeerInfoStatusData?, CGFloat?), isSecretChat: Bool, isContact: Bool, isSettings: Bool, state: PeerInfoState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition, additive: Bool, animateHeader: Bool) -> CGFloat {
|
||||
if self.appliedCustomNavigationContentNode !== self.customNavigationContentNode {
|
||||
if let previous = self.appliedCustomNavigationContentNode {
|
||||
transition.updateAlpha(node: previous, alpha: 0.0, completion: { [weak previous] _ in
|
||||
previous?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
|
||||
self.appliedCustomNavigationContentNode = self.customNavigationContentNode
|
||||
if let customNavigationContentNode = self.customNavigationContentNode {
|
||||
self.addSubnode(customNavigationContentNode)
|
||||
customNavigationContentNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: navigationHeight))
|
||||
customNavigationContentNode.alpha = 0.0
|
||||
transition.updateAlpha(node: customNavigationContentNode, alpha: 1.0)
|
||||
}
|
||||
} else if let customNavigationContentNode = self.customNavigationContentNode {
|
||||
transition.updateFrame(node: customNavigationContentNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: navigationHeight)))
|
||||
}
|
||||
|
||||
var threadData = threadData
|
||||
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId {
|
||||
threadData = nil
|
||||
@ -516,7 +537,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
isForum = true
|
||||
}
|
||||
|
||||
self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0
|
||||
transition.updateAlpha(node: self.regularContentNode, alpha: (state.isEditing || self.customNavigationContentNode != nil) ? 0.0 : 1.0)
|
||||
transition.updateAlpha(node: self.navigationButtonContainer, alpha: self.customNavigationContentNode != nil ? 0.0 : 1.0)
|
||||
|
||||
self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0
|
||||
|
||||
let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, isModalOverlay: isModalOverlay, peer: state.isEditing ? peer : nil, threadData: threadData, chatLocation: self.chatLocation, cachedData: cachedData, isContact: isContact, isSettings: isSettings, presentationData: presentationData, transition: transition)
|
||||
@ -1362,6 +1385,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
if self.navigationTransition == nil && !self.isSettings && effectiveSeparatorAlpha == 1.0 && secondarySeparatorAlpha < 1.0 {
|
||||
effectiveSeparatorAlpha = secondarySeparatorAlpha
|
||||
}
|
||||
if self.customNavigationContentNode != nil {
|
||||
effectiveSeparatorAlpha = 0.0
|
||||
}
|
||||
transition.updateAlpha(node: self.separatorNode, alpha: effectiveSeparatorAlpha)
|
||||
|
||||
self.titleNode.update(stateFractions: [
|
||||
@ -1984,6 +2010,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.regularContentNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: resolvedHeight)))
|
||||
|
||||
transition.updateFrameAdditive(node: self.buttonsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: apparentBackgroundHeight - backgroundHeight), size: CGSize(width: width, height: 1000.0)))
|
||||
|
||||
navigationTransition.updateAlpha(node: self.buttonsContainerNode, alpha: backgroundBannerAlpha)
|
||||
@ -2078,6 +2105,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
return nil
|
||||
}
|
||||
|
||||
if let customNavigationContentNode = self.customNavigationContentNode {
|
||||
if let result = customNavigationContentNode.view.hitTest(self.view.convert(point, to: customNavigationContentNode.view), with: event) {
|
||||
return result
|
||||
}
|
||||
return self.view
|
||||
}
|
||||
|
||||
let setByFrame = self.avatarListNode.listContainerNode.setByYouNode.view.convert(self.avatarListNode.listContainerNode.setByYouNode.bounds, to: self.view).insetBy(dx: -44.0, dy: 0.0)
|
||||
if self.avatarListNode.listContainerNode.setByYouNode.alpha > 0.0, setByFrame.contains(point) {
|
||||
return self.avatarListNode.listContainerNode.setByYouNode.view
|
||||
|
||||
@ -366,7 +366,8 @@ private final class PeerInfoPendingPane {
|
||||
parentController: ViewController?,
|
||||
openMediaCalendar: @escaping () -> Void,
|
||||
paneDidScroll: @escaping () -> Void,
|
||||
ensureRectVisible: @escaping (UIView, CGRect) -> Void
|
||||
ensureRectVisible: @escaping (UIView, CGRect) -> Void,
|
||||
externalDataUpdated: @escaping (ContainedViewLayoutTransition) -> Void
|
||||
) {
|
||||
let captureProtected = data.peer?.isCopyProtectionEnabled ?? false
|
||||
let paneNode: PeerInfoPaneNode
|
||||
@ -425,6 +426,7 @@ private final class PeerInfoPendingPane {
|
||||
case .savedMessages:
|
||||
paneNode = PeerInfoChatPaneNode(context: context, peerId: peerId, navigationController: chatControllerInteraction.navigationController)
|
||||
}
|
||||
paneNode.externalDataUpdated = externalDataUpdated
|
||||
paneNode.parentController = parentController
|
||||
self.pane = PeerInfoPaneWrapper(key: key, node: paneNode)
|
||||
self.disposable = (paneNode.isReady
|
||||
@ -458,7 +460,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
let isReady = Promise<Bool>()
|
||||
var didSetIsReady = false
|
||||
|
||||
private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?)?
|
||||
private var currentParams: (size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, areTabsHidden: Bool)?
|
||||
|
||||
private(set) var currentPaneKey: PeerInfoPaneKey?
|
||||
var pendingSwitchToPaneKey: PeerInfoPaneKey?
|
||||
@ -495,6 +497,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
|
||||
var currentPaneUpdated: ((Bool) -> Void)?
|
||||
var requestExpandTabs: (() -> Bool)?
|
||||
var requestUpdate: ((ContainedViewLayoutTransition) -> Void)?
|
||||
|
||||
var openMediaCalendar: (() -> Void)?
|
||||
var paneDidScroll: (() -> Void)?
|
||||
@ -550,8 +553,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
if strongSelf.currentPanes[key] != nil {
|
||||
strongSelf.currentPaneKey = key
|
||||
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.4, curve: .spring))
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data, areTabsHidden) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, areTabsHidden: areTabsHidden, transition: .animated(duration: 0.4, curve: .spring))
|
||||
|
||||
strongSelf.currentPaneUpdated?(true)
|
||||
|
||||
@ -563,8 +566,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
strongSelf.pendingSwitchToPaneKey = key
|
||||
strongSelf.expandOnSwitch = true
|
||||
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.4, curve: .spring))
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data, areTabsHidden) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, areTabsHidden: areTabsHidden, transition: .animated(duration: 0.4, curve: .spring))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -586,6 +589,9 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
}
|
||||
return [.leftCenter, .rightCenter]
|
||||
}
|
||||
if strongSelf.currentPane?.node.navigationContentNode != nil {
|
||||
return []
|
||||
}
|
||||
if index == 0 {
|
||||
return .left
|
||||
}
|
||||
@ -629,7 +635,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
|
||||
cancelContextGestures(view: self.view)
|
||||
case .changed:
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data, areTabsHidden) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
let translation = recognizer.translation(in: self.view)
|
||||
var transitionFraction = translation.x / size.width
|
||||
if currentIndex <= 0 {
|
||||
@ -644,11 +650,11 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
// print(transitionFraction)
|
||||
self.paneTransitionPromise.set(transitionFraction)
|
||||
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .immediate)
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, areTabsHidden: areTabsHidden, transition: .immediate)
|
||||
self.currentPaneUpdated?(false)
|
||||
}
|
||||
case .cancelled, .ended:
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data, areTabsHidden) = self.currentParams, let availablePanes = data?.availablePanes, availablePanes.count > 1, let currentPaneKey = self.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey) {
|
||||
let translation = recognizer.translation(in: self.view)
|
||||
let velocity = recognizer.velocity(in: self.view)
|
||||
var directionIsToRight: Bool?
|
||||
@ -672,7 +678,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
}
|
||||
}
|
||||
self.transitionFraction = 0.0
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: .animated(duration: 0.35, curve: .spring))
|
||||
self.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, areTabsHidden: areTabsHidden, transition: .animated(duration: 0.35, curve: .spring))
|
||||
self.currentPaneUpdated?(false)
|
||||
|
||||
self.currentPaneStatusPromise.set(self.currentPane?.node.status ?? .single(nil))
|
||||
@ -711,7 +717,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
}
|
||||
}
|
||||
|
||||
func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, transition: ContainedViewLayoutTransition) {
|
||||
func update(size: CGSize, sideInset: CGFloat, bottomInset: CGFloat, deviceMetrics: DeviceMetrics, visibleHeight: CGFloat, expansionFraction: CGFloat, presentationData: PresentationData, data: PeerInfoScreenData?, areTabsHidden: Bool, transition: ContainedViewLayoutTransition) {
|
||||
let previousAvailablePanes = self.currentAvailablePanes
|
||||
let availablePanes = data?.availablePanes ?? []
|
||||
self.currentAvailablePanes = data?.availablePanes
|
||||
@ -755,7 +761,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
currentIndex = nil
|
||||
}
|
||||
|
||||
self.currentParams = (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data)
|
||||
self.currentParams = (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data, areTabsHidden)
|
||||
|
||||
transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction)
|
||||
|
||||
@ -770,6 +776,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
let isScrollingLockedAtTop = expansionFraction < 1.0 - CGFloat.ulpOfOne
|
||||
|
||||
let tabsHeight: CGFloat = 48.0
|
||||
let effectiveTabsHeight: CGFloat = areTabsHidden ? 0.0 : tabsHeight
|
||||
|
||||
let paneFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height))
|
||||
|
||||
@ -825,12 +832,12 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data, areTabsHidden) = strongSelf.currentParams {
|
||||
var transition: ContainedViewLayoutTransition = .immediate
|
||||
if strongSelf.pendingSwitchToPaneKey == key && strongSelf.currentPaneKey != nil {
|
||||
transition = .animated(duration: 0.4, curve: .spring)
|
||||
}
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: transition)
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, areTabsHidden: areTabsHidden, transition: transition)
|
||||
}
|
||||
}
|
||||
if leftScope {
|
||||
@ -849,18 +856,24 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
return
|
||||
}
|
||||
self.ensurePaneRectVisible?(self.view, sourceView.convert(rect, to: self.view))
|
||||
},
|
||||
externalDataUpdated: { [weak self] transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.requestUpdate?(transition)
|
||||
}
|
||||
)
|
||||
self.pendingPanes[key] = pane
|
||||
pane.pane.node.frame = paneFrame
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: .immediate)
|
||||
pane.pane.update(size: paneFrame.size, topInset: effectiveTabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: .immediate)
|
||||
let paneNode = pane.pane.node
|
||||
pane.pane.node.tabBarOffsetUpdated = { [weak self, weak paneNode] transition in
|
||||
guard let strongSelf = self, let paneNode = paneNode, let currentPane = strongSelf.currentPane, paneNode === currentPane.node else {
|
||||
return
|
||||
}
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, transition: transition)
|
||||
if let (size, sideInset, bottomInset, deviceMetrics, visibleHeight, expansionFraction, presentationData, data, areTabsHidden) = strongSelf.currentParams {
|
||||
strongSelf.update(size: size, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, expansionFraction: expansionFraction, presentationData: presentationData, data: data, areTabsHidden: areTabsHidden, transition: transition)
|
||||
}
|
||||
}
|
||||
leftScope = true
|
||||
@ -869,7 +882,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
|
||||
for (key, pane) in self.pendingPanes {
|
||||
pane.pane.node.frame = paneFrame
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: self.currentPaneKey == nil, transition: .immediate)
|
||||
pane.pane.update(size: paneFrame.size, topInset: effectiveTabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: self.currentPaneKey == nil, transition: .immediate)
|
||||
|
||||
if pane.isReady {
|
||||
self.pendingPanes.removeValue(forKey: key)
|
||||
@ -930,7 +943,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
return
|
||||
}
|
||||
pane.isAnimatingOut = false
|
||||
if let (_, _, _, _, _, _, _, data) = strongSelf.currentParams {
|
||||
if let (_, _, _, _, _, _, _, data, _) = strongSelf.currentParams {
|
||||
if let availablePanes = data?.availablePanes, let currentPaneKey = strongSelf.currentPaneKey, let currentIndex = availablePanes.firstIndex(of: currentPaneKey), let paneIndex = availablePanes.firstIndex(of: key), abs(paneIndex - currentIndex) <= 1 {
|
||||
} else {
|
||||
if let pane = strongSelf.currentPanes.removeValue(forKey: key) {
|
||||
@ -961,7 +974,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
paneCompletion()
|
||||
})
|
||||
}
|
||||
pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition)
|
||||
pane.update(size: paneFrame.size, topInset: effectiveTabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: paneWasAdded, transition: paneTransition)
|
||||
}
|
||||
}
|
||||
|
||||
@ -973,7 +986,14 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
if isScrollingLockedAtTop || self.isMediaOnly {
|
||||
tabsOffset = 0.0
|
||||
}
|
||||
var tabsAlpha = 1.0 - tabsOffset / tabsHeight
|
||||
|
||||
var tabsAlpha: CGFloat
|
||||
if areTabsHidden {
|
||||
tabsAlpha = 0.0
|
||||
tabsOffset = tabsHeight
|
||||
} else {
|
||||
tabsAlpha = 1.0 - tabsOffset / tabsHeight
|
||||
}
|
||||
tabsAlpha *= tabsAlpha
|
||||
transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -tabsOffset), size: CGSize(width: size.width, height: tabsHeight)))
|
||||
transition.updateAlpha(node: self.tabsContainerNode, alpha: tabsAlpha)
|
||||
@ -1019,7 +1039,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
||||
for (_, pane) in self.pendingPanes {
|
||||
let paneTransition: ContainedViewLayoutTransition = .immediate
|
||||
paneTransition.updateFrame(node: pane.pane.node, frame: paneFrame)
|
||||
pane.pane.update(size: paneFrame.size, topInset: tabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: paneTransition)
|
||||
pane.pane.update(size: paneFrame.size, topInset: effectiveTabsHeight, sideInset: sideInset, bottomInset: bottomInset, deviceMetrics: deviceMetrics, visibleHeight: visibleHeight, isScrollingLockedAtTop: isScrollingLockedAtTop, expandProgress: expansionFraction, presentationData: presentationData, synchronous: true, transition: paneTransition)
|
||||
}
|
||||
|
||||
var removeKeys: [PeerInfoPaneKey] = []
|
||||
|
||||
@ -102,6 +102,7 @@ import PeerInfoPaneNode
|
||||
import MediaPickerUI
|
||||
import AttachmentUI
|
||||
import BoostLevelIconComponent
|
||||
import PeerInfoChatPaneNode
|
||||
|
||||
public enum PeerInfoAvatarEditingMode {
|
||||
case generic
|
||||
@ -3145,6 +3146,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
}
|
||||
|
||||
self.paneContainerNode.requestUpdate = { [weak self] transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: transition, additive: false)
|
||||
}
|
||||
}
|
||||
|
||||
self.paneContainerNode.ensurePaneRectVisible = { [weak self] sourceView, rect in
|
||||
guard let self else {
|
||||
return
|
||||
@ -3748,8 +3758,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) }
|
||||
strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true)
|
||||
case .search:
|
||||
strongSelf.headerNode.navigationButtonContainer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
|
||||
case .search, .searchWithTags:
|
||||
strongSelf.activateSearch()
|
||||
case .more:
|
||||
if let source = source {
|
||||
@ -9269,6 +9278,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
return
|
||||
}
|
||||
|
||||
if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .savedMessages = currentPaneKey, let paneNode = self.paneContainerNode.currentPane?.node as? PeerInfoChatPaneNode {
|
||||
paneNode.activateSearch()
|
||||
return
|
||||
}
|
||||
|
||||
self.headerNode.navigationButtonContainer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
|
||||
|
||||
if self.isSettings {
|
||||
(self.controller?.parent as? TabBarController)?.updateIsTabBarHidden(true, transition: .animated(duration: 0.3, curve: .linear))
|
||||
|
||||
@ -9803,9 +9819,31 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
}
|
||||
|
||||
private func updateNavigationHeight(width: CGFloat, defaultHeight: CGFloat, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) -> CGFloat {
|
||||
var navigationHeight = defaultHeight
|
||||
if let customNavigationContentNode = self.headerNode.customNavigationContentNode {
|
||||
var mappedTransition = transition
|
||||
if customNavigationContentNode.supernode == nil {
|
||||
mappedTransition = .immediate
|
||||
}
|
||||
let contentHeight = customNavigationContentNode.update(width: width, defaultHeight: defaultHeight, insets: insets, transition: mappedTransition)
|
||||
navigationHeight = contentHeight
|
||||
}
|
||||
return navigationHeight
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition, additive: Bool = false) {
|
||||
self.validLayout = (layout, navigationHeight)
|
||||
|
||||
self.headerNode.customNavigationContentNode = self.paneContainerNode.currentPane?.node.navigationContentNode
|
||||
|
||||
let isScrollEnabled = !self.isMediaOnly && self.headerNode.customNavigationContentNode == nil
|
||||
if self.scrollNode.view.isScrollEnabled != isScrollEnabled {
|
||||
self.scrollNode.view.isScrollEnabled = isScrollEnabled
|
||||
}
|
||||
|
||||
let navigationHeight = self.updateNavigationHeight(width: layout.size.width, defaultHeight: navigationHeight, insets: UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: 0.0, right: layout.safeInsets.right), transition: transition)
|
||||
|
||||
if self.headerNode.isAvatarExpanded && layout.size.width > layout.size.height {
|
||||
self.headerNode.updateIsAvatarExpanded(false, transition: transition)
|
||||
self.updateNavigationExpansionPresentation(isExpanded: false, animated: true)
|
||||
@ -10188,6 +10226,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
let navigationHeight = self.updateNavigationHeight(width: layout.size.width, defaultHeight: navigationHeight, insets: UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: 0.0, right: layout.safeInsets.right), transition: transition)
|
||||
|
||||
if !additive {
|
||||
let sectionInset: CGFloat
|
||||
if layout.size.width >= 375.0 {
|
||||
@ -10222,7 +10262,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
}
|
||||
|
||||
let navigationBarHeight: CGFloat = !self.isSettings && layout.isModalOverlay ? 56.0 : 44.0
|
||||
self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, deviceMetrics: layout.deviceMetrics, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, transition: transition)
|
||||
self.paneContainerNode.update(size: self.paneContainerNode.bounds.size, sideInset: layout.safeInsets.left, bottomInset: bottomInset, deviceMetrics: layout.deviceMetrics, visibleHeight: visibleHeight, expansionFraction: effectiveAreaExpansionFraction, presentationData: self.presentationData, data: self.data, areTabsHidden: self.headerNode.customNavigationContentNode != nil, transition: transition)
|
||||
|
||||
transition.updateFrame(node: self.headerNode.navigationButtonContainer, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left, y: layout.statusBarHeight ?? 0.0), size: CGSize(width: layout.size.width - layout.safeInsets.left * 2.0, height: navigationBarHeight)))
|
||||
|
||||
@ -10249,6 +10289,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
||||
switch currentPaneKey {
|
||||
case .files, .music, .links, .members, .savedMessagesChats:
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true))
|
||||
case .savedMessages:
|
||||
if let data = self.data, data.hasSavedMessageTags {
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .searchWithTags, isForExpandedView: true))
|
||||
} else {
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true))
|
||||
}
|
||||
case .media:
|
||||
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true))
|
||||
default:
|
||||
|
||||
@ -524,4 +524,14 @@ func updateChatPresentationInterfaceStateImpl(
|
||||
}
|
||||
|
||||
selfController.updateDownButtonVisibility()
|
||||
|
||||
if case .standard(.embedded) = selfController.presentationInterfaceState.mode, let controllerInteraction = selfController.controllerInteraction, let interfaceInteraction = selfController.interfaceInteraction {
|
||||
if let titleAccessoryPanelNode = titlePanelForChatPresentationInterfaceState(selfController.presentationInterfaceState, context: selfController.context, currentPanel: selfController.customNavigationPanelNode as? ChatTitleAccessoryPanelNode, controllerInteraction: controllerInteraction, interfaceInteraction: interfaceInteraction) {
|
||||
selfController.customNavigationPanelNode = titleAccessoryPanelNode as? ChatControllerCustomNavigationPanelNode
|
||||
} else {
|
||||
selfController.customNavigationPanelNode = nil
|
||||
}
|
||||
}
|
||||
|
||||
selfController.stateUpdated?(transition)
|
||||
}
|
||||
|
||||
@ -507,6 +507,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
weak var currentImportMessageTooltip: UndoOverlayController?
|
||||
|
||||
public var customNavigationBarContentNode: NavigationBarContentNode?
|
||||
public var customNavigationPanelNode: ChatControllerCustomNavigationPanelNode?
|
||||
public var stateUpdated: ((ContainedViewLayoutTransition) -> Void)?
|
||||
|
||||
public override var customData: Any? {
|
||||
return self.chatLocation
|
||||
}
|
||||
|
||||
@ -1656,13 +1656,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
transition.updateFrame(node: backgroundEffectNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: contentBounds)
|
||||
let wallpaperBounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width - wrappingInsets.left - wrappingInsets.right, height: layout.size.height)
|
||||
|
||||
transition.updateFrame(node: self.backgroundNode, frame: wallpaperBounds)
|
||||
|
||||
var displayMode: WallpaperDisplayMode = .aspectFill
|
||||
if case .regular = layout.metrics.widthClass, layout.size.height == layout.deviceMetrics.screenSize.width {
|
||||
displayMode = .aspectFit
|
||||
}
|
||||
self.backgroundNode.updateLayout(size: contentBounds.size, displayMode: displayMode, transition: transition)
|
||||
self.backgroundNode.updateLayout(size: wallpaperBounds.size, displayMode: displayMode, transition: transition)
|
||||
|
||||
transition.updateBounds(node: self.historyNodeContainer, bounds: contentBounds)
|
||||
transition.updatePosition(node: self.historyNodeContainer, position: contentBounds.center)
|
||||
@ -1796,6 +1798,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
if self.dismissedAsOverlay {
|
||||
inputBackgroundFrame.origin.y = layout.size.height
|
||||
}
|
||||
if case .standard(.embedded) = self.chatPresentationInterfaceState.mode {
|
||||
if self.inputPanelNode == nil {
|
||||
inputBackgroundFrame.origin.y = layout.size.height
|
||||
}
|
||||
}
|
||||
|
||||
let additionalScrollDistance: CGFloat = 0.0
|
||||
var scrollToTop = false
|
||||
@ -2033,11 +2040,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
inputPanelUpdateTransition = .immediate
|
||||
}
|
||||
|
||||
if case .standard(.embedded) = self.chatPresentationInterfaceState.mode {
|
||||
self.inputPanelBackgroundNode.isHidden = true
|
||||
self.inputPanelBackgroundSeparatorNode.isHidden = true
|
||||
self.inputPanelBottomBackgroundSeparatorNode.isHidden = true
|
||||
}
|
||||
self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition, beginWithCurrentState: true)
|
||||
self.inputPanelBottomBackgroundSeparatorBaseOffset = intrinsicInputPanelBackgroundNodeSize.height
|
||||
inputPanelUpdateTransition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: UIScreenPixel)), beginWithCurrentState: true)
|
||||
@ -2661,13 +2663,18 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
self.searchNavigationNode = ChatSearchNavigationContentNode(context: self.context, theme: self.chatPresentationInterfaceState.theme, strings: self.chatPresentationInterfaceState.strings, chatLocation: self.chatPresentationInterfaceState.chatLocation, interaction: interfaceInteraction, presentationInterfaceState: self.chatPresentationInterfaceState)
|
||||
}
|
||||
self.navigationBar?.setContentNode(self.searchNavigationNode, animated: transitionIsAnimated)
|
||||
if let navigationBar = self.navigationBar {
|
||||
navigationBar.setContentNode(self.searchNavigationNode, animated: transitionIsAnimated)
|
||||
} else {
|
||||
self.controller?.customNavigationBarContentNode = self.searchNavigationNode
|
||||
}
|
||||
self.searchNavigationNode?.update(presentationInterfaceState: self.chatPresentationInterfaceState)
|
||||
if activate {
|
||||
self.searchNavigationNode?.activate()
|
||||
}
|
||||
} else if let _ = self.searchNavigationNode {
|
||||
self.searchNavigationNode = nil
|
||||
self.controller?.customNavigationBarContentNode = nil
|
||||
self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated)
|
||||
}
|
||||
|
||||
|
||||
@ -10,10 +10,6 @@ import ChatChannelSubscriberInputPanelNode
|
||||
import ChatMessageSelectionInputPanelNode
|
||||
|
||||
func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatInputPanelNode?, currentSecondaryPanel: ChatInputPanelNode?, textInputPanelNode: ChatTextInputPanelNode?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> (primary: ChatInputPanelNode?, secondary: ChatInputPanelNode?) {
|
||||
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
||||
return (nil, nil)
|
||||
}
|
||||
|
||||
if let renderedPeer = chatPresentationInterfaceState.renderedPeer, renderedPeer.peer?.restrictionText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) != nil {
|
||||
return (nil, nil)
|
||||
}
|
||||
@ -65,6 +61,10 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
||||
}
|
||||
}
|
||||
|
||||
if case .standard(.embedded) = chatPresentationInterfaceState.mode {
|
||||
return (nil, nil)
|
||||
}
|
||||
|
||||
if let selectionState = chatPresentationInterfaceState.interfaceState.selectionState {
|
||||
if let _ = chatPresentationInterfaceState.reportReason {
|
||||
if let currentPanel = (currentPanel as? ChatMessageReportInputPanelNode) ?? (currentSecondaryPanel as? ChatMessageReportInputPanelNode) {
|
||||
|
||||
@ -25,7 +25,7 @@ private let backgroundTagImage: UIImage? = {
|
||||
}
|
||||
}()
|
||||
|
||||
final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UIScrollViewDelegate {
|
||||
final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode, UIScrollViewDelegate {
|
||||
private struct Params: Equatable {
|
||||
var width: CGFloat
|
||||
var leftInset: CGFloat
|
||||
@ -551,6 +551,10 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UISc
|
||||
return LayoutResult(backgroundHeight: panelHeight, insetHeight: panelHeight, hitTestSlop: 0.0)
|
||||
}
|
||||
|
||||
func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition, chatController: ChatController) -> LayoutResult {
|
||||
return self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, transition: transition, interfaceState: (chatController as! ChatControllerImpl).presentationInterfaceState)
|
||||
}
|
||||
|
||||
private func update(params: Params, transition: ContainedViewLayoutTransition) {
|
||||
let panelHeight: CGFloat = 39.0
|
||||
|
||||
|
||||
@ -3,13 +3,10 @@ import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import ChatPresentationInterfaceState
|
||||
import AccountContext
|
||||
|
||||
class ChatTitleAccessoryPanelNode: ASDisplayNode {
|
||||
struct LayoutResult {
|
||||
var backgroundHeight: CGFloat
|
||||
var insetHeight: CGFloat
|
||||
var hitTestSlop: CGFloat
|
||||
}
|
||||
typealias LayoutResult = ChatControllerCustomNavigationPanelNode.LayoutResult
|
||||
|
||||
var interfaceInteraction: ChatPanelInterfaceInteraction?
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user