mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 03:09:56 +00:00
no message
This commit is contained in:
parent
a319509c0c
commit
640865d83c
@ -61,6 +61,8 @@
|
||||
D04614312004E24600EC0EF2 /* LocalMessageHistoryTagsTable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D046142F2004E24600EC0EF2 /* LocalMessageHistoryTagsTable.swift */; };
|
||||
D04614332004F2CC00EC0EF2 /* LocalMessageTagsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04614322004F2CC00EC0EF2 /* LocalMessageTagsView.swift */; };
|
||||
D04614342004F2CC00EC0EF2 /* LocalMessageTagsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04614322004F2CC00EC0EF2 /* LocalMessageTagsView.swift */; };
|
||||
D048B33D203C838500038D05 /* PostboxUpgrade_15to16.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048B33C203C838500038D05 /* PostboxUpgrade_15to16.swift */; };
|
||||
D048B33E203C838500038D05 /* PostboxUpgrade_15to16.swift in Sources */ = {isa = PBXBuildFile; fileRef = D048B33C203C838500038D05 /* PostboxUpgrade_15to16.swift */; };
|
||||
D049EAF01E44D9B900A2CD3A /* PostboxStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAEF1E44D9B900A2CD3A /* PostboxStateView.swift */; };
|
||||
D049EAF11E44D9B900A2CD3A /* PostboxStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D049EAEF1E44D9B900A2CD3A /* PostboxStateView.swift */; };
|
||||
D050F2651E4A5B4800988324 /* fts3_tokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = D07516741B2EC90400AE42E0 /* fts3_tokenizer.h */; };
|
||||
@ -404,6 +406,7 @@
|
||||
D044E1621B2AD677001EE087 /* MurMurHash32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MurMurHash32.m; sourceTree = "<group>"; };
|
||||
D046142F2004E24600EC0EF2 /* LocalMessageHistoryTagsTable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalMessageHistoryTagsTable.swift; sourceTree = "<group>"; };
|
||||
D04614322004F2CC00EC0EF2 /* LocalMessageTagsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalMessageTagsView.swift; sourceTree = "<group>"; };
|
||||
D048B33C203C838500038D05 /* PostboxUpgrade_15to16.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostboxUpgrade_15to16.swift; sourceTree = "<group>"; };
|
||||
D049EAEF1E44D9B900A2CD3A /* PostboxStateView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostboxStateView.swift; sourceTree = "<group>"; };
|
||||
D055BD321B7D3D2D00F06C0A /* MediaBox.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaBox.swift; sourceTree = "<group>"; };
|
||||
D0575AE21E9ECBB2006F2541 /* AccessChallengeDataView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessChallengeDataView.swift; sourceTree = "<group>"; };
|
||||
@ -660,6 +663,7 @@
|
||||
D0F02CE11E9922F50065DEE2 /* PostboxUpgrade_12to13.swift */,
|
||||
D0CE8CF21F70249400AA2DB0 /* PostboxUpgrade_13to14.swift */,
|
||||
D0943B011FDB01D8001522CC /* PostboxUpgrade_14to15.swift */,
|
||||
D048B33C203C838500038D05 /* PostboxUpgrade_15to16.swift */,
|
||||
);
|
||||
name = Upgrade;
|
||||
sourceTree = "<group>";
|
||||
@ -1167,6 +1171,7 @@
|
||||
D073CEA01DCBF3C1007511FD /* ItemCollectionsView.swift in Sources */,
|
||||
D0BE383A1E7C1FD4000079AF /* ItemCollectionInfoView.swift in Sources */,
|
||||
D0B418491D7DFE20004562A4 /* ChatListView.swift in Sources */,
|
||||
D048B33E203C838500038D05 /* PostboxUpgrade_15to16.swift in Sources */,
|
||||
D0F7B1D61E045C6A007EB8A5 /* ContactTable.swift in Sources */,
|
||||
D0943B031FDB01D8001522CC /* PostboxUpgrade_14to15.swift in Sources */,
|
||||
D0F7B1D11E045C6A007EB8A5 /* PeerTable.swift in Sources */,
|
||||
@ -1341,6 +1346,7 @@
|
||||
D0C26D6F1FE2E737004ABF18 /* GroupFeedReadState.swift in Sources */,
|
||||
D0FA0AC71E77F0A2005BB9B7 /* ItemCollectionInfosView.swift in Sources */,
|
||||
D0F019FD1E1DA0CC00F05AB3 /* PeerMergedOperationLogView.swift in Sources */,
|
||||
D048B33D203C838500038D05 /* PostboxUpgrade_15to16.swift in Sources */,
|
||||
D0F9E8651C58CB7F00037222 /* ChatListTable.swift in Sources */,
|
||||
D0E1D30C1ECA1F5500FCEEF1 /* GlobalMessageHistoryTagsTable.swift in Sources */,
|
||||
D0F9E8711C5A0E9B00037222 /* PeerTable.swift in Sources */,
|
||||
|
||||
@ -3,7 +3,7 @@ public protocol CachedPeerData: PostboxCoding {
|
||||
var peerIds: Set<PeerId> { get }
|
||||
var messageIds: Set<MessageId> { get }
|
||||
|
||||
var associatedHistoryPeerId: PeerId? { get }
|
||||
var associatedHistoryMessageId: MessageId? { get }
|
||||
|
||||
func isEqual(to: CachedPeerData) -> Bool
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ final class ChatListIndexTable: Table {
|
||||
assert(self.updatedPreviousGroupCachedIndices.isEmpty)
|
||||
}
|
||||
|
||||
func commitWithTransactionUnreadCountDeltas(_ deltas: [PeerId: Int32], transactionParticipationInTotalUnreadCountUpdates: (added: Set<PeerId>, removed: Set<PeerId>), getPeer: (PeerId) -> Peer?, updatedTotalUnreadCount: inout Int32?) {
|
||||
func commitWithTransactionUnreadCountDeltas(_ deltas: [PeerId: Int32], transactionParticipationInTotalUnreadCountUpdates: (added: Set<PeerId>, removed: Set<PeerId>), getPeer: (PeerId) -> Peer?, updatedTotalUnreadState: inout ChatListTotalUnreadState?) {
|
||||
if !self.updatedPreviousPeerCachedIndices.isEmpty || !deltas.isEmpty || !transactionParticipationInTotalUnreadCountUpdates.added.isEmpty || !transactionParticipationInTotalUnreadCountUpdates.removed.isEmpty {
|
||||
var addedChatListPeerIds = Set<PeerId>()
|
||||
var removedChatListPeerIds = Set<PeerId>()
|
||||
@ -326,7 +326,7 @@ final class ChatListIndexTable: Table {
|
||||
let addedUnreadCountPeerIds = addedChatListPeerIds.union(transactionParticipationInTotalUnreadCountUpdates.added)
|
||||
let removedUnreadCountPeerIds = removedChatListPeerIds.union(transactionParticipationInTotalUnreadCountUpdates.removed)
|
||||
|
||||
var totalUnreadCount = self.metadataTable.getChatListTotalUnreadCount()
|
||||
var totalUnreadState = self.metadataTable.getChatListTotalUnreadState()
|
||||
for (peerId, delta) in deltas {
|
||||
if !addedUnreadCountPeerIds.contains(peerId) && !removedUnreadCountPeerIds.contains(peerId) {
|
||||
var notificationSettings: PeerNotificationSettings?
|
||||
@ -337,8 +337,11 @@ final class ChatListIndexTable: Table {
|
||||
notificationSettings = self.notificationSettingsTable.getEffective(peerId)
|
||||
}
|
||||
}
|
||||
if let _ = self.get(peerId: peerId).includedIndex(peerId: peerId), let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
totalUnreadCount += delta
|
||||
if let _ = self.get(peerId: peerId).includedIndex(peerId: peerId) {
|
||||
totalUnreadState.absoluteCounters.messageCount += delta
|
||||
if let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
totalUnreadState.filteredCounters.messageCount += delta
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -353,7 +356,8 @@ final class ChatListIndexTable: Table {
|
||||
|
||||
if addedToList && startedParticipationInUnreadCount {
|
||||
if let combinedState = self.readStateTable.getCombinedState(peerId) {
|
||||
totalUnreadCount += combinedState.count
|
||||
totalUnreadState.absoluteCounters.messageCount += combinedState.count
|
||||
totalUnreadState.filteredCounters.messageCount += combinedState.count
|
||||
}
|
||||
} else if addedToList {
|
||||
var notificationSettings: PeerNotificationSettings?
|
||||
@ -364,15 +368,16 @@ final class ChatListIndexTable: Table {
|
||||
notificationSettings = self.notificationSettingsTable.getEffective(peerId)
|
||||
}
|
||||
}
|
||||
if let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
if let combinedState = self.readStateTable.getCombinedState(peerId) {
|
||||
totalUnreadCount += combinedState.count
|
||||
if let combinedState = self.readStateTable.getCombinedState(peerId) {
|
||||
totalUnreadState.absoluteCounters.messageCount += combinedState.count
|
||||
if let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
totalUnreadState.filteredCounters.messageCount += combinedState.count
|
||||
}
|
||||
}
|
||||
} else if startedParticipationInUnreadCount {
|
||||
if let _ = self.get(peerId: peerId).includedIndex(peerId: peerId) {
|
||||
if let combinedState = self.readStateTable.getCombinedState(peerId) {
|
||||
totalUnreadCount += combinedState.count
|
||||
totalUnreadState.filteredCounters.messageCount += combinedState.count
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -397,7 +402,8 @@ final class ChatListIndexTable: Table {
|
||||
let removedFromList = removedChatListPeerIds.contains(peerId)
|
||||
let removedFromParticipationInUnreadCount = transactionParticipationInTotalUnreadCountUpdates.removed.contains(peerId)
|
||||
if removedFromList && removedFromParticipationInUnreadCount {
|
||||
totalUnreadCount -= currentPeerUnreadCount
|
||||
totalUnreadState.absoluteCounters.messageCount -= currentPeerUnreadCount
|
||||
totalUnreadState.filteredCounters.messageCount -= currentPeerUnreadCount
|
||||
} else if removedFromList {
|
||||
var notificationSettings: PeerNotificationSettings?
|
||||
if let peer = getPeer(peerId) {
|
||||
@ -407,12 +413,13 @@ final class ChatListIndexTable: Table {
|
||||
notificationSettings = self.notificationSettingsTable.getEffective(peerId)
|
||||
}
|
||||
}
|
||||
totalUnreadState.absoluteCounters.messageCount -= currentPeerUnreadCount
|
||||
if let notificationSettings = notificationSettings, !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
totalUnreadCount -= currentPeerUnreadCount
|
||||
totalUnreadState.filteredCounters.messageCount -= currentPeerUnreadCount
|
||||
}
|
||||
} else if removedFromParticipationInUnreadCount {
|
||||
if let _ = self.get(peerId: peerId).includedIndex(peerId: peerId) {
|
||||
totalUnreadCount -= currentPeerUnreadCount
|
||||
totalUnreadState.filteredCounters.messageCount -= currentPeerUnreadCount
|
||||
}
|
||||
} else {
|
||||
assertionFailure()
|
||||
@ -421,9 +428,9 @@ final class ChatListIndexTable: Table {
|
||||
|
||||
//assert(totalUnreadCount >= 0)
|
||||
|
||||
if self.metadataTable.getChatListTotalUnreadCount() != totalUnreadCount {
|
||||
self.metadataTable.setChatListTotalUnreadCount(totalUnreadCount)
|
||||
updatedTotalUnreadCount = totalUnreadCount
|
||||
if self.metadataTable.getChatListTotalUnreadState() != totalUnreadState {
|
||||
self.metadataTable.setChatListTotalUnreadState(totalUnreadState)
|
||||
updatedTotalUnreadState = totalUnreadState
|
||||
}
|
||||
}
|
||||
|
||||
@ -476,4 +483,30 @@ final class ChatListIndexTable: Table {
|
||||
assert(self.updatedPreviousPeerCachedIndices.isEmpty)
|
||||
assert(self.updatedPreviousGroupCachedIndices.isEmpty)
|
||||
}
|
||||
|
||||
func debugReindexUnreadCounts(postbox: Postbox) -> ChatListTotalUnreadState {
|
||||
var peerIds: [PeerId] = []
|
||||
self.valueBox.scanInt64(self.table, values: { key, _ in
|
||||
let peerId = PeerId(key)
|
||||
if peerId.namespace != Int32.max {
|
||||
peerIds.append(peerId)
|
||||
}
|
||||
return true
|
||||
})
|
||||
var state = ChatListTotalUnreadState(absoluteCounters: ChatListTotalUnreadCounters(messageCount: 0), filteredCounters: ChatListTotalUnreadCounters(messageCount: 0))
|
||||
for peerId in peerIds {
|
||||
let inclusion = self.get(peerId: peerId)
|
||||
if inclusion.includedIndex(peerId: peerId) != nil {
|
||||
if let combinedState = postbox.readStateTable.getCombinedState(peerId) {
|
||||
state.absoluteCounters.messageCount += combinedState.count
|
||||
|
||||
if let notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId), !notificationSettings.isRemovedFromTotalUnreadCount {
|
||||
state.filteredCounters.messageCount += combinedState.count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
func fileSize(_ path: String) -> Int? {
|
||||
public func fileSize(_ path: String) -> Int? {
|
||||
var value = stat()
|
||||
if stat(path, &value) == 0 {
|
||||
return Int(value.st_size)
|
||||
|
||||
@ -173,6 +173,13 @@ public final class MediaBox {
|
||||
}
|
||||
}
|
||||
|
||||
public func moveResourceData(_ id: MediaResourceId, fromTempPath: String) {
|
||||
self.dataQueue.async {
|
||||
let paths = self.storePathsForId(id)
|
||||
let _ = try? FileManager.default.moveItem(at: URL(fileURLWithPath: fromTempPath), to: URL(fileURLWithPath: paths.complete))
|
||||
}
|
||||
}
|
||||
|
||||
public func moveResourceData(from: MediaResourceId, to: MediaResourceId) {
|
||||
self.dataQueue.async {
|
||||
let pathsFrom = self.storePathsForId(from)
|
||||
@ -241,9 +248,9 @@ public final class MediaBox {
|
||||
}
|
||||
}
|
||||
|
||||
disposable.set(ActionDisposable {
|
||||
disposable.set(ActionDisposable { [weak statusContext] in
|
||||
self.statusQueue.async {
|
||||
if let current = self.statusContexts[WrappedMediaResourceId(resource.id)] {
|
||||
if let current = self.statusContexts[WrappedMediaResourceId(resource.id)], current === statusContext {
|
||||
current.subscribers.remove(index)
|
||||
if current.subscribers.isEmpty {
|
||||
self.statusContexts.removeValue(forKey: WrappedMediaResourceId(resource.id))
|
||||
|
||||
@ -396,7 +396,9 @@ final class MediaBoxPartialFile {
|
||||
self.statusRequests.removeAll()
|
||||
self.fd.sync()
|
||||
let linkResult = link(self.path, self.completePath)
|
||||
assert(linkResult == 0)
|
||||
if linkResult != 0 {
|
||||
//assert(linkResult == 0)
|
||||
}
|
||||
self.completed(self.fileMap.sum)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,12 +5,65 @@ private enum MetadataPrefix: Int8 {
|
||||
case PeerHistoryInitialized = 1
|
||||
case PeerNextMessageIdByNamespace = 2
|
||||
case NextStableMessageId = 3
|
||||
case ChatListTotalUnreadCount = 4
|
||||
case ChatListTotalUnreadState = 4
|
||||
case NextPeerOperationLogIndex = 5
|
||||
case ChatListGroupInitialized = 6
|
||||
case GroupFeedIndexInitialized = 7
|
||||
}
|
||||
|
||||
public struct ChatListTotalUnreadCounters: PostboxCoding, Equatable {
|
||||
public var messageCount: Int32
|
||||
|
||||
public init(messageCount: Int32) {
|
||||
self.messageCount = messageCount
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.messageCount = decoder.decodeInt32ForKey("m", orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.messageCount, forKey: "m")
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChatListTotalUnreadCounters, rhs: ChatListTotalUnreadCounters) -> Bool {
|
||||
if lhs.messageCount != rhs.messageCount {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public struct ChatListTotalUnreadState: PostboxCoding, Equatable {
|
||||
public var absoluteCounters: ChatListTotalUnreadCounters
|
||||
public var filteredCounters: ChatListTotalUnreadCounters
|
||||
|
||||
public init(absoluteCounters: ChatListTotalUnreadCounters, filteredCounters: ChatListTotalUnreadCounters) {
|
||||
self.absoluteCounters = absoluteCounters
|
||||
self.filteredCounters = filteredCounters
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.absoluteCounters = decoder.decodeObjectForKey("a", decoder: { ChatListTotalUnreadCounters(decoder: $0) }) as! ChatListTotalUnreadCounters
|
||||
self.filteredCounters = decoder.decodeObjectForKey("f", decoder: { ChatListTotalUnreadCounters(decoder: $0) }) as! ChatListTotalUnreadCounters
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeObject(self.absoluteCounters, forKey: "a")
|
||||
encoder.encodeObject(self.filteredCounters, forKey: "f")
|
||||
}
|
||||
|
||||
public static func ==(lhs: ChatListTotalUnreadState, rhs: ChatListTotalUnreadState) -> Bool {
|
||||
if lhs.absoluteCounters != rhs.absoluteCounters {
|
||||
return false
|
||||
}
|
||||
if lhs.filteredCounters != rhs.filteredCounters {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
private enum InitializedChatListKey: Hashable {
|
||||
case global
|
||||
case group(PeerGroupId)
|
||||
@ -80,8 +133,8 @@ final class MessageHistoryMetadataTable: Table {
|
||||
private var nextMessageStableId: UInt32?
|
||||
private var nextMessageStableIdUpdated = false
|
||||
|
||||
private var chatListTotalUnreadCount: Int32?
|
||||
private var chatListTotalUnreadCountUpdated = false
|
||||
private var chatListTotalUnreadState: ChatListTotalUnreadState?
|
||||
private var chatListTotalUnreadStateUpdated = false
|
||||
|
||||
private var nextPeerOperationLogIndex: UInt32?
|
||||
private var nextPeerOperationLogIndexUpdated = false
|
||||
@ -272,27 +325,28 @@ final class MessageHistoryMetadataTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
func getChatListTotalUnreadCount() -> Int32 {
|
||||
if let cached = self.chatListTotalUnreadCount {
|
||||
func getChatListTotalUnreadState() -> ChatListTotalUnreadState {
|
||||
if let cached = self.chatListTotalUnreadState {
|
||||
return cached
|
||||
} else {
|
||||
if let value = self.valueBox.get(self.table, key: self.key(.ChatListTotalUnreadCount)) {
|
||||
var count: Int32 = 0
|
||||
value.read(&count, offset: 0, length: 4)
|
||||
self.chatListTotalUnreadCount = count
|
||||
return count
|
||||
if let value = self.valueBox.get(self.table, key: self.key(.ChatListTotalUnreadState)), let state = PostboxDecoder(buffer: value).decodeObjectForKey("_", decoder: {
|
||||
ChatListTotalUnreadState(decoder: $0)
|
||||
}) as? ChatListTotalUnreadState {
|
||||
self.chatListTotalUnreadState = state
|
||||
return state
|
||||
} else {
|
||||
self.chatListTotalUnreadCount = 0
|
||||
return 0
|
||||
let state = ChatListTotalUnreadState(absoluteCounters: ChatListTotalUnreadCounters(messageCount: 0), filteredCounters: ChatListTotalUnreadCounters(messageCount: 0))
|
||||
self.chatListTotalUnreadState = state
|
||||
return state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setChatListTotalUnreadCount(_ value: Int32) {
|
||||
let current = self.getChatListTotalUnreadCount()
|
||||
if current != value {
|
||||
self.chatListTotalUnreadCount = value
|
||||
self.chatListTotalUnreadCountUpdated = true
|
||||
func setChatListTotalUnreadState(_ state: ChatListTotalUnreadState) {
|
||||
let current = self.getChatListTotalUnreadState()
|
||||
if current != state {
|
||||
self.chatListTotalUnreadState = state
|
||||
self.chatListTotalUnreadStateUpdated = true
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,8 +357,8 @@ final class MessageHistoryMetadataTable: Table {
|
||||
self.updatedPeerNextMessageIdByNamespace.removeAll()
|
||||
self.nextMessageStableId = nil
|
||||
self.nextMessageStableIdUpdated = false
|
||||
self.chatListTotalUnreadCount = nil
|
||||
self.chatListTotalUnreadCountUpdated = false
|
||||
self.chatListTotalUnreadState = nil
|
||||
self.chatListTotalUnreadStateUpdated = false
|
||||
}
|
||||
|
||||
override func beforeCommit() {
|
||||
@ -339,12 +393,13 @@ final class MessageHistoryMetadataTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
if self.chatListTotalUnreadCountUpdated {
|
||||
if let value = self.chatListTotalUnreadCount {
|
||||
var count: Int32 = value
|
||||
self.valueBox.set(self.table, key: self.key(.ChatListTotalUnreadCount), value: MemoryBuffer(memory: &count, capacity: 4, length: 4, freeWhenDone: false))
|
||||
if self.chatListTotalUnreadStateUpdated {
|
||||
if let state = self.chatListTotalUnreadState {
|
||||
let buffer = PostboxEncoder()
|
||||
buffer.encodeObject(state, forKey: "_")
|
||||
self.valueBox.set(self.table, key: self.key(.ChatListTotalUnreadState), value: buffer.readBufferNoCopy())
|
||||
}
|
||||
self.chatListTotalUnreadCountUpdated = false
|
||||
self.chatListTotalUnreadStateUpdated = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,7 +228,13 @@ final class MessageHistoryReadStateTable: Table {
|
||||
|
||||
self.markReadStatesAsUpdated(peerId, namespaces: states.namespaces)
|
||||
|
||||
states.namespaces[namespace] = currentState.withAddedCount(Int32(-knownCount))
|
||||
var updatedState = currentState.withAddedCount(Int32(-knownCount))
|
||||
if updatedState.count < 0 {
|
||||
invalidate = true
|
||||
updatedState = currentState.withAddedCount(-updatedState.count)
|
||||
}
|
||||
|
||||
states.namespaces[namespace] = updatedState
|
||||
updated = true
|
||||
} else {
|
||||
invalidate = true
|
||||
|
||||
@ -409,7 +409,7 @@ final class MessageHistoryTable: Table {
|
||||
|
||||
private func processIndexOperationsCommitAccumulatedRemoveIndices(peerId: PeerId, accumulatedRemoveIndices: inout [(MessageIndex, Bool)], updatedCombinedState: inout CombinedPeerReadState?, invalidateReadState: inout Bool, unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], outputOperations: inout [MessageHistoryOperation], globalTagsOperations: inout [GlobalMessageHistoryTagsOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], groupFeedOperations: inout [PeerGroupId : [GroupFeedIndexOperation]], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) {
|
||||
if !accumulatedRemoveIndices.isEmpty {
|
||||
let (combinedState, invalidate) = self.readStateTable.deleteMessages(peerId, indices: accumulatedRemoveIndices.map { $0.0 }, incomingStatsInIndices: { peerId, namespace, indices in
|
||||
let (combinedState, invalidate) = self.readStateTable.deleteMessages(peerId, indices: accumulatedRemoveIndices.filter({ $0.1 }).map({ $0.0 }), incomingStatsInIndices: { peerId, namespace, indices in
|
||||
return self.incomingMessageStatsInIndices(peerId, namespace: namespace, indices: indices)
|
||||
})
|
||||
if let combinedState = combinedState {
|
||||
@ -729,7 +729,10 @@ final class MessageHistoryTable: Table {
|
||||
|
||||
func clearHistory(peerId: PeerId, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], updatedMedia: inout [MediaId: Media?], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?], globalTagsOperations: inout [GlobalMessageHistoryTagsOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], groupFeedOperations: inout [PeerGroupId : [GroupFeedIndexOperation]], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) {
|
||||
let indices = self.allIndices(peerId)
|
||||
self.removeMessages(indices.map { $0.id }, operationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations)
|
||||
for index in indices.holes {
|
||||
self.fillHole(index.id, fillType: HoleFill(complete: true, direction: .UpperToLower(updatedMinIndex: nil, clippingMaxIndex: nil)), tagMask: nil, messages: [], operationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations)
|
||||
}
|
||||
self.removeMessages(indices.messages.map { $0.id }, operationsByPeerId: &operationsByPeerId, updatedMedia: &updatedMedia, unsentMessageOperations: &unsentMessageOperations, updatedPeerReadStateOperations: &updatedPeerReadStateOperations, globalTagsOperations: &globalTagsOperations, pendingActionsOperations: &pendingActionsOperations, updatedMessageActionsSummaries: &updatedMessageActionsSummaries, updatedMessageTagSummaries: &updatedMessageTagSummaries, invalidateMessageTagSummaries: &invalidateMessageTagSummaries, groupFeedOperations: &groupFeedOperations, localTagsOperations: &localTagsOperations)
|
||||
}
|
||||
|
||||
func removeAllMessagesWithAuthor(peerId: PeerId, authorId: PeerId, operationsByPeerId: inout [PeerId: [MessageHistoryOperation]], updatedMedia: inout [MediaId: Media?], unsentMessageOperations: inout [IntermediateMessageHistoryUnsentOperation], updatedPeerReadStateOperations: inout [PeerId: PeerReadStateSynchronizationOperation?], globalTagsOperations: inout [GlobalMessageHistoryTagsOperation], pendingActionsOperations: inout [PendingMessageActionsOperation], updatedMessageActionsSummaries: inout [PendingMessageActionsSummaryKey: Int32], updatedMessageTagSummaries: inout [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], invalidateMessageTagSummaries: inout [InvalidatedMessageHistoryTagsSummaryEntryOperation], groupFeedOperations: inout [PeerGroupId : [GroupFeedIndexOperation]], localTagsOperations: inout [IntermediateMessageHistoryLocalTagsOperation]) {
|
||||
@ -3034,14 +3037,19 @@ final class MessageHistoryTable: Table {
|
||||
return messageIds
|
||||
}
|
||||
|
||||
func allIndices(_ peerId: PeerId) -> [MessageIndex] {
|
||||
var indices: [MessageIndex] = []
|
||||
self.valueBox.range(self.table, start: self.key(MessageIndex.lowerBound(peerId: peerId)).predecessor, end: self.key(MessageIndex.upperBound(peerId: peerId)).successor, keys: { key in
|
||||
func allIndices(_ peerId: PeerId) -> (messages: [MessageIndex], holes: [MessageIndex]) {
|
||||
var messages: [MessageIndex] = []
|
||||
var holes: [MessageIndex] = []
|
||||
self.valueBox.range(self.table, start: self.key(MessageIndex.lowerBound(peerId: peerId)).predecessor, end: self.key(MessageIndex.upperBound(peerId: peerId)).successor, values: { key, value in
|
||||
let index = MessageIndex(id: MessageId(peerId: PeerId(key.getInt64(0)), namespace: key.getInt32(8 + 4), id: key.getInt32(8 + 4 + 4)), timestamp: key.getInt32(8))
|
||||
indices.append(index)
|
||||
if extractIntermediateEntryIsMessage(value: value) {
|
||||
messages.append(index)
|
||||
} else {
|
||||
holes.append(index)
|
||||
}
|
||||
return true
|
||||
}, limit: 0)
|
||||
return indices
|
||||
return (messages, holes)
|
||||
}
|
||||
|
||||
func allMessageIndices(_ peerId: PeerId) -> [MessageIndex] {
|
||||
|
||||
@ -14,7 +14,7 @@ public enum AdditionalMessageHistoryViewData {
|
||||
case cachedPeerDataMessages(PeerId)
|
||||
case peerChatState(PeerId)
|
||||
case peerGroupState(PeerGroupId)
|
||||
case totalUnreadCount
|
||||
case totalUnreadState
|
||||
case peerNotificationSettings(PeerId)
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ public enum AdditionalMessageHistoryViewDataEntry {
|
||||
case cachedPeerDataMessages(PeerId, [MessageId: Message]?)
|
||||
case peerChatState(PeerId, PeerChatState?)
|
||||
case peerGroupState(PeerGroupId, PeerGroupState?)
|
||||
case totalUnreadCount(Int32)
|
||||
case totalUnreadState(ChatListTotalUnreadState)
|
||||
case peerNotificationSettings(PeerNotificationSettings?)
|
||||
}
|
||||
|
||||
@ -423,7 +423,7 @@ private func monthUpperBoundIndex(peerId: PeerId, index: MessageMonthIndex) -> M
|
||||
|
||||
public enum MessageHistoryViewPeerIds: Equatable {
|
||||
case single(PeerId)
|
||||
case associated(PeerId, PeerId?)
|
||||
case associated(PeerId, MessageId?)
|
||||
case group(PeerGroupId)
|
||||
|
||||
public static func ==(lhs: MessageHistoryViewPeerIds, rhs: MessageHistoryViewPeerIds) -> Bool {
|
||||
@ -450,6 +450,46 @@ public enum MessageHistoryViewPeerIds: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func clipMessages(peerIds: MessageHistoryViewPeerIds, entries: [MutableMessageHistoryEntry]) -> [MutableMessageHistoryEntry] {
|
||||
switch peerIds {
|
||||
case .single, .group:
|
||||
return entries
|
||||
case let .associated(_, associatedId):
|
||||
if let associatedId = associatedId {
|
||||
var result: [MutableMessageHistoryEntry] = []
|
||||
for entry in entries {
|
||||
switch entry {
|
||||
case let .MessageEntry(message, _, _):
|
||||
if message.id.peerId == associatedId.peerId {
|
||||
if message.id.namespace == associatedId.namespace && message.id.id <= associatedId.id {
|
||||
result.append(entry)
|
||||
}
|
||||
} else {
|
||||
result.append(entry)
|
||||
}
|
||||
case let .IntermediateMessageEntry(message, _, _):
|
||||
if message.id.peerId == associatedId.peerId {
|
||||
if message.id.namespace == associatedId.namespace && message.id.id <= associatedId.id {
|
||||
result.append(entry)
|
||||
}
|
||||
} else {
|
||||
result.append(entry)
|
||||
}
|
||||
case .HoleEntry:
|
||||
result.append(entry)
|
||||
}
|
||||
}
|
||||
return result
|
||||
} else {
|
||||
return entries
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func clipAround(peerIds: MessageHistoryViewPeerIds, _ data: (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?)) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?) {
|
||||
return (entries: clipMessages(peerIds: peerIds, entries: data.entries), lower: data.lower, upper: data.upper)
|
||||
}
|
||||
|
||||
private func fetchAround(postbox: Postbox, peerIds: MessageHistoryViewPeerIds, index: InternalMessageHistoryAnchorIndex, count: Int, tagMask: MessageTags?) -> (entries: [MutableMessageHistoryEntry], lower: MutableMessageHistoryEntry?, upper: MutableMessageHistoryEntry?) {
|
||||
var ids: [PeerId] = []
|
||||
switch peerIds {
|
||||
@ -458,7 +498,7 @@ private func fetchAround(postbox: Postbox, peerIds: MessageHistoryViewPeerIds, i
|
||||
case let .associated(mainId, associatedId):
|
||||
ids.append(mainId)
|
||||
if let associatedId = associatedId {
|
||||
ids.append(associatedId)
|
||||
ids.append(associatedId.peerId)
|
||||
}
|
||||
case let .group(groupId):
|
||||
switch index {
|
||||
@ -473,11 +513,11 @@ private func fetchAround(postbox: Postbox, peerIds: MessageHistoryViewPeerIds, i
|
||||
|
||||
switch index {
|
||||
case let .message(index: index, _):
|
||||
return postbox.fetchAroundHistoryEntries(peerIds: ids, index: index, count: count, tagMask: tagMask)
|
||||
return clipAround(peerIds: peerIds, postbox.fetchAroundHistoryEntries(peerIds: ids, index: index, count: count, tagMask: tagMask))
|
||||
case .upperBound:
|
||||
return postbox.fetchAroundHistoryEntries(peerIds: ids, index: MessageIndex.absoluteUpperBound(), count: count, tagMask: tagMask)
|
||||
return clipAround(peerIds: peerIds, postbox.fetchAroundHistoryEntries(peerIds: ids, index: MessageIndex.absoluteUpperBound(), count: count, tagMask: tagMask))
|
||||
case .lowerBound:
|
||||
return postbox.fetchAroundHistoryEntries(peerIds: ids, index: MessageIndex.absoluteLowerBound(), count: count, tagMask: tagMask)
|
||||
return clipAround(peerIds: peerIds, postbox.fetchAroundHistoryEntries(peerIds: ids, index: MessageIndex.absoluteLowerBound(), count: count, tagMask: tagMask))
|
||||
}
|
||||
}
|
||||
|
||||
@ -690,12 +730,18 @@ final class MutableMessageHistoryView {
|
||||
|
||||
func updatePeerIds(transaction: PostboxTransaction) {
|
||||
switch self.peerIds {
|
||||
case .single, .group:
|
||||
case .group:
|
||||
break
|
||||
case let .single(peerId):
|
||||
if let updatedData = transaction.currentUpdatedCachedPeerData[peerId] {
|
||||
if updatedData.associatedHistoryMessageId != nil {
|
||||
self.peerIds = .associated(peerId, updatedData.associatedHistoryMessageId)
|
||||
}
|
||||
}
|
||||
case let .associated(peerId, associatedId):
|
||||
if let updatedData = transaction.currentUpdatedCachedPeerData[peerId] {
|
||||
if updatedData.associatedHistoryPeerId != associatedId {
|
||||
self.peerIds = .associated(peerId, updatedData.associatedHistoryPeerId)
|
||||
if updatedData.associatedHistoryMessageId != associatedId {
|
||||
self.peerIds = .associated(peerId, updatedData.associatedHistoryMessageId)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -722,7 +768,7 @@ final class MutableMessageHistoryView {
|
||||
case let .associated(mainPeerId, associatedPeerId):
|
||||
ids.insert(mainPeerId)
|
||||
if let associatedPeerId = associatedPeerId {
|
||||
ids.insert(associatedPeerId)
|
||||
ids.insert(associatedPeerId.peerId)
|
||||
}
|
||||
case let .group(groupId):
|
||||
if let operations = transaction.currentGroupFeedOperations[groupId] {
|
||||
@ -1008,7 +1054,7 @@ final class MutableMessageHistoryView {
|
||||
self.additionalDatas[i] = .peerGroupState(groupId, postbox.peerGroupStateTable.get(groupId))
|
||||
hasChanges = true
|
||||
}
|
||||
case .totalUnreadCount:
|
||||
case .totalUnreadState:
|
||||
break
|
||||
case .peerNotificationSettings:
|
||||
break
|
||||
@ -1205,13 +1251,13 @@ final class MutableMessageHistoryView {
|
||||
case let .associated(mainId, associatedId):
|
||||
ids.append(mainId)
|
||||
if let associatedId = associatedId {
|
||||
ids.append(associatedId)
|
||||
ids.append(associatedId.peerId)
|
||||
}
|
||||
case let .group(groupId):
|
||||
return postbox.fetchEarlierGroupFeedEntries(groupId: groupId, index: index, count: count)
|
||||
}
|
||||
|
||||
return postbox.fetchEarlierHistoryEntries(peerIds: ids, index: index, count: count, tagMask: self.tagMask)
|
||||
return clipMessages(peerIds: peerIds, entries: postbox.fetchEarlierHistoryEntries(peerIds: ids, index: index, count: count, tagMask: self.tagMask))
|
||||
}
|
||||
|
||||
private func fetchLater(postbox: Postbox, index: MessageIndex?, count: Int) -> [MutableMessageHistoryEntry] {
|
||||
@ -1222,13 +1268,13 @@ final class MutableMessageHistoryView {
|
||||
case let .associated(mainId, associatedId):
|
||||
ids.append(mainId)
|
||||
if let associatedId = associatedId {
|
||||
ids.append(associatedId)
|
||||
ids.append(associatedId.peerId)
|
||||
}
|
||||
case let .group(groupId):
|
||||
return postbox.fetchLaterGroupFeedEntries(groupId: groupId, index: index, count: count)
|
||||
}
|
||||
|
||||
return postbox.fetchLaterHistoryEntries(ids, index: index, count: count, tagMask: self.tagMask)
|
||||
return clipMessages(peerIds: peerIds, entries: postbox.fetchLaterHistoryEntries(ids, index: index, count: count, tagMask: self.tagMask))
|
||||
}
|
||||
|
||||
func complete(postbox: Postbox, context: MutableMessageHistoryViewReplayContext) {
|
||||
@ -1492,11 +1538,19 @@ public final class MessageHistoryView {
|
||||
var laterId = mutableView.later?.index
|
||||
|
||||
var entries: [MessageHistoryEntry] = []
|
||||
var removeUpperHolePeerId: PeerId?
|
||||
if case let .associated(_, associatedId) = mutableView.peerIds {
|
||||
removeUpperHolePeerId = associatedId?.peerId
|
||||
}
|
||||
if let transientReadStates = mutableView.transientReadStates, case let .peer(states) = transientReadStates {
|
||||
for entry in mutableView.entries {
|
||||
switch entry {
|
||||
case let .HoleEntry(hole, location, _):
|
||||
entries.append(.HoleEntry(hole, location))
|
||||
if let removeUpperHolePeerId = removeUpperHolePeerId, removeUpperHolePeerId == hole.maxIndex.id.peerId, hole.maxIndex.timestamp >= Int32.max - 1 {
|
||||
// skip hole
|
||||
} else {
|
||||
entries.append(.HoleEntry(hole, location))
|
||||
}
|
||||
case let .MessageEntry(message, location, monthLocation):
|
||||
let read: Bool
|
||||
if message.flags.contains(.Incoming) {
|
||||
@ -1515,7 +1569,11 @@ public final class MessageHistoryView {
|
||||
for entry in mutableView.entries {
|
||||
switch entry {
|
||||
case let .HoleEntry(hole, location, _):
|
||||
entries.append(.HoleEntry(hole, location))
|
||||
if let removeUpperHolePeerId = removeUpperHolePeerId, removeUpperHolePeerId == hole.maxIndex.id.peerId, hole.maxIndex.timestamp >= Int32.max - 1 {
|
||||
// skip hole
|
||||
} else {
|
||||
entries.append(.HoleEntry(hole, location))
|
||||
}
|
||||
case let .MessageEntry(message, location, monthLocation):
|
||||
entries.append(.MessageEntry(message, false, location, monthLocation))
|
||||
case .IntermediateMessageEntry:
|
||||
|
||||
@ -4,6 +4,7 @@ enum OrderedItemListOperation {
|
||||
case replace([OrderedItemListEntry])
|
||||
case addOrMoveToFirstPosition(OrderedItemListEntry, Int?)
|
||||
case remove(MemoryBuffer)
|
||||
case update(MemoryBuffer, OrderedItemListEntryContents)
|
||||
}
|
||||
|
||||
private enum OrderedItemListKeyNamespace: UInt8 {
|
||||
@ -85,6 +86,16 @@ final class OrderedItemListTable: Table {
|
||||
}
|
||||
}
|
||||
|
||||
func updateItem(collectionId: Int32, itemId: MemoryBuffer, item: OrderedItemListEntryContents, operations: inout [Int32: [OrderedItemListOperation]]) {
|
||||
if let _ = self.indexTable.get(collectionId: collectionId, id: itemId) as? OrderedItemListEntryContents {
|
||||
self.indexTable.set(collectionId: collectionId, id: itemId, content: item)
|
||||
if operations[collectionId] == nil {
|
||||
operations[collectionId] = []
|
||||
}
|
||||
operations[collectionId]!.append(.update(itemId, item))
|
||||
}
|
||||
}
|
||||
|
||||
func replaceItems(collectionId: Int32, items: [OrderedItemListEntry], operations: inout [Int32: [OrderedItemListOperation]]) {
|
||||
if operations[collectionId] == nil {
|
||||
operations[collectionId] = [.replace(items)]
|
||||
|
||||
@ -37,6 +37,14 @@ final class MutableOrderedItemListView: MutablePostboxView {
|
||||
break inner
|
||||
}
|
||||
}
|
||||
case let .update(itemId, content):
|
||||
inner: for i in 0 ..< self.items.count {
|
||||
if self.items[i].id == itemId {
|
||||
self.items[i] = OrderedItemListEntry(id: itemId, contents: content)
|
||||
updated = true
|
||||
break inner
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,6 +522,11 @@ public final class Modifier {
|
||||
return self.postbox?.getOrderedItemListItem(collectionId: collectionId, itemId: itemId)
|
||||
}
|
||||
|
||||
public func updateOrderedItemListItem(collectionId: Int32, itemId: MemoryBuffer, item: OrderedItemListEntryContents) {
|
||||
assert(!self.disposed)
|
||||
self.postbox?.updateOrderedItemListItem(collectionId: collectionId, itemId: itemId, item: item)
|
||||
}
|
||||
|
||||
public func removeOrderedItemListItem(collectionId: Int32, itemId: MemoryBuffer) {
|
||||
assert(!self.disposed)
|
||||
self.postbox?.removeOrderedItemListItem(collectionId: collectionId, itemId: itemId)
|
||||
@ -679,12 +684,12 @@ public final class Modifier {
|
||||
}
|
||||
}
|
||||
|
||||
public func getTotalUnreadCount() -> Int32 {
|
||||
public func getTotalUnreadState() -> ChatListTotalUnreadState {
|
||||
assert(!self.disposed)
|
||||
if let postbox = self.postbox {
|
||||
return postbox.messageHistoryMetadataTable.getChatListTotalUnreadCount()
|
||||
return postbox.messageHistoryMetadataTable.getChatListTotalUnreadState()
|
||||
} else {
|
||||
return 0
|
||||
return ChatListTotalUnreadState(absoluteCounters: ChatListTotalUnreadCounters(messageCount: 0), filteredCounters: ChatListTotalUnreadCounters(messageCount: 0))
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,11 +844,15 @@ func debugSaveState(basePath:String, name: String) {
|
||||
|
||||
func debugRestoreState(basePath:String, name: String) {
|
||||
let path = basePath + name
|
||||
let _ = try? FileManager.default.removeItem(atPath: basePath)
|
||||
do {
|
||||
try FileManager.default.copyItem(atPath: path, toPath: basePath)
|
||||
} catch (let e) {
|
||||
print("(Postbox debugRestoreState: error \(e))")
|
||||
if FileManager.default.fileExists(atPath: path) {
|
||||
let _ = try? FileManager.default.removeItem(atPath: basePath)
|
||||
do {
|
||||
try FileManager.default.copyItem(atPath: path, toPath: basePath)
|
||||
} catch (let e) {
|
||||
print("(Postbox debugRestoreState: error \(e))")
|
||||
}
|
||||
} else {
|
||||
print("(Postbox debugRestoreState: path doesn't exist")
|
||||
}
|
||||
}
|
||||
|
||||
@ -864,22 +873,26 @@ public func openPostbox(basePath: String, globalMessageIdsNamespace: MessageId.N
|
||||
let metadataTable = MetadataTable(valueBox: valueBox, table: MetadataTable.tableSpec(0))
|
||||
|
||||
let userVersion: Int32? = metadataTable.userVersion()
|
||||
let currentUserVersion: Int32 = 15
|
||||
let currentUserVersion: Int32 = 16
|
||||
|
||||
if let userVersion = userVersion {
|
||||
if userVersion != currentUserVersion {
|
||||
if let operation = registeredUpgrades()[userVersion] {
|
||||
switch operation {
|
||||
case let .inplace(f):
|
||||
valueBox.begin()
|
||||
f(metadataTable, valueBox)
|
||||
valueBox.commit()
|
||||
}
|
||||
continue loop
|
||||
if userVersion > currentUserVersion {
|
||||
postboxLog("Version \(userVersion) is newer than supported")
|
||||
} else {
|
||||
assertionFailure()
|
||||
postboxLog("Couldn't find any upgrade for \(userVersion)")
|
||||
valueBox.drop()
|
||||
if let operation = registeredUpgrades()[userVersion] {
|
||||
switch operation {
|
||||
case let .inplace(f):
|
||||
valueBox.begin()
|
||||
f(metadataTable, valueBox)
|
||||
valueBox.commit()
|
||||
}
|
||||
continue loop
|
||||
} else {
|
||||
assertionFailure()
|
||||
postboxLog("Couldn't find any upgrade for \(userVersion)")
|
||||
valueBox.drop()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -931,7 +944,7 @@ public final class Postbox {
|
||||
private var currentUpdatedCachedPeerData: [PeerId: CachedPeerData] = [:]
|
||||
private var currentUpdatedPeerPresences: [PeerId: PeerPresence] = [:]
|
||||
private var currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?] = [:]
|
||||
private var currentUpdatedTotalUnreadCount: Int32?
|
||||
private var currentUpdatedTotalUnreadState: ChatListTotalUnreadState?
|
||||
private var currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation] = []
|
||||
private var currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation] = []
|
||||
private var currentPreferencesOperations: [PreferencesOperation] = []
|
||||
@ -1171,8 +1184,8 @@ public final class Postbox {
|
||||
return self.cachedPeerDataTable.get(peerId)
|
||||
}, getPeerPresence: { peerId in
|
||||
return self.peerPresenceTable.get(peerId)
|
||||
}, getTotalUnreadCount: {
|
||||
return self.messageHistoryMetadataTable.getChatListTotalUnreadCount()
|
||||
}, getTotalUnreadState: {
|
||||
return self.messageHistoryMetadataTable.getChatListTotalUnreadState()
|
||||
}, getPeerReadState: { peerId in
|
||||
return self.readStateTable.getCombinedState(peerId)
|
||||
}, operationLogGetOperations: { tag, fromIndex, limit in
|
||||
@ -1710,9 +1723,19 @@ public final class Postbox {
|
||||
let transactionParticipationInTotalUnreadCountUpdates = self.peerNotificationSettingsTable.transactionParticipationInTotalUnreadCountUpdates()
|
||||
self.chatListIndexTable.commitWithTransactionUnreadCountDeltas(transactionUnreadCountDeltas, transactionParticipationInTotalUnreadCountUpdates: transactionParticipationInTotalUnreadCountUpdates, getPeer: { peerId in
|
||||
return self.peerTable.get(peerId)
|
||||
}, updatedTotalUnreadCount: &self.currentUpdatedTotalUnreadCount)
|
||||
}, updatedTotalUnreadState: &self.currentUpdatedTotalUnreadState)
|
||||
|
||||
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentOperationsByPeerId: self.currentOperationsByPeerId, currentGroupFeedOperations: self.currentGroupFeedOperations, peerIdsWithFilledHoles: self.currentFilledHolesByPeerId, removedHolesByPeerId: self.currentRemovedHolesByPeerId, groupFeedIdsWithFilledHoles: self.currentGroupFeedIdsWithFilledHoles, removedHolesByPeerGroupId: self.currentRemovedHolesByPeerGroupId, chatListOperations: self.currentChatListOperations, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadCount: self.currentUpdatedTotalUnreadCount, peerIdsWithUpdatedUnreadCounts: Set(transactionUnreadCountDeltas.keys), peerIdsWithUpdatedCombinedReadStates: peerIdsWithUpdatedCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentUpdatedPeerGroupStates: self.currentUpdatedPeerGroupStates, updatedAccessChallengeData: self.currentUpdatedAccessChallengeData, 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, currentGroupFeedReadStateContext: self.currentGroupFeedReadStateContext, currentInitialPeerGroupIdsBeforeUpdate: self.currentInitialPeerGroupIdsBeforeUpdate, currentUpdatedMasterClientId: currentUpdatedMasterClientId)
|
||||
#if DEBUG
|
||||
/*if let updatedState = self.currentUpdatedTotalUnreadState {
|
||||
let state = self.chatListIndexTable.debugReindexUnreadCounts(postbox: self)
|
||||
if state != updatedState {
|
||||
print("read state mismatch \(state) != \(updatedState)")
|
||||
self.messageHistoryMetadataTable.setChatListTotalUnreadState(state)
|
||||
}
|
||||
}*/
|
||||
#endif
|
||||
|
||||
let transaction = PostboxTransaction(currentUpdatedState: self.currentUpdatedState, currentOperationsByPeerId: self.currentOperationsByPeerId, currentGroupFeedOperations: self.currentGroupFeedOperations, peerIdsWithFilledHoles: self.currentFilledHolesByPeerId, removedHolesByPeerId: self.currentRemovedHolesByPeerId, groupFeedIdsWithFilledHoles: self.currentGroupFeedIdsWithFilledHoles, removedHolesByPeerGroupId: self.currentRemovedHolesByPeerGroupId, chatListOperations: self.currentChatListOperations, currentUpdatedPeers: self.currentUpdatedPeers, currentUpdatedPeerNotificationSettings: self.currentUpdatedPeerNotificationSettings, currentUpdatedCachedPeerData: self.currentUpdatedCachedPeerData, currentUpdatedPeerPresences: currentUpdatedPeerPresences, currentUpdatedPeerChatListEmbeddedStates: self.currentUpdatedPeerChatListEmbeddedStates, currentUpdatedTotalUnreadState: self.currentUpdatedTotalUnreadState, peerIdsWithUpdatedUnreadCounts: Set(transactionUnreadCountDeltas.keys), peerIdsWithUpdatedCombinedReadStates: peerIdsWithUpdatedCombinedReadStates, currentPeerMergedOperationLogOperations: self.currentPeerMergedOperationLogOperations, currentTimestampBasedMessageAttributesOperations: self.currentTimestampBasedMessageAttributesOperations, unsentMessageOperations: self.currentUnsentOperations, updatedSynchronizePeerReadStateOperations: self.currentUpdatedSynchronizeReadStateOperations, currentPreferencesOperations: self.currentPreferencesOperations, currentOrderedItemListOperations: self.currentOrderedItemListOperations, currentItemCollectionItemsOperations: self.currentItemCollectionItemsOperations, currentItemCollectionInfosOperations: self.currentItemCollectionInfosOperations, currentUpdatedPeerChatStates: self.currentUpdatedPeerChatStates, currentUpdatedPeerGroupStates: self.currentUpdatedPeerGroupStates, updatedAccessChallengeData: self.currentUpdatedAccessChallengeData, 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, currentGroupFeedReadStateContext: self.currentGroupFeedReadStateContext, currentInitialPeerGroupIdsBeforeUpdate: self.currentInitialPeerGroupIdsBeforeUpdate, currentUpdatedMasterClientId: currentUpdatedMasterClientId)
|
||||
var updatedTransactionState: Int64?
|
||||
var updatedMasterClientId: Int64?
|
||||
if !transaction.isEmpty {
|
||||
@ -1748,7 +1771,7 @@ public final class Postbox {
|
||||
self.currentUpdatedCachedPeerData.removeAll()
|
||||
self.currentUpdatedPeerPresences.removeAll()
|
||||
self.currentUpdatedPeerChatListEmbeddedStates.removeAll()
|
||||
self.currentUpdatedTotalUnreadCount = nil
|
||||
self.currentUpdatedTotalUnreadState = nil
|
||||
self.currentPeerMergedOperationLogOperations.removeAll()
|
||||
self.currentTimestampBasedMessageAttributesOperations.removeAll()
|
||||
self.currentPreferencesOperations.removeAll()
|
||||
@ -2157,8 +2180,8 @@ public final class Postbox {
|
||||
switch chatLocation {
|
||||
case let .peer(peerId):
|
||||
peerIds = .single(peerId)
|
||||
if tagMask == nil, let associatedPeerId = self.cachedPeerDataTable.get(peerId)?.associatedHistoryPeerId, associatedPeerId != peerId {
|
||||
peerIds = .associated(peerId, associatedPeerId)
|
||||
if tagMask == nil, let associatedMessageId = self.cachedPeerDataTable.get(peerId)?.associatedHistoryMessageId, associatedMessageId.peerId != peerId {
|
||||
peerIds = .associated(peerId, associatedMessageId)
|
||||
}
|
||||
case let .group(groupId):
|
||||
peerIds = .group(groupId)
|
||||
@ -2182,7 +2205,7 @@ public final class Postbox {
|
||||
var ids: [PeerId] = []
|
||||
ids.append(mainId)
|
||||
if let associatedId = associatedId {
|
||||
ids.append(associatedId)
|
||||
ids.append(associatedId.peerId)
|
||||
}
|
||||
|
||||
var minIndexWithUnreadMessages: InternalMessageHistoryAnchorIndex?
|
||||
@ -2304,8 +2327,8 @@ public final class Postbox {
|
||||
additionalDataEntries.append(.peerChatState(peerId, self.peerChatStateTable.get(peerId) as? PeerChatState))
|
||||
case let .peerGroupState(groupId):
|
||||
additionalDataEntries.append(.peerGroupState(groupId, self.peerGroupStateTable.get(groupId)))
|
||||
case .totalUnreadCount:
|
||||
additionalDataEntries.append(.totalUnreadCount(self.messageHistoryMetadataTable.getChatListTotalUnreadCount()))
|
||||
case .totalUnreadState:
|
||||
additionalDataEntries.append(.totalUnreadState(self.messageHistoryMetadataTable.getChatListTotalUnreadState()))
|
||||
case let .peerNotificationSettings(peerId):
|
||||
additionalDataEntries.append(.peerNotificationSettings(self.peerNotificationSettingsTable.getEffective(peerId)))
|
||||
}
|
||||
@ -2954,6 +2977,10 @@ public final class Postbox {
|
||||
return self.orderedItemListTable.getItem(collectionId: collectionId, itemId: itemId)
|
||||
}
|
||||
|
||||
fileprivate func updateOrderedItemListItem(collectionId: Int32, itemId: MemoryBuffer, item: OrderedItemListEntryContents) {
|
||||
self.orderedItemListTable.updateItem(collectionId: collectionId, itemId: itemId, item: item, operations: &self.currentOrderedItemListOperations)
|
||||
}
|
||||
|
||||
fileprivate func setAccessChallengeData(_ data: PostboxAccessChallengeData) {
|
||||
self.currentUpdatedAccessChallengeData = data
|
||||
self.metadataTable.setAccessChallengeData(data)
|
||||
|
||||
@ -14,7 +14,7 @@ final class PostboxTransaction {
|
||||
let currentUpdatedCachedPeerData: [PeerId: CachedPeerData]
|
||||
let currentUpdatedPeerPresences: [PeerId: PeerPresence]
|
||||
let currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?]
|
||||
let currentUpdatedTotalUnreadCount: Int32?
|
||||
let currentUpdatedTotalUnreadState: ChatListTotalUnreadState?
|
||||
let peerIdsWithUpdatedUnreadCounts: Set<PeerId>
|
||||
let peerIdsWithUpdatedCombinedReadStates: Set<PeerId>
|
||||
let currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation]
|
||||
@ -101,7 +101,7 @@ final class PostboxTransaction {
|
||||
if currentUpdatedMasterClientId != nil {
|
||||
return false
|
||||
}
|
||||
if currentUpdatedTotalUnreadCount != nil {
|
||||
if currentUpdatedTotalUnreadState != nil {
|
||||
return false
|
||||
}
|
||||
if !peerIdsWithUpdatedCombinedReadStates.isEmpty {
|
||||
@ -167,7 +167,7 @@ final class PostboxTransaction {
|
||||
return true
|
||||
}
|
||||
|
||||
init(currentUpdatedState: PostboxCoding?, currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], currentGroupFeedOperations: [PeerGroupId : [GroupFeedIndexOperation]], peerIdsWithFilledHoles: [PeerId: [MessageIndex: HoleFillDirection]], removedHolesByPeerId: [PeerId: [MessageIndex: HoleFillDirection]], groupFeedIdsWithFilledHoles: [PeerGroupId: [MessageIndex: HoleFillDirection]], removedHolesByPeerGroupId: [PeerGroupId: [MessageIndex: HoleFillDirection]], chatListOperations: [WrappedPeerGroupId: [ChatListOperation]], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: PeerNotificationSettings], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?], currentUpdatedTotalUnreadCount: Int32?, peerIdsWithUpdatedUnreadCounts: Set<PeerId>, peerIdsWithUpdatedCombinedReadStates: Set<PeerId>, currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentUpdatedPeerGroupStates: Set<PeerGroupId>, updatedAccessChallengeData: PostboxAccessChallengeData?, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, currentGroupFeedReadStateContext: GroupFeedReadStateUpdateContext, currentInitialPeerGroupIdsBeforeUpdate: [PeerId: WrappedPeerGroupId], currentUpdatedMasterClientId: Int64?) {
|
||||
init(currentUpdatedState: PostboxCoding?, currentOperationsByPeerId: [PeerId: [MessageHistoryOperation]], currentGroupFeedOperations: [PeerGroupId : [GroupFeedIndexOperation]], peerIdsWithFilledHoles: [PeerId: [MessageIndex: HoleFillDirection]], removedHolesByPeerId: [PeerId: [MessageIndex: HoleFillDirection]], groupFeedIdsWithFilledHoles: [PeerGroupId: [MessageIndex: HoleFillDirection]], removedHolesByPeerGroupId: [PeerGroupId: [MessageIndex: HoleFillDirection]], chatListOperations: [WrappedPeerGroupId: [ChatListOperation]], currentUpdatedPeers: [PeerId: Peer], currentUpdatedPeerNotificationSettings: [PeerId: PeerNotificationSettings], currentUpdatedCachedPeerData: [PeerId: CachedPeerData], currentUpdatedPeerPresences: [PeerId: PeerPresence], currentUpdatedPeerChatListEmbeddedStates: [PeerId: PeerChatListEmbeddedInterfaceState?], currentUpdatedTotalUnreadState: ChatListTotalUnreadState?, peerIdsWithUpdatedUnreadCounts: Set<PeerId>, peerIdsWithUpdatedCombinedReadStates: Set<PeerId>, currentPeerMergedOperationLogOperations: [PeerMergedOperationLogOperation], currentTimestampBasedMessageAttributesOperations: [TimestampBasedMessageAttributesOperation], unsentMessageOperations: [IntermediateMessageHistoryUnsentOperation], updatedSynchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation?], currentPreferencesOperations: [PreferencesOperation], currentOrderedItemListOperations: [Int32: [OrderedItemListOperation]], currentItemCollectionItemsOperations: [ItemCollectionId: [ItemCollectionItemsOperation]], currentItemCollectionInfosOperations: [ItemCollectionInfosOperation], currentUpdatedPeerChatStates: Set<PeerId>, currentUpdatedPeerGroupStates: Set<PeerGroupId>, updatedAccessChallengeData: PostboxAccessChallengeData?, currentGlobalTagsOperations: [GlobalMessageHistoryTagsOperation], currentLocalTagsOperations: [IntermediateMessageHistoryLocalTagsOperation], updatedMedia: [MediaId: Media?], replaceRemoteContactCount: Int32?, replaceContactPeerIds: Set<PeerId>?, currentPendingMessageActionsOperations: [PendingMessageActionsOperation], currentUpdatedMessageActionsSummaries: [PendingMessageActionsSummaryKey: Int32], currentUpdatedMessageTagSummaries: [MessageHistoryTagsSummaryKey: MessageHistoryTagNamespaceSummary], currentInvalidateMessageTagSummaries: [InvalidatedMessageHistoryTagsSummaryEntryOperation], currentUpdatedPendingPeerNotificationSettings: Set<PeerId>, currentGroupFeedReadStateContext: GroupFeedReadStateUpdateContext, currentInitialPeerGroupIdsBeforeUpdate: [PeerId: WrappedPeerGroupId], currentUpdatedMasterClientId: Int64?) {
|
||||
self.currentUpdatedState = currentUpdatedState
|
||||
self.currentOperationsByPeerId = currentOperationsByPeerId
|
||||
self.currentGroupFeedOperations = currentGroupFeedOperations
|
||||
@ -181,7 +181,7 @@ final class PostboxTransaction {
|
||||
self.currentUpdatedCachedPeerData = currentUpdatedCachedPeerData
|
||||
self.currentUpdatedPeerPresences = currentUpdatedPeerPresences
|
||||
self.currentUpdatedPeerChatListEmbeddedStates = currentUpdatedPeerChatListEmbeddedStates
|
||||
self.currentUpdatedTotalUnreadCount = currentUpdatedTotalUnreadCount
|
||||
self.currentUpdatedTotalUnreadState = currentUpdatedTotalUnreadState
|
||||
self.peerIdsWithUpdatedUnreadCounts = peerIdsWithUpdatedUnreadCounts
|
||||
self.peerIdsWithUpdatedCombinedReadStates = peerIdsWithUpdatedCombinedReadStates
|
||||
self.currentPeerMergedOperationLogOperations = currentPeerMergedOperationLogOperations
|
||||
|
||||
@ -16,19 +16,6 @@ private func makeKeyValueForChatListPinningIndex(_ index: UInt16?) -> UInt16 {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private func key(_ index: ChatListIndex, type: ChatListEntryType) -> ValueBoxKey {
|
||||
let key = ValueBoxKey(length: 2 + 4 + 4 + 4 + 8 + 1)
|
||||
key.setUInt16(0, value: keyValueForChatListPinningIndex(index.pinningIndex))
|
||||
key.setInt32(2, value: index.messageIndex.timestamp)
|
||||
key.setInt32(2 + 4, value: index.messageIndex.id.namespace)
|
||||
key.setInt32(2 + 4 + 4, value: index.messageIndex.id.id)
|
||||
key.setInt64(2 + 4 + 4 + 4, value: index.messageIndex.id.peerId.toInt64())
|
||||
key.setInt8(2 + 4 + 4 + 4 + 8, value: type.rawValue)
|
||||
return key
|
||||
}
|
||||
*/
|
||||
|
||||
private func extractPreviousKey(_ key: ValueBoxKey) -> (pinningIndex: UInt16?, index: MessageIndex, type: Int8) {
|
||||
return (
|
||||
pinningIndex: extractPinningIndexFromKeyValue(key.getUInt16(0)),
|
||||
|
||||
248
Postbox/PostboxUpgrade_15to16.swift
Normal file
248
Postbox/PostboxUpgrade_15to16.swift
Normal file
@ -0,0 +1,248 @@
|
||||
import Foundation
|
||||
|
||||
private struct UpgradeChatListIndexFlags: OptionSet {
|
||||
var rawValue: Int8
|
||||
|
||||
init(rawValue: Int8) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
static let hasIndex = UpgradeChatListIndexFlags(rawValue: 1 << 0)
|
||||
}
|
||||
|
||||
private enum UpgradePeerChatListInclusion {
|
||||
case notSpecified
|
||||
case never
|
||||
case ifHasMessages
|
||||
case ifHasMessagesOrOneOf(pinningIndex: UInt16?, minTimestamp: Int32?)
|
||||
}
|
||||
|
||||
private struct UpgradeChatListPeerInclusionIndex {
|
||||
let topMessageIndex: MessageIndex?
|
||||
let inclusion: UpgradePeerChatListInclusion
|
||||
|
||||
func includedIndex(peerId: PeerId) -> Bool {
|
||||
switch inclusion {
|
||||
case .notSpecified, .never:
|
||||
return false
|
||||
case .ifHasMessages:
|
||||
if let _ = self.topMessageIndex {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .ifHasMessagesOrOneOf(pinningIndex, minTimestamp):
|
||||
if let _ = minTimestamp {
|
||||
return true
|
||||
} else if let _ = self.topMessageIndex {
|
||||
return true
|
||||
} else if let _ = pinningIndex {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func parseInclusionIndex(peerId: PeerId, value: ReadBuffer) -> Bool {
|
||||
let topMessageIndex: MessageIndex?
|
||||
|
||||
var flagsValue: Int8 = 0
|
||||
value.read(&flagsValue, offset: 0, length: 1)
|
||||
let flags = UpgradeChatListIndexFlags(rawValue: flagsValue)
|
||||
|
||||
if flags.contains(.hasIndex) {
|
||||
var idNamespace: Int32 = 0
|
||||
var idId: Int32 = 0
|
||||
var idTimestamp: Int32 = 0
|
||||
value.read(&idNamespace, offset: 0, length: 4)
|
||||
value.read(&idId, offset: 0, length: 4)
|
||||
value.read(&idTimestamp, offset: 0, length: 4)
|
||||
topMessageIndex = MessageIndex(id: MessageId(peerId: peerId, namespace: idNamespace, id: idId), timestamp: idTimestamp)
|
||||
} else {
|
||||
topMessageIndex = nil
|
||||
}
|
||||
|
||||
let inclusion: UpgradePeerChatListInclusion
|
||||
|
||||
var inclusionId: Int8 = 0
|
||||
value.read(&inclusionId, offset: 0, length: 1)
|
||||
if inclusionId == 0 {
|
||||
inclusion = .notSpecified
|
||||
} else if inclusionId == 1 {
|
||||
inclusion = .never
|
||||
} else if inclusionId == 2 {
|
||||
inclusion = .ifHasMessages
|
||||
} else if inclusionId == 3 {
|
||||
var pinningIndexValue: UInt16 = 0
|
||||
value.read(&pinningIndexValue, offset: 0, length: 2)
|
||||
|
||||
var hasMinTimestamp: Int8 = 0
|
||||
value.read(&hasMinTimestamp, offset: 0, length: 1)
|
||||
let minTimestamp: Int32?
|
||||
if hasMinTimestamp != 0 {
|
||||
var minTimestampValue: Int32 = 0
|
||||
value.read(&minTimestampValue, offset: 0, length: 4)
|
||||
minTimestamp = minTimestampValue
|
||||
} else {
|
||||
minTimestamp = nil
|
||||
}
|
||||
inclusion = .ifHasMessagesOrOneOf(pinningIndex: chatListPinningIndexFromKeyValue(pinningIndexValue), minTimestamp: minTimestamp)
|
||||
} else {
|
||||
assertionFailure()
|
||||
return false
|
||||
}
|
||||
|
||||
let inclusionIndex = UpgradeChatListPeerInclusionIndex(topMessageIndex: topMessageIndex, inclusion: inclusion)
|
||||
return inclusionIndex.includedIndex(peerId: peerId)
|
||||
}
|
||||
|
||||
private struct UpgradePeerNotificationSettingsTableEntryFlags: OptionSet {
|
||||
var rawValue: Int32
|
||||
|
||||
init(rawValue: Int32) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
static let hasCurrent = UpgradePeerNotificationSettingsTableEntryFlags(rawValue: 1 << 0)
|
||||
static let hasPending = UpgradePeerNotificationSettingsTableEntryFlags(rawValue: 1 << 1)
|
||||
}
|
||||
|
||||
private func parseNotificationSettings(valueBox: ValueBox, table: ValueBoxTable, peerId: PeerId) -> Bool {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
if let value = valueBox.get(table, key: key) {
|
||||
var flagsValue: Int32 = 0
|
||||
value.read(&flagsValue, offset: 0, length: 4)
|
||||
let flags = UpgradePeerNotificationSettingsTableEntryFlags(rawValue: flagsValue)
|
||||
|
||||
var current: PeerNotificationSettings?
|
||||
if flags.contains(.hasCurrent) {
|
||||
var length: Int32 = 0
|
||||
value.read(&length, offset: 0, length: 4)
|
||||
let object = PostboxDecoder(buffer: MemoryBuffer(memory: value.memory.advanced(by: value.offset), capacity: Int(length), length: Int(length), freeWhenDone: false)).decodeRootObject() as? PeerNotificationSettings
|
||||
assert(object != nil)
|
||||
current = object
|
||||
value.skip(Int(length))
|
||||
}
|
||||
|
||||
var pending: PeerNotificationSettings?
|
||||
if flags.contains(.hasPending) {
|
||||
var length: Int32 = 0
|
||||
value.read(&length, offset: 0, length: 4)
|
||||
let object = PostboxDecoder(buffer: MemoryBuffer(memory: value.memory.advanced(by: value.offset), capacity: Int(length), length: Int(length), freeWhenDone: false)).decodeRootObject() as? PeerNotificationSettings
|
||||
assert(object != nil)
|
||||
pending = object
|
||||
value.skip(Int(length))
|
||||
}
|
||||
if let pending = pending {
|
||||
return !pending.isRemovedFromTotalUnreadCount
|
||||
} else if let current = current {
|
||||
return !current.isRemovedFromTotalUnreadCount
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private func getReadStateCount(valueBox: ValueBox, table: ValueBoxTable, peerId: PeerId) -> Int32 {
|
||||
let key = ValueBoxKey(length: 8)
|
||||
key.setInt64(0, value: peerId.toInt64())
|
||||
var totalCount: Int32 = 0
|
||||
if let value = valueBox.get(table, key: key) {
|
||||
var count: Int32 = 0
|
||||
value.read(&count, offset: 0, length: 4)
|
||||
var stateByNamespace: [MessageId.Namespace: PeerReadState] = [:]
|
||||
for _ in 0 ..< count {
|
||||
var namespaceId: Int32 = 0
|
||||
value.read(&namespaceId, offset: 0, length: 4)
|
||||
|
||||
let state: PeerReadState
|
||||
var kind: Int8 = 0
|
||||
value.read(&kind, offset: 0, length: 1)
|
||||
if kind == 0 {
|
||||
var maxIncomingReadId: Int32 = 0
|
||||
var maxOutgoingReadId: Int32 = 0
|
||||
var maxKnownId: Int32 = 0
|
||||
var count: Int32 = 0
|
||||
|
||||
value.read(&maxIncomingReadId, offset: 0, length: 4)
|
||||
value.read(&maxOutgoingReadId, offset: 0, length: 4)
|
||||
value.read(&maxKnownId, offset: 0, length: 4)
|
||||
value.read(&count, offset: 0, length: 4)
|
||||
|
||||
totalCount += count
|
||||
} else {
|
||||
var maxIncomingReadTimestamp: Int32 = 0
|
||||
var maxIncomingReadIdPeerId: Int64 = 0
|
||||
var maxIncomingReadIdNamespace: Int32 = 0
|
||||
var maxIncomingReadIdId: Int32 = 0
|
||||
|
||||
var maxOutgoingReadTimestamp: Int32 = 0
|
||||
var maxOutgoingReadIdPeerId: Int64 = 0
|
||||
var maxOutgoingReadIdNamespace: Int32 = 0
|
||||
var maxOutgoingReadIdId: Int32 = 0
|
||||
|
||||
var count: Int32 = 0
|
||||
|
||||
value.read(&maxIncomingReadTimestamp, offset: 0, length: 4)
|
||||
value.read(&maxIncomingReadIdPeerId, offset: 0, length: 8)
|
||||
value.read(&maxIncomingReadIdNamespace, offset: 0, length: 4)
|
||||
value.read(&maxIncomingReadIdId, offset: 0, length: 4)
|
||||
|
||||
value.read(&maxOutgoingReadTimestamp, offset: 0, length: 4)
|
||||
value.read(&maxOutgoingReadIdPeerId, offset: 0, length: 8)
|
||||
value.read(&maxOutgoingReadIdNamespace, offset: 0, length: 4)
|
||||
value.read(&maxOutgoingReadIdId, offset: 0, length: 4)
|
||||
|
||||
value.read(&count, offset: 0, length: 4)
|
||||
totalCount += count
|
||||
}
|
||||
}
|
||||
}
|
||||
return totalCount
|
||||
}
|
||||
|
||||
func postboxUpgrade_15to16(metadataTable: MetadataTable, valueBox: ValueBox) {
|
||||
let chatListIndexTable = ValueBoxTable(id: 8, keyType: .int64)
|
||||
let notificationSettingsTable = ValueBoxTable(id: 19, keyType: .int64)
|
||||
let readStateTable = ValueBoxTable(id: 14, keyType: .int64)
|
||||
let messageHistoryMetadataTable = ValueBoxTable(id: 10, keyType: .binary)
|
||||
|
||||
var includedPeerIds: [PeerId] = []
|
||||
|
||||
valueBox.scanInt64(chatListIndexTable, values: { key, value in
|
||||
let peerId = PeerId(key)
|
||||
if peerId.namespace != Int32.max {
|
||||
if parseInclusionIndex(peerId: peerId, value: value) {
|
||||
includedPeerIds.append(peerId)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
|
||||
var state = ChatListTotalUnreadState(absoluteCounters: ChatListTotalUnreadCounters(messageCount: 0), filteredCounters: ChatListTotalUnreadCounters(messageCount: 0))
|
||||
for peerId in includedPeerIds {
|
||||
let count = getReadStateCount(valueBox: valueBox, table: readStateTable, peerId: peerId)
|
||||
if count != 0 {
|
||||
state.absoluteCounters.messageCount += count
|
||||
|
||||
if parseNotificationSettings(valueBox: valueBox, table: notificationSettingsTable, peerId: peerId) {
|
||||
state.filteredCounters.messageCount += count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let key = ValueBoxKey(length: 1)
|
||||
key.setInt8(0, value: 4)
|
||||
let encoder = PostboxEncoder()
|
||||
encoder.encodeObject(state, forKey: "_")
|
||||
|
||||
valueBox.set(messageHistoryMetadataTable, key: key, value: encoder.readBufferNoCopy())
|
||||
|
||||
metadataTable.setUserVersion(16)
|
||||
}
|
||||
|
||||
@ -1,14 +1,19 @@
|
||||
import Foundation
|
||||
|
||||
public enum UnreadMessageCountsTotalItem {
|
||||
case raw
|
||||
case filtered
|
||||
}
|
||||
|
||||
public enum UnreadMessageCountsItem: Equatable {
|
||||
case total
|
||||
case total(UnreadMessageCountsTotalItem)
|
||||
case peer(PeerId)
|
||||
case group(PeerGroupId)
|
||||
|
||||
public static func ==(lhs: UnreadMessageCountsItem, rhs: UnreadMessageCountsItem) -> Bool {
|
||||
switch lhs {
|
||||
case .total:
|
||||
if case .total = rhs {
|
||||
case let .total(value):
|
||||
if case .total(value) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -30,13 +35,13 @@ public enum UnreadMessageCountsItem: Equatable {
|
||||
}
|
||||
|
||||
private enum MutableUnreadMessageCountsItemEntry {
|
||||
case total(Int32)
|
||||
case total(ChatListTotalUnreadState)
|
||||
case peer(PeerId, Int32)
|
||||
case group(PeerGroupId, ChatListGroupReferenceUnreadCounters)
|
||||
}
|
||||
|
||||
enum UnreadMessageCountsItemEntry {
|
||||
case total(Int32)
|
||||
case total(ChatListTotalUnreadState)
|
||||
case peer(PeerId, Int32)
|
||||
case group(PeerGroupId, Int32)
|
||||
}
|
||||
@ -48,7 +53,7 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
|
||||
self.entries = items.map { item in
|
||||
switch item {
|
||||
case .total:
|
||||
return .total(postbox.messageHistoryMetadataTable.getChatListTotalUnreadCount())
|
||||
return .total(postbox.messageHistoryMetadataTable.getChatListTotalUnreadState())
|
||||
case let .peer(peerId):
|
||||
var count: Int32 = 0
|
||||
if let combinedState = postbox.readStateTable.getCombinedState(peerId) {
|
||||
@ -64,14 +69,14 @@ final class MutableUnreadMessageCountsView: MutablePostboxView {
|
||||
func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool {
|
||||
var updated = false
|
||||
|
||||
if transaction.currentUpdatedTotalUnreadCount != nil || !transaction.peerIdsWithUpdatedUnreadCounts.isEmpty {
|
||||
if transaction.currentUpdatedTotalUnreadState != nil || !transaction.peerIdsWithUpdatedUnreadCounts.isEmpty {
|
||||
for i in 0 ..< self.entries.count {
|
||||
switch self.entries[i] {
|
||||
case let .total(count):
|
||||
if transaction.currentUpdatedTotalUnreadCount != nil {
|
||||
let updatedCount = postbox.messageHistoryMetadataTable.getChatListTotalUnreadCount()
|
||||
if updatedCount != count {
|
||||
self.entries[i] = .total(updatedCount)
|
||||
case let .total(state):
|
||||
if transaction.currentUpdatedTotalUnreadState != nil {
|
||||
let updatedState = postbox.messageHistoryMetadataTable.getChatListTotalUnreadState()
|
||||
if updatedState != state {
|
||||
self.entries[i] = .total(updatedState)
|
||||
updated = true
|
||||
}
|
||||
}
|
||||
@ -120,9 +125,14 @@ public final class UnreadMessageCountsView: PostboxView {
|
||||
public func count(for item: UnreadMessageCountsItem) -> Int32? {
|
||||
for entry in self.entries {
|
||||
switch entry {
|
||||
case let .total(count):
|
||||
if case .total = item {
|
||||
return count
|
||||
case let .total(state):
|
||||
if case let .total(value) = item {
|
||||
switch value {
|
||||
case .raw:
|
||||
return state.absoluteCounters.messageCount
|
||||
case .filtered:
|
||||
return state.filteredCounters.messageCount
|
||||
}
|
||||
}
|
||||
case let .peer(peerId, count):
|
||||
if case .peer(peerId) = item {
|
||||
|
||||
@ -9,5 +9,6 @@ func registeredUpgrades() -> [Int32: PostboxUpgradeOperation] {
|
||||
dict[12] = .inplace(postboxUpgrade_12to13)
|
||||
dict[13] = .inplace(postboxUpgrade_13to14)
|
||||
dict[14] = .inplace(postboxUpgrade_14to15)
|
||||
dict[15] = .inplace(postboxUpgrade_15to16)
|
||||
return dict
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ final class ViewTracker {
|
||||
private let getPeerNotificationSettings: (PeerId) -> PeerNotificationSettings?
|
||||
private let getCachedPeerData: (PeerId) -> CachedPeerData?
|
||||
private let getPeerPresence: (PeerId) -> PeerPresence?
|
||||
private let getTotalUnreadCount: () -> Int32
|
||||
private let getTotalUnreadState: () -> ChatListTotalUnreadState
|
||||
private let getPeerReadState: (PeerId) -> CombinedPeerReadState?
|
||||
private let operationLogGetOperations: (PeerOperationLogTag, Int32, Int) -> [PeerMergedOperationLogEntry]
|
||||
private let operationLogGetTailIndex: (PeerOperationLogTag) -> Int32?
|
||||
@ -59,7 +59,7 @@ final class ViewTracker {
|
||||
private var multiplePeersViews = Bag<(MutableMultiplePeersView, ValuePipe<MultiplePeersView>)>()
|
||||
private var itemCollectionsViews = Bag<(MutableItemCollectionsView, ValuePipe<ItemCollectionsView>)>()
|
||||
|
||||
init(queue: Queue, fetchAnchorIndex: @escaping (MessageId) -> InternalMessageHistoryAnchorIndex?, renderMessage: @escaping (IntermediateMessage) -> Message, getPeer: @escaping (PeerId) -> Peer?, getPeerNotificationSettings: @escaping (PeerId) -> PeerNotificationSettings?, getCachedPeerData: @escaping (PeerId) -> CachedPeerData?, getPeerPresence: @escaping (PeerId) -> PeerPresence?, getTotalUnreadCount: @escaping () -> Int32, getPeerReadState: @escaping (PeerId) -> CombinedPeerReadState?, operationLogGetOperations: @escaping (PeerOperationLogTag, Int32, Int) -> [PeerMergedOperationLogEntry], operationLogGetTailIndex: @escaping (PeerOperationLogTag) -> Int32?, getTimestampBasedMessageAttributesHead: @escaping (UInt16) -> TimestampBasedMessageAttributesEntry?, getPreferencesEntry: @escaping (ValueBoxKey) -> PreferencesEntry?, unsentMessageIds: [MessageId], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
init(queue: Queue, fetchAnchorIndex: @escaping (MessageId) -> InternalMessageHistoryAnchorIndex?, renderMessage: @escaping (IntermediateMessage) -> Message, getPeer: @escaping (PeerId) -> Peer?, getPeerNotificationSettings: @escaping (PeerId) -> PeerNotificationSettings?, getCachedPeerData: @escaping (PeerId) -> CachedPeerData?, getPeerPresence: @escaping (PeerId) -> PeerPresence?, getTotalUnreadState: @escaping () -> ChatListTotalUnreadState, getPeerReadState: @escaping (PeerId) -> CombinedPeerReadState?, operationLogGetOperations: @escaping (PeerOperationLogTag, Int32, Int) -> [PeerMergedOperationLogEntry], operationLogGetTailIndex: @escaping (PeerOperationLogTag) -> Int32?, getTimestampBasedMessageAttributesHead: @escaping (UInt16) -> TimestampBasedMessageAttributesEntry?, getPreferencesEntry: @escaping (ValueBoxKey) -> PreferencesEntry?, unsentMessageIds: [MessageId], synchronizePeerReadStateOperations: [PeerId: PeerReadStateSynchronizationOperation]) {
|
||||
self.queue = queue
|
||||
self.fetchAnchorIndex = fetchAnchorIndex
|
||||
self.renderMessage = renderMessage
|
||||
@ -67,7 +67,7 @@ final class ViewTracker {
|
||||
self.getPeerNotificationSettings = getPeerNotificationSettings
|
||||
self.getCachedPeerData = getCachedPeerData
|
||||
self.getPeerPresence = getPeerPresence
|
||||
self.getTotalUnreadCount = getTotalUnreadCount
|
||||
self.getTotalUnreadState = getTotalUnreadState
|
||||
self.getPeerReadState = getPeerReadState
|
||||
self.operationLogGetOperations = operationLogGetOperations
|
||||
self.operationLogGetTailIndex = operationLogGetTailIndex
|
||||
@ -348,10 +348,10 @@ final class ViewTracker {
|
||||
switch mutableView.peerIds {
|
||||
case .single:
|
||||
assertionFailure()
|
||||
case let .associated(mainPeerId, associatedPeerId):
|
||||
case let .associated(mainPeerId, associatedId):
|
||||
ids.insert(mainPeerId)
|
||||
if let associatedPeerId = associatedPeerId {
|
||||
ids.insert(associatedPeerId)
|
||||
if let associatedId = associatedId {
|
||||
ids.insert(associatedId.peerId)
|
||||
}
|
||||
case let .group(groupId):
|
||||
if let value = transaction.groupFeedIdsWithFilledHoles[groupId] {
|
||||
@ -396,7 +396,7 @@ final class ViewTracker {
|
||||
}
|
||||
|
||||
mutableView.updatePeerIds(transaction: transaction)
|
||||
if case .associated = mutableView.peerIds, case .Generic = updateType, mutableView.peerIds != previousPeerIds {
|
||||
if mutableView.peerIds != previousPeerIds {
|
||||
updateType = .UpdateVisible
|
||||
|
||||
let _ = mutableView.refreshDueToExternalTransaction(postbox: postbox)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user