diff --git a/submodules/AnimatedCountLabelNode/Sources/AnimatedCountLabelNode.swift b/submodules/AnimatedCountLabelNode/Sources/AnimatedCountLabelNode.swift index e2c74740fa..bf51bd44de 100644 --- a/submodules/AnimatedCountLabelNode/Sources/AnimatedCountLabelNode.swift +++ b/submodules/AnimatedCountLabelNode/Sources/AnimatedCountLabelNode.swift @@ -135,7 +135,7 @@ public class AnimatedCountLabelNode: ASDisplayNode { textNode.layer.animateScale(from: 0.1, to: 1.0, duration: 0.2) textNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } - } else { + } else if textNode.frame != textFrame { transition.updateFrameAdditive(node: textNode, frame: textFrame) } currentOffset.x += layout.size.width diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 847a09c0d7..d6d04f5689 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -2195,7 +2195,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } - strongSelf.openMessageReplies(messageId: messageId, isChannelPost: isChannelPost, atMessage: nil, displayModalProgress: displayModalProgress) + strongSelf.openMessageReplies(messageId: messageId, displayProgressInMessage: displayModalProgress ? nil : messageId, isChannelPost: isChannelPost, atMessage: nil, displayModalProgress: displayModalProgress) }, openReplyThreadOriginalMessage: { [weak self] message in guard let strongSelf = self else { return @@ -2211,7 +2211,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let attribute = attribute as? SourceReferenceMessageAttribute { if let threadMessageId = threadMessageId { if let _ = strongSelf.navigationController as? NavigationController { - strongSelf.openMessageReplies(messageId: threadMessageId, isChannelPost: true, atMessage: attribute.messageId, displayModalProgress: true) + strongSelf.openMessageReplies(messageId: threadMessageId, displayProgressInMessage: message.id, isChannelPost: true, atMessage: attribute.messageId, displayModalProgress: false) } } else { strongSelf.navigateToMessage(from: nil, to: .id(attribute.messageId)) @@ -3491,7 +3491,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }) - self.ready.set(combineLatest(self.chatDisplayNode.historyNode.historyState.get(), self._chatLocationInfoReady.get(), self.cachedDataReady.get(), initialData) |> map { _, chatLocationInfoReady, cachedDataReady, _ in + let effectiveCachedDataReady: Signal + if case .replyThread = self.chatLocation { + effectiveCachedDataReady = self.cachedDataReady.get() + } else { + effectiveCachedDataReady = .single(true) + } + self.ready.set(combineLatest(self.chatDisplayNode.historyNode.historyState.get(), self._chatLocationInfoReady.get(), effectiveCachedDataReady, initialData) |> map { _, chatLocationInfoReady, cachedDataReady, _ in return chatLocationInfoReady && cachedDataReady }) @@ -5402,6 +5408,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatDisplayNode.historyNode.refreshPollActionsForVisibleMessages() } else { self.willAppear = true + + // Limit this to reply threads just to be safe now + if case .replyThread = self.chatLocation { + self.chatDisplayNode.historyNode.refocusOnUnreadMessagesIfNeeded() + } } if self.scheduledActivateInput { @@ -8329,12 +8340,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } - private func openMessageReplies(messageId: MessageId, isChannelPost: Bool, atMessage atMessageId: MessageId?, displayModalProgress: Bool) { + private func openMessageReplies(messageId: MessageId, displayProgressInMessage: MessageId?, isChannelPost: Bool, atMessage atMessageId: MessageId?, displayModalProgress: Bool) { guard let navigationController = self.navigationController as? NavigationController else { return } - if !displayModalProgress, self.controllerInteraction?.currentMessageWithLoadingReplyThread == messageId { + if let displayProgressInMessage = displayProgressInMessage, self.controllerInteraction?.currentMessageWithLoadingReplyThread == displayProgressInMessage { return } @@ -8343,12 +8354,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return EmptyDisposable } - if !displayModalProgress, controllerInteraction.currentMessageWithLoadingReplyThread != messageId { + if let displayProgressInMessage = displayProgressInMessage, controllerInteraction.currentMessageWithLoadingReplyThread != displayProgressInMessage { let previousId = controllerInteraction.currentMessageWithLoadingReplyThread - controllerInteraction.currentMessageWithLoadingReplyThread = messageId - strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(messageId) + controllerInteraction.currentMessageWithLoadingReplyThread = displayProgressInMessage + strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage) if let previousId = previousId { - strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(previousId) + strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage) } } @@ -8357,9 +8368,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else { return } - if !displayModalProgress, controllerInteraction.currentMessageWithLoadingReplyThread == messageId { + if let displayProgressInMessage = displayProgressInMessage, controllerInteraction.currentMessageWithLoadingReplyThread == messageId { controllerInteraction.currentMessageWithLoadingReplyThread = nil - strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(messageId) + strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage) } } } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index deae37c2e9..7de9a8402d 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -420,7 +420,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if isLoading != self.isLoadingValue { self.isLoadingValue = isLoading if isLoading { - self.historyNodeContainer.supernode?.insertSubnode(self.loadingNode, aboveSubnode: self.historyNodeContainer) + self.historyNodeContainer.supernode?.insertSubnode(self.loadingNode, belowSubnode: self.historyNodeContainer) self.loadingNode.layer.removeAllAnimations() self.loadingNode.alpha = 1.0 if animated { diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index cb1c6ce36f..5408fe3285 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -1108,6 +1108,14 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.updateVisibleItemRange(force: true) } + func refocusOnUnreadMessagesIfNeeded() { + self.forEachItemNode({ itemNode in + if let itemNode = itemNode as? ChatUnreadItemNode { + self.ensureItemNodeVisible(itemNode, animated: false, overflow: 0.0, curve: .Default(duration: nil)) + } + }) + } + private func processDisplayedItemRangeChanged(displayedRange: ListViewDisplayedItemRange, transactionState: ChatHistoryTransactionOpaqueState) { let historyView = transactionState.historyView var isTopReplyThreadMessageShownValue = false diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift index 42e7e08dd7..0dd763ed33 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsHistoryTransition.swift @@ -649,18 +649,60 @@ struct ChatRecentActionsEntry: Comparable, Identifiable { } else { var appendedRightsHeader = false - if case let .creator(_, _, prevRank) = prev.participant, case let .creator(_, _, newRank) = new.participant, prevRank != newRank { - appendAttributedText(text: new.peer.addressName == nil ? self.presentationData.strings.Channel_AdminLog_MessageRankName(new.peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), newRank ?? "") : self.presentationData.strings.Channel_AdminLog_MessageRankUsername(new.peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), "@" + new.peer.addressName!, newRank ?? ""), generateEntities: { index in - var result: [MessageTextEntityType] = [] - if index == 0 { - result.append(.TextMention(peerId: new.peer.id)) - } else if index == 1 { - result.append(.Mention) - } else if index == 2 { - result.append(.Bold) + if case let .creator(_, prevAdminInfo, prevRank) = prev.participant, case let .creator(_, newAdminInfo, newRank) = new.participant, (prevRank != newRank || prevAdminInfo?.rights.flags.contains(.canBeAnonymous) != newAdminInfo?.rights.flags.contains(.canBeAnonymous)) { + if prevRank != newRank { + appendAttributedText(text: new.peer.addressName == nil ? self.presentationData.strings.Channel_AdminLog_MessageRankName(new.peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), newRank ?? "") : self.presentationData.strings.Channel_AdminLog_MessageRankUsername(new.peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), "@" + new.peer.addressName!, newRank ?? ""), generateEntities: { index in + var result: [MessageTextEntityType] = [] + if index == 0 { + result.append(.TextMention(peerId: new.peer.id)) + } else if index == 1 { + result.append(.Mention) + } else if index == 2 { + result.append(.Bold) + } + return result + }, to: &text, entities: &entities) + } + if prevAdminInfo?.rights.flags.contains(.canBeAnonymous) != newAdminInfo?.rights.flags.contains(.canBeAnonymous) { + let order: [(TelegramChatAdminRightsFlags, String)] + + if let peer = peer as? TelegramChannel, case .broadcast = peer.info { + order = [] + } else { + order = [ + (.canBeAnonymous, self.presentationData.strings.Channel_AdminLog_CanBeAnonymous) + ] } - return result - }, to: &text, entities: &entities) + + var appendedRightsHeader = false + for (flag, string) in order { + if prevAdminInfo?.rights.flags.contains(flag) != newAdminInfo?.rights.flags.contains(flag) { + if !appendedRightsHeader { + appendedRightsHeader = true + appendAttributedText(text: new.peer.addressName == nil ? self.presentationData.strings.Channel_AdminLog_MessagePromotedName(new.peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder)) : self.presentationData.strings.Channel_AdminLog_MessagePromotedNameUsername(new.peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), "@" + new.peer.addressName!), generateEntities: { index in + var result: [MessageTextEntityType] = [] + if index == 0 { + result.append(.TextMention(peerId: new.peer.id)) + } else if index == 1 { + result.append(.Mention) + } else if index == 2 { + result.append(.Bold) + } + return result + }, to: &text, entities: &entities) + text += "\n" + } + + text += "\n" + if prevAdminInfo?.rights.flags.contains(flag) != true { + text += "+" + } else { + text += "-" + } + appendAttributedText(text: string, withEntities: [.Italic], to: &text, entities: &entities) + } + } + } } else if case let .member(_, _, prevAdminRights, _, prevRank) = prev.participant { if case let .member(_, _, newAdminRights, _, newRank) = new.participant { let prevFlags = prevAdminRights?.rights.flags ?? [] diff --git a/submodules/TelegramUI/Sources/ChatTitleView.swift b/submodules/TelegramUI/Sources/ChatTitleView.swift index b847705db3..3baf18915c 100644 --- a/submodules/TelegramUI/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Sources/ChatTitleView.swift @@ -617,7 +617,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { if titleFrame.size.width < size.width { titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0) } - transition.updateFrameAdditiveToCenter(node: self.titleNode, frame: titleFrame) + transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame) } else { let combinedHeight = titleSize.height + activitySize.height + titleInfoSpacing @@ -626,7 +626,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { titleFrame.origin.x = -clearBounds.minX + floor((size.width - titleFrame.width) / 2.0) } titleFrame.origin.x = max(titleFrame.origin.x, clearBounds.minX + leftIconWidth) - transition.updateFrameAdditiveToCenter(node: self.titleNode, frame: titleFrame) + transition.updateFrameAdditive(node: self.titleNode, frame: titleFrame) var activityFrame = CGRect(origin: CGPoint(x: floor((clearBounds.width - activitySize.width) / 2.0), y: floor((size.height - combinedHeight) / 2.0) + titleSize.height + titleInfoSpacing), size: activitySize) if activitySize.width < size.width { diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index 8ff6a0bbde..cd6d5b2961 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -3308,7 +3308,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { } } else { switch buttonKey { - case .mute, .search, .mute: + case .mute, .search, .videoCall: hiddenWhileExpanded = true default: hiddenWhileExpanded = false