import Foundation final class PeerChatInterfaceStateTable: Table { static func tableSpec(_ id: Int32) -> ValueBoxTable { return ValueBoxTable(id: id, keyType: .int64, compactValuesOnCreation: false) } private var states: [PeerId: StoredPeerChatInterfaceState?] = [:] private var peerIdsWithUpdatedStates = Set() private let sharedKey = ValueBoxKey(length: 8) private func key(_ peerId: PeerId, sharedKey: ValueBoxKey = ValueBoxKey(length: 8)) -> ValueBoxKey { sharedKey.setInt64(0, value: peerId.toInt64()) return sharedKey } func get(_ peerId: PeerId) -> 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: PeerId, state: StoredPeerChatInterfaceState?) -> (updated: Bool, updatedEmbeddedState: Bool) { let currentState = self.get(peerId) var updated = false var updatedEmbeddedState = false if let currentState = currentState, let state = state { if currentState != state { updated = true if currentState.overrideChatTimestamp != state.overrideChatTimestamp { updatedEmbeddedState = true } } } else if (currentState != nil) != (state != nil) { updated = true updatedEmbeddedState = true } if updated { self.states[peerId] = state self.peerIdsWithUpdatedStates.insert(peerId) } return (updated, updatedEmbeddedState) } 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() } } }