diff --git a/submodules/Postbox/Sources/MessageHistoryView.swift b/submodules/Postbox/Sources/MessageHistoryView.swift index 61d5a7cfd2..94b0a438a5 100644 --- a/submodules/Postbox/Sources/MessageHistoryView.swift +++ b/submodules/Postbox/Sources/MessageHistoryView.swift @@ -679,13 +679,16 @@ final class MutableMessageHistoryView: MutablePostboxView { hasChanges = true } case let .UpdateReadState(peerId, combinedReadState): - hasChanges = true - if let transientReadStates = self.transientReadStates { - switch transientReadStates { - case let .peer(states): - var updatedStates = states - updatedStates[peerId] = combinedReadState - self.transientReadStates = .peer(updatedStates) + if case let .single(_, threadId) = self.peerIds, threadId != nil { + } else { + hasChanges = true + if let transientReadStates = self.transientReadStates { + switch transientReadStates { + case let .peer(states): + var updatedStates = states + updatedStates[peerId] = combinedReadState + self.transientReadStates = .peer(updatedStates) + } } } case let .UpdateTimestamp(index, timestamp): @@ -698,8 +701,15 @@ final class MutableMessageHistoryView: MutablePostboxView { var currentThreadId: Int64? switch self.peerIds { - case let .single(_, threadIdValue): + case let .single(peerId, threadIdValue): currentThreadId = threadIdValue + + if let threadIdValue, transaction.updatedPeerThreadInfos.contains(MessageHistoryThreadsTable.ItemId(peerId: peerId, threadId: threadIdValue)) { + if let threadData = postbox.messageHistoryThreadIndexTable.get(peerId: peerId, threadId: threadIdValue) { + hasChanges = true + self.transientReadStates = .peer([peerId: CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: threadData.summary.maxOutgoingReadId, maxKnownId: 0, count: 0, markedUnread: false))])]) + } + } case .associated: break case .external: diff --git a/submodules/Postbox/Sources/MessageThreadIndexTable.swift b/submodules/Postbox/Sources/MessageThreadIndexTable.swift index 9e3c2aec2d..fa39627fa6 100644 --- a/submodules/Postbox/Sources/MessageThreadIndexTable.swift +++ b/submodules/Postbox/Sources/MessageThreadIndexTable.swift @@ -5,17 +5,20 @@ public struct StoredMessageHistoryThreadInfo: Equatable, PostboxCoding { public var totalUnreadCount: Int32 public var isMarkedUnread: Bool public var mutedUntil: Int32? + public var maxOutgoingReadId: Int32 - public init(totalUnreadCount: Int32, isMarkedUnread: Bool, mutedUntil: Int32?) { + public init(totalUnreadCount: Int32, isMarkedUnread: Bool, mutedUntil: Int32?, maxOutgoingReadId: Int32) { self.totalUnreadCount = totalUnreadCount self.isMarkedUnread = isMarkedUnread self.mutedUntil = mutedUntil + self.maxOutgoingReadId = maxOutgoingReadId } public init(decoder: PostboxDecoder) { self.totalUnreadCount = decoder.decodeInt32ForKey("u", orElse: 0) self.mutedUntil = decoder.decodeOptionalInt32ForKey("m") self.isMarkedUnread = decoder.decodeBoolForKey("mu", orElse: false) + self.maxOutgoingReadId = decoder.decodeInt32ForKey("or", orElse: 0) } public func encode(_ encoder: PostboxEncoder) { @@ -26,6 +29,7 @@ public struct StoredMessageHistoryThreadInfo: Equatable, PostboxCoding { } else { encoder.encodeNil(forKey: "m") } + encoder.encodeInt32(self.maxOutgoingReadId, forKey: "or") } } @@ -112,7 +116,7 @@ class MessageHistoryThreadIndexTable: Table { return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: true) } - private struct UpdatedEntry { + struct UpdatedEntry { var value: StoredMessageHistoryThreadInfo? } @@ -127,7 +131,7 @@ class MessageHistoryThreadIndexTable: Table { private let sharedKey = ValueBoxKey(length: 8 + 4 + 8 + 4 + 4) - private var updatedInfoItems: [MessageHistoryThreadsTable.ItemId: UpdatedEntry] = [:] + private(set) var updatedInfoItems: [MessageHistoryThreadsTable.ItemId: UpdatedEntry] = [:] init(valueBox: ValueBox, table: ValueBoxTable, reverseIndexTable: MessageHistoryThreadReverseIndexTable, seedConfiguration: SeedConfiguration, useCaches: Bool) { self.reverseIndexTable = reverseIndexTable diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index cf1cca5917..893f784fec 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -2456,6 +2456,7 @@ final class PostboxImpl { let transactionParticipationInTotalUnreadCountUpdates = self.peerNotificationSettingsTable.transactionParticipationInTotalUnreadCountUpdates(postbox: self, transaction: currentTransaction) let updatedMessageThreadPeerIds = self.messageHistoryThreadIndexTable.replay(threadsTable: self.messageHistoryThreadsTable, namespaces: self.seedConfiguration.chatMessagesNamespaces, updatedIds: self.messageHistoryThreadsTable.updatedIds) + let updatedPeerThreadInfos = Set(self.messageHistoryThreadIndexTable.updatedInfoItems.keys) let alteredInitialPeerThreadsSummaries = self.peerThreadsSummaryTable.update(peerIds: updatedMessageThreadPeerIds.union(self.currentUpdatedPeerThreadCombinedStates), indexTable: self.messageHistoryThreadIndexTable, combinedStateTable: self.peerThreadCombinedStateTable, tagsSummaryTable: self.messageHistoryTagsSummaryTable) self.chatListIndexTable.commitWithTransaction( @@ -2479,7 +2480,62 @@ final class PostboxImpl { let updatedPeerTimeoutAttributes = self.peerTimeoutPropertiesTable.hasUpdates - let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentPeerHoleOperations: self.currentPeerHoleOperations, currentOperationsByPeerId: self.currentOperationsByPeerId, chatListOperations: self.currentChatListOperations, currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentGlobalTagsOperations: self.currentGlobalTagsOperations, currentLocalTagsOperations: self.currentLocalTagsOperations, updatedMedia: self.currentUpdatedMedia, replaceRemoteContactCount: self.currentReplaceRemoteContactCount, replaceContactPeerIds: self.currentReplacedContactPeerIds, currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, currentUpdatedMasterClientId: currentUpdatedMasterClientId, updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, updatedMessageThreadPeerIds: updatedMessageThreadPeerIds, updatedPeerThreadCombinedStates: self.currentUpdatedPeerThreadCombinedStates, updatedPeerThreadsSummaries: Set(alteredInitialPeerThreadsSummaries.keys), updatedPinnedThreads: self.currentUpdatedPinnedThreads, updatedHiddenPeerIds: self.currentUpdatedHiddenPeerIds, storyGeneralStatesEvents: self.currentStoryGeneralStatesEvents, storyPeerStatesEvents: self.currentStoryPeerStatesEvents, storySubscriptionsEvents: self.currentStorySubscriptionsEvents, storyItemsEvents: self.currentStoryItemsEvents, currentStoryTopItemEvents: self.currentStoryTopItemEvents, storyEvents: self.currentStoryEvents) + let transaction = PostboxTransaction( + currentUpdatedState: self.currentUpdatedState, + currentPeerHoleOperations: self.currentPeerHoleOperations, + currentOperationsByPeerId: self.currentOperationsByPeerId, + chatListOperations: self.currentChatListOperations, + currentUpdatedChatListInclusions: self.currentUpdatedChatListInclusions, + currentUpdatedPeers: self.currentUpdatedPeers, + currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, + currentUpdatedPeerNotificationBehaviorTimestamps: self.currentUpdatedPeerNotificationBehaviorTimestamps, + currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, + currentUpdatedPeerPresences: currentUpdatedPeerPresences, + currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, + currentUpdatedTotalUnreadStates: self.currentUpdatedTotalUnreadStates, + currentUpdatedTotalUnreadSummaries: self.currentUpdatedGroupTotalUnreadSummaries, + alteredInitialPeerCombinedReadStates: alteredInitialPeerCombinedReadStates, + currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, + currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, + unsentMessageOperations: self.currentUnsentOperations, + updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, + currentUpdatedGroupSummarySynchronizeOperations: self.currentUpdatedGroupSummarySynchronizeOperations, + currentPreferencesOperations: self.currentPreferencesOperations, + currentOrderedItemListOperations: self.currentOrderedItemListOperations, + currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, + currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, + currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, + currentGlobalTagsOperations: self.currentGlobalTagsOperations, + currentLocalTagsOperations: self.currentLocalTagsOperations, + updatedMedia: self.currentUpdatedMedia, + replaceRemoteContactCount: self.currentReplaceRemoteContactCount, + replaceContactPeerIds: self.currentReplacedContactPeerIds, + currentPendingMessageActionsOperations: self.currentPendingMessageActionsOperations, + currentUpdatedMessageActionsSummaries: self.currentUpdatedMessageActionsSummaries, + currentUpdatedMessageTagSummaries: self.currentUpdatedMessageTagSummaries, + currentInvalidateMessageTagSummaries: self.currentInvalidateMessageTagSummaries, + currentUpdatedPendingPeerNotificationSettings: self.currentUpdatedPendingPeerNotificationSettings, + replacedAdditionalChatListItems: self.currentReplacedAdditionalChatListItems, + updatedNoticeEntryKeys: self.currentUpdatedNoticeEntryKeys, + updatedCacheEntryKeys: self.currentUpdatedCacheEntryKeys, + currentUpdatedMasterClientId: currentUpdatedMasterClientId, + updatedFailedMessagePeerIds: self.messageHistoryFailedTable.updatedPeerIds, + updatedFailedMessageIds: self.messageHistoryFailedTable.updatedMessageIds, + updatedGlobalNotificationSettings: self.currentNeedsReindexUnreadCounters, + updatedPeerTimeoutAttributes: updatedPeerTimeoutAttributes, + updatedMessageThreadPeerIds: updatedMessageThreadPeerIds, + updatedPeerThreadCombinedStates: self.currentUpdatedPeerThreadCombinedStates, + updatedPeerThreadsSummaries: Set(alteredInitialPeerThreadsSummaries.keys), + updatedPeerThreadInfos: updatedPeerThreadInfos, + updatedPinnedThreads: self.currentUpdatedPinnedThreads, + updatedHiddenPeerIds: self.currentUpdatedHiddenPeerIds, + storyGeneralStatesEvents: self.currentStoryGeneralStatesEvents, + storyPeerStatesEvents: self.currentStoryPeerStatesEvents, + storySubscriptionsEvents: self.currentStorySubscriptionsEvents, + storyItemsEvents: self.currentStoryItemsEvents, + currentStoryTopItemEvents: self.currentStoryTopItemEvents, + storyEvents: self.currentStoryEvents + ) var updatedTransactionState: Int64? var updatedMasterClientId: Int64? if !transaction.isEmpty { @@ -3131,6 +3187,7 @@ final class PostboxImpl { let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> = self.transactionSignal(userInteractive: true, { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, ignoreRelatedChats: false) + //TODO:release jump to unread var anchor: HistoryViewInputAnchor = .upperBound switch peerIds { case let .single(peerId, threadId): @@ -3334,8 +3391,14 @@ final class PostboxImpl { var transientReadStates: MessageHistoryViewReadState? switch peerIds { case let .single(peerId, threadId): - if threadId == nil, let readState = self.readStateTable.getCombinedState(peerId) { - transientReadStates = .peer([peerId: readState]) + if let threadId { + if let threadData = self.messageHistoryThreadIndexTable.get(peerId: peerId, threadId: threadId) { + transientReadStates = .peer([peerId: CombinedPeerReadState(states: [(0, .idBased(maxIncomingReadId: 0, maxOutgoingReadId: threadData.summary.maxOutgoingReadId, maxKnownId: 0, count: 0, markedUnread: false))])]) + } + } else { + if let readState = self.readStateTable.getCombinedState(peerId) { + transientReadStates = .peer([peerId: readState]) + } } case let .associated(peerId, _): if let readState = self.readStateTable.getCombinedState(peerId) { diff --git a/submodules/Postbox/Sources/PostboxTransaction.swift b/submodules/Postbox/Sources/PostboxTransaction.swift index 5729f31e3f..0098e5b59c 100644 --- a/submodules/Postbox/Sources/PostboxTransaction.swift +++ b/submodules/Postbox/Sources/PostboxTransaction.swift @@ -47,6 +47,7 @@ final class PostboxTransaction { let updatedMessageThreadPeerIds: Set let updatedPeerThreadCombinedStates: Set let updatedPeerThreadsSummaries: Set + let updatedPeerThreadInfos: Set let updatedPinnedThreads: Set let updatedHiddenPeerIds: Bool let storyGeneralStatesEvents: [StoryGeneralStatesTable.Event] @@ -195,6 +196,9 @@ final class PostboxTransaction { if !self.updatedPeerThreadsSummaries.isEmpty { return false } + if !self.updatedPeerThreadInfos.isEmpty { + return false + } if !self.updatedPinnedThreads.isEmpty { return false } @@ -269,6 +273,7 @@ final class PostboxTransaction { updatedMessageThreadPeerIds: Set, updatedPeerThreadCombinedStates: Set, updatedPeerThreadsSummaries: Set, + updatedPeerThreadInfos: Set, updatedPinnedThreads: Set, updatedHiddenPeerIds: Bool, storyGeneralStatesEvents: [StoryGeneralStatesTable.Event], @@ -323,6 +328,7 @@ final class PostboxTransaction { self.updatedMessageThreadPeerIds = updatedMessageThreadPeerIds self.updatedPeerThreadCombinedStates = updatedPeerThreadCombinedStates self.updatedPeerThreadsSummaries = updatedPeerThreadsSummaries + self.updatedPeerThreadInfos = updatedPeerThreadInfos self.updatedPinnedThreads = updatedPinnedThreads self.updatedHiddenPeerIds = updatedHiddenPeerIds self.storyGeneralStatesEvents = storyGeneralStatesEvents diff --git a/submodules/TelegramCore/Sources/ForumChannels.swift b/submodules/TelegramCore/Sources/ForumChannels.swift index a114815f47..2343e2d27a 100644 --- a/submodules/TelegramCore/Sources/ForumChannels.swift +++ b/submodules/TelegramCore/Sources/ForumChannels.swift @@ -161,7 +161,8 @@ extension StoredMessageHistoryThreadInfo { self.init(data: entry, summary: Summary( totalUnreadCount: data.incomingUnreadCount, isMarkedUnread: data.isMarkedUnread, - mutedUntil: mutedUntil + mutedUntil: mutedUntil, + maxOutgoingReadId: data.maxOutgoingReadId )) } } diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 7f99ebc3e2..a24348e934 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -4262,7 +4262,7 @@ func replayFinalState( } else { updatedIncomingThreadReadStates[peerAndThreadId] = readMaxId } - if let channel = transaction.getPeer(peerAndThreadId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) { + if let channel = transaction.getPeer(peerAndThreadId.peerId) as? TelegramChannel, case .group = channel.info, (channel.flags.contains(.isForum) || channel.flags.contains(.isMonoforum)) { let threadId = peerAndThreadId.threadId if var data = transaction.getMessageHistoryThreadInfo(peerId: peerAndThreadId.peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) { if readMaxId > data.maxIncomingReadId { @@ -4315,7 +4315,7 @@ func replayFinalState( } else { updatedOutgoingThreadReadStates[peerAndThreadId] = readMaxId } - if let channel = transaction.getPeer(peerAndThreadId.peerId) as? TelegramChannel, case .group = channel.info, channel.flags.contains(.isForum) { + if let channel = transaction.getPeer(peerAndThreadId.peerId) as? TelegramChannel, case .group = channel.info, (channel.flags.contains(.isForum) || channel.flags.contains(.isMonoforum)) { if var data = transaction.getMessageHistoryThreadInfo(peerId: peerAndThreadId.peerId, threadId: peerAndThreadId.threadId)?.data.get(MessageHistoryThreadData.self) { if readMaxId >= data.maxOutgoingReadId { data.maxOutgoingReadId = readMaxId diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift index 5bc38f77ae..b0accb28cf 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StandaloneAccountTransaction.swift @@ -194,7 +194,7 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = { }, automaticThreadIndexInfo: { peerId, _ in if peerId.namespace == Namespaces.Peer.CloudUser { - return StoredMessageHistoryThreadInfo(data: CodableEntry(data: Data()), summary: StoredMessageHistoryThreadInfo.Summary(totalUnreadCount: 0, isMarkedUnread: false, mutedUntil: nil)) + return StoredMessageHistoryThreadInfo(data: CodableEntry(data: Data()), summary: StoredMessageHistoryThreadInfo.Summary(totalUnreadCount: 0, isMarkedUnread: false, mutedUntil: nil, maxOutgoingReadId: 0)) } else { return nil }