2020-01-24 13:01:49 +04:00

283 lines
10 KiB
Swift

import Foundation
public struct PeerViewComponents: OptionSet {
public var rawValue: Int32
public init(rawValue: Int32) {
self.rawValue = rawValue
}
public static let cachedData = PeerViewComponents(rawValue: 1 << 0)
public static let subPeers = PeerViewComponents(rawValue: 1 << 1)
public static let messages = PeerViewComponents(rawValue: 1 << 2)
public static let groupId = PeerViewComponents(rawValue: 1 << 3)
public static let all: PeerViewComponents = [.cachedData, .subPeers, .messages, .groupId]
}
final class MutablePeerView: MutablePostboxView {
let peerId: PeerId
let contactPeerId: PeerId
let components: PeerViewComponents
var notificationSettings: PeerNotificationSettings?
var cachedData: CachedPeerData?
var peers: [PeerId: Peer] = [:]
var peerPresences: [PeerId: PeerPresence] = [:]
var messages: [MessageId: Message] = [:]
var peerIsContact: Bool
var groupId: PeerGroupId?
init(postbox: Postbox, peerId: PeerId, components: PeerViewComponents) {
self.components = components
let getPeer: (PeerId) -> Peer? = { peerId in
return postbox.peerTable.get(peerId)
}
let getPeerPresence: (PeerId) -> PeerPresence? = { peerId in
return postbox.peerPresenceTable.get(peerId)
}
self.peerId = peerId
self.groupId = postbox.chatListIndexTable.get(peerId: peerId).inclusion.groupId
var peerIds = Set<PeerId>()
var messageIds = Set<MessageId>()
peerIds.insert(peerId)
if let peer = getPeer(peerId), let associatedPeerId = peer.associatedPeerId {
peerIds.insert(associatedPeerId)
self.contactPeerId = associatedPeerId
self.peerIsContact = postbox.contactsTable.isContact(peerId: associatedPeerId)
} else {
self.contactPeerId = peerId
}
self.cachedData = postbox.cachedPeerDataTable.get(contactPeerId)
self.peerIsContact = postbox.contactsTable.isContact(peerId: self.contactPeerId)
if let cachedData = self.cachedData {
peerIds.formUnion(cachedData.peerIds)
messageIds.formUnion(cachedData.messageIds)
}
for id in peerIds {
if let peer = getPeer(id) {
self.peers[id] = peer
}
if let presence = getPeerPresence(id) {
self.peerPresences[id] = presence
}
}
if let peer = self.peers[peerId], let associatedPeerId = peer.associatedPeerId {
if let peer = getPeer(associatedPeerId) {
self.peers[associatedPeerId] = peer
}
if let presence = getPeerPresence(associatedPeerId) {
self.peerPresences[associatedPeerId] = presence
}
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(associatedPeerId)
} else {
self.notificationSettings = postbox.peerNotificationSettingsTable.getEffective(peerId)
}
for id in messageIds {
if let message = postbox.getMessage(id) {
self.messages[id] = message
}
}
}
func reset(postbox: Postbox) -> Bool {
return false
}
func replay(postbox: Postbox, transaction: PostboxTransaction) -> Bool {
let updatedPeers = transaction.currentUpdatedPeers
let updatedNotificationSettings = transaction.currentUpdatedPeerNotificationSettings
let updatedCachedPeerData = transaction.currentUpdatedCachedPeerData
let updatedPeerPresences = transaction.currentUpdatedPeerPresences
let replaceContactPeerIds = transaction.replaceContactPeerIds
let getPeer: (PeerId) -> Peer? = { peerId in
return postbox.peerTable.get(peerId)
}
let getPeerPresence: (PeerId) -> PeerPresence? = { peerId in
return postbox.peerPresenceTable.get(peerId)
}
var updated = false
var updateMessages = false
if let cachedData = updatedCachedPeerData[self.contactPeerId], self.cachedData == nil || !self.cachedData!.isEqual(to: cachedData) {
if self.cachedData?.messageIds != cachedData.messageIds {
updateMessages = true
}
self.cachedData = cachedData
updated = true
var peerIds = Set<PeerId>()
peerIds.insert(self.peerId)
if let peer = getPeer(self.peerId), let associatedPeerId = peer.associatedPeerId {
peerIds.insert(associatedPeerId)
}
peerIds.formUnion(cachedData.peerIds)
for id in peerIds {
if let peer = updatedPeers[id] {
self.peers[id] = peer
} else if let peer = getPeer(id) {
self.peers[id] = peer
}
if let presence = updatedPeerPresences[id] {
self.peerPresences[id] = presence
} else if let presence = getPeerPresence(id) {
self.peerPresences[id] = presence
}
}
var removePeerIds: [PeerId] = []
for peerId in self.peers.keys {
if !peerIds.contains(peerId) {
removePeerIds.append(peerId)
}
}
for peerId in removePeerIds {
self.peers.removeValue(forKey: peerId)
}
removePeerIds.removeAll()
for peerId in self.peerPresences.keys {
if !peerIds.contains(peerId) {
removePeerIds.append(peerId)
}
}
for peerId in removePeerIds {
self.peerPresences.removeValue(forKey: peerId)
}
} else {
var peerIds = Set<PeerId>()
peerIds.insert(self.peerId)
if let peer = getPeer(self.peerId), let associatedPeerId = peer.associatedPeerId {
peerIds.insert(associatedPeerId)
}
if let cachedData = self.cachedData {
peerIds.formUnion(cachedData.peerIds)
}
for id in peerIds {
if let peer = updatedPeers[id] {
self.peers[id] = peer
updated = true
}
if let presence = updatedPeerPresences[id] {
self.peerPresences[id] = presence
updated = true
}
}
}
if let cachedData = self.cachedData, !cachedData.messageIds.isEmpty, let operations = transaction.currentOperationsByPeerId[self.peerId] {
outer: for operation in operations {
switch operation {
case let .InsertMessage(message):
if cachedData.messageIds.contains(message.id) {
updateMessages = true
break outer
}
case let .Remove(indicesWithTags):
for (index, _) in indicesWithTags {
if cachedData.messageIds.contains(index.id) {
updateMessages = true
break outer
}
}
default:
break
}
}
}
if updateMessages {
var messages: [MessageId: Message] = [:]
if let cachedData = self.cachedData {
for id in cachedData.messageIds {
if let message = postbox.getMessage(id) {
messages[id] = message
}
}
}
self.messages = messages
updated = true
}
if let peer = self.peers[self.peerId] {
if let associatedPeerId = peer.associatedPeerId {
if let (_, notificationSettings) = updatedNotificationSettings[associatedPeerId] {
self.notificationSettings = notificationSettings
updated = true
}
} else {
if let (_, notificationSettings) = updatedNotificationSettings[peer.id] {
self.notificationSettings = notificationSettings
updated = true
}
}
} else if self.notificationSettings != nil {
self.notificationSettings = nil
updated = true
}
if let replaceContactPeerIds = replaceContactPeerIds {
if self.peerIsContact {
if !replaceContactPeerIds.contains(self.contactPeerId) {
self.peerIsContact = false
updated = true
}
} else {
if replaceContactPeerIds.contains(self.contactPeerId) {
self.peerIsContact = true
updated = true
}
}
}
if transaction.currentUpdatedChatListInclusions[self.peerId] != nil {
let groupId = postbox.chatListIndexTable.get(peerId: peerId).inclusion.groupId
if self.groupId != groupId {
self.groupId = groupId
updated = true
}
}
return updated
}
func immutableView() -> PostboxView {
return PeerView(self)
}
}
public final class PeerView: PostboxView {
public let peerId: PeerId
public let cachedData: CachedPeerData?
public let notificationSettings: PeerNotificationSettings?
public let peers: [PeerId: Peer]
public let peerPresences: [PeerId: PeerPresence]
public let messages: [MessageId: Message]
public let peerIsContact: Bool
public let groupId: PeerGroupId?
init(_ mutableView: MutablePeerView) {
self.peerId = mutableView.peerId
self.cachedData = mutableView.cachedData
self.notificationSettings = mutableView.notificationSettings
self.peers = mutableView.peers
self.peerPresences = mutableView.peerPresences
self.messages = mutableView.messages
self.peerIsContact = mutableView.peerIsContact
self.groupId = mutableView.groupId
}
}