diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 3f5693a2b0..00d84db2cf 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -463,6 +463,7 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour { public static let toggleUnread = Actions(rawValue: 1 << 0) public static let delete = Actions(rawValue: 1 << 1) + public static let togglePinned = Actions(rawValue: 1 << 2) } case custom(Actions) diff --git a/submodules/TelegramCore/Sources/ForumChannels.swift b/submodules/TelegramCore/Sources/ForumChannels.swift index 96ca46a17a..6febb45e68 100644 --- a/submodules/TelegramCore/Sources/ForumChannels.swift +++ b/submodules/TelegramCore/Sources/ForumChannels.swift @@ -247,7 +247,7 @@ func _internal_createForumChannelTopic(account: Account, peerId: PeerId, title: } |> castError(CreateForumChannelTopicError.self) |> mapToSignal { _ -> Signal in - return resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: topicId)]) + return resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), additionalPeers: AccumulatedPeers(), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: topicId)]) |> castError(CreateForumChannelTopicError.self) |> map { _ -> Int64 in return topicId @@ -277,7 +277,7 @@ func _internal_fetchForumChannelTopic(account: Account, peerId: PeerId, threadId if let info = info { return .single(.result(info)) } else { - return .single(.progress) |> then(resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: threadId)]) + return .single(.progress) |> then(resolveForumThreads(accountPeerId: account.peerId, postbox: account.postbox, source: .network(account.network), additionalPeers: AccumulatedPeers(), ids: [PeerAndBoundThreadId(peerId: peerId, threadId: threadId)]) |> mapToSignal { _ -> Signal in return account.postbox.transaction { transaction -> FetchForumChannelTopicResult in if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) { diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index cf5a42468c..ef9f61a669 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -2019,7 +2019,16 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM } if peer.flags.contains(.isMonoforum) { - let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer(_:)) })) + let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { threadId in + let threadPeerId = PeerId(threadId) + if let threadPeer = state.peers[threadPeerId] { + return apiInputPeer(threadPeer) + } else if let threadPeer = transaction.getPeer(threadPeerId) { + return apiInputPeer(threadPeer) + } else { + return nil + } + })) |> map { result -> (Peer, FetchedForumThreads)? in let result = FetchedForumThreads(savedDialogs: result) return (peer, result) @@ -2146,7 +2155,7 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM } } -func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, ids: [PeerAndBoundThreadId]) -> Signal { +func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchMessageHistoryHoleSource, additionalPeers: AccumulatedPeers, ids: [PeerAndBoundThreadId]) -> Signal { let forumThreadIds = Set(ids) if forumThreadIds.isEmpty { @@ -2172,7 +2181,16 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM } if peer.flags.contains(.isMonoforum) { - let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer(_:)) })) + let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { threadId in + let threadPeerId = PeerId(threadId) + if let threadPeer = additionalPeers.get(threadPeerId) { + return apiInputPeer(threadPeer) + } else if let threadPeer = transaction.getPeer(threadPeerId) { + return apiInputPeer(threadPeer) + } else { + return nil + } + })) |> map { result -> (Peer, FetchedForumThreads)? in let result = FetchedForumThreads(savedDialogs: result) return (peer, result) @@ -2329,7 +2347,16 @@ func resolveForumThreads(accountPeerId: PeerId, postbox: Postbox, source: FetchM } if peer.flags.contains(.isMonoforum) { - let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { transaction.getPeer(PeerId($0)).flatMap(apiInputPeer(_:)) })) + let signal = source.request(Api.functions.messages.getSavedDialogsByID(flags: 1 << 1, parentPeer: inputPeer, ids: threadIds.compactMap { threadId in + let threadPeerId = PeerId(threadId) + if let threadPeer = fetchedChatList.peers.get(threadPeerId) { + return apiInputPeer(threadPeer) + } else if let threadPeer = transaction.getPeer(threadPeerId) { + return apiInputPeer(threadPeer) + } else { + return nil + } + })) |> map { result -> (Peer, FetchedForumThreads)? in let result = FetchedForumThreads(savedDialogs: result) return (peer, result) diff --git a/submodules/TelegramCore/Sources/State/Holes.swift b/submodules/TelegramCore/Sources/State/Holes.swift index a9e5e8e27d..c73d259282 100644 --- a/submodules/TelegramCore/Sources/State/Holes.swift +++ b/submodules/TelegramCore/Sources/State/Holes.swift @@ -225,7 +225,7 @@ func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHis return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages, additionalPeers: parsedPeers, result: Void()) |> mapToSignal { _ -> Signal in if resolveThreads && !threadIds.isEmpty { - return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, ids: Array(threadIds)) + return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, additionalPeers: parsedPeers, ids: Array(threadIds)) |> mapToSignal { _ -> Signal in return postbox.transaction { transaction -> T in return f(transaction, parsedPeers, []) @@ -325,7 +325,8 @@ func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHis let combinedMessages = storeMessages + additionalMessages return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: combinedMessages, reactions: [], result: Void()) |> mapToSignal { _ -> Signal in - return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: parsedPeers.union(with: additionalPeers), result: Void()) + let additionalPeers = parsedPeers.union(with: additionalPeers) + return resolveAssociatedStories(postbox: postbox, source: source, accountPeerId: accountPeerId, messages: storeMessages + additionalMessages, additionalPeers: additionalPeers, result: Void()) |> mapToSignal { _ -> Signal in var threadIds = Set() for message in combinedMessages { @@ -335,7 +336,7 @@ func withResolvedAssociatedMessages(postbox: Postbox, source: FetchMessageHis } if resolveThreads && !threadIds.isEmpty { - return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, ids: Array(threadIds)) + return resolveForumThreads(accountPeerId: accountPeerId, postbox: postbox, source: source, additionalPeers: additionalPeers, ids: Array(threadIds)) |> mapToSignal { _ -> Signal in return postbox.transaction { transaction -> T in return f(transaction, parsedPeers, []) diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift index 1b059bc3c9..78aa134435 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageAnimatedStickerItemNode/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -1426,7 +1426,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { strongSelf.textNode.textNode.frame = imageFrame } - strongSelf.imageNode.frame = updatedContentFrame + animation.animator.updateFrame(layer: strongSelf.imageNode.layer, frame: updatedContentFrame, completion: nil) strongSelf.contextSourceNode.contentRect = contextContentFrame strongSelf.containerNode.targetNodeForActivationProgressContentRect = strongSelf.contextSourceNode.contentRect @@ -1458,11 +1458,13 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { let foregroundColor: UIColor = .clear// = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderColor, wallpaper: item.presentationData.theme.wallpaper) let shimmeringColor = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderShimmerColor, wallpaper: item.presentationData.theme.wallpaper) strongSelf.placeholderNode.update(backgroundColor: nil, foregroundColor: foregroundColor, shimmeringColor: shimmeringColor, data: immediateThumbnailData, size: animationNodeFrame.size, enableEffect: item.context.sharedContext.energyUsageSettings.fullTranslucency, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)) - strongSelf.placeholderNode.frame = animationNodeFrame + animation.animator.updateFrame(layer: strongSelf.placeholderNode.layer, frame: animationNodeFrame, completion: nil) } if strongSelf.animationNode?.supernode === strongSelf.contextSourceNode.contentNode { - strongSelf.animationNode?.frame = animationNodeFrame + if let animationNode = strongSelf.animationNode { + animation.animator.updateFrame(layer: animationNode.layer, frame: animationNodeFrame, completion: nil) + } if let animationNode = strongSelf.animationNode as? AnimatedStickerNode { animationNode.updateLayout(size: updatedContentFrame.insetBy(dx: imageInset, dy: imageInset).size) @@ -1494,7 +1496,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } } let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, controllerInteraction: item.controllerInteraction, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account) - updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: !incoming ? updatedImageFrame.minX - buttonSize.width - 6.0 : updatedImageFrame.maxX + 8.0, y: updatedImageFrame.maxY - buttonSize.height - 4.0 + imageBottomPadding), size: buttonSize) + animation.animator.updateFrame(layer: updatedShareButtonNode.layer, frame: CGRect(origin: CGPoint(x: !incoming ? updatedImageFrame.minX - buttonSize.width - 6.0 : updatedImageFrame.maxX + 8.0, y: updatedImageFrame.maxY - buttonSize.height - 4.0 + imageBottomPadding), size: buttonSize), completion: nil) } else if let shareButtonNode = strongSelf.shareButtonNode { shareButtonNode.removeFromSupernode() strongSelf.shareButtonNode = nil diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift index 772f6cbde2..386b50a569 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageNotificationItem/Sources/ChatMessageNotificationItem.swift @@ -178,6 +178,9 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { if firstMessage.id.peerId.isRepliesOrVerificationCodes, let author = firstMessage.forwardInfo?.author { avatarPeer = EnginePeer(author) } + if case let .channel(channel) = avatarPeer, channel.isMonoForum, let linkedMonoforumId = channel.linkedMonoforumId, let mainChannel = firstMessage.peers[linkedMonoforumId] as? TelegramChannel { + avatarPeer = .channel(mainChannel) + } self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: avatarPeer, overrideImage: peer.id == item.context.account.peerId ? .savedMessagesIcon : nil, emptyColor: presentationData.theme.list.mediaPlaceholderColor) } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift index d3f6727a94..cb1cce2204 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageStickerItemNode/Sources/ChatMessageStickerItemNode.swift @@ -995,7 +995,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { let placeholderFrame = updatedImageFrame.insetBy(dx: innerImageInset, dy: innerImageInset) strongSelf.placeholderNode.update(backgroundColor: nil, foregroundColor: foregroundColor, shimmeringColor: shimmeringColor, data: immediateThumbnailData, size: placeholderFrame.size, enableEffect: item.context.sharedContext.energyUsageSettings.fullTranslucency) - strongSelf.placeholderNode.frame = placeholderFrame + animation.animator.updateFrame(layer: strongSelf.placeholderNode.layer, frame: placeholderFrame, completion: nil) } strongSelf.messageAccessibilityArea.frame = CGRect(origin: CGPoint(), size: layoutSize) @@ -1067,7 +1067,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { strongSelf.contextSourceNode.contentNode.addSubnode(threadInfoNode) } let threadInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 6.0) : (params.width - params.rightInset - threadInfoSize.width - layoutConstants.bubble.edgeInset - 8.0)), y: 8.0), size: threadInfoSize) - threadInfoNode.frame = threadInfoFrame + animation.animator.updateFrame(layer: threadInfoNode.layer, frame: threadInfoFrame, completion: nil) headersOffset += threadInfoSize.height + 10.0 } else if let replyInfoNode = strongSelf.replyInfoNode { @@ -1120,7 +1120,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView { } } let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0 + 5.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 8.0 - 5.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: forwardInfoSize) - forwardInfoNode.frame = forwardInfoFrame + animation.animator.updateFrame(layer: forwardInfoNode.layer, frame: forwardInfoFrame, completion: nil) messageInfoSize = CGSize(width: messageInfoSize.width, height: messageInfoSize.height + forwardInfoSize.height + 8.0) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index ea0cd685b3..11db0caad0 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1409,11 +1409,11 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { } } - /*#if DEBUG + #if DEBUG if "".isEmpty { hasTranslationPanel = true } - #endif*/ + #endif if hasTranslationPanel { let translationPanelNode: ChatTranslationPanelNode @@ -3283,71 +3283,16 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { guard let self else { return nil } - guard let peerId = self.chatPresentationInterfaceState.chatLocation.peerId else { + guard let peer = self.chatPresentationInterfaceState.renderedPeer?.peer else { + return nil + } + if !peer.isForumOrMonoForum { return nil } - let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: peerId) + let threadListSignal: Signal = context.sharedContext.subscribeChatListData(context: self.context, location: peer.isMonoForum ? .savedMessagesChats(peerId: peer.id) : .forum(peerId: peer.id)) - let threadListSignal: Signal = self.context.account.postbox.combinedView(keys: [viewKey]) - |> map { views -> EngineChatList? in - guard let view = views.views[viewKey] as? MessageHistorySavedMessagesIndexView else { - preconditionFailure() - } - - var items: [EngineChatList.Item] = [] - for item in view.items { - guard let sourcePeer = item.peer else { - continue - } - - let sourceId = PeerId(item.id) - - var messages: [EngineMessage] = [] - if let topMessage = item.topMessage { - messages.append(EngineMessage(topMessage)) - } - - let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: item.index.id.namespace, id: item.index.id.id), timestamp: item.index.timestamp) - - items.append(EngineChatList.Item( - id: .chatList(sourceId), - index: .chatList(ChatListIndex(pinningIndex: item.pinnedIndex.flatMap(UInt16.init), messageIndex: mappedMessageIndex)), - messages: messages, - readCounters: EnginePeerReadCounters( - incomingReadId: 0, outgoingReadId: 0, count: Int32(item.unreadCount), markedUnread: item.markedUnread), - isMuted: false, - draft: nil, - threadData: nil, - renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)), - presence: nil, - hasUnseenMentions: false, - hasUnseenReactions: false, - forumTopicData: nil, - topForumTopicItems: [], - hasFailed: false, - isContact: false, - autoremoveTimeout: nil, - storyStats: nil, - displayAsTopicList: false, - isPremiumRequiredToMessage: false, - mediaDraftContentType: nil - )) - } - - let list = EngineChatList( - items: items.reversed(), - groupItems: [], - additionalItems: [], - hasEarlier: false, - hasLater: false, - isLoading: view.isLoading - ) - - return list - } - - return threadListSignal + return threadListSignal |> map(Optional.init) }, loadMoreSearchResults: { [weak self] in guard let self, let controller = self.controller else { diff --git a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift index add15899cf..1bcf383d04 100644 --- a/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTranslationPanelNode.swift @@ -167,9 +167,13 @@ final class ChatTranslationPanelNode: ASDisplayNode { let buttonTextSize = self.buttonTextNode.updateLayout(CGSize(width: width - contentRightInset - moreButtonSize.width, height: panelHeight)) if let icon = self.buttonIconNode.image { let buttonSize = CGSize(width: buttonTextSize.width + icon.size.width + buttonSpacing + buttonPadding * 2.0, height: panelHeight) - self.button.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((width - buttonSize.width) / 2.0), y: 0.0), size: buttonSize) - self.buttonIconNode.frame = CGRect(origin: CGPoint(x: buttonPadding, y: floorToScreenPixels((buttonSize.height - icon.size.height) / 2.0)), size: icon.size) - self.buttonTextNode.frame = CGRect(origin: CGPoint(x: buttonPadding + icon.size.width + buttonSpacing, y: floorToScreenPixels((buttonSize.height - buttonTextSize.height) / 2.0)), size: buttonTextSize) + transition.updateFrame(node: self.button, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((width - buttonSize.width) / 2.0), y: 0.0), size: buttonSize)) + + transition.updateFrame(node: self.buttonIconNode, frame: CGRect(origin: CGPoint(x: buttonPadding, y: floorToScreenPixels((buttonSize.height - icon.size.height) / 2.0)), size: icon.size)) + + let buttonTextFrame = CGRect(origin: CGPoint(x: buttonPadding + icon.size.width + buttonSpacing, y: floorToScreenPixels((buttonSize.height - buttonTextSize.height) / 2.0)), size: buttonTextSize) + transition.updatePosition(node: self.buttonTextNode, position: buttonTextFrame.center) + self.buttonTextNode.bounds = CGRect(origin: CGPoint(), size: buttonTextFrame.size) } transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: width, height: UIScreenPixel)))