Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
Ilya Laktyushin 2025-05-22 15:23:34 +02:00
commit e7772bb581
15 changed files with 391 additions and 133 deletions

View File

@ -1763,7 +1763,7 @@ private final class NotificationServiceHandler {
|> mapToSignal { content, _ -> Signal<(NotificationContent, Media?), NoError> in
return stateManager.postbox.transaction { transaction -> (NotificationContent, Media?) in
var parsedMedia: Media?
if let messageId, let message = transaction.getMessage(messageId), !message.containsSecretMedia {
if let messageId, let message = transaction.getMessage(messageId), !message.containsSecretMedia, !message.attributes.contains(where: { $0 is MediaSpoilerMessageAttribute }) {
if let media = message.media.first {
parsedMedia = media
}

View File

@ -1105,7 +1105,7 @@ public struct PresentationResourcesChat {
public static func chatFreeNavigateButtonIcon(_ theme: PresentationTheme, wallpaper: TelegramWallpaper) -> UIImage? {
return theme.image(PresentationResourceKey.chatFreeNavigateButtonIcon.rawValue, { _ in
return generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: bubbleVariableColor(variableColor: theme.chat.message.shareButtonForegroundColor, wallpaper: wallpaper))
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/NavigateToMessageIcon"), color: bubbleVariableColor(variableColor: theme.chat.message.shareButtonForegroundColor, wallpaper: wallpaper))
})
}

View File

@ -1926,7 +1926,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
inlineBotNameString = attribute.title
}
} else if let attribute = attribute as? ReplyMessageAttribute {
if case let .replyThread(replyThreadMessage) = item.chatLocation, Int32(clamping: replyThreadMessage.threadId) == attribute.messageId.id {
if let threadId = firstMessage.threadId, Int32(clamping: threadId) == attribute.messageId.id {
} else {
replyMessage = firstMessage.associatedMessages[attribute.messageId]
}

View File

@ -531,7 +531,11 @@ public class ChatMessageForwardInfoNode: ASDisplayNode {
avatarNode.frame = CGRect(origin: CGPoint(x: leftOffset, y: titleLayout.size.height + titleAuthorSpacing), size: avatarSize)
avatarNode.updateSize(size: avatarSize)
if let peer {
avatarNode.setPeer(context: context, theme: presentationData.theme.theme, peer: EnginePeer(peer), displayDimensions: avatarSize)
if peer.smallProfileImage != nil {
avatarNode.setPeerV2(context: context, theme: presentationData.theme.theme, peer: EnginePeer(peer), displayDimensions: avatarSize)
} else {
avatarNode.setPeer(context: context, theme: presentationData.theme.theme, peer: EnginePeer(peer), displayDimensions: avatarSize)
}
} else if let authorName, !authorName.isEmpty {
avatarNode.setCustomLetters([String(authorName[authorName.startIndex])])
} else {

View File

@ -322,7 +322,9 @@ public final class ChatMessageItemImpl: ChatMessageItem, CustomStringConvertible
if let channel = content.firstMessage.peers[content.firstMessage.id.peerId] as? TelegramChannel, channel.isForumOrMonoForum {
if case .replyThread = chatLocation {
displayAuthorInfo = false
if channel.isMonoForum && chatLocation.threadId != context.account.peerId.toInt64() {
displayAuthorInfo = false
}
} else {
if channel.isMonoForum {
if let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = content.firstMessage.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil {

View File

@ -38,7 +38,7 @@ public class ChatUnreadItem: ListViewItem {
Queue.mainQueue().async {
completion(node, {
return (nil, { _ in
apply()
apply(.None)
})
})
}
@ -56,7 +56,7 @@ public class ChatUnreadItem: ListViewItem {
let (layout, apply) = nodeLayout(self, params, dateAtBottom)
Queue.mainQueue().async {
completion(layout, { _ in
apply()
apply(animation)
})
}
}
@ -122,18 +122,18 @@ public class ChatUnreadItemNode: ListViewItemNode {
if let item = item as? ChatUnreadItem {
let dateAtBottom = !chatItemsHaveCommonDateHeader(item, nextItem)
let (layout, apply) = self.asyncLayout()(item, params, dateAtBottom)
apply()
apply(.None)
self.contentSize = layout.contentSize
self.insets = layout.insets
}
}
public func asyncLayout() -> (_ item: ChatUnreadItem, _ params: ListViewItemLayoutParams, _ dateAtBottom: Bool) -> (ListViewItemNodeLayout, () -> Void) {
public func asyncLayout() -> (_ item: ChatUnreadItem, _ params: ListViewItemLayoutParams, _ dateAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation) -> Void) {
let labelLayout = TextNode.asyncLayout(self.labelNode)
let layoutConstants = self.layoutConstants
let currentTheme = self.theme
return { item, params, dateAtBottom in
return { [weak self] item, params, dateAtBottom in
var updatedBackgroundImage: UIImage?
if currentTheme != item.presentationData.theme {
updatedBackgroundImage = PresentationResourcesChat.chatUnreadBarBackgroundImage(item.presentationData.theme.theme)
@ -144,7 +144,7 @@ public class ChatUnreadItemNode: ListViewItemNode {
let backgroundSize = CGSize(width: params.width, height: 25.0)
return (ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 25.0), insets: UIEdgeInsets(top: 6.0 + (dateAtBottom ? layoutConstants.timestampHeaderHeight : 0.0), left: 0.0, bottom: 5.0, right: 0.0)), { [weak self] in
return (ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 25.0), insets: UIEdgeInsets(top: 6.0 + (dateAtBottom ? layoutConstants.timestampHeaderHeight : 0.0), left: 0.0, bottom: 5.0, right: 0.0)), { animation in
if let strongSelf = self {
strongSelf.item = item
strongSelf.theme = item.presentationData.theme
@ -159,7 +159,10 @@ public class ChatUnreadItemNode: ListViewItemNode {
strongSelf.activateArea.accessibilityLabel = string
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: backgroundSize)
strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - size.size.width) / 2.0), y: floorToScreenPixels((backgroundSize.height - size.size.height) / 2.0)), size: size.size)
let labelFrame = CGRect(origin: CGPoint(x: params.leftInset + floorToScreenPixels((backgroundSize.width - params.leftInset - params.rightInset - size.size.width) / 2.0), y: floorToScreenPixels((backgroundSize.height - size.size.height) / 2.0)), size: size.size)
animation.animator.updatePosition(layer: strongSelf.labelNode.layer, position: labelFrame.center, completion: nil)
strongSelf.labelNode.bounds = CGRect(origin: CGPoint(), size: labelFrame.size)
if item.controllerInteraction.presentationContext.backgroundNode?.hasExtraBubbleBackground() == true {
if strongSelf.backgroundContent == nil, let backgroundContent = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) {

View File

@ -1148,7 +1148,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
self.superview?.insertSubview(snapshotState.snapshotView, belowSubview: self)
let snapshotView = snapshotState.snapshotView
snapshotState.snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotState.snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.14, removeOnCompletion: false, completion: { [weak snapshotView] _ in
snapshotView?.removeFromSuperview()
})
snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: -offset.x, y: -offset.y), duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true)

View File

@ -127,7 +127,7 @@ import PostSuggestionsSettingsScreen
import ChatSendStarsScreen
extension ChatControllerImpl {
func reloadChatLocation(chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, historyNode: ChatHistoryListNodeImpl, isReady: Promise<Bool>?) {
func reloadChatLocation(chatLocation: ChatLocation, chatLocationContextHolder: Atomic<ChatLocationContextHolder?>, historyNode: ChatHistoryListNodeImpl, apply: @escaping ((Bool) -> Void) -> Void) {
self.contentDataReady.set(false)
self.contentDataDisposable?.dispose()
@ -159,29 +159,42 @@ extension ChatControllerImpl {
self.contentDataDisposable = (contentData.isReady.get()
|> filter { $0 }
|> take(1)
|> deliverOnMainQueue).startStrict(next: { [weak self, weak contentData] _ in
|> deliverOnMainQueue).startStrict(next: { [weak self, weak contentData, weak historyNode] _ in
guard let self, let contentData, self.pendingContentData?.contentData === contentData else {
return
}
self.contentData = contentData
self.pendingContentData = nil
self.contentDataUpdated(synchronous: true, previousState: contentData.state)
self.chatThemeEmoticonPromise.set(contentData.chatThemeEmoticonPromise.get())
self.chatWallpaperPromise.set(contentData.chatWallpaperPromise.get())
self.contentDataReady.set(true)
contentData.onUpdated = { [weak self, weak contentData] previousState in
guard let self, let contentData, self.contentData === contentData else {
apply({ [weak self, weak contentData] forceAnimation in
guard let self, let contentData, self.pendingContentData?.contentData === contentData else {
return
}
self.contentDataUpdated(synchronous: false, previousState: previousState)
}
self.contentData = contentData
self.pendingContentData = nil
self.contentDataUpdated(synchronous: true, forceAnimation: forceAnimation, previousState: contentData.state)
self.chatThemeEmoticonPromise.set(contentData.chatThemeEmoticonPromise.get())
self.chatWallpaperPromise.set(contentData.chatWallpaperPromise.get())
if let historyNode {
self.setupChatHistoryNode(historyNode: historyNode)
historyNode.contentPositionChanged(historyNode.visibleContentOffset())
}
self.contentDataReady.set(true)
contentData.onUpdated = { [weak self, weak contentData] previousState in
guard let self, let contentData, self.contentData === contentData else {
return
}
self.contentDataUpdated(synchronous: false, forceAnimation: false, previousState: previousState)
}
})
})
}
func contentDataUpdated(synchronous: Bool, previousState: ContentData.State) {
func contentDataUpdated(synchronous: Bool, forceAnimation: Bool, previousState: ContentData.State) {
guard let contentData = self.contentData else {
return
}
@ -293,19 +306,23 @@ extension ChatControllerImpl {
if self.presentationInterfaceState.search != nil && contentData.state.hasSearchTags {
displayActionsPanel = true
}
if displayActionsPanel != didDisplayActionsPanel {
animated = true
}
if previousState.pinnedMessage != contentData.state.pinnedMessage {
animated = true
}
if forceAnimation {
animated = true
}
self.updateChatPresentationInterfaceState(animated: animated && self.willAppear, interactive: false, { presentationInterfaceState in
var presentationInterfaceState = presentationInterfaceState
presentationInterfaceState = presentationInterfaceState.updatedPeer({ _ in
return contentData.state.renderedPeer
})
presentationInterfaceState = presentationInterfaceState.updatedChatLocation(contentData.chatLocation)
presentationInterfaceState = presentationInterfaceState.updatedIsNotAccessible(contentData.state.isNotAccessible)
presentationInterfaceState = presentationInterfaceState.updatedContactStatus(contentData.state.contactStatus)
presentationInterfaceState = presentationInterfaceState.updatedHasBots(contentData.state.hasBots)
@ -749,7 +766,7 @@ extension ChatControllerImpl {
})).startStandalone()
}
self.setupChatHistoryNode()
self.setupChatHistoryNode(historyNode: self.chatDisplayNode.historyNode)
self.chatDisplayNode.requestLayout = { [weak self] transition in
self?.requestLayout(transition: transition)
@ -1206,7 +1223,7 @@ extension ChatControllerImpl {
self.scrollToEndOfHistory()
}
} else {
if let messageId = self.historyNavigationStack.removeLast() {
if let messageId = self.contentData?.historyNavigationStack.removeLast() {
self.navigateToMessage(from: nil, to: .id(messageId.id, NavigateToMessageParams(timestamp: nil, quote: nil)), rememberInStack: false)
} else {
if case .known = self.chatDisplayNode.historyNode.visibleContentOffset() {
@ -4295,7 +4312,7 @@ extension ChatControllerImpl {
self.displayNodeDidLoad()
}
func setupChatHistoryNode() {
func setupChatHistoryNode(historyNode: ChatHistoryListNodeImpl) {
do {
let peerId = self.chatLocation.peerId
if let subject = self.subject, case .scheduledMessages = subject {
@ -4582,8 +4599,10 @@ extension ChatControllerImpl {
}
}
self.chatDisplayNode.historyNode.contentPositionChanged = { [weak self] offset in
guard let strongSelf = self else { return }
historyNode.contentPositionChanged = { [weak self, weak historyNode] offset in
guard let strongSelf = self, let historyNode, strongSelf.chatDisplayNode.historyNode === historyNode else {
return
}
var minOffsetForNavigation: CGFloat = 40.0
strongSelf.chatDisplayNode.historyNode.enumerateItemNodes { itemNode in
@ -4632,7 +4651,7 @@ extension ChatControllerImpl {
strongSelf.chatDisplayNode.updatePlainInputSeparatorAlpha(plainInputSeparatorAlpha, transition: .animated(duration: 0.2, curve: .easeInOut))
}
self.chatDisplayNode.historyNode.scrolledToIndex = { [weak self] toSubject, initial in
historyNode.scrolledToIndex = { [weak self] toSubject, initial in
if let strongSelf = self, case let .message(index) = toSubject.index {
if case let .message(messageSubject, _, _, _) = strongSelf.subject, initial, case let .id(messageId) = messageSubject, messageId != index.id {
if messageId.peerId == index.id.peerId {
@ -4693,16 +4712,16 @@ extension ChatControllerImpl {
}
}
self.chatDisplayNode.historyNode.scrolledToSomeIndex = { [weak self] in
historyNode.scrolledToSomeIndex = { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.contentData?.scrolledToMessageIdValue = nil
}
self.chatDisplayNode.historyNode.maxVisibleMessageIndexUpdated = { [weak self] index in
if let strongSelf = self, !strongSelf.historyNavigationStack.isEmpty {
strongSelf.historyNavigationStack.filterOutIndicesLessThan(index)
historyNode.maxVisibleMessageIndexUpdated = { [weak self] index in
if let strongSelf = self, let contentData = strongSelf.contentData, !contentData.historyNavigationStack.isEmpty {
contentData.historyNavigationStack.filterOutIndicesLessThan(index)
}
}
@ -4723,7 +4742,7 @@ extension ChatControllerImpl {
hasActiveCalls = .single(false)
}
let shouldBeActive = combineLatest(self.context.sharedContext.mediaManager.audioSession.isPlaybackActive() |> deliverOnMainQueue, self.chatDisplayNode.historyNode.hasVisiblePlayableItemNodes, hasActiveCalls)
let shouldBeActive = combineLatest(self.context.sharedContext.mediaManager.audioSession.isPlaybackActive() |> deliverOnMainQueue, historyNode.hasVisiblePlayableItemNodes, hasActiveCalls)
|> mapToSignal { [weak self] isPlaybackActive, hasVisiblePlayableItemNodes, hasActiveCalls -> Signal<Bool, NoError> in
if hasVisiblePlayableItemNodes && !isPlaybackActive && !hasActiveCalls {
return Signal<Bool, NoError> { [weak self] subscriber in
@ -4776,7 +4795,7 @@ extension ChatControllerImpl {
downPressed: buttonAction
)
self.chatDisplayNode.historyNode.openNextChannelToRead = { [weak self] peer, threadData, location in
historyNode.openNextChannelToRead = { [weak self] peer, threadData, location in
guard let strongSelf = self else {
return
}
@ -4831,7 +4850,7 @@ extension ChatControllerImpl {
}
}
self.chatDisplayNode.historyNode.beganDragging = { [weak self] in
historyNode.beganDragging = { [weak self] in
guard let self else {
return
}
@ -4846,7 +4865,7 @@ extension ChatControllerImpl {
}
}
self.chatDisplayNode.historyNode.didScrollWithOffset = { [weak self] offset, transition, itemNode, isTracking in
historyNode.didScrollWithOffset = { [weak self] offset, transition, itemNode, isTracking in
guard let strongSelf = self else {
return
}
@ -4876,23 +4895,22 @@ extension ChatControllerImpl {
strongSelf.chatDisplayNode.loadingPlaceholderNode?.addContentOffset(offset: offset, transition: transition)
}
strongSelf.chatDisplayNode.messageTransitionNode.addExternalOffset(offset: offset, transition: transition, itemNode: itemNode, isRotated: strongSelf.chatDisplayNode.historyNode.rotated)
}
self.chatDisplayNode.historyNode.hasAtLeast3MessagesUpdated = { [weak self] hasAtLeast3Messages in
historyNode.hasAtLeast3MessagesUpdated = { [weak self] hasAtLeast3Messages in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(interactive: false, { $0.updatedHasAtLeast3Messages(hasAtLeast3Messages) })
}
}
self.chatDisplayNode.historyNode.hasPlentyOfMessagesUpdated = { [weak self] hasPlentyOfMessages in
historyNode.hasPlentyOfMessagesUpdated = { [weak self] hasPlentyOfMessages in
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(interactive: false, { $0.updatedHasPlentyOfMessages(hasPlentyOfMessages) })
}
}
if self.didAppear {
self.chatDisplayNode.historyNode.canReadHistory.set(self.computedCanReadHistoryPromise.get())
historyNode.canReadHistory.set(self.computedCanReadHistoryPromise.get())
}
}
}

View File

@ -317,7 +317,7 @@ extension ChatControllerImpl {
})
} else if forceInCurrentChat {
if let _ = fromId, let fromIndex = fromIndex, rememberInStack {
self.historyNavigationStack.add(fromIndex)
self.contentData?.historyNavigationStack.add(fromIndex)
}
let scrollFromIndex: MessageIndex?
@ -505,7 +505,7 @@ extension ChatControllerImpl {
return
}
if let _ = fromId, rememberInStack {
self.historyNavigationStack.add(fromIndex)
self.contentData?.historyNavigationStack.add(fromIndex)
}
self.loadingMessage.set(.single(statusSubject) |> delay(0.1, queue: .mainQueue()))

View File

@ -23,8 +23,6 @@ func updateChatPresentationInterfaceStateImpl(
_ f: (ChatPresentationInterfaceState) -> ChatPresentationInterfaceState,
completion externalCompletion: @escaping (ContainedViewLayoutTransition) -> Void
) {
let previousChatLocation = selfController.chatDisplayNode.historyNode.chatLocation
var completion = externalCompletion
var temporaryChatPresentationInterfaceState = f(selfController.presentationInterfaceState)
@ -436,13 +434,13 @@ func updateChatPresentationInterfaceStateImpl(
selfController.presentationInterfaceState = updatedChatPresentationInterfaceState
if selfController.chatDisplayNode.chatLocation != selfController.presentationInterfaceState.chatLocation {
/*if selfController.chatDisplayNode.chatLocation != selfController.presentationInterfaceState.chatLocation {
let defaultDirection: ChatControllerAnimateInnerChatSwitchDirection? = selfController.chatDisplayNode.chatLocationTabSwitchDirection(from: selfController.chatLocation.threadId, to: selfController.presentationInterfaceState.chatLocation.threadId).flatMap { direction -> ChatControllerAnimateInnerChatSwitchDirection in
return direction ? .right : .left
}
let tabSwitchDirection = selfController.currentChatSwitchDirection ?? defaultDirection
selfController.chatDisplayNode.updateChatLocation(chatLocation: selfController.presentationInterfaceState.chatLocation, transition: transition, tabSwitchDirection: tabSwitchDirection)
}
}*/
selfController.updateSlowmodeStatus()
@ -603,12 +601,6 @@ func updateChatPresentationInterfaceStateImpl(
}
}
if previousChatLocation != selfController.presentationInterfaceState.chatLocation {
selfController.chatLocation = selfController.presentationInterfaceState.chatLocation
selfController.reloadCachedData()
selfController.setupChatHistoryNode()
}
selfController.updateDownButtonVisibility()
if selfController.presentationInterfaceState.hasBirthdayToday {

View File

@ -389,8 +389,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var searchDisposable: MetaDisposable?
var historyNavigationStack = ChatHistoryNavigationStack()
public let canReadHistory = ValuePromise<Bool>(true, ignoreRepeated: true)
public let hasBrowserOrAppInFront = Promise<Bool>(false)
@ -5230,7 +5228,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}
self.reloadChatLocation(chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, historyNode: self.chatDisplayNode.historyNode, isReady: nil)
self.reloadChatLocation(chatLocation: self.chatLocation, chatLocationContextHolder: self.chatLocationContextHolder, historyNode: self.chatDisplayNode.historyNode, apply: { $0(false) })
self.botCallbackAlertMessageDisposable = (self.botCallbackAlertMessage.get()
|> deliverOnMainQueue).startStrict(next: { [weak self] message in
@ -9711,10 +9709,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var currentChatSwitchDirection: ChatControllerAnimateInnerChatSwitchDirection?
public func updateChatLocationThread(threadId: Int64?, animationDirection: ChatControllerAnimateInnerChatSwitchDirection? = nil) {
/*if self.isUpdatingChatLocationThread {
if self.isUpdatingChatLocationThread {
return
}
guard let peerId = self.chatLocation.peerId else {
return
}
@ -9725,16 +9722,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
let navigationSnapshot = self.chatTitleView?.prepareSnapshotState()
//let historyNode = self.chatDisplayNode.createHistoryNodeForChatLocation(chatLocation: self.chatLocation, chatLocationContextHolder: )
let rightBarButtonItemSnapshots: [(UIView, CGRect)] = (self.navigationItem.rightBarButtonItems ?? []).compactMap { item -> (UIView, CGRect)? in
guard let view = item.customDisplayNode?.view, let snapshotView = view.snapshotView(afterScreenUpdates: false) else {
return nil
}
return (snapshotView, view.convert(view.bounds, to: self.view))
}
self.saveInterfaceState()
let updatedChatLocation: ChatLocation
if let threadId {
@ -9762,6 +9750,77 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
updatedChatLocation = .peer(id: peerId)
}
let navigationSnapshot = self.chatTitleView?.prepareSnapshotState()
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
let historyNode = self.chatDisplayNode.createHistoryNodeForChatLocation(chatLocation: updatedChatLocation, chatLocationContextHolder: chatLocationContextHolder)
self.isUpdatingChatLocationThread = true
self.reloadChatLocation(chatLocation: updatedChatLocation, chatLocationContextHolder: chatLocationContextHolder, historyNode: historyNode, apply: { [weak self, weak historyNode] apply in
guard let self, let historyNode else {
return
}
self.currentChatSwitchDirection = animationDirection
self.chatLocation = updatedChatLocation
self.chatDisplayNode.prepareSwitchToChatLocation(historyNode: historyNode, animationDirection: animationDirection)
apply(true)
if let navigationSnapshot, let animationDirection {
let mappedAnimationDirection: ChatTitleView.AnimateFromSnapshotDirection
switch animationDirection {
case .up:
mappedAnimationDirection = .up
case .down:
mappedAnimationDirection = .down
case .left:
mappedAnimationDirection = .left
case .right:
mappedAnimationDirection = .right
}
self.chatTitleView?.animateFromSnapshot(navigationSnapshot, direction: mappedAnimationDirection)
/*if let rightBarButtonItems = self.navigationItem.rightBarButtonItems {
for i in 0 ..< rightBarButtonItems.count {
let item = rightBarButtonItems[i]
if let customDisplayNode = item.customDisplayNode {
customDisplayNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
//customDisplayNode.layer.animateScale(from: 0.001, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
let _ = rightBarButtonItemSnapshots
/*if i < rightBarButtonItemSnapshots.count {
let (snapshotItem, snapshotFrame) = rightBarButtonItemSnapshots[i]
if let targetSuperview = customDisplayNode.view.superview {
snapshotItem.frame = targetSuperview.convert(snapshotFrame, from: self.view)
targetSuperview.addSubview(snapshotItem)
snapshotItem.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, completion: { [weak snapshotItem] _ in
snapshotItem?.removeFromSuperview()
})
snapshotItem.layer.animateScale(from: 1.0, to: 0.1, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring)
}
}*/
}
}
}*/
}
self.currentChatSwitchDirection = nil
self.isUpdatingChatLocationThread = false
})
/*
//
let rightBarButtonItemSnapshots: [(UIView, CGRect)] = (self.navigationItem.rightBarButtonItems ?? []).compactMap { item -> (UIView, CGRect)? in
guard let view = item.customDisplayNode?.view, let snapshotView = view.snapshotView(afterScreenUpdates: false) else {
return nil
}
return (snapshotView, view.convert(view.bounds, to: self.view))
}
let isReady = Promise<Bool>()
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
self.reloadChatLocation(chatLocation: updatedChatLocation, chatLocationContextHolder: chatLocationContextHolder, historyNode: historyNode, isReady: isReady)

View File

@ -144,6 +144,7 @@ extension ChatControllerImpl {
private let isChatLocationInfoReady = ValuePromise<Bool>(false, ignoreRepeated: true)
private let isCachedDataReady = ValuePromise<Bool>(false, ignoreRepeated: true)
let chatLocation: ChatLocation
let chatLocationInfoData: ChatLocationInfoData
private(set) var state: State = State()
@ -172,6 +173,8 @@ extension ChatControllerImpl {
}
}
var historyNavigationStack = ChatHistoryNavigationStack()
let chatThemeEmoticonPromise = Promise<String?>()
let chatWallpaperPromise = Promise<TelegramWallpaper?>()
@ -191,6 +194,7 @@ extension ChatControllerImpl {
presentationData: PresentationData,
historyNode: ChatHistoryListNodeImpl
) {
self.chatLocation = chatLocation
self.presentationData = presentationData
let strings = self.presentationData.strings

View File

@ -133,6 +133,19 @@ class HistoryNodeContainer: ASDisplayNode {
}
}
private final class PendingSwitchToChatLocation {
let historyNode: ChatHistoryListNodeImpl
let animationDirection: ChatControllerAnimateInnerChatSwitchDirection?
init(
historyNode: ChatHistoryListNodeImpl,
animationDirection: ChatControllerAnimateInnerChatSwitchDirection?
) {
self.historyNode = historyNode
self.animationDirection = animationDirection
}
}
class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
let context: AccountContext
private(set) var chatLocation: ChatLocation
@ -162,7 +175,10 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
var historyNode: ChatHistoryListNodeImpl
var blurredHistoryNode: ASImageNode?
let historyNodeContainer: HistoryNodeContainer
let loadingNode: ChatLoadingNode
private(set) var loadingNode: ChatLoadingNode
private var isLoadingValue: Bool = false
private var isLoadingEarlier: Bool = false
private(set) var loadingPlaceholderNode: ChatLoadingPlaceholderNode?
var alwaysShowSearchResultsAsList: Bool = false
@ -316,8 +332,8 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
let adMessagesContext: AdMessagesHistoryContext?
private var isLoadingValue: Bool = false
private var isLoadingEarlier: Bool = false
private var pendingSwitchToChatLocation: PendingSwitchToChatLocation?
private func updateIsLoading(isLoading: Bool, earlier: Bool, animated: Bool) {
var useLoadingPlaceholder = self.chatLocation.peerId?.namespace != Namespaces.Peer.CloudUser && self.chatLocation.peerId?.namespace != Namespaces.Peer.SecretChat
if case let .replyThread(message) = self.chatLocation, message.peerId == self.context.account.peerId {
@ -351,10 +367,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
loadingPlaceholderNode.setup(self.historyNode, updating: false)
if let (layout, navigationHeight) = self.validLayout {
self.containerLayoutUpdated(layout, navigationBarHeight: navigationHeight, transition: .immediate, listViewTransaction: { _, _, _, _ in
}, updateExtraNavigationBarBackgroundHeight: { _, _, _, _ in
})
let contentBounds = self.loadingNode.frame
loadingPlaceholderNode.frame = contentBounds
if let loadingPlaceholderNode = self.loadingPlaceholderNode, let validLayout = self.validLayout {
loadingPlaceholderNode.updateLayout(size: contentBounds.size, insets: self.visibleAreaInset, metrics: validLayout.0.metrics, transition: .immediate)
loadingPlaceholderNode.update(rect: contentBounds, within: contentBounds.size, transition: .immediate)
}
}
loadingPlaceholderNode.alpha = 1.0
@ -371,12 +388,17 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
} else {
if useLoadingPlaceholder {
if let loadingPlaceholderNode = self.loadingPlaceholderNode {
loadingPlaceholderNode.animateOut(self.historyNode, completion: { [weak self] in
if let strongSelf = self {
strongSelf.loadingPlaceholderNode?.removeFromSupernode()
strongSelf.loadingPlaceholderNode = nil
}
})
if animated {
loadingPlaceholderNode.animateOut(self.historyNode, completion: { [weak self] in
if let strongSelf = self {
strongSelf.loadingPlaceholderNode?.removeFromSupernode()
strongSelf.loadingPlaceholderNode = nil
}
})
} else {
self.loadingPlaceholderNode = nil
loadingPlaceholderNode.removeFromSupernode()
}
}
} else {
self.loadingNode.alpha = 0.0
@ -1295,8 +1317,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
self.containerLayoutAndNavigationBarHeight = (layout, navigationBarHeight)
var extraTransition = transition
var dismissedTitleTopicsAccessoryPanelNode: ChatTopicListTitleAccessoryPanelNode?
var immediatelyLayoutTitleTopicsAccessoryPanelNodeAndAnimateAppearance = false
var titleTopicsAccessoryPanelHeight: CGFloat?
@ -1357,9 +1377,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.titleAccessoryPanelContainer.addSubnode(titleAccessoryPanelNode)
titleAccessoryPanelNode.clipsToBounds = true
if transition.isAnimated {
extraTransition = .animated(duration: 0.2, curve: .easeInOut)
}
}
let layoutResult = titleAccessoryPanelNode.updateLayout(width: layout.size.width, leftInset: leftPanelSize?.width ?? layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: immediatelyLayoutTitleAccessoryPanelNodeAndAnimateAppearance ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState)
@ -1367,9 +1384,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
titleAccessoryPanelBackgroundHeight = layoutResult.backgroundHeight
titleAccessoryPanelHitTestSlop = layoutResult.hitTestSlop
if immediatelyLayoutTitleAccessoryPanelNodeAndAnimateAppearance {
titleAccessoryPanelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
if transition.isAnimated {
titleAccessoryPanelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
titleAccessoryPanelNode.subnodeTransform = CATransform3DMakeTranslation(0.0, -layoutResult.backgroundHeight, 0.0)
extraTransition.updateSublayerTransformOffset(layer: titleAccessoryPanelNode.layer, offset: CGPoint())
transition.updateSublayerTransformOffset(layer: titleAccessoryPanelNode.layer, offset: CGPoint())
}
} else if let titleAccessoryPanelNode = self.titleAccessoryPanelNode {
dismissedTitleAccessoryPanelNode = titleAccessoryPanelNode
@ -1412,9 +1431,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
self.titleAccessoryPanelContainer.addSubnode(translationPanelNode)
translationPanelNode.clipsToBounds = true
if transition.isAnimated {
extraTransition = .animated(duration: 0.2, curve: .easeInOut)
}
}
let height = translationPanelNode.updateLayout(width: layout.size.width, leftInset: leftPanelSize?.width ?? layout.safeInsets.left, rightInset: layout.safeInsets.right, transition: immediatelyLayoutTitleAccessoryPanelNodeAndAnimateAppearance ? .immediate : transition, interfaceState: self.chatPresentationInterfaceState)
@ -1422,7 +1438,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
if immediatelyLayoutTranslationPanelNodeAndAnimateAppearance {
translationPanelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
translationPanelNode.subnodeTransform = CATransform3DMakeTranslation(0.0, -height, 0.0)
extraTransition.updateSublayerTransformOffset(layer: translationPanelNode.layer, offset: CGPoint())
transition.updateSublayerTransformOffset(layer: translationPanelNode.layer, offset: CGPoint())
}
} else if let chatTranslationPanel = self.chatTranslationPanel {
dismissedTranslationPanelNode = chatTranslationPanel
@ -1803,18 +1819,6 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
wrappingInsets.top += statusBarHeight
}
}
var isSelectionEnabled = true
if previewing {
isSelectionEnabled = false
} else if case .pinnedMessages = self.chatPresentationInterfaceState.subject {
isSelectionEnabled = false
} else if self.chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState != nil {
isSelectionEnabled = false
} else if case .customChatContents = self.chatLocation {
isSelectionEnabled = false
}
self.historyNode.isSelectionGestureEnabled = isSelectionEnabled
transition.updateFrame(node: self.titleAccessoryPanelContainer, frame: CGRect(origin: CGPoint(x: 0.0, y: insets.top), size: CGSize(width: layout.size.width, height: 200.0)))
self.titleAccessoryPanelContainer.hitTestExcludeInsets = UIEdgeInsets(top: 0.0, left: leftPanelSize?.width ?? 0.0, bottom: 0.0, right: 0.0)
@ -1839,6 +1843,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
var titleAccessoryPanelFrame: CGRect?
let titleAccessoryPanelBaseY = titlePanelsContentOffset
if let _ = self.titleAccessoryPanelNode, let panelHeight = titleAccessoryPanelHeight {
titleAccessoryPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: titlePanelsContentOffset), size: CGSize(width: layout.size.width, height: panelHeight))
insets.top += panelHeight
@ -1881,7 +1886,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
extraNavigationBarLeftCutout = CGSize(width: 0.0, height: navigationBarHeight)
}
updateExtraNavigationBarBackgroundHeight(extraNavigationBarHeight, extraNavigationBarHitTestSlop, extraNavigationBarLeftCutout, extraTransition)
updateExtraNavigationBarBackgroundHeight(extraNavigationBarHeight, extraNavigationBarHitTestSlop, extraNavigationBarLeftCutout, transition)
let contentBounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width - wrappingInsets.left - wrappingInsets.right, height: layout.size.height - wrappingInsets.top - wrappingInsets.bottom)
@ -1908,13 +1913,154 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
transition.updateBounds(node: self.historyNodeContainer, bounds: contentBounds)
transition.updatePosition(node: self.historyNodeContainer, position: contentBounds.center)
transition.updateBounds(node: self.historyNode, bounds: CGRect(origin: CGPoint(), size: contentBounds.size))
transition.updatePosition(node: self.historyNode, position: CGPoint(x: contentBounds.size.width / 2.0, y: contentBounds.size.height / 2.0))
if let pendingSwitchToChatLocation = self.pendingSwitchToChatLocation {
self.pendingSwitchToChatLocation = nil
let previousHistoryNode = self.historyNode
self.historyNode = pendingSwitchToChatLocation.historyNode
self.historyNode.position = previousHistoryNode.position
self.historyNode.bounds = previousHistoryNode.bounds
self.historyNode.transform = previousHistoryNode.transform
self.historyNode.messageTransitionNode = { [weak self] in
guard let self else {
return nil
}
return self.messageTransitionNode
}
transition.updateBounds(node: self.historyNode, bounds: CGRect(origin: CGPoint(), size: contentBounds.size))
transition.updatePosition(node: self.historyNode, position: CGPoint(x: contentBounds.size.width / 2.0, y: contentBounds.size.height / 2.0))
previousHistoryNode.supernode?.insertSubnode(self.historyNode, aboveSubnode: previousHistoryNode)
let messageTransitionNode = ChatMessageTransitionNodeImpl(listNode: self.historyNode, getContentAreaInScreenSpace: { [weak self] in
guard let self else {
return CGRect()
}
return self.view.convert(self.frameForVisibleArea(), to: nil)
}, onTransitionEvent: { [weak self] transition in
guard let self else {
return
}
if (self.context.sharedContext.currentPresentationData.with({ $0 })).reduceMotion {
return
}
if self.context.sharedContext.energyUsageSettings.fullTranslucency {
self.backgroundNode.animateEvent(transition: transition, extendAnimation: false)
}
})
let previousMessageTransitionNode = self.messageTransitionNode
self.messageTransitionNode = messageTransitionNode
messageTransitionNode.position = previousMessageTransitionNode.position
messageTransitionNode.bounds = previousMessageTransitionNode.bounds
messageTransitionNode.transform = previousMessageTransitionNode.transform
self.wrappingNode.contentNode.insertSubnode(self.messageTransitionNode, aboveSubnode: previousMessageTransitionNode)
self.emptyType = nil
self.isLoadingValue = false
self.isLoadingEarlier = false
let previousLoadingNode = self.loadingNode
self.loadingNode = ChatLoadingNode(context: self.context, theme: self.chatPresentationInterfaceState.theme, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper, bubbleCorners: self.chatPresentationInterfaceState.bubbleCorners)
self.loadingNode.frame = previousLoadingNode.frame
self.loadingNode.isHidden = previousLoadingNode.isHidden
self.loadingNode.alpha = previousLoadingNode.alpha
previousLoadingNode.supernode?.insertSubnode(self.loadingNode, aboveSubnode: previousLoadingNode)
let previousLoadingPlaceholderNode = self.loadingPlaceholderNode
self.loadingPlaceholderNode = nil
let previousEmptyNode = self.emptyNode
self.emptyNode = nil
self.setupHistoryNode()
self.historyNode.loadStateUpdated?(self.historyNode.loadState ?? .messages, false)
if let animationDirection = pendingSwitchToChatLocation.animationDirection {
var offsetMultiplier = CGPoint()
switch animationDirection {
case .up:
offsetMultiplier.y = -1.0
case .down:
offsetMultiplier.y = 1.0
case .left:
offsetMultiplier.x = -1.0
case .right:
offsetMultiplier.x = 1.0
}
previousHistoryNode.clipsToBounds = true
self.historyNode.clipsToBounds = true
transition.animatePosition(layer: self.historyNode.layer, from: CGPoint(x: offsetMultiplier.x * layout.size.width, y: offsetMultiplier.y * layout.size.height), to: CGPoint(), removeOnCompletion: true, additive: true, completion: { [weak self] _ in
guard let self else {
return
}
self.historyNode.clipsToBounds = false
})
transition.animatePosition(layer: previousHistoryNode.layer, from: CGPoint(), to: CGPoint(x: -offsetMultiplier.x * layout.size.width, y: -offsetMultiplier.y * layout.size.height), removeOnCompletion: false, additive: true, completion: { [weak previousHistoryNode] _ in
previousHistoryNode?.removeFromSupernode()
})
transition.animatePosition(layer: self.messageTransitionNode.layer, from: CGPoint(x: offsetMultiplier.x * layout.size.width, y: offsetMultiplier.y * layout.size.height), to: CGPoint(), removeOnCompletion: true, additive: true)
transition.animatePosition(layer: previousMessageTransitionNode.layer, from: CGPoint(), to: CGPoint(x: -offsetMultiplier.x * layout.size.width, y: -offsetMultiplier.y * layout.size.height), removeOnCompletion: false, additive: true, completion: { [weak previousMessageTransitionNode] _ in
previousMessageTransitionNode?.removeFromSupernode()
})
transition.animatePosition(layer: self.loadingNode.layer, from: CGPoint(x: offsetMultiplier.x * layout.size.width, y: offsetMultiplier.y * layout.size.height), to: CGPoint(), removeOnCompletion: true, additive: true)
transition.animatePosition(layer: previousLoadingNode.layer, from: CGPoint(), to: CGPoint(x: -offsetMultiplier.x * layout.size.width, y: -offsetMultiplier.y * layout.size.height), removeOnCompletion: false, additive: true, completion: { [weak previousLoadingNode] _ in
previousLoadingNode?.removeFromSupernode()
})
if let loadingPlaceholderNode = self.loadingPlaceholderNode {
transition.animatePosition(layer: loadingPlaceholderNode.layer, from: CGPoint(x: offsetMultiplier.x * layout.size.width, y: offsetMultiplier.y * layout.size.height), to: CGPoint(), removeOnCompletion: true, additive: true)
}
if let previousLoadingPlaceholderNode {
transition.animatePosition(layer: previousLoadingPlaceholderNode.layer, from: CGPoint(), to: CGPoint(x: -offsetMultiplier.x * layout.size.width, y: -offsetMultiplier.y * layout.size.height), removeOnCompletion: false, additive: true, completion: { [weak previousLoadingPlaceholderNode] _ in
previousLoadingPlaceholderNode?.removeFromSupernode()
})
}
if let emptyNode = self.emptyNode {
transition.animatePosition(layer: emptyNode.layer, from: CGPoint(x: offsetMultiplier.x * layout.size.width, y: offsetMultiplier.y * layout.size.height), to: CGPoint(), removeOnCompletion: true, additive: true)
}
if let previousEmptyNode {
transition.animatePosition(layer: previousEmptyNode.layer, from: CGPoint(), to: CGPoint(x: -offsetMultiplier.x * layout.size.width, y: -offsetMultiplier.y * layout.size.height), removeOnCompletion: false, additive: true, completion: { [weak previousEmptyNode] _ in
previousEmptyNode?.removeFromSupernode()
})
}
} else {
previousHistoryNode.removeFromSupernode()
previousMessageTransitionNode.removeFromSupernode()
previousLoadingNode.removeFromSupernode()
previousLoadingPlaceholderNode?.removeFromSupernode()
previousEmptyNode?.removeFromSupernode()
}
} else {
transition.updateBounds(node: self.historyNode, bounds: CGRect(origin: CGPoint(), size: contentBounds.size))
transition.updatePosition(node: self.historyNode, position: CGPoint(x: contentBounds.size.width / 2.0, y: contentBounds.size.height / 2.0))
}
if let blurredHistoryNode = self.blurredHistoryNode {
transition.updateFrame(node: blurredHistoryNode, frame: contentBounds)
}
//transition.updateFrame(node: self.historyScrollingArea, frame: contentBounds)
var isSelectionEnabled = true
if previewing {
isSelectionEnabled = false
} else if case .pinnedMessages = self.chatPresentationInterfaceState.subject {
isSelectionEnabled = false
} else if self.chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState != nil {
isSelectionEnabled = false
} else if case .customChatContents = self.chatLocation {
isSelectionEnabled = false
}
self.historyNode.isSelectionGestureEnabled = isSelectionEnabled
transition.updateFrame(node: self.loadingNode, frame: contentBounds)
if let loadingPlaceholderNode = self.loadingPlaceholderNode {
@ -2552,7 +2698,13 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
if let dismissedTitleAccessoryPanelNode {
var dismissedPanelFrame = dismissedTitleAccessoryPanelNode.frame
dismissedPanelFrame.origin.y = -dismissedPanelFrame.size.height
transition.updateSublayerTransformOffset(layer: dismissedTitleAccessoryPanelNode.layer, offset: CGPoint(x: 0.0, y: -dismissedPanelFrame.height))
dismissedPanelFrame.origin.y = titleAccessoryPanelBaseY
dismissedTitleAccessoryPanelNode.clipsToBounds = true
dismissedPanelFrame.size.height = 0.0
if transition.isAnimated {
dismissedTitleAccessoryPanelNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
}
transition.updateFrame(node: dismissedTitleAccessoryPanelNode, frame: dismissedPanelFrame, completion: { [weak dismissedTitleAccessoryPanelNode] _ in
dismissedTitleAccessoryPanelNode?.removeFromSupernode()
})
@ -5078,9 +5230,27 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
return nil
}
)
historyNode.position = self.historyNode.position
historyNode.bounds = self.historyNode.bounds
historyNode.transform = self.historyNode.transform
if let currentListViewLayout = self.currentListViewLayout {
let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: currentListViewLayout.size, insets: currentListViewLayout.insets, scrollIndicatorInsets: currentListViewLayout.scrollIndicatorInsets, duration: 0.0, curve: .Default(duration: nil), ensureTopInsetForOverlayHighlightedItems: nil, customAnimationTransition: nil)
historyNode.updateLayout(transition: .immediate, updateSizeAndInsets: updateSizeAndInsets, additionalScrollDistance: 0.0, scrollToTop: false, completion: {})
}
return historyNode
}
func prepareSwitchToChatLocation(historyNode: ChatHistoryListNodeImpl, animationDirection: ChatControllerAnimateInnerChatSwitchDirection?) {
self.chatLocation = historyNode.chatLocation
self.pendingSwitchToChatLocation = PendingSwitchToChatLocation(
historyNode: historyNode,
animationDirection: animationDirection
)
}
func updateChatLocation(chatLocation: ChatLocation, transition: ContainedViewLayoutTransition, tabSwitchDirection: ChatControllerAnimateInnerChatSwitchDirection?) {
if chatLocation == self.chatLocation {
return

View File

@ -667,7 +667,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
public var contentPositionChanged: (ListViewVisibleContentOffset) -> Void = { _ in }
public private(set) var loadState: ChatHistoryNodeLoadState?
private var loadStateUpdated: ((ChatHistoryNodeLoadState, Bool) -> Void)?
public private(set) var loadStateUpdated: ((ChatHistoryNodeLoadState, Bool) -> Void)?
private var additionalLoadStateUpdated: [(ChatHistoryNodeLoadState, Bool) -> Void] = []
public private(set) var hasAtLeast3Messages: Bool = false
@ -1830,11 +1830,6 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
let initialData: ChatHistoryCombinedInitialData?
switch update.0 {
case let .Loading(combinedInitialData, type):
if case .Generic(.FillHole) = type {
applyHole()
return
}
initialData = combinedInitialData
if resetScrolling, let previousViewValue = previousView.with({ $0 })?.0 {
@ -1891,13 +1886,6 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
Queue.mainQueue().async {
if let strongSelf = self {
if !strongSelf.didSetInitialData {
strongSelf.didSetInitialData = true
var combinedInitialData = combinedInitialData
combinedInitialData?.cachedData = nil
strongSelf._initialData.set(.single(combinedInitialData))
}
let cachedData = initialData?.cachedData
let cachedDataMessages = initialData?.cachedDataMessages
@ -1917,8 +1905,30 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
strongSelf.currentHistoryState = historyState
strongSelf.historyState.set(historyState)
}
if !strongSelf.didSetInitialData {
strongSelf.didSetInitialData = true
var combinedInitialData = combinedInitialData
combinedInitialData?.cachedData = nil
strongSelf._initialData.set(.single(combinedInitialData))
}
strongSelf._isReady.set(true)
if !strongSelf.didSetReady {
strongSelf.didSetReady = true
#if DEBUG
let deltaTime = (CFAbsoluteTimeGetCurrent() - strongSelf.initTimestamp) * 1000.0
print("Chat init to dequeue time: \(deltaTime) ms")
#endif
}
}
}
if case .Generic(.FillHole) = type {
applyHole()
return
}
return
case let .HistoryView(view, type, scrollPosition, flashIndicators, originalScrollPosition, data, id):
if case .Generic(.FillHole) = type {

View File

@ -230,10 +230,6 @@ func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceStat
}
func titleTopicsPanelForChatPresentationInterfaceState(_ chatPresentationInterfaceState: ChatPresentationInterfaceState, context: AccountContext, currentPanel: ChatTitleAccessoryPanelNode?, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, force: Bool) -> ChatTopicListTitleAccessoryPanelNode? {
//TODO:release
if "".isEmpty {
return nil
}
if let channel = chatPresentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.isForumOrMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = chatPresentationInterfaceState.renderedPeer?.peers[linkedMonoforumId] as? TelegramChannel, mainChannel.adminRights != nil, chatPresentationInterfaceState.search == nil {
let topicListDisplayMode = chatPresentationInterfaceState.topicListDisplayMode ?? .top
if case .top = topicListDisplayMode, let peerId = chatPresentationInterfaceState.chatLocation.peerId {