mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
182 lines
8.0 KiB
Swift
182 lines
8.0 KiB
Swift
import Foundation
|
|
|
|
public protocol PendingMessageActionData: PostboxCoding {
|
|
func isEqual(to: PendingMessageActionData) -> Bool
|
|
}
|
|
|
|
public struct PendingMessageActionsEntry {
|
|
public let id: MessageId
|
|
public let action: PendingMessageActionData
|
|
|
|
public init(id: MessageId, action: PendingMessageActionData) {
|
|
self.id = id
|
|
self.action = action
|
|
}
|
|
}
|
|
|
|
public struct PendingMessageActionType: RawRepresentable, Equatable, Hashable {
|
|
public var rawValue: UInt32
|
|
|
|
public init(rawValue: UInt32) {
|
|
self.rawValue = rawValue
|
|
}
|
|
}
|
|
|
|
enum PendingMessageActionsOperation {
|
|
case add(PendingMessageActionType, MessageId, PendingMessageActionData)
|
|
case remove(PendingMessageActionType, MessageId)
|
|
}
|
|
|
|
struct PendingMessageActionsSummaryKey: Equatable, Hashable {
|
|
let type: PendingMessageActionType
|
|
let peerId: PeerId
|
|
let namespace: MessageId.Namespace
|
|
}
|
|
|
|
private func getReverseId(_ key: ValueBoxKey) -> MessageId {
|
|
return MessageId(peerId: PeerId(key.getInt64(1 + 4)), namespace: key.getInt32(1 + 4 + 8), id: key.getInt32(1 + 4 + 8 + 4))
|
|
}
|
|
|
|
private func getActionType(_ key: ValueBoxKey) -> PendingMessageActionType {
|
|
return PendingMessageActionType(rawValue: key.getUInt32(1 + 8 + 4 + 4))
|
|
}
|
|
|
|
private enum PendingMessageActionsTableSection: UInt8 {
|
|
case actions = 0
|
|
case index = 1
|
|
}
|
|
|
|
final class PendingMessageActionsTable: Table {
|
|
static func tableSpec(_ id: Int32) -> ValueBoxTable {
|
|
return ValueBoxTable(id: id, keyType: .binary, compactValuesOnCreation: true)
|
|
}
|
|
|
|
private let metadataTable: PendingMessageActionsMetadataTable
|
|
|
|
init(valueBox: ValueBox, table: ValueBoxTable, useCaches: Bool, metadataTable: PendingMessageActionsMetadataTable) {
|
|
self.metadataTable = metadataTable
|
|
|
|
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
|
}
|
|
|
|
private func forwardKey(id: MessageId, actionType: PendingMessageActionType) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 1 + 8 + 4 + 4 + 4)
|
|
key.setUInt8(0, value: PendingMessageActionsTableSection.actions.rawValue)
|
|
key.setInt64(1, value: id.peerId.toInt64())
|
|
key.setInt32(1 + 8, value: id.namespace)
|
|
key.setInt32(1 + 8 + 4, value: id.id)
|
|
key.setUInt32(1 + 8 + 4 + 4, value: actionType.rawValue)
|
|
return key
|
|
}
|
|
|
|
private func reverseKey(id: MessageId, actionType: PendingMessageActionType) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 1 + 8 + 4 + 4 + 4)
|
|
key.setUInt8(0, value: PendingMessageActionsTableSection.index.rawValue)
|
|
key.setUInt32(1, value: actionType.rawValue)
|
|
key.setInt64(1 + 4, value: id.peerId.toInt64())
|
|
key.setInt32(1 + 4 + 8, value: id.namespace)
|
|
key.setInt32(1 + 4 + 8 + 4, value: id.id)
|
|
return key
|
|
}
|
|
|
|
private func lowerBoundForward(id: MessageId) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 1 + 8 + 4 + 4)
|
|
key.setUInt8(0, value: PendingMessageActionsTableSection.actions.rawValue)
|
|
key.setInt64(1, value: id.peerId.toInt64())
|
|
key.setInt32(1 + 8, value: id.namespace)
|
|
key.setInt32(1 + 8 + 4, value: id.id)
|
|
return key
|
|
}
|
|
|
|
private func upperBoundForward(id: MessageId) -> ValueBoxKey {
|
|
return self.lowerBoundForward(id: id).successor
|
|
}
|
|
|
|
private func lowerBoundReverse(type: PendingMessageActionType) -> ValueBoxKey {
|
|
let key = ValueBoxKey(length: 1 + 4)
|
|
key.setUInt8(0, value: PendingMessageActionsTableSection.index.rawValue)
|
|
key.setUInt32(1, value: type.rawValue)
|
|
return key
|
|
}
|
|
|
|
private func upperBoundReverse(type: PendingMessageActionType) -> ValueBoxKey {
|
|
return self.lowerBoundReverse(type: type).successor
|
|
}
|
|
|
|
func getAction(id: MessageId, type: PendingMessageActionType) -> PendingMessageActionData? {
|
|
if let value = self.valueBox.get(self.table, key: self.forwardKey(id: id, actionType: type)) {
|
|
if let action = PostboxDecoder(buffer: value).decodeRootObject() as? PendingMessageActionData {
|
|
return action
|
|
} else {
|
|
assertionFailure()
|
|
return nil
|
|
}
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func setAction(id: MessageId, type: PendingMessageActionType, action: PendingMessageActionData?, operations: inout [PendingMessageActionsOperation], updatedSummaries: inout [PendingMessageActionsSummaryKey: Int32]) {
|
|
let currentAction = self.getAction(id: id, type: type)
|
|
if let action = action {
|
|
let encoder = PostboxEncoder()
|
|
encoder.encodeRootObject(action)
|
|
self.valueBox.set(self.table, key: self.forwardKey(id: id, actionType: type), value: encoder.readBufferNoCopy())
|
|
self.valueBox.set(self.table, key: self.reverseKey(id: id, actionType: type), value: MemoryBuffer())
|
|
if currentAction != nil {
|
|
operations.append(.remove(type, id))
|
|
}
|
|
operations.append(.add(type, id, action))
|
|
if currentAction == nil {
|
|
let updatedCount = self.metadataTable.addCount(.peerNamespaceAction(id.peerId, id.namespace, type), value: 1)
|
|
updatedSummaries[PendingMessageActionsSummaryKey(type: type, peerId: id.peerId, namespace: id.namespace)] = updatedCount
|
|
let _ = self.metadataTable.addCount(.peerNamespace(id.peerId, id.namespace), value: 1)
|
|
|
|
}
|
|
} else if currentAction != nil {
|
|
operations.append(.remove(type, id))
|
|
self.valueBox.remove(self.table, key: self.forwardKey(id: id, actionType: type), secure: false)
|
|
self.valueBox.remove(self.table, key: self.reverseKey(id: id, actionType: type), secure: false)
|
|
let updatedCount = self.metadataTable.addCount(.peerNamespaceAction(id.peerId, id.namespace, type), value: -1)
|
|
updatedSummaries[PendingMessageActionsSummaryKey(type: type, peerId: id.peerId, namespace: id.namespace)] = updatedCount
|
|
let _ = self.metadataTable.addCount(.peerNamespace(id.peerId, id.namespace), value: -1)
|
|
}
|
|
}
|
|
|
|
func removeMessage(id: MessageId, operations: inout [PendingMessageActionsOperation], updatedSummaries: inout [PendingMessageActionsSummaryKey: Int32]) {
|
|
if self.metadataTable.getCount(.peerNamespace(id.peerId, id.namespace)) != 0 {
|
|
var removeTypes: [PendingMessageActionType] = []
|
|
self.valueBox.range(self.table, start: self.lowerBoundForward(id: id), end: self.upperBoundForward(id: id), keys: { key in
|
|
removeTypes.append(getActionType(key))
|
|
return true
|
|
}, limit: 0)
|
|
for type in removeTypes {
|
|
operations.append(.remove(type, id))
|
|
self.valueBox.remove(self.table, key: self.forwardKey(id: id, actionType: type), secure: false)
|
|
self.valueBox.remove(self.table, key: self.reverseKey(id: id, actionType: type), secure: false)
|
|
let updatedCount = self.metadataTable.addCount(.peerNamespaceAction(id.peerId, id.namespace, type), value: -1)
|
|
updatedSummaries[PendingMessageActionsSummaryKey(type: type, peerId: id.peerId, namespace: id.namespace)] = updatedCount
|
|
}
|
|
let _ = self.metadataTable.addCount(.peerNamespace(id.peerId, id.namespace), value: Int32(-removeTypes.count))
|
|
}
|
|
}
|
|
|
|
func getActions(type: PendingMessageActionType) -> [PendingMessageActionsEntry] {
|
|
var ids: [MessageId] = []
|
|
self.valueBox.range(self.table, start: self.lowerBoundReverse(type: type), end: self.upperBoundReverse(type: type), keys: { key in
|
|
ids.append(getReverseId(key))
|
|
return true
|
|
}, limit: 0)
|
|
|
|
var entries: [PendingMessageActionsEntry] = []
|
|
for id in ids {
|
|
if let action = self.getAction(id: id, type: type) {
|
|
entries.append(PendingMessageActionsEntry(id: id, action: action))
|
|
} else {
|
|
assertionFailure()
|
|
}
|
|
}
|
|
return entries
|
|
}
|
|
}
|