mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
State management fixes
This commit is contained in:
parent
4a045feb2f
commit
fb07f06a26
@ -10,6 +10,11 @@ public final class InteractivePhoneFormatter {
|
||||
public func updateText(_ text: String) -> (String?, String) {
|
||||
self.formatter.clear()
|
||||
let string = self.formatter.inputString(text)
|
||||
return (self.formatter.regionPrefix, string ?? "")
|
||||
|
||||
var regionPrefix = self.formatter.regionPrefix
|
||||
if let string = string, string.hasPrefix("+383") {
|
||||
regionPrefix = "+383"
|
||||
}
|
||||
return (regionPrefix, string ?? "")
|
||||
}
|
||||
}
|
||||
|
@ -10,20 +10,24 @@ struct PeerChatInfo {
|
||||
var notificationSettings: PeerNotificationSettings
|
||||
}
|
||||
|
||||
struct AccountStateChannelState: Equatable {
|
||||
var pts: Int32
|
||||
}
|
||||
|
||||
final class AccountInitialState {
|
||||
let state: AuthorizedAccountState.State
|
||||
let peerIds: Set<PeerId>
|
||||
let chatStates: [PeerId: PeerChatState]
|
||||
let channelStates: [PeerId: AccountStateChannelState]
|
||||
let peerChatInfos: [PeerId: PeerChatInfo]
|
||||
let peerIdsRequiringLocalChatState: Set<PeerId>
|
||||
let locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]
|
||||
let cloudReadStates: [PeerId: PeerReadState]
|
||||
let channelsToPollExplicitely: Set<PeerId>
|
||||
|
||||
init(state: AuthorizedAccountState.State, peerIds: Set<PeerId>, peerIdsRequiringLocalChatState: Set<PeerId>, chatStates: [PeerId: PeerChatState], peerChatInfos: [PeerId: PeerChatInfo], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]], cloudReadStates: [PeerId: PeerReadState], channelsToPollExplicitely: Set<PeerId>) {
|
||||
init(state: AuthorizedAccountState.State, peerIds: Set<PeerId>, peerIdsRequiringLocalChatState: Set<PeerId>, channelStates: [PeerId: AccountStateChannelState], peerChatInfos: [PeerId: PeerChatInfo], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]], cloudReadStates: [PeerId: PeerReadState], channelsToPollExplicitely: Set<PeerId>) {
|
||||
self.state = state
|
||||
self.peerIds = peerIds
|
||||
self.chatStates = chatStates
|
||||
self.channelStates = channelStates
|
||||
self.peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatState
|
||||
self.peerChatInfos = peerChatInfos
|
||||
self.locallyGeneratedMessageTimestamps = locallyGeneratedMessageTimestamps
|
||||
@ -72,7 +76,9 @@ enum AccountStateMutationOperation {
|
||||
case ResetMessageTagSummary(PeerId, MessageId.Namespace, Int32, MessageHistoryTagNamespaceCountValidityRange)
|
||||
case ReadGroupFeedInbox(PeerGroupId, MessageIndex)
|
||||
case UpdateState(AuthorizedAccountState.State)
|
||||
case UpdateChannelState(PeerId, ChannelState)
|
||||
case UpdateChannelState(PeerId, Int32)
|
||||
case UpdateChannelInvalidationPts(PeerId, Int32)
|
||||
case UpdateChannelSynchronizedUntilMessage(PeerId, MessageId.Id)
|
||||
case UpdateNotificationSettings(AccountStateNotificationSettingsSubject, PeerNotificationSettings)
|
||||
case UpdateGlobalNotificationSettings(AccountStateGlobalNotificationSettingsSubject, MessageNotificationSettings)
|
||||
case MergeApiChats([Api.Chat])
|
||||
@ -110,7 +116,7 @@ struct AccountMutableState {
|
||||
|
||||
var state: AuthorizedAccountState.State
|
||||
var peers: [PeerId: Peer]
|
||||
var chatStates: [PeerId: PeerChatState]
|
||||
var channelStates: [PeerId: AccountStateChannelState]
|
||||
var peerChatInfos: [PeerId: PeerChatInfo]
|
||||
var referencedMessageIds: Set<MessageId>
|
||||
var storedMessages: Set<MessageId>
|
||||
@ -139,7 +145,7 @@ struct AccountMutableState {
|
||||
self.referencedMessageIds = initialReferencedMessageIds
|
||||
self.storedMessages = initialStoredMessages
|
||||
self.readInboxMaxIds = initialReadInboxMaxIds
|
||||
self.chatStates = initialState.chatStates
|
||||
self.channelStates = initialState.channelStates
|
||||
self.peerChatInfos = initialState.peerChatInfos
|
||||
self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp
|
||||
self.branchOperationIndex = 0
|
||||
@ -147,12 +153,12 @@ struct AccountMutableState {
|
||||
self.updatedOutgoingUniqueMessageIds = [:]
|
||||
}
|
||||
|
||||
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], chatStates: [PeerId: PeerChatState], peerChatInfos: [PeerId: PeerChatInfo], referencedMessageIds: Set<MessageId>, storedMessages: Set<MessageId>, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], namespacesWithHolesFromPreviousState: [PeerId: Set<MessageId.Namespace>], updatedOutgoingUniqueMessageIds: [Int64: Int32], displayAlerts: [(text: String, isDropAuth: Bool)], branchOperationIndex: Int) {
|
||||
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: AccountStateChannelState], peerChatInfos: [PeerId: PeerChatInfo], referencedMessageIds: Set<MessageId>, storedMessages: Set<MessageId>, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], namespacesWithHolesFromPreviousState: [PeerId: Set<MessageId.Namespace>], updatedOutgoingUniqueMessageIds: [Int64: Int32], displayAlerts: [(text: String, isDropAuth: Bool)], branchOperationIndex: Int) {
|
||||
self.initialState = initialState
|
||||
self.operations = operations
|
||||
self.state = state
|
||||
self.peers = peers
|
||||
self.chatStates = chatStates
|
||||
self.channelStates = channelStates
|
||||
self.referencedMessageIds = referencedMessageIds
|
||||
self.storedMessages = storedMessages
|
||||
self.peerChatInfos = peerChatInfos
|
||||
@ -165,7 +171,7 @@ struct AccountMutableState {
|
||||
}
|
||||
|
||||
func branch() -> AccountMutableState {
|
||||
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, chatStates: self.chatStates, peerChatInfos: self.peerChatInfos, referencedMessageIds: self.referencedMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, updatedOutgoingUniqueMessageIds: self.updatedOutgoingUniqueMessageIds, displayAlerts: self.displayAlerts, branchOperationIndex: self.operations.count)
|
||||
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerChatInfos: self.peerChatInfos, referencedMessageIds: self.referencedMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, updatedOutgoingUniqueMessageIds: self.updatedOutgoingUniqueMessageIds, displayAlerts: self.displayAlerts, branchOperationIndex: self.operations.count)
|
||||
}
|
||||
|
||||
mutating func merge(_ other: AccountMutableState) {
|
||||
@ -269,8 +275,16 @@ struct AccountMutableState {
|
||||
self.addOperation(.UpdateState(state))
|
||||
}
|
||||
|
||||
mutating func updateChannelState(_ peerId: PeerId, state: ChannelState) {
|
||||
self.addOperation(.UpdateChannelState(peerId, state))
|
||||
mutating func updateChannelState(_ peerId: PeerId, pts: Int32) {
|
||||
self.addOperation(.UpdateChannelState(peerId, pts))
|
||||
}
|
||||
|
||||
mutating func updateChannelInvalidationPts(_ peerId: PeerId, invalidationPts: Int32) {
|
||||
self.addOperation(.UpdateChannelInvalidationPts(peerId, invalidationPts))
|
||||
}
|
||||
|
||||
mutating func updateChannelSynchronizedUntilMessage(_ peerId: PeerId, id: MessageId.Id) {
|
||||
self.addOperation(.UpdateChannelSynchronizedUntilMessage(peerId, id))
|
||||
}
|
||||
|
||||
mutating func updateNotificationSettings(_ subject: AccountStateNotificationSettingsSubject, notificationSettings: PeerNotificationSettings) {
|
||||
@ -464,8 +478,12 @@ struct AccountMutableState {
|
||||
}
|
||||
case let .UpdateState(state):
|
||||
self.state = state
|
||||
case let .UpdateChannelState(peerId, channelState):
|
||||
self.chatStates[peerId] = channelState
|
||||
case let .UpdateChannelState(peerId, pts):
|
||||
self.channelStates[peerId] = AccountStateChannelState(pts: pts)
|
||||
case .UpdateChannelInvalidationPts:
|
||||
break
|
||||
case .UpdateChannelSynchronizedUntilMessage:
|
||||
break
|
||||
case let .UpdateNotificationSettings(subject, notificationSettings):
|
||||
if case let .peer(peerId) = subject {
|
||||
if var currentInfo = self.peerChatInfos[peerId] {
|
||||
|
@ -356,7 +356,7 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u
|
||||
|
||||
private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<PeerId>, activeChannelIds: Set<PeerId>, associatedMessageIds: Set<MessageId>, peerIdsRequiringLocalChatState: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
var chatStates: [PeerId: PeerChatState] = [:]
|
||||
var channelStates: [PeerId: AccountStateChannelState] = [:]
|
||||
|
||||
var channelsToPollExplicitely = Set<PeerId>()
|
||||
|
||||
@ -367,11 +367,11 @@ private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<Pe
|
||||
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
if let channelState = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
chatStates[peerId] = channelState
|
||||
channelStates[peerId] = AccountStateChannelState(pts: channelState.pts)
|
||||
}
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
if let chatState = transaction.getPeerChatState(peerId) as? RegularChatState {
|
||||
chatStates[peerId] = chatState
|
||||
if let _ = transaction.getPeerChatState(peerId) as? RegularChatState {
|
||||
//chatStates[peerId] = chatState
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -434,7 +434,7 @@ private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<Pe
|
||||
}
|
||||
}
|
||||
|
||||
return AccountMutableState(initialState: AccountInitialState(state: (transaction.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, chatStates: chatStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates, channelsToPollExplicitely: channelsToPollExplicitely), initialPeers: peers, initialReferencedMessageIds: associatedMessageIds, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
|
||||
return AccountMutableState(initialState: AccountInitialState(state: (transaction.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates, channelsToPollExplicitely: channelsToPollExplicitely), initialPeers: peers, initialReferencedMessageIds: associatedMessageIds, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
|
||||
}
|
||||
|
||||
func initialStateWithUpdateGroups(postbox: Postbox, groups: [UpdateGroup]) -> Signal<AccountMutableState, NoError> {
|
||||
@ -772,7 +772,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
case let .updateChannelTooLong(_, channelId, channelPts):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
if !channelsToPoll.contains(peerId) {
|
||||
if let channelPts = channelPts, let channelState = state.chatStates[peerId] as? ChannelState, channelState.pts >= channelPts {
|
||||
if let channelPts = channelPts, let channelState = state.channelStates[peerId], channelState.pts >= channelPts {
|
||||
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip updateChannelTooLong by pts")
|
||||
} else {
|
||||
channelsToPoll.insert(peerId)
|
||||
@ -780,12 +780,12 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
}
|
||||
case let .updateDeleteChannelMessages(channelId, messages, pts: pts, ptsCount):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
if let previousState = updatedState.chatStates[peerId] as? ChannelState {
|
||||
if let previousState = updatedState.channelStates[peerId] {
|
||||
if previousState.pts >= pts {
|
||||
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip old delete update")
|
||||
} else if previousState.pts + ptsCount == pts {
|
||||
updatedState.deleteMessages(messages.map({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }))
|
||||
updatedState.updateChannelState(peerId, state: previousState.withUpdatedPts(pts))
|
||||
updatedState.updateChannelState(peerId, pts: pts)
|
||||
} else {
|
||||
if !channelsToPoll.contains(peerId) {
|
||||
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) delete pts hole")
|
||||
@ -802,7 +802,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
case let .updateEditChannelMessage(apiMessage, pts, ptsCount):
|
||||
if let message = StoreMessage(apiMessage: apiMessage), case let .Id(messageId) = message.id {
|
||||
let peerId = messageId.peerId
|
||||
if let previousState = updatedState.chatStates[peerId] as? ChannelState {
|
||||
if let previousState = updatedState.channelStates[peerId] {
|
||||
if previousState.pts >= pts {
|
||||
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip old edit update")
|
||||
} else if previousState.pts + ptsCount == pts {
|
||||
@ -814,7 +814,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
var attributes = message.attributes
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
||||
updatedState.editMessage(messageId, message: message.withUpdatedAttributes(attributes))
|
||||
updatedState.updateChannelState(peerId, state: previousState.withUpdatedPts(pts))
|
||||
updatedState.updateChannelState(peerId, pts: pts)
|
||||
} else {
|
||||
if !channelsToPoll.contains(peerId) {
|
||||
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) edit message pts hole")
|
||||
@ -833,7 +833,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
}
|
||||
case let .updateChannelWebPage(channelId, apiWebpage, pts, ptsCount):
|
||||
let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||
if let previousState = updatedState.chatStates[peerId] as? ChannelState {
|
||||
if let previousState = updatedState.channelStates[peerId] {
|
||||
if previousState.pts >= pts {
|
||||
} else if previousState.pts + ptsCount == pts {
|
||||
switch apiWebpage {
|
||||
@ -845,7 +845,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
}
|
||||
}
|
||||
|
||||
updatedState.updateChannelState(peerId, state: previousState.withUpdatedPts(pts))
|
||||
updatedState.updateChannelState(peerId, pts: pts)
|
||||
} else {
|
||||
if !channelsToPoll.contains(peerId) {
|
||||
Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) updateWebPage pts hole")
|
||||
@ -880,7 +880,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
}
|
||||
case let .updateNewChannelMessage(apiMessage, pts, ptsCount):
|
||||
if let message = StoreMessage(apiMessage: apiMessage) {
|
||||
if let previousState = updatedState.chatStates[message.id.peerId] as? ChannelState {
|
||||
if let previousState = updatedState.channelStates[message.id.peerId] {
|
||||
if previousState.pts >= pts {
|
||||
let messageText: String
|
||||
if Logger.shared.redactSensitiveData {
|
||||
@ -898,7 +898,10 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
var attributes = message.attributes
|
||||
attributes.append(ChannelMessageStateVersionAttribute(pts: pts))
|
||||
updatedState.addMessages([message.withUpdatedAttributes(attributes)], location: .UpperHistoryBlock)
|
||||
updatedState.updateChannelState(message.id.peerId, state: previousState.withUpdatedPts(pts))
|
||||
updatedState.updateChannelState(message.id.peerId, pts: pts)
|
||||
if case let .Id(id) = message.id {
|
||||
updatedState.updateChannelSynchronizedUntilMessage(id.peerId, id: id.id)
|
||||
}
|
||||
} else {
|
||||
if !channelsToPoll.contains(message.id.peerId) {
|
||||
Logger.shared.log("State", "channel \(message.id.peerId) (\((updatedState.peers[message.id.peerId] as? TelegramChannel)?.title ?? "nil")) message pts hole")
|
||||
@ -1587,9 +1590,9 @@ private func resolveMissingPeerChatInfos(network: Network, state: AccountMutable
|
||||
func keepPollingChannel(postbox: Postbox, network: Network, peerId: PeerId, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
||||
return postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
if let accountState = (transaction.getState() as? AuthorizedAccountState)?.state, let peer = transaction.getPeer(peerId) {
|
||||
var chatStates: [PeerId: PeerChatState] = [:]
|
||||
var channelStates: [PeerId: AccountStateChannelState] = [:]
|
||||
if let channelState = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
chatStates[peerId] = channelState
|
||||
channelStates[peerId] = AccountStateChannelState(pts: channelState.pts)
|
||||
}
|
||||
let initialPeers: [PeerId: Peer] = [peerId: peer]
|
||||
var peerChatInfos: [PeerId: PeerChatInfo] = [:]
|
||||
@ -1606,7 +1609,7 @@ func keepPollingChannel(postbox: Postbox, network: Network, peerId: PeerId, stat
|
||||
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
|
||||
}
|
||||
}
|
||||
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), chatStates: chatStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
||||
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
|
||||
return pollChannel(network: network, peer: peer, state: initialState)
|
||||
|> mapToSignal { (finalState, _, timeout) -> Signal<Void, NoError> in
|
||||
return resolveAssociatedMessages(network: network, state: finalState)
|
||||
@ -1657,7 +1660,9 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
|
||||
var mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary] = [:]
|
||||
var channelStates: [PeerId: ChannelState] = [:]
|
||||
var channelStates: [PeerId: AccountStateChannelState] = [:]
|
||||
var invalidateChannelStates: [PeerId: Int32] = [:]
|
||||
var channelSynchronizedUntilMessage: [PeerId: MessageId.Id] = [:]
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
|
||||
if let result = result {
|
||||
@ -1714,7 +1719,8 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl
|
||||
}
|
||||
|
||||
if let apiChannelPts = apiChannelPts {
|
||||
channelStates[peerId] = ChannelState(pts: apiChannelPts, invalidatedPts: apiChannelPts, synchronizedUntilMessageId: nil)
|
||||
channelStates[peerId] = AccountStateChannelState(pts: apiChannelPts)
|
||||
invalidateChannelStates[peerId] = apiChannelPts
|
||||
}
|
||||
|
||||
notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
|
||||
@ -1744,6 +1750,7 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl
|
||||
for message in storeMessages {
|
||||
if case let .Id(id) = message.id, id.namespace == Namespaces.Message.Cloud {
|
||||
updatedState.setNeedsHoleFromPreviousState(peerId: id.peerId, namespace: id.namespace)
|
||||
channelSynchronizedUntilMessage[id.peerId] = id.id
|
||||
}
|
||||
}
|
||||
|
||||
@ -1766,7 +1773,13 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl
|
||||
}
|
||||
|
||||
for (peerId, channelState) in channelStates {
|
||||
updatedState.updateChannelState(peerId, state: channelState)
|
||||
updatedState.updateChannelState(peerId, pts: channelState.pts)
|
||||
}
|
||||
for (peerId, pts) in invalidateChannelStates {
|
||||
updatedState.updateChannelInvalidationPts(peerId, invalidationPts: pts)
|
||||
}
|
||||
for (peerId, id) in channelSynchronizedUntilMessage {
|
||||
updatedState.updateChannelSynchronizedUntilMessage(peerId, id: id)
|
||||
}
|
||||
|
||||
for (peerId, settings) in notificationSettings {
|
||||
@ -1792,7 +1805,7 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
||||
#endif
|
||||
|
||||
let pollPts: Int32
|
||||
if let channelState = state.chatStates[peer.id] as? ChannelState {
|
||||
if let channelState = state.channelStates[peer.id] {
|
||||
pollPts = channelState.pts
|
||||
} else {
|
||||
pollPts = 1
|
||||
@ -1814,13 +1827,13 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
||||
switch difference {
|
||||
case let .channelDifference(_, pts, timeout, newMessages, otherUpdates, chats, users):
|
||||
apiTimeout = timeout
|
||||
let channelState: ChannelState
|
||||
if let previousState = updatedState.chatStates[peer.id] as? ChannelState {
|
||||
channelState = previousState.withUpdatedPts(pts)
|
||||
let channelPts: Int32
|
||||
if let _ = updatedState.channelStates[peer.id] {
|
||||
channelPts = pts
|
||||
} else {
|
||||
channelState = ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil)
|
||||
channelPts = pts
|
||||
}
|
||||
updatedState.updateChannelState(peer.id, state: channelState)
|
||||
updatedState.updateChannelState(peer.id, pts: channelPts)
|
||||
|
||||
updatedState.mergeChats(chats)
|
||||
updatedState.mergeUsers(users)
|
||||
@ -1833,6 +1846,9 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
||||
}
|
||||
}
|
||||
updatedState.addMessages([message], location: .UpperHistoryBlock)
|
||||
if case let .Id(id) = message.id {
|
||||
updatedState.updateChannelSynchronizedUntilMessage(id.peerId, id: id.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
for update in otherUpdates {
|
||||
@ -1895,13 +1911,13 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
||||
case let .channelDifferenceEmpty(_, pts, timeout):
|
||||
apiTimeout = timeout
|
||||
|
||||
let channelState: ChannelState
|
||||
if let previousState = updatedState.chatStates[peer.id] as? ChannelState {
|
||||
channelState = previousState.withUpdatedPts(pts)
|
||||
let channelPts: Int32
|
||||
if let previousState = updatedState.channelStates[peer.id] {
|
||||
channelPts = pts
|
||||
} else {
|
||||
channelState = ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil)
|
||||
channelPts = pts
|
||||
}
|
||||
updatedState.updateChannelState(peer.id, state: channelState)
|
||||
updatedState.updateChannelState(peer.id, pts: channelPts)
|
||||
case let .channelDifferenceTooLong(_, timeout, dialog, messages, chats, users):
|
||||
apiTimeout = timeout
|
||||
|
||||
@ -1917,8 +1933,8 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
||||
}
|
||||
|
||||
if let (peer, pts, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount) = parameters {
|
||||
let channelState = ChannelState(pts: pts, invalidatedPts: pts, synchronizedUntilMessageId: nil)
|
||||
updatedState.updateChannelState(peer.peerId, state: channelState)
|
||||
updatedState.updateChannelState(peer.peerId, pts: pts)
|
||||
updatedState.updateChannelInvalidationPts(peer.peerId, invalidationPts: pts)
|
||||
|
||||
updatedState.mergeChats(chats)
|
||||
updatedState.mergeUsers(users)
|
||||
@ -1936,6 +1952,7 @@ private func pollChannel(network: Network, peer: Peer, state: AccountMutableStat
|
||||
let location: AddMessagesLocation
|
||||
if case let .Id(id) = message.id, id.id == topMessage {
|
||||
location = .UpperHistoryBlock
|
||||
updatedState.updateChannelSynchronizedUntilMessage(id.peerId, id: id.id)
|
||||
} else {
|
||||
location = .Random
|
||||
}
|
||||
@ -2007,9 +2024,9 @@ private func verifyTransaction(_ transaction: Transaction, finalState: AccountMu
|
||||
for peerId in channelsWithUpdatedStates {
|
||||
let currentState = transaction.getPeerChatState(peerId)
|
||||
var previousStateMatches = false
|
||||
let previousState = finalState.initialState.chatStates[peerId] as? ChannelState
|
||||
if let currentState = currentState, let previousState = previousState {
|
||||
if currentState.equals(previousState) {
|
||||
let previousState = finalState.initialState.channelStates[peerId]
|
||||
if let currentState = currentState as? ChannelState, let previousState = previousState {
|
||||
if currentState.pts == previousState.pts {
|
||||
previousStateMatches = true
|
||||
}
|
||||
} else if currentState == nil && previousState == nil {
|
||||
@ -2048,7 +2065,9 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
||||
var result: [AccountStateMutationOperation] = []
|
||||
|
||||
var updatedState: AuthorizedAccountState.State?
|
||||
var updatedChannelStates: [PeerId: ChannelState] = [:]
|
||||
var updatedChannelStates: [PeerId: AccountStateChannelState] = [:]
|
||||
var invalidateChannelPts: [PeerId: Int32] = [:]
|
||||
var updateChannelSynchronizedUntilMessage: [PeerId: MessageId.Id] = [:]
|
||||
|
||||
var currentAddMessages: OptimizeAddMessagesState?
|
||||
var currentAddScheduledMessages: OptimizeAddMessagesState?
|
||||
@ -2065,8 +2084,12 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
||||
result.append(operation)
|
||||
case let .UpdateState(state):
|
||||
updatedState = state
|
||||
case let .UpdateChannelState(peerId, state):
|
||||
updatedChannelStates[peerId] = state
|
||||
case let .UpdateChannelState(peerId, pts):
|
||||
updatedChannelStates[peerId] = AccountStateChannelState(pts: pts)
|
||||
case let .UpdateChannelInvalidationPts(peerId, pts):
|
||||
invalidateChannelPts[peerId] = pts
|
||||
case let .UpdateChannelSynchronizedUntilMessage(peerId, id):
|
||||
updateChannelSynchronizedUntilMessage[peerId] = id
|
||||
case let .AddMessages(messages, location):
|
||||
if let currentAddMessages = currentAddMessages, currentAddMessages.location == location {
|
||||
currentAddMessages.messages.append(contentsOf: messages)
|
||||
@ -2097,7 +2120,15 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
||||
}
|
||||
|
||||
for (peerId, state) in updatedChannelStates {
|
||||
result.append(.UpdateChannelState(peerId, state))
|
||||
result.append(.UpdateChannelState(peerId, state.pts))
|
||||
}
|
||||
|
||||
for (peerId, pts) in invalidateChannelPts {
|
||||
result.append(.UpdateChannelInvalidationPts(peerId, pts))
|
||||
}
|
||||
|
||||
for (peerId, id) in updateChannelSynchronizedUntilMessage {
|
||||
result.append(.UpdateChannelSynchronizedUntilMessage(peerId, id))
|
||||
}
|
||||
|
||||
return result
|
||||
@ -2144,8 +2175,18 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
|
||||
for (peerId, namespaces) in finalState.state.namespacesWithHolesFromPreviousState {
|
||||
for namespace in namespaces {
|
||||
if let id = transaction.getTopPeerMessageId(peerId: peerId, namespace: namespace) {
|
||||
holesFromPreviousStateMessageIds.append(MessageId(peerId: id.peerId, namespace: id.namespace, id: id.id + 1))
|
||||
var topId: Int32?
|
||||
if namespace == Namespaces.Message.Cloud, let channelState = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
if let synchronizedUntilMessageId = channelState.synchronizedUntilMessageId {
|
||||
topId = synchronizedUntilMessageId + 1
|
||||
}
|
||||
}
|
||||
if topId == nil {
|
||||
topId = transaction.getTopPeerMessageId(peerId: peerId, namespace: namespace)?.id
|
||||
}
|
||||
|
||||
if let id = topId {
|
||||
holesFromPreviousStateMessageIds.append(MessageId(peerId: peerId, namespace: namespace, id: id + 1))
|
||||
} else {
|
||||
holesFromPreviousStateMessageIds.append(MessageId(peerId: peerId, namespace: namespace, id: 1))
|
||||
}
|
||||
@ -2494,9 +2535,21 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
let currentState = transaction.getState() as! AuthorizedAccountState
|
||||
transaction.setState(currentState.changedState(state))
|
||||
Logger.shared.log("State", "apply state \(state)")
|
||||
case let .UpdateChannelState(peerId, channelState):
|
||||
transaction.setPeerChatState(peerId, state: channelState)
|
||||
Logger.shared.log("State", "apply channel state \(peerId): \(channelState)")
|
||||
case let .UpdateChannelState(peerId, pts):
|
||||
var state = (transaction.getPeerChatState(peerId) as? ChannelState) ?? ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil)
|
||||
state = state.withUpdatedPts(pts)
|
||||
transaction.setPeerChatState(peerId, state: state)
|
||||
Logger.shared.log("State", "apply channel state \(peerId): \(state)")
|
||||
case let .UpdateChannelInvalidationPts(peerId, pts):
|
||||
var state = (transaction.getPeerChatState(peerId) as? ChannelState) ?? ChannelState(pts: 0, invalidatedPts: pts, synchronizedUntilMessageId: nil)
|
||||
state = state.withUpdatedInvalidatedPts(pts)
|
||||
transaction.setPeerChatState(peerId, state: state)
|
||||
Logger.shared.log("State", "apply channel invalidation pts \(peerId): \(state)")
|
||||
case let .UpdateChannelSynchronizedUntilMessage(peerId, id):
|
||||
var state = (transaction.getPeerChatState(peerId) as? ChannelState) ?? ChannelState(pts: 0, invalidatedPts: nil, synchronizedUntilMessageId: id)
|
||||
state = state.withUpdatedSynchronizedUntilMessageId(id)
|
||||
transaction.setPeerChatState(peerId, state: state)
|
||||
Logger.shared.log("State", "apply channel synchronized until message \(peerId): \(state)")
|
||||
case let .UpdateNotificationSettings(subject, notificationSettings):
|
||||
switch subject {
|
||||
case let .peer(peerId):
|
||||
|
@ -564,7 +564,7 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
|
||||
var peers: [Peer] = []
|
||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
var channelStates: [PeerId: ChannelState] = [:]
|
||||
var channelStates: [PeerId: Int32] = [:]
|
||||
|
||||
switch result {
|
||||
case let .peerDialogs(dialogs, messages, chats, users, _):
|
||||
@ -644,9 +644,10 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
|
||||
transaction.replaceMessageTagSummary(peerId: peerId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: unreadMentionsCount, maxId: topMessage)
|
||||
|
||||
if let pts = pts {
|
||||
let channelState = ChannelState(pts: pts, invalidatedPts: pts, synchronizedUntilMessageId: nil)
|
||||
transaction.setPeerChatState(peerId, state: channelState)
|
||||
channelStates[peer.peerId] = channelState
|
||||
if transaction.getPeerChatState(peerId) == nil {
|
||||
transaction.setPeerChatState(peerId, state: ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil))
|
||||
}
|
||||
channelStates[peer.peerId] = pts
|
||||
}
|
||||
case .dialogFolder:
|
||||
assertionFailure()
|
||||
@ -659,9 +660,9 @@ private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox,
|
||||
if let storeMessage = StoreMessage(apiMessage: message) {
|
||||
var updatedStoreMessage = storeMessage
|
||||
if case let .Id(id) = storeMessage.id {
|
||||
if let channelState = channelStates[id.peerId] {
|
||||
if let channelPts = channelStates[id.peerId] {
|
||||
var updatedAttributes = storeMessage.attributes
|
||||
updatedAttributes.append(ChannelMessageStateVersionAttribute(pts: channelState.pts))
|
||||
updatedAttributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
|
||||
updatedStoreMessage = updatedStoreMessage.withUpdatedAttributes(updatedAttributes)
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ struct ParsedDialogs {
|
||||
let notificationSettings: [PeerId: PeerNotificationSettings]
|
||||
let readStates: [PeerId: [MessageId.Namespace: PeerReadState]]
|
||||
let mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary]
|
||||
let chatStates: [PeerId: PeerChatState]
|
||||
let channelStates: [PeerId: Int32]
|
||||
let topMessageIds: [PeerId: MessageId]
|
||||
let storeMessages: [StoreMessage]
|
||||
|
||||
@ -50,7 +50,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
|
||||
var mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary] = [:]
|
||||
var chatStates: [PeerId: PeerChatState] = [:]
|
||||
var channelStates: [PeerId: Int32] = [:]
|
||||
var topMessageIds: [PeerId: MessageId] = [:]
|
||||
|
||||
var storeMessages: [StoreMessage] = []
|
||||
@ -131,7 +131,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
}
|
||||
|
||||
if let apiChannelPts = apiChannelPts {
|
||||
chatStates[peerId] = ChannelState(pts: apiChannelPts, invalidatedPts: nil, synchronizedUntilMessageId: nil)
|
||||
channelStates[peerId] = apiChannelPts
|
||||
}
|
||||
|
||||
notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
|
||||
@ -149,9 +149,9 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
if let storeMessage = StoreMessage(apiMessage: message) {
|
||||
var updatedStoreMessage = storeMessage
|
||||
if case let .Id(id) = storeMessage.id {
|
||||
if let channelState = chatStates[id.peerId] as? ChannelState {
|
||||
if let channelPts = channelStates[id.peerId] {
|
||||
var updatedAttributes = storeMessage.attributes
|
||||
updatedAttributes.append(ChannelMessageStateVersionAttribute(pts: channelState.pts))
|
||||
updatedAttributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
|
||||
updatedStoreMessage = updatedStoreMessage.withUpdatedAttributes(updatedAttributes)
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
|
||||
notificationSettings: notificationSettings,
|
||||
readStates: readStates,
|
||||
mentionTagSummaries: mentionTagSummaries,
|
||||
chatStates: chatStates,
|
||||
channelStates: channelStates,
|
||||
topMessageIds: topMessageIds,
|
||||
storeMessages: storeMessages,
|
||||
|
||||
@ -190,7 +190,7 @@ struct FetchedChatList {
|
||||
let notificationSettings: [PeerId: PeerNotificationSettings]
|
||||
let readStates: [PeerId: [MessageId.Namespace: PeerReadState]]
|
||||
let mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary]
|
||||
let chatStates: [PeerId: PeerChatState]
|
||||
let channelStates: [PeerId: Int32]
|
||||
let storeMessages: [StoreMessage]
|
||||
let topMessageIds: [PeerId: MessageId]
|
||||
|
||||
@ -295,7 +295,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
|
||||
var mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary] = [:]
|
||||
var chatStates: [PeerId: PeerChatState] = [:]
|
||||
var channelStates: [PeerId: Int32] = [:]
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var topMessageIds: [PeerId: MessageId] = [:]
|
||||
|
||||
@ -304,7 +304,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
notificationSettings.merge(parsedRemoteChats.notificationSettings, uniquingKeysWith: { _, updated in updated })
|
||||
readStates.merge(parsedRemoteChats.readStates, uniquingKeysWith: { _, updated in updated })
|
||||
mentionTagSummaries.merge(parsedRemoteChats.mentionTagSummaries, uniquingKeysWith: { _, updated in updated })
|
||||
chatStates.merge(parsedRemoteChats.chatStates, uniquingKeysWith: { _, updated in updated })
|
||||
channelStates.merge(parsedRemoteChats.channelStates, uniquingKeysWith: { _, updated in updated })
|
||||
storeMessages.append(contentsOf: parsedRemoteChats.storeMessages)
|
||||
topMessageIds.merge(parsedRemoteChats.topMessageIds, uniquingKeysWith: { _, updated in updated })
|
||||
|
||||
@ -314,7 +314,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
notificationSettings.merge(parsedPinnedChats.notificationSettings, uniquingKeysWith: { _, updated in updated })
|
||||
readStates.merge(parsedPinnedChats.readStates, uniquingKeysWith: { _, updated in updated })
|
||||
mentionTagSummaries.merge(parsedPinnedChats.mentionTagSummaries, uniquingKeysWith: { _, updated in updated })
|
||||
chatStates.merge(parsedPinnedChats.chatStates, uniquingKeysWith: { _, updated in updated })
|
||||
channelStates.merge(parsedPinnedChats.channelStates, uniquingKeysWith: { _, updated in updated })
|
||||
storeMessages.append(contentsOf: parsedPinnedChats.storeMessages)
|
||||
topMessageIds.merge(parsedPinnedChats.topMessageIds, uniquingKeysWith: { _, updated in updated })
|
||||
}
|
||||
@ -336,7 +336,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
notificationSettings.merge(folderChats.notificationSettings, uniquingKeysWith: { _, updated in updated })
|
||||
readStates.merge(folderChats.readStates, uniquingKeysWith: { _, updated in updated })
|
||||
mentionTagSummaries.merge(folderChats.mentionTagSummaries, uniquingKeysWith: { _, updated in updated })
|
||||
chatStates.merge(folderChats.chatStates, uniquingKeysWith: { _, updated in updated })
|
||||
channelStates.merge(folderChats.channelStates, uniquingKeysWith: { _, updated in updated })
|
||||
storeMessages.append(contentsOf: folderChats.storeMessages)
|
||||
}
|
||||
|
||||
@ -369,7 +369,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
|
||||
notificationSettings: notificationSettings,
|
||||
readStates: readStates,
|
||||
mentionTagSummaries: mentionTagSummaries,
|
||||
chatStates: chatStates,
|
||||
channelStates: channelStates,
|
||||
storeMessages: storeMessages,
|
||||
topMessageIds: topMessageIds,
|
||||
|
||||
|
@ -479,15 +479,11 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
|
||||
}
|
||||
}
|
||||
|
||||
for (peerId, chatState) in fetchedChats.chatStates {
|
||||
if let chatState = chatState as? ChannelState {
|
||||
for (peerId, pts) in fetchedChats.channelStates {
|
||||
if let current = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
transaction.setPeerChatState(peerId, state: current.withUpdatedPts(chatState.pts))
|
||||
transaction.setPeerChatState(peerId, state: current.withUpdatedPts(pts))
|
||||
} else {
|
||||
transaction.setPeerChatState(peerId, state: chatState)
|
||||
}
|
||||
} else {
|
||||
transaction.setPeerChatState(peerId, state: chatState)
|
||||
transaction.setPeerChatState(peerId, state: ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,70 +2,134 @@ import Foundation
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
|
||||
private final class ManagedSynchronizePeerReadStatesState {
|
||||
private var synchronizeDisposables: [PeerId: (PeerReadStateSynchronizationOperation, Disposable)] = [:]
|
||||
private final class SynchronizePeerReadStatesContextImpl {
|
||||
private final class Operation {
|
||||
let operation: PeerReadStateSynchronizationOperation
|
||||
let disposable: Disposable
|
||||
|
||||
func clearDisposables() -> [Disposable] {
|
||||
let disposables = Array(self.synchronizeDisposables.values.map({ $0.1 }))
|
||||
self.synchronizeDisposables.removeAll()
|
||||
return disposables
|
||||
init(
|
||||
operation: PeerReadStateSynchronizationOperation,
|
||||
disposable: Disposable
|
||||
) {
|
||||
self.operation = operation
|
||||
self.disposable = disposable
|
||||
}
|
||||
|
||||
func update(operations: [PeerId: PeerReadStateSynchronizationOperation]) -> (removed: [Disposable], added: [(PeerId, PeerReadStateSynchronizationOperation, MetaDisposable)]) {
|
||||
var removed: [Disposable] = []
|
||||
var added: [(PeerId, PeerReadStateSynchronizationOperation, MetaDisposable)] = []
|
||||
|
||||
for (peerId, (operation, disposable)) in self.synchronizeDisposables {
|
||||
if operations[peerId] != operation {
|
||||
removed.append(disposable)
|
||||
self.synchronizeDisposables.removeValue(forKey: peerId)
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
for (peerId, operation) in operations {
|
||||
if self.synchronizeDisposables[peerId] == nil {
|
||||
let disposable = MetaDisposable()
|
||||
self.synchronizeDisposables[peerId] = (operation, disposable)
|
||||
added.append((peerId, operation, disposable))
|
||||
private let queue: Queue
|
||||
private let network: Network
|
||||
private let postbox: Postbox
|
||||
private let stateManager: AccountStateManager
|
||||
|
||||
private var disposable: Disposable?
|
||||
|
||||
private var currentState: [PeerId : PeerReadStateSynchronizationOperation] = [:]
|
||||
private var activeOperations: [PeerId: Operation] = [:]
|
||||
private var pendingOperations: [PeerId: PeerReadStateSynchronizationOperation] = [:]
|
||||
|
||||
init(queue: Queue, network: Network, postbox: Postbox, stateManager: AccountStateManager) {
|
||||
self.queue = queue
|
||||
self.network = network
|
||||
self.postbox = postbox
|
||||
self.stateManager = stateManager
|
||||
|
||||
self.disposable = (postbox.synchronizePeerReadStatesView()
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] view in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.currentState = view.operations
|
||||
strongSelf.update()
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable?.dispose()
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
}
|
||||
|
||||
private func update() {
|
||||
let peerIds = Set(self.currentState.keys).union(Set(self.pendingOperations.keys))
|
||||
|
||||
for peerId in peerIds {
|
||||
var maybeOperation: PeerReadStateSynchronizationOperation?
|
||||
if let operation = self.currentState[peerId] {
|
||||
maybeOperation = operation
|
||||
} else if let operation = self.pendingOperations[peerId] {
|
||||
maybeOperation = operation
|
||||
self.pendingOperations.removeValue(forKey: peerId)
|
||||
}
|
||||
|
||||
if let operation = maybeOperation {
|
||||
if let current = self.activeOperations[peerId] {
|
||||
if current.operation != operation {
|
||||
self.pendingOperations[peerId] = operation
|
||||
}
|
||||
} else {
|
||||
let operationDisposable = MetaDisposable()
|
||||
let activeOperation = Operation(
|
||||
operation: operation,
|
||||
disposable: operationDisposable
|
||||
)
|
||||
self.activeOperations[peerId] = activeOperation
|
||||
let signal: Signal<Never, NoError>
|
||||
switch operation {
|
||||
case .Validate:
|
||||
signal = synchronizePeerReadState(network: self.network, postbox: self.postbox, stateManager: self.stateManager, peerId: peerId, push: false, validate: true)
|
||||
|> ignoreValues
|
||||
case let .Push(_, thenSync):
|
||||
signal = synchronizePeerReadState(network: self.network, postbox: self.postbox, stateManager: stateManager, peerId: peerId, push: true, validate: thenSync)
|
||||
|> ignoreValues
|
||||
}
|
||||
operationDisposable.set((signal
|
||||
|> deliverOn(self.queue)).start(completed: { [weak self, weak activeOperation] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let activeOperation = activeOperation {
|
||||
if let current = strongSelf.activeOperations[peerId], current === activeOperation {
|
||||
strongSelf.activeOperations.removeValue(forKey: peerId)
|
||||
strongSelf.update()
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (removed, added)
|
||||
private final class SynchronizePeerReadStatesStatesContext {
|
||||
private let queue: Queue
|
||||
private let impl: QueueLocalObject<SynchronizePeerReadStatesContextImpl>
|
||||
|
||||
init(network: Network, postbox: Postbox, stateManager: AccountStateManager) {
|
||||
self.queue = Queue()
|
||||
let queue = self.queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return SynchronizePeerReadStatesContextImpl(queue: queue, network: network, postbox: postbox, stateManager: stateManager)
|
||||
})
|
||||
}
|
||||
|
||||
func dispose() {
|
||||
self.impl.with { impl in
|
||||
impl.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func managedSynchronizePeerReadStates(network: Network, postbox: Postbox, stateManager: AccountStateManager) -> Signal<Void, NoError> {
|
||||
return Signal { _ in
|
||||
let state = Atomic(value: ManagedSynchronizePeerReadStatesState())
|
||||
|
||||
let disposable = postbox.synchronizePeerReadStatesView().start(next: { view in
|
||||
let (removed, added) = state.with { state -> (removed: [Disposable], added: [(PeerId, PeerReadStateSynchronizationOperation, MetaDisposable)]) in
|
||||
return state.update(operations: view.operations)
|
||||
}
|
||||
|
||||
for disposable in removed {
|
||||
disposable.dispose()
|
||||
}
|
||||
|
||||
for (peerId, operation, disposable) in added {
|
||||
let synchronizeOperation: Signal<Void, NoError>
|
||||
switch operation {
|
||||
case .Validate:
|
||||
synchronizeOperation = synchronizePeerReadState(network: network, postbox: postbox, stateManager: stateManager, peerId: peerId, push: false, validate: true)
|
||||
case let .Push(_, thenSync):
|
||||
synchronizeOperation = synchronizePeerReadState(network: network, postbox: postbox, stateManager: stateManager, peerId: peerId, push: true, validate: thenSync)
|
||||
}
|
||||
disposable.set(synchronizeOperation.start())
|
||||
}
|
||||
})
|
||||
let context = SynchronizePeerReadStatesStatesContext(network: network, postbox: postbox, stateManager: stateManager)
|
||||
|
||||
return ActionDisposable {
|
||||
disposable.dispose()
|
||||
for disposable in state.with({ state -> [Disposable] in
|
||||
state.clearDisposables()
|
||||
}) {
|
||||
disposable.dispose()
|
||||
}
|
||||
context.dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox,
|
||||
|> mapToSignal { dialogs -> Signal<Void, NoError> in
|
||||
var storeMessages: [StoreMessage] = []
|
||||
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
|
||||
var chatStates: [PeerId: PeerChatState] = [:]
|
||||
var channelStates: [PeerId: Int32] = [:]
|
||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||
|
||||
var remoteItemIds: [PinnedItemId] = []
|
||||
@ -200,7 +200,7 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox,
|
||||
readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount, markedUnread: apiMarkedUnread)
|
||||
|
||||
if let apiChannelPts = apiChannelPts {
|
||||
chatStates[peerId] = ChannelState(pts: apiChannelPts, invalidatedPts: nil, synchronizedUntilMessageId: nil)
|
||||
channelStates[peerId] = apiChannelPts
|
||||
}
|
||||
|
||||
notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings)
|
||||
@ -245,15 +245,11 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox,
|
||||
|
||||
transaction.resetIncomingReadStates(readStates)
|
||||
|
||||
for (peerId, chatState) in chatStates {
|
||||
if let chatState = chatState as? ChannelState {
|
||||
for (peerId, pts) in channelStates {
|
||||
if let _ = transaction.getPeerChatState(peerId) as? ChannelState {
|
||||
// skip changing state
|
||||
} else {
|
||||
transaction.setPeerChatState(peerId, state: chatState)
|
||||
}
|
||||
} else {
|
||||
transaction.setPeerChatState(peerId, state: chatState)
|
||||
transaction.setPeerChatState(peerId, state: ChannelState(pts: pts, invalidatedPts: nil, synchronizedUntilMessageId: nil))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,20 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo
|
||||
}
|
||||
} else if message.id.peerId.namespace == Namespaces.Peer.SecretChat || message.id.namespace != Namespaces.Message.Cloud {
|
||||
hasEditRights = false
|
||||
} else if let author = message.author, author.id == accountPeerId {
|
||||
} else if let author = message.author, author.id == accountPeerId, let peer = message.peers[message.id.peerId] {
|
||||
hasEditRights = true
|
||||
if let peer = peer as? TelegramChannel {
|
||||
switch peer.info {
|
||||
case .broadcast:
|
||||
if peer.hasPermission(.editAllMessages) || !message.flags.contains(.Incoming) {
|
||||
unlimitedInterval = true
|
||||
}
|
||||
case .group:
|
||||
if peer.hasPermission(.pinMessages) {
|
||||
unlimitedInterval = true
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if message.author?.id == message.id.peerId, let peer = message.peers[message.id.peerId] {
|
||||
if let peer = peer as? TelegramChannel {
|
||||
switch peer.info {
|
||||
|
Loading…
x
Reference in New Issue
Block a user