Saved message search

This commit is contained in:
Isaac 2024-01-28 00:15:21 +01:00
parent 960d968e0f
commit ca4eb2cb69
21 changed files with 439 additions and 68 deletions

View File

@ -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 { public protocol ChatController: ViewController {
var chatLocation: ChatLocation { get } var chatLocation: ChatLocation { get }
var canReadHistory: ValuePromise<Bool> { get } var canReadHistory: ValuePromise<Bool> { get }
@ -919,9 +937,14 @@ public protocol ChatController: ViewController {
var purposefulAction: (() -> Void)? { get set } var purposefulAction: (() -> Void)? { get set }
var stateUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set }
var selectedMessageIds: Set<EngineMessage.Id>? { get } var selectedMessageIds: Set<EngineMessage.Id>? { get }
var presentationInterfaceStateSignal: Signal<Any, NoError> { get } var presentationInterfaceStateSignal: Signal<Any, NoError> { get }
var customNavigationBarContentNode: NavigationBarContentNode? { get }
var customNavigationPanelNode: ChatControllerCustomNavigationPanelNode? { get }
func updatePresentationMode(_ mode: ChatControllerPresentationMode) func updatePresentationMode(_ mode: ChatControllerPresentationMode)
func beginMessageSearch(_ query: String) func beginMessageSearch(_ query: String)
func displayPromoAnnouncement(text: String) func displayPromoAnnouncement(text: String)

View File

@ -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) { func updateContentsRect(layer: CALayer, contentsRect: CGRect, completion: ((Bool) -> Void)? = nil) {
if layer.contentsRect == contentsRect { if layer.contentsRect == contentsRect {
if let completion = completion { if let completion = completion {

View File

@ -493,6 +493,8 @@ open class NavigationBar: ASDisplayNode {
public var makeCustomTransitionNode: ((NavigationBar, Bool) -> CustomNavigationTransitionNode?)? public var makeCustomTransitionNode: ((NavigationBar, Bool) -> CustomNavigationTransitionNode?)?
public var allowsCustomTransition: (() -> Bool)? public var allowsCustomTransition: (() -> Bool)?
public var customSetContentNode: ((NavigationBarContentNode?, Bool) -> Void)?
private var collapsed: Bool { private var collapsed: Bool {
get { get {
return self.frame.size.height.isLess(than: 44.0) return self.frame.size.height.isLess(than: 44.0)
@ -1649,6 +1651,11 @@ open class NavigationBar: ASDisplayNode {
} }
public func setContentNode(_ contentNode: NavigationBarContentNode?, animated: Bool) { public func setContentNode(_ contentNode: NavigationBarContentNode?, animated: Bool) {
if let customSetContentNode = self.customSetContentNode {
customSetContentNode(contentNode, animated)
return
}
if self.contentNode !== contentNode { if self.contentNode !== contentNode {
if let previous = self.contentNode { if let previous = self.contentNode {
if animated { if animated {

View File

@ -110,7 +110,7 @@ private extension MessageHistoryInput {
assert(Set(items.map({ $0.stableId })).count == items.count) assert(Set(items.map({ $0.stableId })).count == items.count)
if items.count > limit { if items.count > limit {
let overLimit = limit - items.count let overLimit = items.count - limit
switch direction { switch direction {
case .lowToHigh: case .lowToHigh:
items.removeFirst(overLimit) items.removeFirst(overLimit)

View File

@ -21,6 +21,7 @@ public enum PresentationResourceKey: Int32 {
case navigationSearchIcon case navigationSearchIcon
case navigationCompactSearchIcon case navigationCompactSearchIcon
case navigationCompactTagsSearchIcon case navigationCompactTagsSearchIcon
case navigationCompactTagsSearchWhiteIcon
case navigationCalendarIcon case navigationCalendarIcon
case navigationMoreIcon case navigationMoreIcon
case navigationMoreCircledIcon case navigationMoreCircledIcon

View File

@ -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? { public static func navigationCalendarIcon(_ theme: PresentationTheme) -> UIImage? {
return theme.image(PresentationResourceKey.navigationCalendarIcon.rawValue, { theme in return theme.image(PresentationResourceKey.navigationCalendarIcon.rawValue, { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Search/Calendar"), color: theme.rootController.navigationBar.accentTextColor) return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Search/Calendar"), color: theme.rootController.navigationBar.accentTextColor)

View File

@ -427,15 +427,15 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
if let tagButton { if let tagButton {
buttons = [ buttons = [
self.deleteButton, self.deleteButton,
self.forwardButton,
tagButton, tagButton,
self.forwardButton,
self.shareButton self.shareButton
] ]
} else { } else {
buttons = [ buttons = [
self.deleteButton, self.deleteButton,
self.forwardButton, self.shareButton,
self.shareButton self.forwardButton
] ]
} }
} else if !self.deleteButton.isHidden { } else if !self.deleteButton.isHidden {
@ -459,17 +459,17 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
if let tagButton { if let tagButton {
buttons = [ buttons = [
self.deleteButton, self.deleteButton,
self.forwardButton,
self.reportButton, self.reportButton,
tagButton, tagButton,
self.shareButton self.shareButton,
self.forwardButton
] ]
} else { } else {
buttons = [ buttons = [
self.deleteButton, self.deleteButton,
self.forwardButton,
self.reportButton, self.reportButton,
self.shareButton self.shareButton,
self.forwardButton
] ]
} }
} }

View File

@ -11,6 +11,83 @@ import TelegramUIPreferences
import AppBundle import AppBundle
import PeerInfoPaneNode 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 { public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScrollViewDelegate, UIGestureRecognizerDelegate {
private let context: AccountContext private let context: AccountContext
private let peerId: EnginePeer.Id private let peerId: EnginePeer.Id
@ -52,6 +129,12 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
return 0.0 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 presentationData: PresentationData
private var presentationDataDisposable: Disposable? private var presentationDataDisposable: Disposable?
@ -77,6 +160,29 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
self.addSubnode(self.chatController.displayNode) self.addSubnode(self.chatController.displayNode)
self.chatController.displayNode.clipsToBounds = true 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 { deinit {
@ -124,6 +230,9 @@ public final class PeerInfoChatPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
super.didLoad() super.didLoad()
} }
public func activateSearch() {
self.chatController.activateSearch(domain: .everything, query: "")
}
override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { override public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return true return true

View File

@ -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 { public protocol PeerInfoPaneNode: ASDisplayNode {
var isReady: Signal<Bool, NoError> { get } var isReady: Signal<Bool, NoError> { get }
@ -48,6 +52,9 @@ public protocol PeerInfoPaneNode: ASDisplayNode {
var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set } var tabBarOffsetUpdated: ((ContainedViewLayoutTransition) -> Void)? { get set }
var tabBarOffset: CGFloat { get } 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 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 scrollToTop() -> Bool
func transferVelocity(_ velocity: CGFloat) func transferVelocity(_ velocity: CGFloat)
@ -59,3 +66,15 @@ public protocol PeerInfoPaneNode: ASDisplayNode {
func updateSelectedMessages(animated: Bool) func updateSelectedMessages(animated: Bool)
func ensureMessageIsVisible(id: MessageId) func ensureMessageIsVisible(id: MessageId)
} }
public extension PeerInfoPaneNode {
var navigationContentNode: PeerInfoPanelNodeNavigationContentNode? {
return nil
}
var externalDataUpdated: ((ContainedViewLayoutTransition) -> Void)? {
get {
return nil
} set(value) {
}
}
}

View File

@ -207,6 +207,7 @@ final class PeerInfoScreenData {
let appConfiguration: AppConfiguration? let appConfiguration: AppConfiguration?
let isPowerSavingEnabled: Bool? let isPowerSavingEnabled: Bool?
let accountIsPremium: Bool let accountIsPremium: Bool
let hasSavedMessageTags: Bool
let _isContact: Bool let _isContact: Bool
var forceIsContact: Bool = false var forceIsContact: Bool = false
@ -242,7 +243,8 @@ final class PeerInfoScreenData {
threadData: MessageHistoryThreadData?, threadData: MessageHistoryThreadData?,
appConfiguration: AppConfiguration?, appConfiguration: AppConfiguration?,
isPowerSavingEnabled: Bool?, isPowerSavingEnabled: Bool?,
accountIsPremium: Bool accountIsPremium: Bool,
hasSavedMessageTags: Bool
) { ) {
self.peer = peer self.peer = peer
self.chatPeer = chatPeer self.chatPeer = chatPeer
@ -267,6 +269,7 @@ final class PeerInfoScreenData {
self.appConfiguration = appConfiguration self.appConfiguration = appConfiguration
self.isPowerSavingEnabled = isPowerSavingEnabled self.isPowerSavingEnabled = isPowerSavingEnabled
self.accountIsPremium = accountIsPremium self.accountIsPremium = accountIsPremium
self.hasSavedMessageTags = hasSavedMessageTags
} }
} }
@ -662,7 +665,8 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
threadData: nil, threadData: nil,
appConfiguration: appConfiguration, appConfiguration: appConfiguration,
isPowerSavingEnabled: isPowerSavingEnabled, 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, threadData: nil,
appConfiguration: nil, appConfiguration: nil,
isPowerSavingEnabled: nil, isPowerSavingEnabled: nil,
accountIsPremium: false accountIsPremium: false,
hasSavedMessageTags: false
)) ))
case let .user(userPeerId, secretChatId, kind): case let .user(userPeerId, secretChatId, kind):
let groupsInCommon: GroupsInCommonContext? let groupsInCommon: GroupsInCommonContext?
@ -853,6 +858,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
hasSavedMessagesChats = .single(false) 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( return combineLatest(
context.account.viewTracker.peerView(peerId, updateData: true), context.account.viewTracker.peerView(peerId, updateData: true),
peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder), peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder),
@ -863,9 +881,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
accountIsPremium, accountIsPremium,
savedMessagesPeer, savedMessagesPeer,
hasSavedMessagesChats, 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 var availablePanes = availablePanes
if let hasStories { if let hasStories {
@ -924,7 +943,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
threadData: nil, threadData: nil,
appConfiguration: nil, appConfiguration: nil,
isPowerSavingEnabled: nil, isPowerSavingEnabled: nil,
accountIsPremium: accountIsPremium accountIsPremium: accountIsPremium,
hasSavedMessageTags: hasSavedMessageTags
) )
} }
case .channel: case .channel:
@ -985,6 +1005,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
hasSavedMessagesChats = .single(false) 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( return combineLatest(
context.account.viewTracker.peerView(peerId, updateData: true), context.account.viewTracker.peerView(peerId, updateData: true),
peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder), peerInfoAvailableMediaPanes(context: context, peerId: peerId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder),
@ -998,9 +1031,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
accountIsPremium, accountIsPremium,
context.engine.peers.recommendedChannels(peerId: peerId), context.engine.peers.recommendedChannels(peerId: peerId),
hasSavedMessages, 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 var availablePanes = availablePanes
if let hasStories { if let hasStories {
if hasStories { if hasStories {
@ -1072,7 +1106,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
threadData: nil, threadData: nil,
appConfiguration: nil, appConfiguration: nil,
isPowerSavingEnabled: nil, isPowerSavingEnabled: nil,
accountIsPremium: accountIsPremium accountIsPremium: accountIsPremium,
hasSavedMessageTags: hasSavedMessageTags
) )
} }
case let .group(groupId): case let .group(groupId):
@ -1219,6 +1254,19 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
hasSavedMessagesChats = .single(false) 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(), return combineLatest(queue: .mainQueue(),
context.account.viewTracker.peerView(groupId, updateData: true), context.account.viewTracker.peerView(groupId, updateData: true),
peerInfoAvailableMediaPanes(context: context, peerId: groupId, chatLocation: chatLocation, chatLocationContextHolder: chatLocationContextHolder), 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]), context.account.postbox.preferencesView(keys: [PreferencesKeys.appConfiguration]),
accountIsPremium, accountIsPremium,
hasSavedMessages, 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? var discussionPeer: Peer?
if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] { if case let .known(maybeLinkedDiscussionPeerId) = (peerView.cachedData as? CachedChannelData)?.linkedDiscussionPeerId, let linkedDiscussionPeerId = maybeLinkedDiscussionPeerId, let peer = peerView.peers[linkedDiscussionPeerId] {
discussionPeer = peer discussionPeer = peer
@ -1320,7 +1369,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
threadData: threadData, threadData: threadData,
appConfiguration: appConfiguration, appConfiguration: appConfiguration,
isPowerSavingEnabled: nil, isPowerSavingEnabled: nil,
accountIsPremium: accountIsPremium accountIsPremium: accountIsPremium,
hasSavedMessageTags: hasSavedMessageTags
)) ))
} }
} }

View File

@ -178,7 +178,7 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
self.backgroundNode.updateColor(color: backgroundColor, transition: transition) self.backgroundNode.updateColor(color: backgroundColor, transition: transition)
transition.updateTintColor(layer: self.textNode.layer, color: self.contentsColor) 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) transition.updateStrokeColor(layer: self.backIconLayer, strokeColor: self.contentsColor)
switch self.key { switch self.key {
@ -247,9 +247,13 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
case .search: case .search:
text = "" text = ""
accessibilityText = presentationData.strings.Common_Search accessibilityText = presentationData.strings.Common_Search
icon = nil// PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme) icon = nil
isAnimation = true isAnimation = true
animationState = .search animationState = .search
case .searchWithTags:
text = ""
accessibilityText = presentationData.strings.Common_Search
icon = PresentationResourcesRootController.navigationCompactTagsSearchWhiteIcon(presentationData.theme)
case .editPhoto: case .editPhoto:
text = presentationData.strings.Settings_EditPhoto text = presentationData.strings.Settings_EditPhoto
accessibilityText = text accessibilityText = text

View File

@ -13,6 +13,7 @@ enum PeerInfoHeaderNavigationButtonKey {
case select case select
case selectionDone case selectionDone
case search case search
case searchWithTags
case editPhoto case editPhoto
case editVideo case editVideo
case more case more
@ -210,7 +211,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
if wasAdded { if wasAdded {
buttonNode.updateContentsColor(backgroundColor: self.backgroundContentColor, contentsColor: self.contentsColor, canBeExpanded: self.canBeExpanded, transition: .immediate) 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) buttonNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.2)
} }
@ -236,7 +237,7 @@ final class PeerInfoHeaderNavigationButtonContainerNode: SparseNode {
} }
for key in removeKeys { for key in removeKeys {
if let buttonNode = self.rightButtonNodes.removeValue(forKey: key) { 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.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak buttonNode] _ in
buttonNode?.removeFromSupernode() buttonNode?.removeFromSupernode()
}) })

View File

@ -169,6 +169,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var emojiStatusPackDisposable = MetaDisposable() var emojiStatusPackDisposable = MetaDisposable()
var emojiStatusFileAndPackTitle = Promise<(TelegramMediaFile, LoadedStickerPack)?>() var emojiStatusFileAndPackTitle = Promise<(TelegramMediaFile, LoadedStickerPack)?>()
var customNavigationContentNode: PeerInfoPanelNodeNavigationContentNode?
private var appliedCustomNavigationContentNode: PeerInfoPanelNodeNavigationContentNode?
private var validLayout: (width: CGFloat, deviceMetrics: DeviceMetrics)? private var validLayout: (width: CGFloat, deviceMetrics: DeviceMetrics)?
init(context: AccountContext, controller: PeerInfoScreenImpl, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isMediaOnly: Bool, isSettings: Bool, forumTopicThreadId: Int64?, chatLocation: ChatLocation) { 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? 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 { 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 var threadData = threadData
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId { if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId {
threadData = nil threadData = nil
@ -516,7 +537,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
isForum = true 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 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) 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 { if self.navigationTransition == nil && !self.isSettings && effectiveSeparatorAlpha == 1.0 && secondarySeparatorAlpha < 1.0 {
effectiveSeparatorAlpha = secondarySeparatorAlpha effectiveSeparatorAlpha = secondarySeparatorAlpha
} }
if self.customNavigationContentNode != nil {
effectiveSeparatorAlpha = 0.0
}
transition.updateAlpha(node: self.separatorNode, alpha: effectiveSeparatorAlpha) transition.updateAlpha(node: self.separatorNode, alpha: effectiveSeparatorAlpha)
self.titleNode.update(stateFractions: [ 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.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))) 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) navigationTransition.updateAlpha(node: self.buttonsContainerNode, alpha: backgroundBannerAlpha)
@ -2078,6 +2105,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
return nil 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) 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) { if self.avatarListNode.listContainerNode.setByYouNode.alpha > 0.0, setByFrame.contains(point) {
return self.avatarListNode.listContainerNode.setByYouNode.view return self.avatarListNode.listContainerNode.setByYouNode.view

View File

@ -366,7 +366,8 @@ private final class PeerInfoPendingPane {
parentController: ViewController?, parentController: ViewController?,
openMediaCalendar: @escaping () -> Void, openMediaCalendar: @escaping () -> Void,
paneDidScroll: @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 captureProtected = data.peer?.isCopyProtectionEnabled ?? false
let paneNode: PeerInfoPaneNode let paneNode: PeerInfoPaneNode
@ -425,6 +426,7 @@ private final class PeerInfoPendingPane {
case .savedMessages: case .savedMessages:
paneNode = PeerInfoChatPaneNode(context: context, peerId: peerId, navigationController: chatControllerInteraction.navigationController) paneNode = PeerInfoChatPaneNode(context: context, peerId: peerId, navigationController: chatControllerInteraction.navigationController)
} }
paneNode.externalDataUpdated = externalDataUpdated
paneNode.parentController = parentController paneNode.parentController = parentController
self.pane = PeerInfoPaneWrapper(key: key, node: paneNode) self.pane = PeerInfoPaneWrapper(key: key, node: paneNode)
self.disposable = (paneNode.isReady self.disposable = (paneNode.isReady
@ -458,7 +460,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
let isReady = Promise<Bool>() let isReady = Promise<Bool>()
var didSetIsReady = false 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? private(set) var currentPaneKey: PeerInfoPaneKey?
var pendingSwitchToPaneKey: PeerInfoPaneKey? var pendingSwitchToPaneKey: PeerInfoPaneKey?
@ -495,6 +497,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
var currentPaneUpdated: ((Bool) -> Void)? var currentPaneUpdated: ((Bool) -> Void)?
var requestExpandTabs: (() -> Bool)? var requestExpandTabs: (() -> Bool)?
var requestUpdate: ((ContainedViewLayoutTransition) -> Void)?
var openMediaCalendar: (() -> Void)? var openMediaCalendar: (() -> Void)?
var paneDidScroll: (() -> Void)? var paneDidScroll: (() -> Void)?
@ -550,8 +553,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
if strongSelf.currentPanes[key] != nil { if strongSelf.currentPanes[key] != nil {
strongSelf.currentPaneKey = key strongSelf.currentPaneKey = key
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 {
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)) 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) strongSelf.currentPaneUpdated?(true)
@ -563,8 +566,8 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
strongSelf.pendingSwitchToPaneKey = key strongSelf.pendingSwitchToPaneKey = key
strongSelf.expandOnSwitch = true strongSelf.expandOnSwitch = true
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 {
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)) 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] return [.leftCenter, .rightCenter]
} }
if strongSelf.currentPane?.node.navigationContentNode != nil {
return []
}
if index == 0 { if index == 0 {
return .left return .left
} }
@ -629,7 +635,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
cancelContextGestures(view: self.view) cancelContextGestures(view: self.view)
case .changed: 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) let translation = recognizer.translation(in: self.view)
var transitionFraction = translation.x / size.width var transitionFraction = translation.x / size.width
if currentIndex <= 0 { if currentIndex <= 0 {
@ -644,11 +650,11 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
// print(transitionFraction) // print(transitionFraction)
self.paneTransitionPromise.set(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) self.currentPaneUpdated?(false)
} }
case .cancelled, .ended: 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 translation = recognizer.translation(in: self.view)
let velocity = recognizer.velocity(in: self.view) let velocity = recognizer.velocity(in: self.view)
var directionIsToRight: Bool? var directionIsToRight: Bool?
@ -672,7 +678,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
} }
} }
self.transitionFraction = 0.0 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.currentPaneUpdated?(false)
self.currentPaneStatusPromise.set(self.currentPane?.node.status ?? .single(nil)) 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 previousAvailablePanes = self.currentAvailablePanes
let availablePanes = data?.availablePanes ?? [] let availablePanes = data?.availablePanes ?? []
self.currentAvailablePanes = data?.availablePanes self.currentAvailablePanes = data?.availablePanes
@ -755,7 +761,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
currentIndex = nil 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) transition.updateAlpha(node: self.coveringBackgroundNode, alpha: expansionFraction)
@ -770,6 +776,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
let isScrollingLockedAtTop = expansionFraction < 1.0 - CGFloat.ulpOfOne let isScrollingLockedAtTop = expansionFraction < 1.0 - CGFloat.ulpOfOne
let tabsHeight: CGFloat = 48.0 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)) 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 { guard let strongSelf = self else {
return 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 var transition: ContainedViewLayoutTransition = .immediate
if strongSelf.pendingSwitchToPaneKey == key && strongSelf.currentPaneKey != nil { if strongSelf.pendingSwitchToPaneKey == key && strongSelf.currentPaneKey != nil {
transition = .animated(duration: 0.4, curve: .spring) 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 { if leftScope {
@ -849,18 +856,24 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
return return
} }
self.ensurePaneRectVisible?(self.view, sourceView.convert(rect, to: self.view)) 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 self.pendingPanes[key] = pane
pane.pane.node.frame = paneFrame 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 let paneNode = pane.pane.node
pane.pane.node.tabBarOffsetUpdated = { [weak self, weak paneNode] transition in 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 { guard let strongSelf = self, let paneNode = paneNode, let currentPane = strongSelf.currentPane, paneNode === currentPane.node else {
return 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 {
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)
} }
} }
leftScope = true leftScope = true
@ -869,7 +882,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
for (key, pane) in self.pendingPanes { for (key, pane) in self.pendingPanes {
pane.pane.node.frame = paneFrame 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 { if pane.isReady {
self.pendingPanes.removeValue(forKey: key) self.pendingPanes.removeValue(forKey: key)
@ -930,7 +943,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
return return
} }
pane.isAnimatingOut = false 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 { 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 { } else {
if let pane = strongSelf.currentPanes.removeValue(forKey: key) { if let pane = strongSelf.currentPanes.removeValue(forKey: key) {
@ -961,7 +974,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
paneCompletion() 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 { if isScrollingLockedAtTop || self.isMediaOnly {
tabsOffset = 0.0 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 tabsAlpha *= tabsAlpha
transition.updateFrame(node: self.tabsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -tabsOffset), size: CGSize(width: size.width, height: tabsHeight))) 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) transition.updateAlpha(node: self.tabsContainerNode, alpha: tabsAlpha)
@ -1019,7 +1039,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
for (_, pane) in self.pendingPanes { for (_, pane) in self.pendingPanes {
let paneTransition: ContainedViewLayoutTransition = .immediate let paneTransition: ContainedViewLayoutTransition = .immediate
paneTransition.updateFrame(node: pane.pane.node, frame: paneFrame) 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] = [] var removeKeys: [PeerInfoPaneKey] = []

View File

@ -102,6 +102,7 @@ import PeerInfoPaneNode
import MediaPickerUI import MediaPickerUI
import AttachmentUI import AttachmentUI
import BoostLevelIconComponent import BoostLevelIconComponent
import PeerInfoChatPaneNode
public enum PeerInfoAvatarEditingMode { public enum PeerInfoAvatarEditingMode {
case generic 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 self.paneContainerNode.ensurePaneRectVisible = { [weak self] sourceView, rect in
guard let self else { guard let self else {
return return
@ -3748,8 +3758,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
} }
strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) } strongSelf.chatInterfaceInteraction.selectionState = strongSelf.state.selectedMessageIds.flatMap { ChatInterfaceSelectionState(selectedIds: $0) }
strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true) strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true)
case .search: case .search, .searchWithTags:
strongSelf.headerNode.navigationButtonContainer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue)
strongSelf.activateSearch() strongSelf.activateSearch()
case .more: case .more:
if let source = source { if let source = source {
@ -9269,6 +9278,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
return 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 { if self.isSettings {
(self.controller?.parent as? TabBarController)?.updateIsTabBarHidden(true, transition: .animated(duration: 0.3, curve: .linear)) (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) { func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition, additive: Bool = false) {
self.validLayout = (layout, navigationHeight) 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 { if self.headerNode.isAvatarExpanded && layout.size.width > layout.size.height {
self.headerNode.updateIsAvatarExpanded(false, transition: transition) self.headerNode.updateIsAvatarExpanded(false, transition: transition)
self.updateNavigationExpansionPresentation(isExpanded: false, animated: true) self.updateNavigationExpansionPresentation(isExpanded: false, animated: true)
@ -10188,6 +10226,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
} }
if let (layout, navigationHeight) = self.validLayout { 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 { if !additive {
let sectionInset: CGFloat let sectionInset: CGFloat
if layout.size.width >= 375.0 { 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 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))) 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 { switch currentPaneKey {
case .files, .music, .links, .members, .savedMessagesChats: case .files, .music, .links, .members, .savedMessagesChats:
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true)) 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: case .media:
rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true)) rightNavigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .more, isForExpandedView: true))
default: default:

View File

@ -524,4 +524,14 @@ func updateChatPresentationInterfaceStateImpl(
} }
selfController.updateDownButtonVisibility() 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)
} }

View File

@ -507,6 +507,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
weak var currentImportMessageTooltip: UndoOverlayController? weak var currentImportMessageTooltip: UndoOverlayController?
public var customNavigationBarContentNode: NavigationBarContentNode?
public var customNavigationPanelNode: ChatControllerCustomNavigationPanelNode?
public var stateUpdated: ((ContainedViewLayoutTransition) -> Void)?
public override var customData: Any? { public override var customData: Any? {
return self.chatLocation return self.chatLocation
} }

View File

@ -1656,13 +1656,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
transition.updateFrame(node: backgroundEffectNode, frame: CGRect(origin: CGPoint(), size: layout.size)) 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 var displayMode: WallpaperDisplayMode = .aspectFill
if case .regular = layout.metrics.widthClass, layout.size.height == layout.deviceMetrics.screenSize.width { if case .regular = layout.metrics.widthClass, layout.size.height == layout.deviceMetrics.screenSize.width {
displayMode = .aspectFit 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.updateBounds(node: self.historyNodeContainer, bounds: contentBounds)
transition.updatePosition(node: self.historyNodeContainer, position: contentBounds.center) transition.updatePosition(node: self.historyNodeContainer, position: contentBounds.center)
@ -1796,6 +1798,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if self.dismissedAsOverlay { if self.dismissedAsOverlay {
inputBackgroundFrame.origin.y = layout.size.height 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 let additionalScrollDistance: CGFloat = 0.0
var scrollToTop = false var scrollToTop = false
@ -2033,11 +2040,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
inputPanelUpdateTransition = .immediate 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.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition, beginWithCurrentState: true)
self.inputPanelBottomBackgroundSeparatorBaseOffset = intrinsicInputPanelBackgroundNodeSize.height 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) 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.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) self.searchNavigationNode?.update(presentationInterfaceState: self.chatPresentationInterfaceState)
if activate { if activate {
self.searchNavigationNode?.activate() self.searchNavigationNode?.activate()
} }
} else if let _ = self.searchNavigationNode { } else if let _ = self.searchNavigationNode {
self.searchNavigationNode = nil self.searchNavigationNode = nil
self.controller?.customNavigationBarContentNode = nil
self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated) self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated)
} }

View File

@ -10,10 +10,6 @@ import ChatChannelSubscriberInputPanelNode
import ChatMessageSelectionInputPanelNode import ChatMessageSelectionInputPanelNode
func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatInputPanelNode?, currentSecondaryPanel: ChatInputPanelNode?, textInputPanelNode: ChatTextInputPanelNode?, interfaceInteraction: ChatPanelInterfaceInteraction?) -> (primary: ChatInputPanelNode?, secondary: ChatInputPanelNode?) { 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 { if let renderedPeer = chatPresentationInterfaceState.renderedPeer, renderedPeer.peer?.restrictionText(platform: "ios", contentSettings: context.currentContentSettings.with { $0 }) != nil {
return (nil, 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 selectionState = chatPresentationInterfaceState.interfaceState.selectionState {
if let _ = chatPresentationInterfaceState.reportReason { if let _ = chatPresentationInterfaceState.reportReason {
if let currentPanel = (currentPanel as? ChatMessageReportInputPanelNode) ?? (currentSecondaryPanel as? ChatMessageReportInputPanelNode) { if let currentPanel = (currentPanel as? ChatMessageReportInputPanelNode) ?? (currentSecondaryPanel as? ChatMessageReportInputPanelNode) {

View File

@ -25,7 +25,7 @@ private let backgroundTagImage: UIImage? = {
} }
}() }()
final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UIScrollViewDelegate { final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, ChatControllerCustomNavigationPanelNode, UIScrollViewDelegate {
private struct Params: Equatable { private struct Params: Equatable {
var width: CGFloat var width: CGFloat
var leftInset: CGFloat var leftInset: CGFloat
@ -551,6 +551,10 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, UISc
return LayoutResult(backgroundHeight: panelHeight, insetHeight: panelHeight, hitTestSlop: 0.0) 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) { private func update(params: Params, transition: ContainedViewLayoutTransition) {
let panelHeight: CGFloat = 39.0 let panelHeight: CGFloat = 39.0

View File

@ -3,13 +3,10 @@ import UIKit
import Display import Display
import AsyncDisplayKit import AsyncDisplayKit
import ChatPresentationInterfaceState import ChatPresentationInterfaceState
import AccountContext
class ChatTitleAccessoryPanelNode: ASDisplayNode { class ChatTitleAccessoryPanelNode: ASDisplayNode {
struct LayoutResult { typealias LayoutResult = ChatControllerCustomNavigationPanelNode.LayoutResult
var backgroundHeight: CGFloat
var insetHeight: CGFloat
var hitTestSlop: CGFloat
}
var interfaceInteraction: ChatPanelInterfaceInteraction? var interfaceInteraction: ChatPanelInterfaceInteraction?