Implement chat stack display

This commit is contained in:
Ali 2022-01-18 20:29:18 +04:00
parent c46f91eb20
commit 4adb3879d9
7 changed files with 81 additions and 12 deletions

View File

@ -293,10 +293,11 @@ public final class NavigateToChatControllerParams {
public let options: NavigationAnimationOptions
public let parentGroupId: PeerGroupId?
public let chatListFilter: Int32?
public let chatNavigationStack: [PeerId]
public let changeColors: Bool
public let completion: (ChatController) -> Void
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, changeColors: Bool = false, completion: @escaping (ChatController) -> Void = { _ in }) {
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, useExisting: Bool = true, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, activateMessageSearch: (ChatSearchDomain, String)? = nil, peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, reportReason: ReportReason? = nil, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = [], changeColors: Bool = false, completion: @escaping (ChatController) -> Void = { _ in }) {
self.navigationController = navigationController
self.chatController = chatController
self.chatLocationContextHolder = chatLocationContextHolder
@ -318,6 +319,7 @@ public final class NavigateToChatControllerParams {
self.options = options
self.parentGroupId = parentGroupId
self.chatListFilter = chatListFilter
self.chatNavigationStack = chatNavigationStack
self.changeColors = changeColors
self.completion = completion
}

View File

@ -540,7 +540,17 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
})
if self.controlsHistoryPreload {
self.context.account.viewTracker.chatListPreloadItems.set(itemNode.listNode.preloadItems.get())
self.context.account.viewTracker.chatListPreloadItems.set(combineLatest(queue: .mainQueue(),
context.sharedContext.hasOngoingCall.get(),
itemNode.listNode.preloadItems.get()
)
|> map { hasOngoingCall, preloadItems -> [ChatHistoryPreloadItem] in
if hasOngoingCall {
return []
} else {
return preloadItems
}
})
}
}

View File

@ -1,7 +1,7 @@
import Foundation
import AsyncDisplayKit
public final class ContextReferenceContentNode: ASDisplayNode {
open class ContextReferenceContentNode: ASDisplayNode {
}
public final class ContextExtractedContentContainingNode: ASDisplayNode {

View File

@ -1,7 +1,7 @@
import Foundation
import AsyncDisplayKit
open class ContextControllerSourceNode: ASDisplayNode {
open class ContextControllerSourceNode: ContextReferenceContentNode {
public private(set) var contextGesture: ContextGesture?
public var isGestureEnabled: Bool = true {

View File

@ -325,7 +325,7 @@ private final class NavigationButtonItemNode: ImmediateTextNode {
}
public final class NavigationButtonNode: ASDisplayNode {
public final class NavigationButtonNode: ContextControllerSourceNode {
private var nodes: [NavigationButtonItemNode] = []
public var singleCustomNode: ASDisplayNode? {
@ -379,6 +379,7 @@ public final class NavigationButtonNode: ASDisplayNode {
super.init()
self.isAccessibilityElement = false
self.isGestureEnabled = false
}
var manualText: String {

View File

@ -218,6 +218,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
public weak var parentController: ViewController?
private let currentChatListFilter: Int32?
private let chatNavigationStack: [PeerId]
public var peekActions: ChatControllerPeekActions = .standard
private var didSetup3dTouch: Bool = false
@ -494,7 +495,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private var inviteRequestsContext: PeerInvitationImportersContext?
private var inviteRequestsDisposable = MetaDisposable()
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil) {
public init(context: AccountContext, chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?> = Atomic<ChatLocationContextHolder?>(value: nil), subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false), peekData: ChatPeekTimeout? = nil, peerNearbyData: ChatPeerNearbyData? = nil, chatListFilter: Int32? = nil, chatNavigationStack: [PeerId] = []) {
let _ = ChatControllerCount.modify { value in
return value + 1
}
@ -506,6 +507,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.botStart = botStart
self.peekData = peekData
self.currentChatListFilter = chatListFilter
self.chatNavigationStack = chatNavigationStack
var useSharedAnimationPhase = false
switch mode {
@ -8267,12 +8269,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
default:
nextFolderId = nil
}
var updatedChatNavigationStack = strongSelf.chatNavigationStack
updatedChatNavigationStack.removeAll(where: { $0 == peer.id})
if case let .peer(peerId) = strongSelf.chatLocation {
updatedChatNavigationStack.insert(peerId, at: 0)
}
//Queue.mainQueue().after(1.0, {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: nextFolderId, completion: { nextController in
(nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState)
}))
//})
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in
(nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState)
}))
}
}
@ -8323,6 +8329,56 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return state.updatedInputMode({ _ in .text })
})
}
if !self.chatNavigationStack.isEmpty {
self.chatDisplayNode.navigationBar?.backButtonNode.isGestureEnabled = true
self.chatDisplayNode.navigationBar?.backButtonNode.activated = { [weak self] gesture, _ in
guard let strongSelf = self else {
gesture.cancel()
return
}
let chatNavigationStack = strongSelf.chatNavigationStack
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in
return chatNavigationStack.compactMap(transaction.getPeer)
}
|> deliverOnMainQueue).start(next: { peers in
guard let strongSelf = self, let backButtonNode = strongSelf.chatDisplayNode.navigationBar?.backButtonNode else {
return
}
let avatarSize = CGSize(width: 28.0, height: 28.0)
var items: [ContextMenuItem] = []
for peer in peers {
items.append(.action(ContextMenuActionItem(text: EnginePeer(peer).displayTitle(strings: strongSelf.presentationData.strings, displayOrder: strongSelf.presentationData.nameDisplayOrder), icon: { _ in return nil }, iconSource: ContextMenuActionItemIconSource(size: avatarSize, signal: peerAvatarCompleteImage(account: strongSelf.context.account, peer: EnginePeer(peer), size: avatarSize)), action: { _, f in
f(.default)
guard let strongSelf = self, let navigationController = strongSelf.effectiveNavigationController else {
return
}
let snapshotState = strongSelf.chatDisplayNode.prepareSnapshotState(
titleViewSnapshotState: strongSelf.chatTitleView?.prepareSnapshotState(),
avatarSnapshotState: (strongSelf.chatInfoNavigationButton?.buttonItem.customDisplayNode as? ChatAvatarNavigationNode)?.prepareSnapshotState()
)
let nextFolderId: Int32? = strongSelf.currentChatListFilter
var updatedChatNavigationStack = strongSelf.chatNavigationStack
if let index = updatedChatNavigationStack.firstIndex(of: peer.id) {
updatedChatNavigationStack.removeSubrange(0 ..< (index + 1))
}
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), animated: false, chatListFilter: nextFolderId, chatNavigationStack: updatedChatNavigationStack, completion: { nextController in
(nextController as! ChatControllerImpl).animateFromPreviousController(snapshotState: snapshotState)
}))
})))
}
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .reference(ChatControllerContextReferenceContentSource(controller: strongSelf, sourceNode: backButtonNode, insets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 4.0, right: 0.0))), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController)
})
}
}
}
private var returnInputViewFocus = false

View File

@ -76,7 +76,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
})
}
} else {
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter)
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, chatLocationContextHolder: params.chatLocationContextHolder, subject: params.subject, botStart: params.botStart, peekData: params.peekData, peerNearbyData: params.peerNearbyData, chatListFilter: params.chatListFilter, chatNavigationStack: params.chatNavigationStack)
}
controller.purposefulAction = params.purposefulAction
if let search = params.activateMessageSearch {