diff --git a/submodules/TelegramCore/Sources/ForumChannels.swift b/submodules/TelegramCore/Sources/ForumChannels.swift index 97704a58e6..0b0a050430 100644 --- a/submodules/TelegramCore/Sources/ForumChannels.swift +++ b/submodules/TelegramCore/Sources/ForumChannels.swift @@ -59,7 +59,7 @@ public struct MessageHistoryThreadData: Codable, Equatable { public var author: PeerId public var info: EngineMessageHistoryThread.Info public var incomingUnreadCount: Int32 - public var maxIncomingReadId: Int32 + public var maxIncomingReadId: Int32 public var maxKnownMessageId: Int32 public var maxOutgoingReadId: Int32 public var notificationSettings: TelegramPeerNotificationSettings diff --git a/submodules/TelegramCore/Sources/State/AccountStateManager.swift b/submodules/TelegramCore/Sources/State/AccountStateManager.swift index 957e2ab1cb..8fe05f8738 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManager.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManager.swift @@ -100,8 +100,8 @@ public final class AccountStateManager { return self.isUpdatingValue.get() } - private let notificationMessagesPipe = ValuePipe<[([Message], PeerGroupId, Bool)]>() - public var notificationMessages: Signal<[([Message], PeerGroupId, Bool)], NoError> { + private let notificationMessagesPipe = ValuePipe<[([Message], PeerGroupId, Bool, MessageHistoryThreadData?)]>() + public var notificationMessages: Signal<[([Message], PeerGroupId, Bool, MessageHistoryThreadData?)], NoError> { return self.notificationMessagesPipe.signal() } @@ -723,12 +723,13 @@ public final class AccountStateManager { let _ = self.delayNotificatonsUntil.swap(events.delayNotificatonsUntil) } - let signal = self.postbox.transaction { transaction -> [([Message], PeerGroupId, Bool)] in - var messageList: [([Message], PeerGroupId, Bool)] = [] + let signal = self.postbox.transaction { transaction -> [([Message], PeerGroupId, Bool, MessageHistoryThreadData?)] in + var messageList: [([Message], PeerGroupId, Bool, MessageHistoryThreadData?)] = [] + for id in events.addedIncomingMessageIds { - let (messages, notify, _, _) = messagesForNotification(transaction: transaction, id: id, alwaysReturnMessage: false) + let (messages, notify, _, _, threadData) = messagesForNotification(transaction: transaction, id: id, alwaysReturnMessage: false) if !messages.isEmpty { - messageList.append((messages, .root, notify)) + messageList.append((messages, .root, notify, threadData)) } } var wasScheduledMessages: [Message] = [] @@ -738,7 +739,16 @@ public final class AccountStateManager { } } if !wasScheduledMessages.isEmpty { - messageList.append((wasScheduledMessages, .root, true)) + var threadData: MessageHistoryThreadData? + let first = wasScheduledMessages[0] + for attr in first.attributes { + if let attribute = attr as? ReplyMessageAttribute { + if let threadId = attribute.threadMessageId { + threadData = transaction.getMessageHistoryThreadInfo(peerId: first.id.peerId, threadId: makeMessageThreadId(threadId))?.get(MessageHistoryThreadData.self) + } + } + } + messageList.append((wasScheduledMessages, .root, true, threadData)) } return messageList } @@ -1318,16 +1328,17 @@ public final class AccountStateManager { } } -public func messagesForNotification(transaction: Transaction, id: MessageId, alwaysReturnMessage: Bool) -> (messages: [Message], notify: Bool, sound: PeerMessageSound, displayContents: Bool) { +public func messagesForNotification(transaction: Transaction, id: MessageId, alwaysReturnMessage: Bool) -> (messages: [Message], notify: Bool, sound: PeerMessageSound, displayContents: Bool, threadData: MessageHistoryThreadData?) { guard let message = transaction.getMessage(id) else { Logger.shared.log("AccountStateManager", "notification message doesn't exist") - return ([], false, defaultCloudPeerNotificationSound, false) + return ([], false, defaultCloudPeerNotificationSound, false, nil) } var notify = true var sound: PeerMessageSound = defaultCloudPeerNotificationSound var muted = false var displayContents = true + var threadData: MessageHistoryThreadData? for attribute in message.attributes { if let attribute = attribute as? NotificationInfoMessageAttribute { @@ -1335,7 +1346,14 @@ public func messagesForNotification(transaction: Transaction, id: MessageId, alw muted = true } } + if let attribute = attribute as? ReplyMessageAttribute { + if let threadId = attribute.threadMessageId { + threadData = transaction.getMessageHistoryThreadInfo(peerId: message.id.peerId, threadId: makeMessageThreadId(threadId))?.get(MessageHistoryThreadData.self) + } + } } + + for media in message.media { if let action = media as? TelegramMediaAction { switch action.action { @@ -1408,7 +1426,7 @@ public func messagesForNotification(transaction: Transaction, id: MessageId, alw if let channel = message.peers[message.id.peerId] as? TelegramChannel { switch channel.participationStatus { case .kicked, .left: - return ([], false, sound, false) + return ([], false, sound, false, threadData) case .member: break } @@ -1440,8 +1458,8 @@ public func messagesForNotification(transaction: Transaction, id: MessageId, alw } if notify { - return (resultMessages, isUnread, sound, displayContents) + return (resultMessages, isUnread, sound, displayContents, threadData) } else { - return (alwaysReturnMessage ? resultMessages : [], false, sound, displayContents) + return (alwaysReturnMessage ? resultMessages : [], false, sound, displayContents, threadData) } } diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index faa73cc986..57f3bf1a06 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -1527,7 +1527,7 @@ public final class AccountViewTracker { if let current = current { return current } else { - return view.0.fixedReadStates ?? .peer([peerId: readState]) + return .peer([peerId: readState]) } } @@ -1701,7 +1701,7 @@ public final class AccountViewTracker { if let account = self.account { let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> if let peerId = chatLocation.peerId, let threadId = chatLocation.threadId, tagMask == nil { - return account.postbox.transaction { transaction -> MessageHistoryThreadData? in + signal = account.postbox.transaction { transaction -> MessageHistoryThreadData? in return transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) } |> mapToSignal { threadInfo -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SearchMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SearchMessages.swift index 0f2c44af65..ffe379aaaa 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SearchMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SearchMessages.swift @@ -16,6 +16,7 @@ public enum SearchMessagesLocation: Equatable { private struct SearchMessagesPeerState: Equatable { let messages: [Message] let readStates: [PeerId: CombinedPeerReadState] + let threadInfo: [MessageId: MessageHistoryThreadData] let totalCount: Int32 let completed: Bool let nextRate: Int32? @@ -44,12 +45,14 @@ private struct SearchMessagesPeerState: Equatable { public struct SearchMessagesResult { public let messages: [Message] + public let threadInfo:[MessageId : MessageHistoryThreadData] public let readStates: [PeerId: CombinedPeerReadState] public let totalCount: Int32 public let completed: Bool - public init(messages: [Message], readStates: [PeerId: CombinedPeerReadState], totalCount: Int32, completed: Bool) { + public init(messages: [Message], readStates: [PeerId: CombinedPeerReadState], threadInfo:[MessageId : MessageHistoryThreadData], totalCount: Int32, completed: Bool) { self.messages = messages + self.threadInfo = threadInfo self.readStates = readStates self.totalCount = totalCount self.completed = completed @@ -113,12 +116,25 @@ private func mergedState(transaction: Transaction, state: SearchMessagesPeerStat var peerIdsSet: Set = Set() var readStates: [PeerId: CombinedPeerReadState] = [:] + var threadInfo:[MessageId : MessageHistoryThreadData] = [:] var renderedMessages: [Message] = [] for message in messages { if let message = StoreMessage(apiMessage: message), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) { + let peerId = renderedMessage.id.peerId renderedMessages.append(renderedMessage) - peerIdsSet.insert(message.id.peerId) + peerIdsSet.insert(peerId) + for attribute in renderedMessage.attributes { + if let attribute = attribute as? ReplyMessageAttribute { + if let threadMessageId = attribute.threadMessageId { + let threadId = makeMessageThreadId(threadMessageId) + if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) { + threadInfo[renderedMessage.id] = data + break + } + } + } + } } } @@ -153,9 +169,9 @@ private func mergedState(transaction: Transaction, state: SearchMessagesPeerStat mergedMessages.sort(by: { lhs, rhs in return lhs.index > rhs.index }) - return SearchMessagesPeerState(messages: mergedMessages, readStates: readStates, totalCount: completed ? Int32(mergedMessages.count) : totalCount, completed: completed, nextRate: nextRate) + return SearchMessagesPeerState(messages: mergedMessages, readStates: readStates, threadInfo: threadInfo, totalCount: completed ? Int32(mergedMessages.count) : totalCount, completed: completed, nextRate: nextRate) } else { - return SearchMessagesPeerState(messages: renderedMessages, readStates: readStates, totalCount: completed ? Int32(renderedMessages.count) : totalCount, completed: completed, nextRate: nextRate) + return SearchMessagesPeerState(messages: renderedMessages, readStates: readStates, threadInfo: threadInfo, totalCount: completed ? Int32(renderedMessages.count) : totalCount, completed: completed, nextRate: nextRate) } } @@ -181,7 +197,15 @@ private func mergedResult(_ state: SearchMessagesState) -> SearchMessagesResult } } - return SearchMessagesResult(messages: messages, readStates: readStates, totalCount: state.main.totalCount + (state.additional?.totalCount ?? 0), completed: state.main.completed && (state.additional?.completed ?? true)) + var threadInfo: [MessageId: MessageHistoryThreadData] = [:] + for message in messages { + let data = state.main.threadInfo[message.id] ?? state.additional?.threadInfo[message.id] + if let data = data { + threadInfo[message.id] = data + } + } + + return SearchMessagesResult(messages: messages, readStates: readStates, threadInfo: threadInfo, totalCount: state.main.totalCount + (state.additional?.totalCount ?? 0), completed: state.main.completed && (state.additional?.completed ?? true)) } func _internal_searchMessages(account: Account, location: SearchMessagesLocation, query: String, state: SearchMessagesState?, limit: Int32 = 100) -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> { @@ -191,11 +215,27 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation if peerId.namespace == Namespaces.Peer.SecretChat { return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in var readStates: [PeerId: CombinedPeerReadState] = [:] + var threadInfo: [MessageId: MessageHistoryThreadData] = [:] if let readState = transaction.getCombinedPeerReadState(peerId) { readStates[peerId] = readState } let result = transaction.searchMessages(peerId: peerId, query: query, tags: tags) - return (SearchMessagesResult(messages: result, readStates: readStates, totalCount: Int32(result.count), completed: true), SearchMessagesState(main: SearchMessagesPeerState(messages: [], readStates: [:], totalCount: 0, completed: true, nextRate: nil), additional: nil)) + + for message in result { + for attribute in message.attributes { + if let attribute = attribute as? ReplyMessageAttribute { + if let threadMessageId = attribute.threadMessageId { + let threadId = makeMessageThreadId(threadMessageId) + if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) { + threadInfo[message.id] = data + break + } + } + } + } + } + + return (SearchMessagesResult(messages: result, readStates: readStates, threadInfo: threadInfo, totalCount: Int32(result.count), completed: true), SearchMessagesState(main: SearchMessagesPeerState(messages: [], readStates: [:], threadInfo: [:], totalCount: 0, completed: true, nextRate: nil), additional: nil)) } } @@ -366,6 +406,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation let secretMessages = transaction.searchMessages(peerId: nil, query: query, tags: tags) var filteredMessages: [Message] = [] var readStates: [PeerId: CombinedPeerReadState] = [:] + var threadInfo:[MessageId : MessageHistoryThreadData] = [:] for message in secretMessages { var match = true if let minDate = minDate, message.timestamp < minDate { @@ -379,15 +420,26 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation if let readState = transaction.getCombinedPeerReadState(message.id.peerId) { readStates[message.id.peerId] = readState } + for attribute in message.attributes { + if let attribute = attribute as? ReplyMessageAttribute { + if let threadMessageId = attribute.threadMessageId { + let threadId = makeMessageThreadId(threadMessageId) + if let data = transaction.getMessageHistoryThreadInfo(peerId: message.id.peerId, threadId: threadId)?.get(MessageHistoryThreadData.self) { + threadInfo[message.id] = data + break + } + } + } + } } } - additional = SearchMessagesPeerState(messages: filteredMessages, readStates: readStates, totalCount: Int32(filteredMessages.count), completed: true, nextRate: nil) + additional = SearchMessagesPeerState(messages: filteredMessages, readStates: readStates, threadInfo: threadInfo, totalCount: Int32(filteredMessages.count), completed: true, nextRate: nil) default: break } } - let updatedState = SearchMessagesState(main: mergedState(transaction: transaction, state: state?.main, result: result) ?? SearchMessagesPeerState(messages: [], readStates: [:], totalCount: 0, completed: true, nextRate: nil), additional: additional) + let updatedState = SearchMessagesState(main: mergedState(transaction: transaction, state: state?.main, result: result) ?? SearchMessagesPeerState(messages: [], readStates: [:], threadInfo: [:], totalCount: 0, completed: true, nextRate: nil), additional: additional) return (mergedResult(updatedState), updatedState) } }