Folder improvements

This commit is contained in:
Ali
2020-03-20 15:18:57 +04:00
parent ceccb98af7
commit 752fb745d3
7 changed files with 214 additions and 12 deletions

View File

@@ -1796,8 +1796,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
}
} else {
let groupId = self.groupId
let filterPredicate = (self.chatListDisplayNode.containerNode.currentItemNode.chatListFilter?.data).flatMap(chatListFilterPredicate)
signal = self.context.account.postbox.transaction { transaction -> Void in
let filterPredicate = (self.chatListDisplayNode.containerNode.currentItemNode.chatListFilter?.data).flatMap(chatListFilterPredicate)
markAllChatsAsReadInteractively(transaction: transaction, viewTracker: context.account.viewTracker, groupId: groupId, filterPredicate: filterPredicate)
if let filterPredicate = filterPredicate {
for additionalGroupId in filterPredicate.includeAdditionalPeerGroupIds {

View File

@@ -341,7 +341,7 @@ private final class ChatListContainerItemNode: ASDisplayNode {
if strongSelf.emptyShimmerEffectNode == nil {
let emptyShimmerEffectNode = ChatListShimmerNode()
strongSelf.emptyShimmerEffectNode = emptyShimmerEffectNode
strongSelf.addSubnode(emptyShimmerEffectNode)
strongSelf.insertSubnode(emptyShimmerEffectNode, belowSubnode: strongSelf.listNode)
if let (size, insets, _) = strongSelf.validLayout, let offset = strongSelf.floatingHeaderOffset {
strongSelf.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: size, insets: insets, verticalOffset: offset, transition: .immediate)
}

View File

@@ -119,7 +119,7 @@ final class ChatListEmptyNode: ASDisplayNode {
let string = NSMutableAttributedString(string: self.isFilter ? strings.ChatList_EmptyChatListFilterTitle : strings.ChatList_EmptyChatList, font: Font.medium(17.0), textColor: theme.list.itemPrimaryTextColor)
let descriptionString: NSAttributedString
if self.isFilter {
descriptionString = NSAttributedString(string: strings.ChatList_EmptyChatListFilterText, font: Font.medium(14.0), textColor: theme.list.itemSecondaryTextColor)
descriptionString = NSAttributedString(string: strings.ChatList_EmptyChatListFilterText, font: Font.regular(14.0), textColor: theme.list.itemSecondaryTextColor)
} else {
descriptionString = NSAttributedString()
}

View File

@@ -283,6 +283,7 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
if view.laterIndex == nil && savedMessagesPeer == nil {
pinnedIndexOffset += UInt16(view.additionalItemEntries.count)
}
var filterAfterHole = false
loop: for entry in view.entries {
switch entry {
case let .MessageEntry(index, message, combinedReadState, isRemovedFromTotalUnreadCount, embeddedState, peer, peerPresence, summaryInfo, hasFailed, isContact):
@@ -301,8 +302,9 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
result.append(.PeerEntry(index: offsetPinnedIndex(index, offset: pinnedIndexOffset), presentationData: state.presentationData, message: updatedMessage, readState: updatedCombinedReadState, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, embeddedInterfaceState: embeddedState, peer: peer, presence: peerPresence, summaryInfo: summaryInfo, editing: state.editing, hasActiveRevealControls: index.messageIndex.id.peerId == state.peerIdWithRevealedOptions, selected: state.selectedPeerIds.contains(index.messageIndex.id.peerId), inputActivities: state.peerInputActivities?.activities[index.messageIndex.id.peerId], isAd: false, hasFailedMessages: hasFailed, isContact: isContact))
case let .HoleEntry(hole):
if hole.index.timestamp == Int32.max - 1 {
return ([.HeaderEntry], true)
//return ([.HeaderEntry], true)
}
filterAfterHole = true
result.append(.HoleEntry(hole, theme: state.presentationData.theme))
}
}
@@ -352,10 +354,34 @@ func chatListNodeEntriesForView(_ view: ChatListView, state: ChatListNodeState,
}
}
var isLoading: Bool = false
if filterAfterHole {
var seenHole = false
for i in (0 ..< result.count).reversed() {
if seenHole {
result.remove(at: i)
} else {
switch result[i] {
case .HeaderEntry:
break
case .ArchiveIntro, .AdditionalCategory, .GroupReferenceEntry:
break
case .PeerEntry:
break
case .HoleEntry:
isLoading = true
seenHole = true
result.remove(at: i)
}
}
}
}
if result.count >= 1, case .HoleEntry = result[result.count - 1] {
return ([.HeaderEntry], true)
} else if result.count == 1, case .HoleEntry = result[0] {
return ([.HeaderEntry], true)
}
return (result, false)
return (result, isLoading)
}

View File

@@ -262,7 +262,9 @@ final class ChatListTable: Table {
let messageTagSummaryResult = resolveChatListMessageTagSummaryResultCalculation(postbox: postbox, peerId: peer.id, calculation: filterPredicate.messageTagSummary)
if filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: messageTagSummaryResult) {
if filterPredicate.pinnedPeerIds.contains(peer.id) {
passFilter = true
} else if filterPredicate.includes(peer: peer, groupId: groupId, isRemovedFromTotalUnreadCount: isRemovedFromTotalUnreadCount, isUnread: isUnread, isContact: isContact, messageTagSummaryResult: messageTagSummaryResult) {
passFilter = true
} else {
passFilter = false

View File

@@ -1488,7 +1488,7 @@ private func resolveMissingPeerChatInfos(network: Network, state: AccountMutable
var updatedState = state
switch result {
case let .peerDialogs(dialogs, messages, chats, users, state):
case let .peerDialogs(dialogs, messages, chats, users, _):
updatedState.mergeChats(chats)
updatedState.mergeUsers(users)
@@ -1496,7 +1496,7 @@ private func resolveMissingPeerChatInfos(network: Network, state: AccountMutable
for dialog in dialogs {
switch dialog {
case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, notifySettings, pts, draft, folderId):
case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, notifySettings, pts, _, folderId):
let peerId = peer.peerId
updatedState.setNeedsHoleFromPreviousState(peerId: peerId, namespace: Namespaces.Message.Cloud)

View File

@@ -2,9 +2,12 @@ import Foundation
import Postbox
import SwiftSignalKit
import SyncCore
import TelegramApi
private final class ManagedChatListHolesState {
private var currentHole: (ChatListHolesEntry, Disposable)?
private var currentPinnedIds: (Set<PeerId>, Disposable)?
private var processedPinnedIds: Set<PeerId>?
func clearDisposables() -> [Disposable] {
if let (_, disposable) = self.currentHole {
@@ -15,9 +18,17 @@ private final class ManagedChatListHolesState {
}
}
func update(entries: [ChatListHolesEntry]) -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable]) {
func update(entries: [ChatListHolesEntry], pinnedIds: Set<PeerId>) -> (removed: [Disposable], added: [ChatListHolesEntry: MetaDisposable], addedPinnedIds: (Set<PeerId>, MetaDisposable)?) {
var removed: [Disposable] = []
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 !entries.contains(entry) {
@@ -32,7 +43,7 @@ private final class ManagedChatListHolesState {
added[entry] = disposable
}
return (removed, added)
return (removed, added, addedPinnedIds)
}
}
@@ -50,7 +61,13 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee
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 {
for filter in filtersState.filters {
pinnedIds.formUnion(filter.data.includePeers.pinnedPeers)
}
if let topRootHole = combinedView.views[topRootHoleKey] as? AllChatListHolesView, let hole = topRootHole.latestHole {
let entry = ChatListHolesEntry(groupId: .root, hole: hole)
if !entries.contains(entry) {
@@ -67,8 +84,8 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee
}
}
let (removed, added) = state.with { state in
return state.update(entries: entries)
let (removed, added, addedPinnedIds) = state.with { state in
return state.update(entries: entries, pinnedIds: pinnedIds)
}
for disposable in removed {
@@ -78,6 +95,22 @@ func managedChatListHoles(network: Network, postbox: Postbox, accountPeerId: Pee
for (entry, disposable) in added {
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 {
@@ -90,3 +123,144 @@ 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
}
}