import Foundation public struct PeerChatThreadId: Hashable { public var peerId: PeerId public var threadId: Int64 public init(peerId: PeerId, threadId: Int64) { self.peerId = peerId self.threadId = threadId } } final class PeerChatThreadInterfaceStateTable: Table { static func tableSpec(_ id: Int32) -> ValueBoxTable { return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: false) } private var states: [PeerChatThreadId: StoredPeerChatInterfaceState?] = [:] private var peerIdsWithUpdatedStates = Set() private let sharedKey = ValueBoxKey(length: 8 + 8) private func key(_ peerId: PeerChatThreadId, sharedKey: ValueBoxKey = ValueBoxKey(length: 8)) -> ValueBoxKey { sharedKey.setInt64(0, value: peerId.peerId.toInt64()) sharedKey.setInt64(8, value: peerId.threadId) return sharedKey } func get(_ peerId: PeerChatThreadId) -> StoredPeerChatInterfaceState? { if let cachedValue = self.states[peerId] { return cachedValue } else if let value = self.valueBox.get(self.table, key: self.key(peerId, sharedKey: self.sharedKey)), let state = try? AdaptedPostboxDecoder().decode(StoredPeerChatInterfaceState.self, from: value.makeData()) { self.states[peerId] = state return state } else { self.states[peerId] = nil return nil } } func set(_ peerId: PeerChatThreadId, state: StoredPeerChatInterfaceState?) -> Bool { let currentState = self.get(peerId) var updated = false if let currentState = currentState, let state = state { if currentState != state { updated = true } } else if (currentState != nil) != (state != nil) { updated = true } if updated { self.states[peerId] = state self.peerIdsWithUpdatedStates.insert(peerId) } return updated } override func clearMemoryCache() { self.states.removeAll() self.peerIdsWithUpdatedStates.removeAll() } override func beforeCommit() { if !self.peerIdsWithUpdatedStates.isEmpty { for peerId in self.peerIdsWithUpdatedStates { if let state = self.states[peerId] { if let state = state, let data = try? AdaptedPostboxEncoder().encode(state) { self.valueBox.set(self.table, key: self.key(peerId, sharedKey: self.sharedKey), value: ReadBuffer(data: data)) } else { self.valueBox.remove(self.table, key: self.key(peerId, sharedKey: self.sharedKey), secure: false) } } } self.peerIdsWithUpdatedStates.removeAll() } } }