Updated chat list reset

This commit is contained in:
Peter Iakovlev 2018-12-25 17:57:06 +04:00
parent 217f262605
commit 1cd169f5fe
8 changed files with 658 additions and 405 deletions

View File

@ -251,7 +251,7 @@ let telegramPostboxSeedConfiguration: SeedConfiguration = {
} else {
return [.regularChatsAndPrivateGroups]
}
})
}, additionalChatListIndexNamespace: Namespaces.Message.Cloud)
}()
public func accountWithId(networkArguments: NetworkInitializationArguments, id: AccountRecordId, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> {

View File

@ -369,7 +369,11 @@ public final class AccountStateManager {
|> take(1)
|> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in
if let authorizedState = state.state {
let request = network.request(Api.functions.updates.getDifference(flags: 1 << 0, pts: authorizedState.pts, ptsTotalLimit: 1000, date: authorizedState.date, qts: authorizedState.qts))
var ptsTotalLimit: Int32 = 10000
#if DEBUG
ptsTotalLimit = 1000
#endif
let request = network.request(Api.functions.updates.getDifference(flags: 1 << 0, pts: authorizedState.pts, ptsTotalLimit: ptsTotalLimit, date: authorizedState.date, qts: authorizedState.qts))
|> retryRequest
return request

View File

@ -9,14 +9,242 @@ import Foundation
import MtProtoKitDynamic
#endif
private struct LocalChatListEntryRange {
var upperBound: ChatListIndex?
var lowerBound: ChatListIndex
var count: Int32
var hash: UInt32
var apiHash: Int32 {
return Int32(bitPattern: self.hash & UInt32(0x7FFFFFFF))
}
}
private func combineHash(_ value: Int32, into hash: inout UInt32) {
let low = UInt32(bitPattern: value)
hash = (hash &* 20261) &+ low
}
private func localChatListEntryRanges(_ entries: [ChatListNamespaceEntry], limit: Int) -> [LocalChatListEntryRange] {
var result: [LocalChatListEntryRange] = []
var currentRange: LocalChatListEntryRange?
for i in 0 ..< entries.count {
switch entries[i] {
case let .peer(index, readState, topMessageAttributes, tagSummary, interfaceState):
var updatedRange: LocalChatListEntryRange
if let current = currentRange {
updatedRange = current
} else {
updatedRange = LocalChatListEntryRange(upperBound: result.last?.lowerBound, lowerBound: index, count: 0, hash: 0)
}
updatedRange.lowerBound = index
updatedRange.count += 1
/*
dialog.pinned ? 1 : 0,
dialog.unread_mark ? 1 : 0,
dialog.peer.channel_id || dialog.peer.chat_id || dialog.peer.user_id,
dialog.top_message.id,
top_message.edit_date || top_message.date,
dialog.read_inbox_max_id,
dialog.read_outbox_max_id,
dialog.unread_count,
dialog.unread_mentions_count,
draft.draft.date || 0
*/
combineHash(index.pinningIndex != nil ? 1 : 0, into: &updatedRange.hash)
if let readState = readState, readState.markedUnread {
combineHash(1, into: &updatedRange.hash)
} else {
combineHash(0, into: &updatedRange.hash)
}
combineHash(index.messageIndex.id.peerId.id, into: &updatedRange.hash)
combineHash(index.messageIndex.id.id, into: &updatedRange.hash)
var timestamp = index.messageIndex.timestamp
for attribute in topMessageAttributes {
if let attribute = attribute as? EditedMessageAttribute {
timestamp = max(timestamp, attribute.date)
}
}
combineHash(timestamp, into: &updatedRange.hash)
if let readState = readState, case let .idBased(maxIncomingReadId, maxOutgoingReadId, _, count, _) = readState {
combineHash(maxIncomingReadId, into: &updatedRange.hash)
combineHash(maxOutgoingReadId, into: &updatedRange.hash)
combineHash(count, into: &updatedRange.hash)
} else {
combineHash(0, into: &updatedRange.hash)
combineHash(0, into: &updatedRange.hash)
combineHash(0, into: &updatedRange.hash)
}
if let tagSummary = tagSummary {
combineHash(tagSummary.count, into: &updatedRange.hash)
} else {
combineHash(0, into: &updatedRange.hash)
}
if let embeddedState = interfaceState?.chatListEmbeddedState {
combineHash(embeddedState.timestamp, into: &updatedRange.hash)
} else {
combineHash(0, into: &updatedRange.hash)
}
if Int(updatedRange.count) >= limit {
result.append(updatedRange)
currentRange = nil
} else {
currentRange = updatedRange
}
case .hole:
if let currentRangeValue = currentRange {
result.append(currentRangeValue)
currentRange = nil
}
}
}
if let currentRangeValue = currentRange {
result.append(currentRangeValue)
currentRange = nil
}
return result
}
private struct ResolvedChatListResetRange {
let head: Bool
let local: LocalChatListEntryRange
let remote: FetchedChatList
}
func accountStateReset(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Void, NoError> {
let pinnedChats: Signal<Api.messages.PeerDialogs, NoError> = network.request(Api.functions.messages.getPinnedDialogs())
|> retryRequest
let state: Signal<Api.updates.State, NoError> =
network.request(Api.functions.updates.getState())
let state: Signal<Api.updates.State, NoError> = network.request(Api.functions.updates.getState())
|> retryRequest
return combineLatest(network.request(Api.functions.messages.getDialogs(flags: 0, /*feed*//*feedId: nil,*/ offsetDate: 0, offsetId: 0, offsetPeer: .inputPeerEmpty, limit: 100, hash: 0))
return postbox.transaction { transaction -> [ChatListNamespaceEntry] in
return transaction.getChatListNamespaceEntries(groupId: nil, namespace: Namespaces.Message.Cloud, summaryTag: MessageTags.unseenPersonalMessage)
}
|> mapToSignal { localChatListEntries -> Signal<Void, NoError> in
let localRanges = localChatListEntryRanges(localChatListEntries, limit: 10)
var signal: Signal<ResolvedChatListResetRange?, NoError> = .complete()
for i in 0 ..< localRanges.count {
let upperBound: MessageIndex
let head = i == 0
let localRange = localRanges[i]
if let rangeUpperBound = localRange.upperBound {
upperBound = rangeUpperBound.messageIndex
} else {
upperBound = MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 0), timestamp: 0)
}
let rangeSignal: Signal<ResolvedChatListResetRange?, NoError> = fetchChatList(postbox: postbox, network: network, location: .general, upperBound: upperBound, hash: localRange.apiHash, limit: localRange.count)
|> map { remote -> ResolvedChatListResetRange? in
if let remote = remote {
return ResolvedChatListResetRange(head: head, local: localRange, remote: remote)
} else {
return nil
}
}
signal = signal
|> then(rangeSignal)
}
let collectedResolvedRanges: Signal<[ResolvedChatListResetRange], NoError> = signal
|> map { next -> [ResolvedChatListResetRange] in
if let next = next {
return [next]
} else {
return []
}
}
|> reduceLeft(value: [], f: { list, next in
var list = list
list.append(contentsOf: next)
return list
})
return combineLatest(collectedResolvedRanges, state)
|> mapToSignal { collectedRanges, state -> Signal<Void, NoError> in
return postbox.transaction { transaction -> Void in
for range in collectedRanges {
let previousPeerIds = transaction.resetChatList(keepPeerNamespaces: [Namespaces.Peer.SecretChat], upperBound: range.local.upperBound ?? ChatListIndex.absoluteUpperBound, lowerBound: range.local.lowerBound)
updatePeers(transaction: transaction, peers: range.remote.peers, update: { _, updated -> Peer in
return updated
})
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: range.remote.peerPresences)
transaction.updateCurrentPeerNotificationSettings(range.remote.notificationSettings)
var allPeersWithMessages = Set<PeerId>()
for message in range.remote.storeMessages {
allPeersWithMessages.insert(message.id.peerId)
}
for (_, messageId) in range.remote.topMessageIds {
if messageId.id > 1 {
var skipHole = false
if let localTopId = transaction.getTopPeerMessageIndex(peerId: messageId.peerId, namespace: messageId.namespace)?.id {
if localTopId >= messageId {
skipHole = true
}
}
if !skipHole {
transaction.addHole(MessageId(peerId: messageId.peerId, namespace: messageId.namespace, id: messageId.id - 1))
}
}
}
let _ = transaction.addMessages(range.remote.storeMessages, location: .UpperHistoryBlock)
transaction.resetIncomingReadStates(range.remote.readStates)
for (peerId, chatState) in range.remote.chatStates {
if let chatState = chatState as? ChannelState {
if let current = transaction.getPeerChatState(peerId) as? ChannelState {
transaction.setPeerChatState(peerId, state: current.withUpdatedPts(chatState.pts))
} else {
transaction.setPeerChatState(peerId, state: chatState)
}
} else {
transaction.setPeerChatState(peerId, state: chatState)
}
}
for (peerId, summary) in range.remote.mentionTagSummaries {
transaction.replaceMessageTagSummary(peerId: peerId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId)
}
let namespacesWithHoles: [PeerId.Namespace: [MessageId.Namespace]] = [
Namespaces.Peer.CloudUser: [Namespaces.Message.Cloud],
Namespaces.Peer.CloudGroup: [Namespaces.Message.Cloud],
Namespaces.Peer.CloudChannel: [Namespaces.Message.Cloud]
]
for peerId in previousPeerIds {
if !allPeersWithMessages.contains(peerId), let namespaces = namespacesWithHoles[peerId.namespace] {
for namespace in namespaces {
transaction.addHole(MessageId(peerId: peerId, namespace: namespace, id: Int32.max - 1))
}
}
}
if range.head {
transaction.setPinnedItemIds(range.remote.pinnedItemIds ?? [])
}
}
if let currentState = transaction.getState() as? AuthorizedAccountState, let embeddedState = currentState.state {
switch state {
case let .state(pts, _, _, seq, _):
transaction.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: embeddedState.qts, date: embeddedState.date, seq: seq)))
}
}
}
}
return combineLatest(network.request(Api.functions.messages.getDialogs(flags: 0, offsetDate: 0, offsetId: 0, offsetPeer: .inputPeerEmpty, limit: 100, hash: 0))
|> retryRequest, pinnedChats, state)
|> mapToSignal { result, pinnedChats, state -> Signal<Void, NoError> in
var dialogsDialogs: [Api.Dialog] = []
@ -259,4 +487,5 @@ func accountStateReset(postbox: Postbox, network: Network, accountPeerId: PeerId
}
})
}
}
}

View File

@ -132,10 +132,10 @@ public func channelBlacklistParticipants(account: Account, peerId: PeerId) -> Si
}
}
public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChannelBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> {
public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, memberId: PeerId, rights: TelegramChannelBannedRights?) -> Signal<(ChannelParticipant?, RenderedChannelParticipant?), NoError> {
return fetchChannelParticipant(account: account, peerId: peerId, participantId: memberId)
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> in
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> in
|> mapToSignal { currentParticipant -> Signal<(ChannelParticipant?, RenderedChannelParticipant?), NoError> in
return account.postbox.transaction { transaction -> Signal<(ChannelParticipant?, RenderedChannelParticipant?), NoError> in
if let peer = transaction.getPeer(peerId), let inputChannel = apiInputChannel(peer), let _ = transaction.getPeer(account.peerId), let memberPeer = transaction.getPeer(memberId), let inputUser = apiInputUser(memberPeer) {
let updatedParticipant: ChannelParticipant
if let currentParticipant = currentParticipant, case let .member(_, invitedAt, _, currentBanInfo) = currentParticipant {
@ -160,13 +160,9 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
return account.network.request(Api.functions.channels.editBanned(channel: inputChannel, userId: inputUser, bannedRights: effectiveRights.apiBannedRights))
|> retryRequest
|> mapToSignal { result -> Signal<(ChannelParticipant?, RenderedChannelParticipant), NoError> in
|> mapToSignal { result -> Signal<(ChannelParticipant?, RenderedChannelParticipant?), NoError> in
account.stateManager.addUpdates(result)
return account.postbox.transaction { transaction -> (ChannelParticipant?, RenderedChannelParticipant) in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
var updatedData = cachedData
var wasKicked = false
var wasBanned = false
var wasMember = false
@ -176,7 +172,7 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
case .creator:
break
case let .member(_, _, adminInfo, banInfo):
if let adminInfo = adminInfo {
if let _ = adminInfo {
wasAdmin = true
}
if let banInfo = banInfo {
@ -184,12 +180,13 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
wasKicked = true
} else if !banInfo.rights.flags.isEmpty {
wasBanned = true
wasMember = true
}
}
} else {
wasMember = true
}
}
}
var isKicked = false
var isBanned = false
@ -201,6 +198,10 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
let isMember = !wasKicked && !effectiveRights.flags.contains(.banReadMessages)
return account.postbox.transaction { transaction -> (ChannelParticipant?, RenderedChannelParticipant?) in
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, cachedData -> CachedPeerData? in
if let cachedData = cachedData as? CachedChannelData {
var updatedData = cachedData
if isKicked != wasKicked {
if let kickedCount = updatedData.participantsSummary.kickedCount {
updatedData = updatedData.withUpdatedParticipantsSummary(updatedData.participantsSummary.withUpdatedKickedCount(max(0, kickedCount + (isKicked ? 1 : -1))))
@ -250,7 +251,8 @@ public func updateChannelMemberBannedRights(account: Account, peerId: PeerId, me
peers[peer.id] = peer
}
}
return (currentParticipant, RenderedChannelParticipant(participant: updatedParticipant, peer: memberPeer, peers: peers, presences: presences))
return (currentParticipant, isMember ? RenderedChannelParticipant(participant: updatedParticipant, peer: memberPeer, peers: peers, presences: presences) : nil)
}
}
} else {

View File

@ -23,7 +23,7 @@ struct ParsedDialogs {
let readStates: [PeerId: [MessageId.Namespace: PeerReadState]]
let mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary]
let chatStates: [PeerId: PeerChatState]
let topMessageIds: [PeerId: MessageId]
let storeMessages: [StoreMessage]
let lowerNonPinnedIndex: MessageIndex?
@ -54,6 +54,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]
var mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary] = [:]
var chatStates: [PeerId: PeerChatState] = [:]
var topMessageIds: [PeerId: MessageId] = [:]
var storeMessages: [StoreMessage] = []
var nonPinnedDialogsTopMessageIds = Set<MessageId>()
@ -104,6 +105,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
if apiTopMessage != 0 {
mentionTagSummaries[peerId] = MessageHistoryTagNamespaceSummary(version: 1, count: apiUnreadMentionsCount, range: MessageHistoryTagNamespaceCountValidityRange(maxId: apiTopMessage))
topMessageIds[peerId] = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: apiTopMessage)
}
if let apiChannelPts = apiChannelPts {
@ -165,7 +167,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message],
readStates: readStates,
mentionTagSummaries: mentionTagSummaries,
chatStates: chatStates,
topMessageIds: topMessageIds,
storeMessages: storeMessages,
lowerNonPinnedIndex: lowerNonPinnedIndex,
@ -181,6 +183,7 @@ struct FetchedChatList {
let mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary]
let chatStates: [PeerId: PeerChatState]
let storeMessages: [StoreMessage]
let topMessageIds: [PeerId: MessageId]
let lowerNonPinnedIndex: MessageIndex?
@ -188,7 +191,7 @@ struct FetchedChatList {
let feeds: [(PeerGroupId, MessageIndex?)]
}
func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLocation, upperBound: MessageIndex) -> Signal<FetchedChatList, NoError> {
func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLocation, upperBound: MessageIndex, hash: Int32, limit: Int32) -> Signal<FetchedChatList?, NoError> {
return postbox.stateView()
|> mapToSignal { view -> Signal<AuthorizedAccountState, NoError> in
if let state = view.state as? AuthorizedAccountState {
@ -198,7 +201,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
}
}
|> take(1)
|> mapToSignal { _ -> Signal<FetchedChatList, NoError> in
|> mapToSignal { _ -> Signal<FetchedChatList?, NoError> in
let offset: Signal<(Int32, Int32, Api.InputPeer), NoError>
if upperBound.id.peerId.namespace == Namespaces.Peer.Empty {
offset = single((0, 0, Api.InputPeer.inputPeerEmpty), NoError.self)
@ -211,7 +214,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
}
return offset
|> mapToSignal { (timestamp, id, peer) -> Signal<FetchedChatList, NoError> in
|> mapToSignal { (timestamp, id, peer) -> Signal<FetchedChatList?, NoError> in
let additionalPinnedChats: Signal<Api.messages.PeerDialogs?, NoError>
if case .general = location, case .inputPeerEmpty = peer, timestamp == 0 {
additionalPinnedChats = network.request(Api.functions.messages.getPinnedDialogs())
@ -233,11 +236,14 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
flags |= 1 << 1*/
break
}
let requestChats = network.request(Api.functions.messages.getDialogs(flags: flags/*feed*//*, feedId: requestFeedId*/, offsetDate: timestamp, offsetId: id, offsetPeer: peer, limit: 100, hash: 0))
let requestChats = network.request(Api.functions.messages.getDialogs(flags: flags/*feed*//*, feedId: requestFeedId*/, offsetDate: timestamp, offsetId: id, offsetPeer: peer, limit: limit, hash: hash))
|> retryRequest
return combineLatest(requestChats, additionalPinnedChats)
|> mapToSignal { remoteChats, pinnedChats -> Signal<FetchedChatList, NoError> in
|> mapToSignal { remoteChats, pinnedChats -> Signal<FetchedChatList?, NoError> in
if case .dialogsNotModified = remoteChats {
return .single(nil)
}
let extractedRemoteDialogs = extractDialogsData(dialogs: remoteChats)
let parsedRemoteChats = parseDialogs(apiDialogs: extractedRemoteDialogs.apiDialogs, apiMessages: extractedRemoteDialogs.apiMessages, apiChats: extractedRemoteDialogs.apiChats, apiUsers: extractedRemoteDialogs.apiUsers, apiIsAtLowestBoundary: extractedRemoteDialogs.apiIsAtLowestBoundary)
var parsedPinnedChats: ParsedDialogs?
@ -269,7 +275,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
}
return combineLatest(feedSignals)
|> map { feeds -> FetchedChatList in
|> map { feeds -> FetchedChatList? in
var peers: [Peer] = []
var peerPresences: [PeerId: PeerPresence] = [:]
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
@ -277,6 +283,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
var mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary] = [:]
var chatStates: [PeerId: PeerChatState] = [:]
var storeMessages: [StoreMessage] = []
var topMessageIds: [PeerId: MessageId] = [:]
peers.append(contentsOf: parsedRemoteChats.peers)
peerPresences.merge(parsedRemoteChats.peerPresences, uniquingKeysWith: { _, updated in updated })
@ -285,6 +292,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
mentionTagSummaries.merge(parsedRemoteChats.mentionTagSummaries, uniquingKeysWith: { _, updated in updated })
chatStates.merge(parsedRemoteChats.chatStates, uniquingKeysWith: { _, updated in updated })
storeMessages.append(contentsOf: parsedRemoteChats.storeMessages)
topMessageIds.merge(parsedRemoteChats.topMessageIds, uniquingKeysWith: { _, updated in updated })
if let parsedPinnedChats = parsedPinnedChats {
peers.append(contentsOf: parsedPinnedChats.peers)
@ -294,6 +302,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
mentionTagSummaries.merge(parsedPinnedChats.mentionTagSummaries, uniquingKeysWith: { _, updated in updated })
chatStates.merge(parsedPinnedChats.chatStates, uniquingKeysWith: { _, updated in updated })
storeMessages.append(contentsOf: parsedPinnedChats.storeMessages)
topMessageIds.merge(parsedPinnedChats.topMessageIds, uniquingKeysWith: { _, updated in updated })
}
for (_, feedChats) in feeds {
@ -314,6 +323,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo
mentionTagSummaries: mentionTagSummaries,
chatStates: chatStates,
storeMessages: storeMessages,
topMessageIds: topMessageIds,
lowerNonPinnedIndex: parsedRemoteChats.lowerNonPinnedIndex,

View File

@ -567,8 +567,13 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId
} else {
location = .general
}
return fetchChatList(postbox: postbox, network: network, location: location, upperBound: hole.index)
return fetchChatList(postbox: postbox, network: network, location: location, upperBound: hole.index, hash: 0, limit: 100)
|> mapToSignal { fetchedChats -> Signal<Void, NoError> in
guard let fetchedChats = fetchedChats else {
return postbox.transaction { transaction -> Void in
transaction.replaceChatListHole(groupId: groupId, index: hole.index, hole: nil)
}
}
return withResolvedAssociatedMessages(postbox: postbox, source: .network(network), storeMessages: fetchedChats.storeMessages, { transaction, additionalPeers, additionalMessages in
for peer in fetchedChats.peers {
updatePeers(transaction: transaction, peers: [peer], update: { _, updated -> Peer in

View File

@ -315,7 +315,7 @@ private final class MultipartUploadManager {
case let .data(data):
fileData = data
}
if let fileData = fileData {
if let fileData = fileData, fileData.count >= partOffset + partSize {
let partData = self.state.transform(data: fileData.subdata(in: partOffset ..< (partOffset + partSize)))
var currentBigTotalParts = self.bigTotalParts
if self.bigParts && resourceData.complete && partOffset + partSize == resourceData.size {

View File

@ -337,11 +337,11 @@ private func pushPeerReadState(network: Network, postbox: Postbox, stateManager:
}
private func pushPeerReadState(network: Network, postbox: Postbox, stateManager: AccountStateManager, peerId: PeerId) -> Signal<Void, NoError> {
let currentReadState = postbox.transaction { transaction -> PeerReadState? in
let currentReadState = postbox.transaction { transaction -> (MessageId.Namespace, PeerReadState)? in
if let readStates = transaction.getPeerReadStates(peerId) {
for (namespace, readState) in readStates {
if namespace == Namespaces.Message.Cloud || namespace == Namespaces.Message.SecretIncoming {
return readState
return (namespace, readState)
}
}
}
@ -349,20 +349,23 @@ private func pushPeerReadState(network: Network, postbox: Postbox, stateManager:
}
let pushedState = currentReadState
|> mapToSignalPromotingError { readState -> Signal<PeerReadState, VerifyReadStateError> in
if let readState = readState {
|> mapToSignalPromotingError { namespaceAndReadState -> Signal<(MessageId.Namespace, PeerReadState), VerifyReadStateError> in
if let (namespace, readState) = namespaceAndReadState {
return pushPeerReadState(network: network, postbox: postbox, stateManager: stateManager, peerId: peerId, readState: readState)
|> map { updatedReadState -> (MessageId.Namespace, PeerReadState) in
return (namespace, updatedReadState)
}
} else {
return .complete()
}
}
let verifiedState = pushedState
|> mapToSignal { readState -> Signal<Void, VerifyReadStateError> in
|> mapToSignal { namespaceAndReadState -> Signal<Void, VerifyReadStateError> in
return stateManager.addCustomOperation(postbox.transaction { transaction -> VerifyReadStateError? in
if let readStates = transaction.getPeerReadStates(peerId) {
for (namespace, currentReadState) in readStates where namespace == Namespaces.Message.Cloud {
if currentReadState == readState {
for (namespace, currentReadState) in readStates where namespace == namespaceAndReadState.0 {
if currentReadState == namespaceAndReadState.1 {
transaction.confirmSynchronizedIncomingReadState(peerId)
return nil
}