mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
607 lines
27 KiB
Swift
607 lines
27 KiB
Swift
import Foundation
|
|
|
|
private enum MetadataPrefix: Int8 {
|
|
case ChatListInitialized = 0
|
|
case PeerNextMessageIdByNamespace = 2
|
|
case NextStableMessageId = 3
|
|
case ChatListTotalUnreadState = 4
|
|
case NextPeerOperationLogIndex = 5
|
|
case ChatListGroupInitialized = 6
|
|
case GroupFeedIndexInitialized = 7
|
|
case ShouldReindexUnreadCounts = 8
|
|
case PeerHistoryInitialized = 9
|
|
case ShouldReindexUnreadCountsState = 10
|
|
case TotalUnreadCountStates = 11
|
|
case PeerHistoryTagInitialized = 12
|
|
case PeerHistoryThreadHoleIndexInitialized = 13
|
|
case NextCustomTagId = 14
|
|
case PeerHistoryCustomTagInitialized = 15
|
|
case PeerHistoryCustomTagWithTagInitialized = 16
|
|
case PeerHistoryCustomTagWithTagReindexed = 17
|
|
}
|
|
|
|
public struct ChatListTotalUnreadCounters: PostboxCoding, Equatable {
|
|
public var messageCount: Int32
|
|
public var chatCount: Int32
|
|
|
|
public init(messageCount: Int32, chatCount: Int32) {
|
|
self.messageCount = messageCount
|
|
self.chatCount = chatCount
|
|
}
|
|
|
|
public init(decoder: PostboxDecoder) {
|
|
self.messageCount = decoder.decodeInt32ForKey("m", orElse: 0)
|
|
self.chatCount = decoder.decodeInt32ForKey("c", orElse: 0)
|
|
}
|
|
|
|
public func encode(_ encoder: PostboxEncoder) {
|
|
encoder.encodeInt32(self.messageCount, forKey: "m")
|
|
encoder.encodeInt32(self.chatCount, forKey: "c")
|
|
}
|
|
}
|
|
|
|
private struct InitializedChatListKey: Hashable {
|
|
let groupId: PeerGroupId
|
|
}
|
|
|
|
final class MessageHistoryMetadataTable: Table {
|
|
private struct PeerIdThreadIdAndTag: Hashable {
|
|
var peerId: PeerId
|
|
var threadId: Int64?
|
|
var tag: Int32
|
|
var regularTag: UInt32?
|
|
|
|
init(peerId: PeerId, threadId: Int64?, tag: Int32, regularTag: UInt32?) {
|
|
self.peerId = peerId
|
|
self.threadId = threadId
|
|
self.tag = tag
|
|
self.regularTag = regularTag
|
|
}
|
|
}
|
|
|
|
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
|
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: true)
|
|
}
|
|
|
|
let sharedPeerHistoryInitializedKey = ValueBoxKey(length: 8 + 1)
|
|
let sharedPeerThreadHoleIndexInitializedKey = ValueBoxKey(length: 8 + 1 + 8)
|
|
let sharedGroupFeedIndexInitializedKey = ValueBoxKey(length: 4 + 1)
|
|
let sharedChatListGroupHistoryInitializedKey = ValueBoxKey(length: 4 + 1)
|
|
let sharedPeerNextMessageIdByNamespaceKey = ValueBoxKey(length: 8 + 1 + 4)
|
|
let sharedBuffer = WriteBuffer()
|
|
|
|
private var initializedChatList = Set<InitializedChatListKey>()
|
|
private var initializedHistoryPeerIds = Set<PeerId>()
|
|
private var initializedHistoryPeerIdTags: [PeerId: Set<MessageTags>] = [:]
|
|
private var initializedHistoryPeerIdCustomTags: [PeerId: Set<PeerIdThreadIdAndTag>] = [:]
|
|
private var reindexedHistoryPeerIdCustomTags: [PeerId: Set<PeerIdThreadIdAndTag>] = [:]
|
|
private var initializedGroupFeedIndexIds = Set<PeerGroupId>()
|
|
|
|
private var peerNextMessageIdByNamespace: [PeerId: [MessageId.Namespace: MessageId.Id]] = [:]
|
|
private var updatedPeerNextMessageIdByNamespace: [PeerId: Set<MessageId.Namespace>] = [:]
|
|
|
|
private var nextMessageStableId: UInt32?
|
|
private var nextMessageStableIdUpdated = false
|
|
|
|
private var chatListTotalUnreadStates: [PeerGroupId: ChatListTotalUnreadState] = [:]
|
|
private var updatedChatListTotalUnreadStates = Set<PeerGroupId>()
|
|
|
|
private var nextPeerOperationLogIndex: UInt32?
|
|
private var nextPeerOperationLogIndexUpdated = false
|
|
|
|
private var currentPinnedChatPeerIds: Set<PeerId>?
|
|
private var currentPinnedChatPeerIdsUpdated = false
|
|
|
|
private func peerHistoryInitializedKey(_ id: PeerId) -> ValueBoxKey {
|
|
self.sharedPeerHistoryInitializedKey.setInt64(0, value: id.toInt64())
|
|
self.sharedPeerHistoryInitializedKey.setInt8(8, value: MetadataPrefix.PeerHistoryInitialized.rawValue)
|
|
return self.sharedPeerHistoryInitializedKey
|
|
}
|
|
|
|
private func peerThreadHoleIndexInitializedKey(peerId: PeerId, threadId: Int64) -> ValueBoxKey {
|
|
self.sharedPeerThreadHoleIndexInitializedKey.setInt64(0, value: peerId.toInt64())
|
|
self.sharedPeerThreadHoleIndexInitializedKey.setInt8(8, value: MetadataPrefix.PeerHistoryThreadHoleIndexInitialized.rawValue)
|
|
self.sharedPeerThreadHoleIndexInitializedKey.setInt64(8 + 1, value: threadId)
|
|
return self.sharedPeerThreadHoleIndexInitializedKey
|
|
}
|
|
|
|
private func peerHistoryInitializedTagKey(id: PeerId, tag: UInt32) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 8 + 1 + 4)
|
|
key.setInt64(0, value: id.toInt64())
|
|
key.setInt8(8, value: MetadataPrefix.PeerHistoryTagInitialized.rawValue)
|
|
key.setUInt32(8 + 1, value: tag)
|
|
return key
|
|
}
|
|
|
|
private func peerHistoryInitializedCustomTagKey(id: PeerId, threadId: Int64?, tag: Int32) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 8 + 1 + 8 + 4)
|
|
key.setInt64(0, value: id.toInt64())
|
|
key.setInt8(8, value: MetadataPrefix.PeerHistoryCustomTagInitialized.rawValue)
|
|
key.setInt64(8 + 1, value: threadId ?? 0)
|
|
key.setInt32(8 + 1 + 8, value: tag)
|
|
return key
|
|
}
|
|
|
|
private func peerHistoryReindexedCustomTagKey(id: PeerId, threadId: Int64?, tag: Int32) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 8 + 1 + 8 + 4)
|
|
key.setInt64(0, value: id.toInt64())
|
|
key.setInt8(8, value: MetadataPrefix.PeerHistoryCustomTagWithTagReindexed.rawValue)
|
|
key.setInt64(8 + 1, value: threadId ?? 0)
|
|
key.setInt32(8 + 1 + 8, value: tag)
|
|
return key
|
|
}
|
|
|
|
private func peerHistoryInitializedCustomTagWithTagKey(id: PeerId, threadId: Int64?, tag: Int32, regularTag: UInt32) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 8 + 1 + 8 + 4 + 4)
|
|
key.setInt64(0, value: id.toInt64())
|
|
key.setInt8(8, value: MetadataPrefix.PeerHistoryCustomTagWithTagInitialized.rawValue)
|
|
key.setInt64(8 + 1, value: threadId ?? 0)
|
|
key.setInt32(8 + 1 + 8, value: tag)
|
|
key.setUInt32(8 + 1 + 8 + 4, value: regularTag)
|
|
return key
|
|
}
|
|
|
|
private func groupFeedIndexInitializedKey(_ id: PeerGroupId) -> ValueBoxKey {
|
|
self.sharedGroupFeedIndexInitializedKey.setInt32(0, value: id.rawValue)
|
|
self.sharedGroupFeedIndexInitializedKey.setInt8(4, value: MetadataPrefix.GroupFeedIndexInitialized.rawValue)
|
|
return self.sharedGroupFeedIndexInitializedKey
|
|
}
|
|
|
|
private func chatListGroupInitializedKey(_ key: InitializedChatListKey) -> ValueBoxKey {
|
|
self.sharedChatListGroupHistoryInitializedKey.setInt32(0, value: key.groupId.rawValue)
|
|
self.sharedChatListGroupHistoryInitializedKey.setInt8(4, value: MetadataPrefix.ChatListGroupInitialized.rawValue)
|
|
return self.sharedChatListGroupHistoryInitializedKey
|
|
}
|
|
|
|
private func peerNextMessageIdByNamespaceKey(_ id: PeerId, namespace: MessageId.Namespace) -> ValueBoxKey {
|
|
self.sharedPeerNextMessageIdByNamespaceKey.setInt64(0, value: id.toInt64())
|
|
self.sharedPeerNextMessageIdByNamespaceKey.setInt8(8, value: MetadataPrefix.PeerNextMessageIdByNamespace.rawValue)
|
|
self.sharedPeerNextMessageIdByNamespaceKey.setInt32(8 + 1, value: namespace)
|
|
|
|
return self.sharedPeerNextMessageIdByNamespaceKey
|
|
}
|
|
|
|
private func key(_ prefix: MetadataPrefix) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 1)
|
|
key.setInt8(0, value: prefix.rawValue)
|
|
return key
|
|
}
|
|
|
|
private func totalUnreadCountStateKey(groupId: PeerGroupId) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 1 + 4)
|
|
key.setInt8(0, value: MetadataPrefix.TotalUnreadCountStates.rawValue)
|
|
key.setInt32(1, value: groupId.rawValue)
|
|
return key
|
|
}
|
|
|
|
private func totalUnreadCountLowerBound() -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 1)
|
|
key.setInt8(0, value: MetadataPrefix.TotalUnreadCountStates.rawValue)
|
|
return key
|
|
}
|
|
|
|
private func totalUnreadCountUpperBound() -> ValueBoxKey {
|
|
return self.totalUnreadCountLowerBound().successor
|
|
}
|
|
|
|
func setInitializedChatList(groupId: PeerGroupId) {
|
|
switch groupId {
|
|
case .root:
|
|
self.valueBox.set(self.table, key: self.key(MetadataPrefix.ChatListInitialized), value: MemoryBuffer())
|
|
case .group:
|
|
self.valueBox.set(self.table, key: self.chatListGroupInitializedKey(InitializedChatListKey(groupId: groupId)), value: MemoryBuffer())
|
|
}
|
|
self.initializedChatList.insert(InitializedChatListKey(groupId: groupId))
|
|
}
|
|
|
|
func isInitializedChatList(groupId: PeerGroupId) -> Bool {
|
|
let key = InitializedChatListKey(groupId: groupId)
|
|
if self.initializedChatList.contains(key) {
|
|
return true
|
|
} else {
|
|
switch groupId {
|
|
case .root:
|
|
if self.valueBox.exists(self.table, key: self.key(MetadataPrefix.ChatListInitialized)) {
|
|
self.initializedChatList.insert(key)
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
case .group:
|
|
if self.valueBox.exists(self.table, key: self.chatListGroupInitializedKey(key)) {
|
|
self.initializedChatList.insert(key)
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func setShouldReindexUnreadCounts(value: Bool) {
|
|
if value {
|
|
self.valueBox.set(self.table, key: self.key(MetadataPrefix.ShouldReindexUnreadCounts), value: MemoryBuffer())
|
|
} else {
|
|
self.valueBox.remove(self.table, key: self.key(MetadataPrefix.ShouldReindexUnreadCounts), secure: false)
|
|
}
|
|
}
|
|
|
|
func shouldReindexUnreadCounts() -> Bool {
|
|
if self.valueBox.exists(self.table, key: self.key(MetadataPrefix.ShouldReindexUnreadCounts)) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func setShouldReindexUnreadCountsState(value: Int32) {
|
|
var value = value
|
|
self.valueBox.set(self.table, key: self.key(MetadataPrefix.ShouldReindexUnreadCountsState), value: MemoryBuffer(memory: &value, capacity: 4, length: 4, freeWhenDone: false))
|
|
}
|
|
|
|
func getShouldReindexUnreadCountsState() -> Int32? {
|
|
if let value = self.valueBox.get(self.table, key: self.key(MetadataPrefix.ShouldReindexUnreadCountsState)) {
|
|
var version: Int32 = 0
|
|
value.read(&version, offset: 0, length: 4)
|
|
return version
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func setInitialized(_ peerId: PeerId) {
|
|
self.initializedHistoryPeerIds.insert(peerId)
|
|
self.sharedBuffer.reset()
|
|
self.valueBox.set(self.table, key: self.peerHistoryInitializedKey(peerId), value: self.sharedBuffer)
|
|
}
|
|
|
|
func isInitialized(_ peerId: PeerId) -> Bool {
|
|
if self.initializedHistoryPeerIds.contains(peerId) {
|
|
return true
|
|
} else {
|
|
if self.valueBox.exists(self.table, key: self.peerHistoryInitializedKey(peerId)) {
|
|
self.initializedHistoryPeerIds.insert(peerId)
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
func isThreadHoleIndexInitialized(peerId: PeerId, threadId: Int64) -> Bool {
|
|
if self.valueBox.exists(self.table, key: self.peerThreadHoleIndexInitializedKey(peerId: peerId, threadId: threadId)) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func setIsThreadHoleIndexInitialized(peerId: PeerId, threadId: Int64) {
|
|
self.valueBox.set(self.table, key: self.peerThreadHoleIndexInitializedKey(peerId: peerId, threadId: threadId), value: MemoryBuffer())
|
|
}
|
|
|
|
func setPeerTagInitialized(peerId: PeerId, tag: MessageTags) {
|
|
if self.initializedHistoryPeerIdTags[peerId] == nil {
|
|
self.initializedHistoryPeerIdTags[peerId] = Set()
|
|
}
|
|
initializedHistoryPeerIdTags[peerId]!.insert(tag)
|
|
self.sharedBuffer.reset()
|
|
self.valueBox.set(self.table, key: self.peerHistoryInitializedTagKey(id: peerId, tag: tag.rawValue), value: self.sharedBuffer)
|
|
}
|
|
|
|
func isPeerTagInitialized(peerId: PeerId, tag: MessageTags) -> Bool {
|
|
if let currentTags = self.initializedHistoryPeerIdTags[peerId], currentTags.contains(tag) {
|
|
return true
|
|
} else {
|
|
if self.valueBox.exists(self.table, key: self.peerHistoryInitializedTagKey(id: peerId, tag: tag.rawValue)) {
|
|
if self.initializedHistoryPeerIdTags[peerId] == nil {
|
|
self.initializedHistoryPeerIdTags[peerId] = Set()
|
|
}
|
|
initializedHistoryPeerIdTags[peerId]!.insert(tag)
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
func setPeerCustomTagInitialized(peerId: PeerId, threadId: Int64?, tag: Int32) {
|
|
if self.initializedHistoryPeerIdCustomTags[peerId] == nil {
|
|
self.initializedHistoryPeerIdCustomTags[peerId] = Set()
|
|
}
|
|
self.initializedHistoryPeerIdCustomTags[peerId]!.insert(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: nil))
|
|
self.valueBox.set(self.table, key: self.peerHistoryInitializedCustomTagKey(id: peerId, threadId: threadId, tag: tag), value: MemoryBuffer())
|
|
}
|
|
|
|
func isPeerCustomTagInitialized(peerId: PeerId, threadId: Int64?, tag: Int32) -> Bool {
|
|
if let currentTags = self.initializedHistoryPeerIdCustomTags[peerId], currentTags.contains(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: nil)) {
|
|
return true
|
|
} else {
|
|
if self.valueBox.exists(self.table, key: self.peerHistoryInitializedCustomTagKey(id: peerId, threadId: threadId, tag: tag)) {
|
|
if self.initializedHistoryPeerIdCustomTags[peerId] == nil {
|
|
self.initializedHistoryPeerIdCustomTags[peerId] = Set()
|
|
}
|
|
self.initializedHistoryPeerIdCustomTags[peerId]!.insert(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: nil))
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
func isPeerCustomTagInitialized(peerId: PeerId, threadId: Int64?, tag: Int32, regularTag: UInt32) -> Bool {
|
|
if let currentTags = self.initializedHistoryPeerIdCustomTags[peerId], currentTags.contains(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: regularTag)) {
|
|
return true
|
|
} else {
|
|
if self.valueBox.exists(self.table, key: self.peerHistoryInitializedCustomTagWithTagKey(id: peerId, threadId: threadId, tag: tag, regularTag: regularTag)) {
|
|
if self.initializedHistoryPeerIdCustomTags[peerId] == nil {
|
|
self.initializedHistoryPeerIdCustomTags[peerId] = Set()
|
|
}
|
|
self.initializedHistoryPeerIdCustomTags[peerId]!.insert(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: regularTag))
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
func setPeerCustomTagInitialized(peerId: PeerId, threadId: Int64?, tag: Int32, regularTag: UInt32) {
|
|
if self.initializedHistoryPeerIdCustomTags[peerId] == nil {
|
|
self.initializedHistoryPeerIdCustomTags[peerId] = Set()
|
|
}
|
|
self.initializedHistoryPeerIdCustomTags[peerId]!.insert(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: regularTag))
|
|
self.valueBox.set(self.table, key: self.peerHistoryInitializedCustomTagWithTagKey(id: peerId, threadId: threadId, tag: tag, regularTag: regularTag), value: MemoryBuffer())
|
|
}
|
|
|
|
func setPeerCustomTagReindexed(peerId: PeerId, threadId: Int64?, tag: Int32) {
|
|
if self.reindexedHistoryPeerIdCustomTags[peerId] == nil {
|
|
self.reindexedHistoryPeerIdCustomTags[peerId] = Set()
|
|
}
|
|
self.reindexedHistoryPeerIdCustomTags[peerId]!.insert(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: nil))
|
|
self.valueBox.set(self.table, key: self.peerHistoryReindexedCustomTagKey(id: peerId, threadId: threadId, tag: tag), value: MemoryBuffer())
|
|
}
|
|
|
|
func isPeerCustomTagReindexed(peerId: PeerId, threadId: Int64?, tag: Int32) -> Bool {
|
|
if let currentTags = self.reindexedHistoryPeerIdCustomTags[peerId], currentTags.contains(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: nil)) {
|
|
return true
|
|
} else {
|
|
if self.valueBox.exists(self.table, key: self.peerHistoryReindexedCustomTagKey(id: peerId, threadId: threadId, tag: tag)) {
|
|
if self.reindexedHistoryPeerIdCustomTags[peerId] == nil {
|
|
self.reindexedHistoryPeerIdCustomTags[peerId] = Set()
|
|
}
|
|
self.reindexedHistoryPeerIdCustomTags[peerId]!.insert(PeerIdThreadIdAndTag(peerId: peerId, threadId: threadId, tag: tag, regularTag: nil))
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
func removePeerCustomTagInitializedList() {
|
|
self.initializedHistoryPeerIdCustomTags.removeAll()
|
|
|
|
var removeKeys: [ValueBoxKey] = []
|
|
self.valueBox.scan(self.table, keys: { key in
|
|
if key.length == 8 + 1 + 8 + 4 {
|
|
if key.getInt8(8) == MetadataPrefix.PeerHistoryCustomTagInitialized.rawValue {
|
|
removeKeys.append(key)
|
|
}
|
|
}
|
|
|
|
return true
|
|
})
|
|
self.valueBox.scan(self.table, keys: { key in
|
|
if key.length == 8 + 1 + 8 + 4 {
|
|
if key.getInt8(8) == MetadataPrefix.PeerHistoryCustomTagWithTagInitialized.rawValue {
|
|
removeKeys.append(key)
|
|
}
|
|
}
|
|
|
|
return true
|
|
})
|
|
|
|
for key in removeKeys {
|
|
self.valueBox.remove(self.table, key: key, secure: false)
|
|
}
|
|
}
|
|
|
|
func setGroupFeedIndexInitialized(_ groupId: PeerGroupId) {
|
|
self.initializedGroupFeedIndexIds.insert(groupId)
|
|
self.sharedBuffer.reset()
|
|
self.valueBox.set(self.table, key: self.groupFeedIndexInitializedKey(groupId), value: self.sharedBuffer)
|
|
}
|
|
|
|
func isGroupFeedIndexInitialized(_ groupId: PeerGroupId) -> Bool {
|
|
if self.initializedGroupFeedIndexIds.contains(groupId) {
|
|
return true
|
|
} else {
|
|
if self.valueBox.exists(self.table, key: self.groupFeedIndexInitializedKey(groupId)) {
|
|
self.initializedGroupFeedIndexIds.insert(groupId)
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
func getNextMessageIdAndIncrement(_ peerId: PeerId, namespace: MessageId.Namespace) -> MessageId {
|
|
if let messageIdByNamespace = self.peerNextMessageIdByNamespace[peerId] {
|
|
if let nextId = messageIdByNamespace[namespace] {
|
|
self.peerNextMessageIdByNamespace[peerId]![namespace] = nextId + 1
|
|
if updatedPeerNextMessageIdByNamespace[peerId] != nil {
|
|
updatedPeerNextMessageIdByNamespace[peerId]!.insert(namespace)
|
|
} else {
|
|
updatedPeerNextMessageIdByNamespace[peerId] = Set<MessageId.Namespace>([namespace])
|
|
}
|
|
return MessageId(peerId: peerId, namespace: namespace, id: nextId)
|
|
} else {
|
|
var nextId: Int32 = 1
|
|
if let value = self.valueBox.get(self.table, key: self.peerNextMessageIdByNamespaceKey(peerId, namespace: namespace)) {
|
|
value.read(&nextId, offset: 0, length: 4)
|
|
}
|
|
self.peerNextMessageIdByNamespace[peerId]![namespace] = nextId + 1
|
|
if updatedPeerNextMessageIdByNamespace[peerId] != nil {
|
|
updatedPeerNextMessageIdByNamespace[peerId]!.insert(namespace)
|
|
} else {
|
|
updatedPeerNextMessageIdByNamespace[peerId] = Set<MessageId.Namespace>([namespace])
|
|
}
|
|
return MessageId(peerId: peerId, namespace: namespace, id: nextId)
|
|
}
|
|
} else {
|
|
var nextId: Int32 = 1
|
|
if let value = self.valueBox.get(self.table, key: self.peerNextMessageIdByNamespaceKey(peerId, namespace: namespace)) {
|
|
value.read(&nextId, offset: 0, length: 4)
|
|
}
|
|
|
|
self.peerNextMessageIdByNamespace[peerId] = [namespace: nextId + 1]
|
|
if updatedPeerNextMessageIdByNamespace[peerId] != nil {
|
|
updatedPeerNextMessageIdByNamespace[peerId]!.insert(namespace)
|
|
} else {
|
|
updatedPeerNextMessageIdByNamespace[peerId] = Set<MessageId.Namespace>([namespace])
|
|
}
|
|
return MessageId(peerId: peerId, namespace: namespace, id: nextId)
|
|
}
|
|
}
|
|
|
|
func getNextStableMessageIndexId() -> UInt32 {
|
|
if let nextId = self.nextMessageStableId {
|
|
self.nextMessageStableId = nextId + 1
|
|
self.nextMessageStableIdUpdated = true
|
|
return nextId
|
|
} else {
|
|
if let value = self.valueBox.get(self.table, key: self.key(.NextStableMessageId)) {
|
|
var nextId: UInt32 = 0
|
|
value.read(&nextId, offset: 0, length: 4)
|
|
self.nextMessageStableId = nextId + 1
|
|
self.nextMessageStableIdUpdated = true
|
|
return nextId
|
|
} else {
|
|
let nextId: UInt32 = 1
|
|
self.nextMessageStableId = nextId + 1
|
|
self.nextMessageStableIdUpdated = true
|
|
return nextId
|
|
}
|
|
}
|
|
}
|
|
|
|
func getNextPeerOperationLogIndex() -> UInt32 {
|
|
if let nextId = self.nextPeerOperationLogIndex {
|
|
self.nextPeerOperationLogIndex = nextId + 1
|
|
self.nextPeerOperationLogIndexUpdated = true
|
|
return nextId
|
|
} else {
|
|
if let value = self.valueBox.get(self.table, key: self.key(.NextPeerOperationLogIndex)) {
|
|
var nextId: UInt32 = 0
|
|
value.read(&nextId, offset: 0, length: 4)
|
|
self.nextPeerOperationLogIndex = nextId + 1
|
|
self.nextPeerOperationLogIndexUpdated = true
|
|
return nextId
|
|
} else {
|
|
let nextId: UInt32 = 1
|
|
self.nextPeerOperationLogIndex = nextId + 1
|
|
self.nextPeerOperationLogIndexUpdated = true
|
|
return nextId
|
|
}
|
|
}
|
|
}
|
|
|
|
func removeAllTotalUnreadStates() {
|
|
var groupIds: [PeerGroupId] = []
|
|
self.valueBox.range(self.table, start: self.totalUnreadCountLowerBound(), end: self.totalUnreadCountUpperBound(), keys: { key in
|
|
let groupId = key.getInt32(1)
|
|
groupIds.append(PeerGroupId(rawValue: groupId))
|
|
return true
|
|
}, limit: 0)
|
|
for groupId in groupIds {
|
|
self.setTotalUnreadState(groupId: groupId, state: ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:]))
|
|
}
|
|
}
|
|
|
|
func getTotalUnreadState(groupId: PeerGroupId) -> ChatListTotalUnreadState {
|
|
if let cached = self.chatListTotalUnreadStates[groupId] {
|
|
return cached
|
|
} else {
|
|
if let value = self.valueBox.get(self.table, key: self.totalUnreadCountStateKey(groupId: groupId)), let state = PostboxDecoder(buffer: value).decodeObjectForKey("_", decoder: { ChatListTotalUnreadState(decoder: $0) }) as? ChatListTotalUnreadState {
|
|
self.chatListTotalUnreadStates[groupId] = state
|
|
return state
|
|
} else {
|
|
let state = ChatListTotalUnreadState(absoluteCounters: [:], filteredCounters: [:])
|
|
self.chatListTotalUnreadStates[groupId] = state
|
|
return state
|
|
}
|
|
}
|
|
}
|
|
|
|
func setTotalUnreadState(groupId: PeerGroupId, state: ChatListTotalUnreadState) {
|
|
let current = self.getTotalUnreadState(groupId: groupId)
|
|
if current != state {
|
|
self.chatListTotalUnreadStates[groupId] = state
|
|
self.updatedChatListTotalUnreadStates.insert(groupId)
|
|
}
|
|
}
|
|
|
|
override func clearMemoryCache() {
|
|
self.initializedChatList.removeAll()
|
|
self.initializedHistoryPeerIds.removeAll()
|
|
self.peerNextMessageIdByNamespace.removeAll()
|
|
self.updatedPeerNextMessageIdByNamespace.removeAll()
|
|
self.nextMessageStableId = nil
|
|
self.nextMessageStableIdUpdated = false
|
|
self.chatListTotalUnreadStates.removeAll()
|
|
self.updatedChatListTotalUnreadStates.removeAll()
|
|
}
|
|
|
|
override func beforeCommit() {
|
|
let sharedBuffer = WriteBuffer()
|
|
for (peerId, namespaces) in self.updatedPeerNextMessageIdByNamespace {
|
|
for namespace in namespaces {
|
|
if let messageIdByNamespace = self.peerNextMessageIdByNamespace[peerId], let maxId = messageIdByNamespace[namespace] {
|
|
sharedBuffer.reset()
|
|
var mutableMaxId = maxId
|
|
sharedBuffer.write(&mutableMaxId, offset: 0, length: 4)
|
|
self.valueBox.set(self.table, key: self.peerNextMessageIdByNamespaceKey(peerId, namespace: namespace), value: sharedBuffer)
|
|
} else {
|
|
self.valueBox.remove(self.table, key: self.peerNextMessageIdByNamespaceKey(peerId, namespace: namespace), secure: false)
|
|
}
|
|
}
|
|
}
|
|
self.updatedPeerNextMessageIdByNamespace.removeAll()
|
|
|
|
if self.nextMessageStableIdUpdated {
|
|
if let nextMessageStableId = self.nextMessageStableId {
|
|
var nextId: UInt32 = nextMessageStableId
|
|
self.valueBox.set(self.table, key: self.key(.NextStableMessageId), value: MemoryBuffer(memory: &nextId, capacity: 4, length: 4, freeWhenDone: false))
|
|
self.nextMessageStableIdUpdated = false
|
|
}
|
|
}
|
|
|
|
if self.nextPeerOperationLogIndexUpdated {
|
|
if let nextPeerOperationLogIndex = self.nextPeerOperationLogIndex {
|
|
var nextId: UInt32 = nextPeerOperationLogIndex
|
|
self.valueBox.set(self.table, key: self.key(.NextPeerOperationLogIndex), value: MemoryBuffer(memory: &nextId, capacity: 4, length: 4, freeWhenDone: false))
|
|
self.nextPeerOperationLogIndexUpdated = false
|
|
}
|
|
}
|
|
|
|
for groupId in self.updatedChatListTotalUnreadStates {
|
|
if let state = self.chatListTotalUnreadStates[groupId] {
|
|
let buffer = PostboxEncoder()
|
|
buffer.encodeObject(state, forKey: "_")
|
|
self.valueBox.set(self.table, key: self.totalUnreadCountStateKey(groupId: groupId), value: buffer.readBufferNoCopy())
|
|
}
|
|
self.updatedChatListTotalUnreadStates.removeAll()
|
|
}
|
|
}
|
|
|
|
func getNextCustomTagIdAndIncrement() -> Int32 {
|
|
var nextId: Int32 = 1
|
|
if let value = self.valueBox.get(self.table, key: self.key(.NextCustomTagId)) {
|
|
value.read(&nextId, offset: 0, length: 4)
|
|
}
|
|
var storeNextId = nextId + 1
|
|
self.valueBox.set(self.table, key: self.key(.NextCustomTagId), value: MemoryBuffer(memory: &storeNextId, capacity: 4, length: 4, freeWhenDone: false))
|
|
|
|
return nextId
|
|
}
|
|
}
|