mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Move folder preloading to filter resolution
This commit is contained in:
parent
957726219b
commit
a52334046d
@ -1044,7 +1044,7 @@ public class Account {
|
|||||||
self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.postbox, network: self.network).start())
|
self.managedOperationsDisposable.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.postbox, network: self.network).start())
|
||||||
self.managedOperationsDisposable.add(managedApplyPendingScheduledMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
self.managedOperationsDisposable.add(managedApplyPendingScheduledMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start())
|
||||||
self.managedOperationsDisposable.add(managedChatListFilters(postbox: self.postbox, network: self.network).start())
|
self.managedOperationsDisposable.add(managedChatListFilters(postbox: self.postbox, network: self.network, accountPeerId: self.peerId).start())
|
||||||
|
|
||||||
let importantBackgroundOperations: [Signal<AccountRunningImportantTasks, NoError>] = [
|
let importantBackgroundOperations: [Signal<AccountRunningImportantTasks, NoError>] = [
|
||||||
managedSynchronizeChatInputStateOperations(postbox: self.postbox, network: self.network) |> map { $0 ? AccountRunningImportantTasks.other : [] },
|
managedSynchronizeChatInputStateOperations(postbox: self.postbox, network: self.network) |> map { $0 ? AccountRunningImportantTasks.other : [] },
|
||||||
|
@ -351,16 +351,18 @@ private enum RequestChatListFiltersError {
|
|||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
|
|
||||||
private func requestChatListFilters(postbox: Postbox, network: Network) -> Signal<[ChatListFilter], RequestChatListFiltersError> {
|
private func requestChatListFilters(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<[ChatListFilter], RequestChatListFiltersError> {
|
||||||
return network.request(Api.functions.messages.getDialogFilters())
|
return network.request(Api.functions.messages.getDialogFilters())
|
||||||
|> mapError { _ -> RequestChatListFiltersError in
|
|> mapError { _ -> RequestChatListFiltersError in
|
||||||
return .generic
|
return .generic
|
||||||
}
|
}
|
||||||
|> mapToSignal { result -> Signal<[ChatListFilter], RequestChatListFiltersError> in
|
|> mapToSignal { result -> Signal<[ChatListFilter], RequestChatListFiltersError> in
|
||||||
return postbox.transaction { transaction -> ([ChatListFilter], [Api.InputPeer]) in
|
return postbox.transaction { transaction -> ([ChatListFilter], [Api.InputPeer], [Api.InputPeer]) in
|
||||||
var filters: [ChatListFilter] = []
|
var filters: [ChatListFilter] = []
|
||||||
var missingPeers: [Api.InputPeer] = []
|
var missingPeers: [Api.InputPeer] = []
|
||||||
|
var missingChats: [Api.InputPeer] = []
|
||||||
var missingPeerIds = Set<PeerId>()
|
var missingPeerIds = Set<PeerId>()
|
||||||
|
var missingChatIds = Set<PeerId>()
|
||||||
for apiFilter in result {
|
for apiFilter in result {
|
||||||
let filter = ChatListFilter(apiFilter: apiFilter)
|
let filter = ChatListFilter(apiFilter: apiFilter)
|
||||||
filters.append(filter)
|
filters.append(filter)
|
||||||
@ -385,13 +387,33 @@ private func requestChatListFilters(postbox: Postbox, network: Network) -> Signa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for peer in pinnedPeers {
|
||||||
|
var peerId: PeerId?
|
||||||
|
switch peer {
|
||||||
|
case let .inputPeerUser(userId, _):
|
||||||
|
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
|
||||||
|
case let .inputPeerChat(chatId):
|
||||||
|
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
|
||||||
|
case let .inputPeerChannel(channelId, _):
|
||||||
|
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if let peerId = peerId, !missingChatIds.contains(peerId) {
|
||||||
|
if transaction.getPeerChatListIndex(peerId) == nil {
|
||||||
|
missingChatIds.insert(peerId)
|
||||||
|
missingChats.append(peer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (filters, missingPeers)
|
return (filters, missingPeers, missingChats)
|
||||||
}
|
}
|
||||||
|> castError(RequestChatListFiltersError.self)
|
|> castError(RequestChatListFiltersError.self)
|
||||||
|> mapToSignal { filtersAndMissingPeers -> Signal<[ChatListFilter], RequestChatListFiltersError> in
|
|> mapToSignal { filtersAndMissingPeers -> Signal<[ChatListFilter], RequestChatListFiltersError> in
|
||||||
let (filters, missingPeers) = filtersAndMissingPeers
|
let (filters, missingPeers, missingChats) = filtersAndMissingPeers
|
||||||
|
|
||||||
var missingUsers: [Api.InputUser] = []
|
var missingUsers: [Api.InputUser] = []
|
||||||
var missingChannels: [Api.InputChannel] = []
|
var missingChannels: [Api.InputChannel] = []
|
||||||
@ -493,6 +515,13 @@ private func requestChatListFilters(postbox: Postbox, network: Network) -> Signa
|
|||||||
resolveMissingGroups = .complete()
|
resolveMissingGroups = .complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let loadMissingChats: Signal<Never, NoError>
|
||||||
|
if !missingChats.isEmpty {
|
||||||
|
loadMissingChats = loadAndStorePeerChatInfos(accountPeerId: accountPeerId, postbox: postbox, network: network, peers: missingChats)
|
||||||
|
} else {
|
||||||
|
loadMissingChats = .complete()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
resolveMissingUsers
|
resolveMissingUsers
|
||||||
)
|
)
|
||||||
@ -502,6 +531,9 @@ private func requestChatListFilters(postbox: Postbox, network: Network) -> Signa
|
|||||||
|> then(
|
|> then(
|
||||||
resolveMissingGroups
|
resolveMissingGroups
|
||||||
)
|
)
|
||||||
|
|> then(
|
||||||
|
loadMissingChats
|
||||||
|
)
|
||||||
|> castError(RequestChatListFiltersError.self)
|
|> castError(RequestChatListFiltersError.self)
|
||||||
|> mapToSignal { _ -> Signal<[ChatListFilter], RequestChatListFiltersError> in
|
|> mapToSignal { _ -> Signal<[ChatListFilter], RequestChatListFiltersError> in
|
||||||
#if swift(<5.1)
|
#if swift(<5.1)
|
||||||
@ -515,6 +547,147 @@ private func requestChatListFilters(postbox: Postbox, network: Network) -> Signa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox, network: Network, peers: [Api.InputPeer]) -> Signal<Never, NoError> {
|
||||||
|
let signal = network.request(Api.functions.messages.getPeerDialogs(peers: peers.map(Api.InputDialogPeer.inputDialogPeer(peer:))))
|
||||||
|
|> map(Optional.init)
|
||||||
|
|
||||||
|
return signal
|
||||||
|
|> `catch` { _ -> Signal<Api.messages.PeerDialogs?, NoError> in
|
||||||
|
return .single(nil)
|
||||||
|
}
|
||||||
|
|> mapToSignal { result -> Signal<Never, NoError> in
|
||||||
|
guard let result = result else {
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
|
||||||
|
return postbox.transaction { transaction -> Void in
|
||||||
|
var peers: [Peer] = []
|
||||||
|
var peerPresences: [PeerId: PeerPresence] = [:]
|
||||||
|
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
||||||
|
var channelStates: [PeerId: ChannelState] = [:]
|
||||||
|
|
||||||
|
switch result {
|
||||||
|
case let .peerDialogs(dialogs, messages, chats, users, _):
|
||||||
|
for chat in chats {
|
||||||
|
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||||
|
peers.append(groupOrChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for user in users {
|
||||||
|
let telegramUser = TelegramUser(user: user)
|
||||||
|
peers.append(telegramUser)
|
||||||
|
if let presence = TelegramUserPresence(apiUser: user) {
|
||||||
|
peerPresences[telegramUser.id] = presence
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var topMessageIds = Set<MessageId>()
|
||||||
|
|
||||||
|
for dialog in dialogs {
|
||||||
|
switch dialog {
|
||||||
|
case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, notifySettings, pts, _, folderId):
|
||||||
|
let peerId = peer.peerId
|
||||||
|
|
||||||
|
if topMessage != 0 {
|
||||||
|
topMessageIds.insert(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: topMessage))
|
||||||
|
}
|
||||||
|
|
||||||
|
var isExcludedFromChatList = false
|
||||||
|
for chat in chats {
|
||||||
|
if chat.peerId == peerId {
|
||||||
|
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
||||||
|
if let group = groupOrChannel as? TelegramGroup {
|
||||||
|
if group.flags.contains(.deactivated) {
|
||||||
|
isExcludedFromChatList = true
|
||||||
|
} else {
|
||||||
|
switch group.membership {
|
||||||
|
case .Member:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
isExcludedFromChatList = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if let channel = groupOrChannel as? TelegramChannel {
|
||||||
|
switch channel.participationStatus {
|
||||||
|
case .member:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
isExcludedFromChatList = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isExcludedFromChatList {
|
||||||
|
let groupId = PeerGroupId(rawValue: folderId ?? 0)
|
||||||
|
let currentInclusion = transaction.getPeerChatListInclusion(peerId)
|
||||||
|
var currentPinningIndex: UInt16?
|
||||||
|
var currentMinTimestamp: Int32?
|
||||||
|
switch currentInclusion {
|
||||||
|
case let .ifHasMessagesOrOneOf(currentGroupId, pinningIndex, minTimestamp):
|
||||||
|
if currentGroupId == groupId {
|
||||||
|
currentPinningIndex = pinningIndex
|
||||||
|
}
|
||||||
|
currentMinTimestamp = minTimestamp
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessagesOrOneOf(groupId: groupId, pinningIndex: currentPinningIndex, minTimestamp: currentMinTimestamp))
|
||||||
|
}
|
||||||
|
|
||||||
|
notificationSettings[peer.peerId] = TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||||
|
|
||||||
|
transaction.resetIncomingReadStates([peerId: [Namespaces.Message.Cloud: .idBased(maxIncomingReadId: readInboxMaxId, maxOutgoingReadId: readOutboxMaxId, maxKnownId: topMessage, count: unreadCount, markedUnread: false)]])
|
||||||
|
|
||||||
|
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)
|
||||||
|
transaction.setPeerChatState(peerId, state: channelState)
|
||||||
|
channelStates[peer.peerId] = channelState
|
||||||
|
}
|
||||||
|
case .dialogFolder:
|
||||||
|
assertionFailure()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var storeMessages: [StoreMessage] = []
|
||||||
|
for message in messages {
|
||||||
|
if let storeMessage = StoreMessage(apiMessage: message) {
|
||||||
|
var updatedStoreMessage = storeMessage
|
||||||
|
if case let .Id(id) = storeMessage.id {
|
||||||
|
if let channelState = channelStates[id.peerId] {
|
||||||
|
var updatedAttributes = storeMessage.attributes
|
||||||
|
updatedAttributes.append(ChannelMessageStateVersionAttribute(pts: channelState.pts))
|
||||||
|
updatedStoreMessage = updatedStoreMessage.withUpdatedAttributes(updatedAttributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storeMessages.append(updatedStoreMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for message in storeMessages {
|
||||||
|
if case let .Id(id) = message.id {
|
||||||
|
let _ = transaction.addMessages([message], location: topMessageIds.contains(id) ? .UpperHistoryBlock : .Random)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
||||||
|
return updated
|
||||||
|
})
|
||||||
|
|
||||||
|
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
||||||
|
|
||||||
|
transaction.updateCurrentPeerNotificationSettings(notificationSettings)
|
||||||
|
}
|
||||||
|
|> ignoreValues
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct ChatListFiltersState: PreferencesEntry, Equatable {
|
struct ChatListFiltersState: PreferencesEntry, Equatable {
|
||||||
var filters: [ChatListFilter]
|
var filters: [ChatListFilter]
|
||||||
var remoteFilters: [ChatListFilter]?
|
var remoteFilters: [ChatListFilter]?
|
||||||
@ -877,7 +1050,7 @@ func requestChatListFiltersSync(transaction: Transaction) {
|
|||||||
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeChatListFiltersOperation(content: .sync))
|
transaction.operationLogAddEntry(peerId: peerId, tag: tag, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: SynchronizeChatListFiltersOperation(content: .sync))
|
||||||
}
|
}
|
||||||
|
|
||||||
func managedChatListFilters(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
|
func managedChatListFilters(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Void, NoError> {
|
||||||
return Signal { _ in
|
return Signal { _ in
|
||||||
let updateFeaturedDisposable = updateChatListFeaturedFilters(postbox: postbox, network: network).start()
|
let updateFeaturedDisposable = updateChatListFeaturedFilters(postbox: postbox, network: network).start()
|
||||||
let _ = postbox.transaction({ transaction in
|
let _ = postbox.transaction({ transaction in
|
||||||
@ -901,7 +1074,7 @@ func managedChatListFilters(postbox: Postbox, network: Network) -> Signal<Void,
|
|||||||
let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Never, NoError> in
|
let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tag: tag, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal<Never, NoError> in
|
||||||
if let entry = entry {
|
if let entry = entry {
|
||||||
if let operation = entry.contents as? SynchronizeChatListFiltersOperation {
|
if let operation = entry.contents as? SynchronizeChatListFiltersOperation {
|
||||||
return synchronizeChatListFilters(transaction: transaction, postbox: postbox, network: network, operation: operation)
|
return synchronizeChatListFilters(transaction: transaction, accountPeerId: accountPeerId, postbox: postbox, network: network, operation: operation)
|
||||||
} else {
|
} else {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
}
|
}
|
||||||
@ -933,14 +1106,14 @@ func managedChatListFilters(postbox: Postbox, network: Network) -> Signal<Void,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func synchronizeChatListFilters(transaction: Transaction, postbox: Postbox, network: Network, operation: SynchronizeChatListFiltersOperation) -> Signal<Never, NoError> {
|
private func synchronizeChatListFilters(transaction: Transaction, accountPeerId: PeerId, postbox: Postbox, network: Network, operation: SynchronizeChatListFiltersOperation) -> Signal<Never, NoError> {
|
||||||
switch operation.content {
|
switch operation.content {
|
||||||
case .sync:
|
case .sync:
|
||||||
let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default
|
let settings = transaction.getPreferencesEntry(key: PreferencesKeys.chatListFilters) as? ChatListFiltersState ?? ChatListFiltersState.default
|
||||||
let localFilters = settings.filters
|
let localFilters = settings.filters
|
||||||
let locallyKnownRemoteFilters = settings.remoteFilters ?? []
|
let locallyKnownRemoteFilters = settings.remoteFilters ?? []
|
||||||
|
|
||||||
return requestChatListFilters(postbox: postbox, network: network)
|
return requestChatListFilters(accountPeerId: accountPeerId, postbox: postbox, network: network)
|
||||||
|> `catch` { _ -> Signal<[ChatListFilter], NoError> in
|
|> `catch` { _ -> Signal<[ChatListFilter], NoError> in
|
||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,6 @@ import TelegramApi
|
|||||||
|
|
||||||
private final class ManagedChatListHolesState {
|
private final class ManagedChatListHolesState {
|
||||||
private var currentHole: (ChatListHolesEntry, Disposable)?
|
private var currentHole: (ChatListHolesEntry, Disposable)?
|
||||||
private var currentPinnedIds: (Set<PeerId>, Disposable)?
|
|
||||||
private var processedPinnedIds: Set<PeerId>?
|
|
||||||
|
|
||||||
func clearDisposables() -> [Disposable] {
|
func clearDisposables() -> [Disposable] {
|
||||||
if let (_, disposable) = self.currentHole {
|
if let (_, disposable) = self.currentHole {
|
||||||
@ -18,17 +16,9 @@ private final class ManagedChatListHolesState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(entries: [ChatListHolesEntry], pinnedIds: Set<PeerId>) -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable], addedPinnedIds: (Set<PeerId>, MetaDisposable)?) {
|
func update(entries: [ChatListHolesEntry]) -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable]) {
|
||||||
var removed: [Disposable] = []
|
var removed: [Disposable] = []
|
||||||
var added: [ChatListHolesEntry: MetaDisposable] = [:]
|
var added: [ChatListHolesEntry: MetaDisposable] = [:]
|
||||||
var addedPinnedIds: (Set<PeerId>, MetaDisposable)?
|
|
||||||
|
|
||||||
if self.processedPinnedIds == nil && !pinnedIds.isEmpty {
|
|
||||||
self.processedPinnedIds = pinnedIds
|
|
||||||
let disposable = MetaDisposable()
|
|
||||||
self.currentPinnedIds = (pinnedIds, disposable)
|
|
||||||
addedPinnedIds = (pinnedIds, disposable)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let (entry, disposable) = self.currentHole {
|
if let (entry, disposable) = self.currentHole {
|
||||||
if !entries.contains(entry) {
|
if !entries.contains(entry) {
|
||||||
@ -43,7 +33,7 @@ private final class ManagedChatListHolesState {
|
|||||||
added[entry] = disposable
|
added[entry] = disposable
|
||||||
}
|
}
|
||||||
|
|
||||||
return (removed, added, addedPinnedIds)
|
return (removed, added)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,13 +51,7 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee
|
|||||||
return lhs.hole.index > rhs.hole.index
|
return lhs.hole.index > rhs.hole.index
|
||||||
})
|
})
|
||||||
|
|
||||||
var pinnedIds = Set<PeerId>()
|
|
||||||
|
|
||||||
if let preferencesView = combinedView.views[filtersKey] as? PreferencesView, let filtersState = preferencesView.values[PreferencesKeys.chatListFilters] as? ChatListFiltersState, !filtersState.filters.isEmpty {
|
if let preferencesView = combinedView.views[filtersKey] as? PreferencesView, let filtersState = preferencesView.values[PreferencesKeys.chatListFilters] as? ChatListFiltersState, !filtersState.filters.isEmpty {
|
||||||
for filter in filtersState.filters {
|
|
||||||
pinnedIds.formUnion(filter.data.includePeers.pinnedPeers)
|
|
||||||
}
|
|
||||||
|
|
||||||
if let topRootHole = combinedView.views[topRootHoleKey] as? AllChatListHolesView, let hole = topRootHole.latestHole {
|
if let topRootHole = combinedView.views[topRootHoleKey] as? AllChatListHolesView, let hole = topRootHole.latestHole {
|
||||||
let entry = ChatListHolesEntry(groupId: .root, hole: hole)
|
let entry = ChatListHolesEntry(groupId: .root, hole: hole)
|
||||||
if !entries.contains(entry) {
|
if !entries.contains(entry) {
|
||||||
@ -84,8 +68,8 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (removed, added, addedPinnedIds) = state.with { state in
|
let (removed, added) = state.with { state in
|
||||||
return state.update(entries: entries, pinnedIds: pinnedIds)
|
return state.update(entries: entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
for disposable in removed {
|
for disposable in removed {
|
||||||
@ -95,22 +79,6 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee
|
|||||||
for (entry, disposable) in added {
|
for (entry, disposable) in added {
|
||||||
disposable.set(fetchChatListHole(postbox: postbox, network: network, accountPeerId: accountPeerId, groupId: entry.groupId, hole: entry.hole).start())
|
disposable.set(fetchChatListHole(postbox: postbox, network: network, accountPeerId: accountPeerId, groupId: entry.groupId, hole: entry.hole).start())
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (ids, disposable) = addedPinnedIds {
|
|
||||||
let signal = postbox.transaction { transaction -> [Api.InputPeer] in
|
|
||||||
var peers: [Api.InputPeer] = []
|
|
||||||
for id in ids {
|
|
||||||
if let inputPeer = transaction.getPeer(id).flatMap(apiInputPeer) {
|
|
||||||
peers.append(inputPeer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return peers
|
|
||||||
}
|
|
||||||
|> mapToSignal { inputPeers -> Signal<Never, NoError> in
|
|
||||||
return loadAndStorePeerChatInfos(accountPeerId: accountPeerId, postbox: postbox, network: network, peers: inputPeers)
|
|
||||||
}
|
|
||||||
disposable.set(signal.start())
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return ActionDisposable {
|
return ActionDisposable {
|
||||||
@ -123,144 +91,3 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func loadAndStorePeerChatInfos(accountPeerId: PeerId, postbox: Postbox, network: Network, peers: [Api.InputPeer]) -> Signal<Never, NoError> {
|
|
||||||
let signal = network.request(Api.functions.messages.getPeerDialogs(peers: peers.map(Api.InputDialogPeer.inputDialogPeer(peer:))))
|
|
||||||
|> map(Optional.init)
|
|
||||||
|
|
||||||
return signal
|
|
||||||
|> `catch` { _ -> Signal<Api.messages.PeerDialogs?, NoError> in
|
|
||||||
return .single(nil)
|
|
||||||
}
|
|
||||||
|> mapToSignal { result -> Signal<Never, NoError> in
|
|
||||||
guard let result = result else {
|
|
||||||
return .complete()
|
|
||||||
}
|
|
||||||
|
|
||||||
return postbox.transaction { transaction -> Void in
|
|
||||||
var peers: [Peer] = []
|
|
||||||
var peerPresences: [PeerId: PeerPresence] = [:]
|
|
||||||
var notificationSettings: [PeerId: PeerNotificationSettings] = [:]
|
|
||||||
var channelStates: [PeerId: ChannelState] = [:]
|
|
||||||
|
|
||||||
switch result {
|
|
||||||
case let .peerDialogs(dialogs, messages, chats, users, _):
|
|
||||||
for chat in chats {
|
|
||||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
|
||||||
peers.append(groupOrChannel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for user in users {
|
|
||||||
let telegramUser = TelegramUser(user: user)
|
|
||||||
peers.append(telegramUser)
|
|
||||||
if let presence = TelegramUserPresence(apiUser: user) {
|
|
||||||
peerPresences[telegramUser.id] = presence
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var topMessageIds = Set<MessageId>()
|
|
||||||
|
|
||||||
for dialog in dialogs {
|
|
||||||
switch dialog {
|
|
||||||
case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, notifySettings, pts, _, folderId):
|
|
||||||
let peerId = peer.peerId
|
|
||||||
|
|
||||||
if topMessage != 0 {
|
|
||||||
topMessageIds.insert(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: topMessage))
|
|
||||||
}
|
|
||||||
|
|
||||||
var isExcludedFromChatList = false
|
|
||||||
for chat in chats {
|
|
||||||
if chat.peerId == peerId {
|
|
||||||
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
|
|
||||||
if let group = groupOrChannel as? TelegramGroup {
|
|
||||||
if group.flags.contains(.deactivated) {
|
|
||||||
isExcludedFromChatList = true
|
|
||||||
} else {
|
|
||||||
switch group.membership {
|
|
||||||
case .Member:
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
isExcludedFromChatList = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if let channel = groupOrChannel as? TelegramChannel {
|
|
||||||
switch channel.participationStatus {
|
|
||||||
case .member:
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
isExcludedFromChatList = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isExcludedFromChatList {
|
|
||||||
let groupId = PeerGroupId(rawValue: folderId ?? 0)
|
|
||||||
let currentInclusion = transaction.getPeerChatListInclusion(peerId)
|
|
||||||
var currentPinningIndex: UInt16?
|
|
||||||
var currentMinTimestamp: Int32?
|
|
||||||
switch currentInclusion {
|
|
||||||
case let .ifHasMessagesOrOneOf(currentGroupId, pinningIndex, minTimestamp):
|
|
||||||
if currentGroupId == groupId {
|
|
||||||
currentPinningIndex = pinningIndex
|
|
||||||
}
|
|
||||||
currentMinTimestamp = minTimestamp
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessagesOrOneOf(groupId: groupId, pinningIndex: currentPinningIndex, minTimestamp: currentMinTimestamp))
|
|
||||||
}
|
|
||||||
|
|
||||||
notificationSettings[peer.peerId] = TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
|
||||||
|
|
||||||
transaction.resetIncomingReadStates([peerId: [Namespaces.Message.Cloud: .idBased(maxIncomingReadId: readInboxMaxId, maxOutgoingReadId: readOutboxMaxId, maxKnownId: topMessage, count: unreadCount, markedUnread: false)]])
|
|
||||||
|
|
||||||
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)
|
|
||||||
transaction.setPeerChatState(peerId, state: channelState)
|
|
||||||
channelStates[peer.peerId] = channelState
|
|
||||||
}
|
|
||||||
case .dialogFolder:
|
|
||||||
assertionFailure()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var storeMessages: [StoreMessage] = []
|
|
||||||
for message in messages {
|
|
||||||
if let storeMessage = StoreMessage(apiMessage: message) {
|
|
||||||
var updatedStoreMessage = storeMessage
|
|
||||||
if case let .Id(id) = storeMessage.id {
|
|
||||||
if let channelState = channelStates[id.peerId] {
|
|
||||||
var updatedAttributes = storeMessage.attributes
|
|
||||||
updatedAttributes.append(ChannelMessageStateVersionAttribute(pts: channelState.pts))
|
|
||||||
updatedStoreMessage = updatedStoreMessage.withUpdatedAttributes(updatedAttributes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeMessages.append(updatedStoreMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for message in storeMessages {
|
|
||||||
if case let .Id(id) = message.id {
|
|
||||||
let _ = transaction.addMessages([message], location: topMessageIds.contains(id) ? .UpperHistoryBlock : .Random)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in
|
|
||||||
return updated
|
|
||||||
})
|
|
||||||
|
|
||||||
updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences)
|
|
||||||
|
|
||||||
transaction.updateCurrentPeerNotificationSettings(notificationSettings)
|
|
||||||
}
|
|
||||||
|> ignoreValues
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user