diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/BUILD b/submodules/TelegramUI/Components/ShareWithPeersScreen/BUILD index 2655843936..3190b954b5 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/BUILD +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/BUILD @@ -37,6 +37,7 @@ swift_library( "//submodules/TelegramUI/Components/LottieComponent", "//submodules/TelegramUI/Components/SwitchComponent", "//submodules/TooltipUI", + "//submodules/OverlayStatusController", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift index fc6c5f9890..a4db8ab186 100644 --- a/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift +++ b/submodules/TelegramUI/Components/ShareWithPeersScreen/Sources/ShareWithPeersScreen.swift @@ -22,6 +22,7 @@ import LocalizedPeerData import PeerListItemComponent import LottieComponent import TooltipUI +import OverlayStatusController final class ShareWithPeersScreenComponent: Component { typealias EnvironmentType = ViewControllerComponentContainer.Environment @@ -561,6 +562,7 @@ final class ShareWithPeersScreenComponent: Component { controller.present(tooltipScreen, in: .window(.root)) } + private weak var progressController: ViewController? private func toggleGroupPeer(_ peer: EnginePeer) { guard let component = self.component, let environment = self.environment, let controller = self.environment?.controller() else { return @@ -604,11 +606,33 @@ final class ShareWithPeersScreenComponent: Component { append = true } + let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme) + let progressSignal = Signal { [weak self, weak controller] subscriber in + let progressController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) + controller?.present(progressController, in: .window(.root)) + + self?.progressController = progressController + + return ActionDisposable { [weak progressController, weak self] in + Queue.mainQueue().async() { + progressController?.dismiss() + + self?.progressController = nil + } + } + } + |> runOn(Queue.mainQueue()) + |> delay(0.15, queue: Queue.mainQueue()) + let progressDisposable = progressSignal.start() + let processPeers: ([EnginePeer]) -> Void = { [weak self] peers in guard let self else { return } + progressDisposable.dispose() + + var peerIds = Set() for peer in peers { self.peersMap[peer.id] = peer @@ -635,7 +659,7 @@ final class ShareWithPeersScreenComponent: Component { let transition = Transition(animation: .curve(duration: 0.35, curve: .spring)) self.state?.updated(transition: transition) } - + let context = component.context if peer.id.namespace == Namespaces.Peer.CloudGroup { let _ = (context.engine.data.subscribe( @@ -649,7 +673,13 @@ final class ShareWithPeersScreenComponent: Component { |> map { peers in var result: [EnginePeer] = [] for participant in participants { - if let peer = peers[participant.peerId], let peer, peer.id != context.account.peerId { + if let peer = peers[participant.peerId], let peer { + if peer.id == context.account.peerId { + continue + } + if case let .user(user) = peer, user.botInfo != nil { + continue + } result.append(peer) } } @@ -666,9 +696,15 @@ final class ShareWithPeersScreenComponent: Component { }) } else if peer.id.namespace == Namespaces.Peer.CloudChannel { let participants: Signal<[EnginePeer], NoError> = Signal { subscriber in - let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peer.id, requestUpdate: true, updated: { list in + let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peer.id, requestUpdate: true, count: 200, updated: { list in var peers: [EnginePeer] = [] for item in list.list { + if item.peer.id == context.account.peerId { + continue + } + if let user = item.peer as? TelegramUser, user.botInfo != nil { + continue + } peers.append(EnginePeer(item.peer)) } if !peers.isEmpty { @@ -2017,17 +2053,18 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { case .chats: self.stateDisposable = (combineLatest( context.engine.messages.chatList(group: .root, count: 200) |> take(1), - context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.List(includePresences: true)) + context.engine.data.get(TelegramEngine.EngineData.Item.Contacts.List(includePresences: true)), + context.engine.data.get(EngineDataMap(Array(self.initialPeerIds).map(TelegramEngine.EngineData.Item.Peer.Peer.init))) ) - |> mapToSignal { chatList, contacts -> Signal<(EngineChatList, EngineContactList, [EnginePeer.Id: Optional]), NoError> in + |> mapToSignal { chatList, contacts, initialPeers -> Signal<(EngineChatList, EngineContactList, [EnginePeer.Id: Optional], [EnginePeer.Id: Optional]), NoError> in return context.engine.data.subscribe( EngineDataMap(chatList.items.map(\.renderedPeer.peerId).map(TelegramEngine.EngineData.Item.Peer.ParticipantCount.init)) ) - |> map { participantCountMap -> (EngineChatList, EngineContactList, [EnginePeer.Id: Optional]) in - return (chatList, contacts, participantCountMap) + |> map { participantCountMap -> (EngineChatList, EngineContactList, [EnginePeer.Id: Optional], [EnginePeer.Id: Optional]) in + return (chatList, contacts, initialPeers, participantCountMap) } } - |> deliverOnMainQueue).start(next: { [weak self] chatList, contacts, participantCounts in + |> deliverOnMainQueue).start(next: { [weak self] chatList, contacts, initialPeers, participantCounts in guard let self else { return } @@ -2048,6 +2085,13 @@ public class ShareWithPeersScreen: ViewControllerComponentContainer { } } + for peerId in self.initialPeerIds { + if !existingIds.contains(peerId), let maybePeer = initialPeers[peerId], let peer = maybePeer { + selectedPeers.append(peer) + existingIds.insert(peerId) + } + } + var presences: [EnginePeer.Id: EnginePeer.Presence] = [:] for item in chatList.items { presences[item.renderedPeer.peerId] = item.presence diff --git a/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift b/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift index c68e194539..6d8b21210a 100644 --- a/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift +++ b/submodules/TemporaryCachedPeerDataManager/Sources/ChannelMemberCategoryListContext.swift @@ -108,6 +108,7 @@ private final class ChannelMemberSingleCategoryListContext: ChannelMemberCategor private let network: Network private let accountPeerId: PeerId private let peerId: PeerId + private let batchCount: Int32? private let category: ChannelMemberListCategory var listStateValue: ChannelMemberListState { @@ -153,12 +154,13 @@ private final class ChannelMemberSingleCategoryListContext: ChannelMemberCategor private var headUpdateTimer: SwiftSignalKit.Timer? - init(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, category: ChannelMemberListCategory) { + init(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, batchCount: Int32?, category: ChannelMemberListCategory) { self.engine = engine self.postbox = postbox self.network = network self.accountPeerId = accountPeerId self.peerId = peerId + self.batchCount = batchCount self.category = category self.listStateValue = ChannelMemberListState(list: [], peerStoryStats: [:], loadingState: .ready(hasMore: true)) @@ -183,9 +185,9 @@ private final class ChannelMemberSingleCategoryListContext: ChannelMemberCategor let loadCount: Int32 if case .ready(true) = self.listStateValue.loadingState, self.listStateValue.list.isEmpty { - loadCount = initialBatchSize + loadCount = self.batchCount ?? initialBatchSize } else { - loadCount = requestBatchSize + loadCount = self.batchCount ?? requestBatchSize } self.listStateValue.loadingState = .loading(initial: initial) @@ -201,8 +203,9 @@ private final class ChannelMemberSingleCategoryListContext: ChannelMemberCategor } else { var list = self.listStateValue.list var loadingState: ChannelMemberListLoadingState = .ready(hasMore: true) - if list.count > Int(initialBatchSize) && !force { - list.removeSubrange(Int(initialBatchSize) ..< list.count) + let batchSize = self.batchCount ?? initialBatchSize + if list.count > Int(batchSize) && !force { + list.removeSubrange(Int(batchSize) ..< list.count) loadingState = .ready(hasMore: true) } @@ -331,13 +334,13 @@ private final class ChannelMemberSingleCategoryListContext: ChannelMemberCategor } var acc: UInt64 = 0 - - for i in 0 ..< min(strongSelf.listStateValue.list.count, Int(initialBatchSize)) { + let batchSize = strongSelf.batchCount ?? initialBatchSize + for i in 0 ..< min(strongSelf.listStateValue.list.count, Int(batchSize)) { let peerId = strongSelf.listStateValue.list[i].peer.id combineInt64Hash(&acc, with: peerId) } let hashResult = finalizeInt64Hash(acc) - strongSelf.headUpdateDisposable.set((strongSelf.loadSignal(offset: 0, count: initialBatchSize, hash: hashResult) + strongSelf.headUpdateDisposable.set((strongSelf.loadSignal(offset: 0, count: batchSize, hash: hashResult) |> deliverOnMainQueue).start(next: { members in self?.updateHeadMembers(members) })) @@ -617,7 +620,7 @@ private final class ChannelMemberMultiCategoryListContext: ChannelMemberCategory init(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, categories: [ChannelMemberListCategory]) { self.contexts = categories.map { category in - return ChannelMemberSingleCategoryListContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, category: category) + return ChannelMemberSingleCategoryListContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, batchCount: nil, category: category) } } @@ -732,16 +735,18 @@ final class PeerChannelMemberCategoriesContext { private let network: Network private let accountPeerId: PeerId private let peerId: PeerId + private let batchCount: Int32? private var becameEmpty: (Bool) -> Void private var contexts: [PeerChannelMemberContextKey: PeerChannelMemberContextWithSubscribers] = [:] - init(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, becameEmpty: @escaping (Bool) -> Void) { + init(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, batchCount: Int32?, becameEmpty: @escaping (Bool) -> Void) { self.engine = engine self.postbox = postbox self.network = network self.accountPeerId = accountPeerId self.peerId = peerId + self.batchCount = batchCount self.becameEmpty = becameEmpty } @@ -786,13 +791,13 @@ final class PeerChannelMemberCategoriesContext { default: mappedCategory = .recent } - context = ChannelMemberSingleCategoryListContext(engine: self.engine, postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: self.peerId, category: mappedCategory) + context = ChannelMemberSingleCategoryListContext(engine: self.engine, postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: self.peerId, batchCount: self.batchCount, category: mappedCategory) case let .restrictedAndBanned(query): context = ChannelMemberMultiCategoryListContext(engine: self.engine, postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: self.peerId, categories: [.restricted(query), .banned(query)]) case let .restricted(query): - context = ChannelMemberSingleCategoryListContext(engine: self.engine, postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: self.peerId, category: .restricted(query)) + context = ChannelMemberSingleCategoryListContext(engine: self.engine, postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: self.peerId, batchCount: nil, category: .restricted(query)) case let .banned(query): - context = ChannelMemberSingleCategoryListContext(engine: self.engine, postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: self.peerId, category: .banned(query)) + context = ChannelMemberSingleCategoryListContext(engine: self.engine, postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: self.peerId, batchCount: nil, category: .banned(query)) } let contextWithSubscribers = PeerChannelMemberContextWithSubscribers(context: context, emptyTimeout: emptyTimeout, becameEmpty: { [weak self] in assert(Queue.mainQueue().isCurrent()) diff --git a/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift b/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift index a5b9b8513b..78ec00f3eb 100644 --- a/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift +++ b/submodules/TemporaryCachedPeerDataManager/Sources/PeerChannelMemberCategoriesContextsManager.swift @@ -56,12 +56,12 @@ private final class PeerChannelMemberCategoriesContextsManagerImpl { fileprivate var profileDataPreloadContexts: [PeerId: ProfileDataPreloadContext] = [:] fileprivate var profileDataPhotoPreloadContexts: [PeerId: ProfileDataPhotoPreloadContext] = [:] - func getContext(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, key: PeerChannelMemberContextKey, requestUpdate: Bool, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl) { + func getContext(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, key: PeerChannelMemberContextKey, requestUpdate: Bool, count: Int32? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl) { if let current = self.contexts[peerId] { return current.getContext(key: key, requestUpdate: requestUpdate, updated: updated) } else { var becameEmptyImpl: ((Bool) -> Void)? - let context = PeerChannelMemberCategoriesContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, becameEmpty: { value in + let context = PeerChannelMemberCategoriesContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, batchCount: count, becameEmpty: { value in becameEmptyImpl?(value) }) becameEmptyImpl = { [weak self, weak context] value in @@ -297,10 +297,10 @@ public final class PeerChannelMemberCategoriesContextsManager { } } - private func getContext(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, key: PeerChannelMemberContextKey, requestUpdate: Bool, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + private func getContext(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, key: PeerChannelMemberContextKey, requestUpdate: Bool, count: Int32? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { assert(Queue.mainQueue().isCurrent()) let (disposable, control) = self.impl.syncWith({ impl in - return impl.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, updated: updated) + return impl.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, count: count, updated: updated) }) return (disposable, control) } @@ -325,14 +325,14 @@ public final class PeerChannelMemberCategoriesContextsManager { } } - public func recent(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, requestUpdate: Bool = true, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { + public func recent(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, searchQuery: String? = nil, requestUpdate: Bool = true, count: Int32? = nil, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) { let key: PeerChannelMemberContextKey if let searchQuery = searchQuery { key = .recentSearch(searchQuery) } else { key = .recent } - return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, updated: updated) + return self.getContext(engine: engine, postbox: postbox, network: network, accountPeerId: accountPeerId, peerId: peerId, key: key, requestUpdate: requestUpdate, count: count, updated: updated) } public func mentions(engine: TelegramEngine, postbox: Postbox, network: Network, accountPeerId: PeerId, peerId: PeerId, threadMessageId: MessageId?, searchQuery: String? = nil, requestUpdate: Bool = true, updated: @escaping (ChannelMemberListState) -> Void) -> (Disposable, PeerChannelMemberCategoryControl?) {