mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Add peer categories in members lists
This commit is contained in:
parent
47f3dde265
commit
cc5de9372f
@ -7242,3 +7242,11 @@ Sorry for the inconvenience.";
|
||||
|
||||
"Conversation.CopyProtectionForwardingDisabledBot" = "Forwards from this bot are restricted";
|
||||
"Conversation.CopyProtectionSavingDisabledBot" = "Saving from this bot is restricted";
|
||||
|
||||
"Channel.ChannelSubscribersHeader" = "CHANNEL SUBSCRIBERS";
|
||||
|
||||
"Channel.Members.Contacts" = "CONTACTS IN THIS CHANNEL";
|
||||
"Channel.Members.Other" = "OTHERS SUBSCRIBERS";
|
||||
|
||||
"Group.Members.Contacts" = "CONTACTS IN THIS GROUP";
|
||||
"Group.Members.Other" = "OTHERS MEMBERS";
|
||||
|
@ -26,6 +26,7 @@ public enum ChatListSearchItemHeaderType {
|
||||
case activeVoiceChats
|
||||
case recentCalls
|
||||
case orImportIntoAnExistingGroup
|
||||
case subscribers
|
||||
|
||||
fileprivate func title(strings: PresentationStrings) -> String {
|
||||
switch self {
|
||||
@ -71,6 +72,8 @@ public enum ChatListSearchItemHeaderType {
|
||||
return strings.CallList_RecentCallsHeader
|
||||
case .orImportIntoAnExistingGroup:
|
||||
return strings.ChatList_HeaderImportIntoAnExistingGroup
|
||||
case .subscribers:
|
||||
return strings.Channel_ChannelSubscribersHeader
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,6 +121,8 @@ public enum ChatListSearchItemHeaderType {
|
||||
return .recentCalls
|
||||
case .orImportIntoAnExistingGroup:
|
||||
return .orImportIntoAnExistingGroup
|
||||
case .subscribers:
|
||||
return .subscribers
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -148,6 +153,7 @@ private enum ChatListSearchItemHeaderId: Int32 {
|
||||
case activeVoiceChats
|
||||
case recentCalls
|
||||
case orImportIntoAnExistingGroup
|
||||
case subscribers
|
||||
}
|
||||
|
||||
public final class ChatListSearchItemHeader: ListViewItemHeader {
|
||||
|
@ -36,6 +36,7 @@ private final class ChannelMembersControllerArguments {
|
||||
|
||||
private enum ChannelMembersSection: Int32 {
|
||||
case addMembers
|
||||
case contacts
|
||||
case peers
|
||||
}
|
||||
|
||||
@ -48,14 +49,20 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
case addMember(PresentationTheme, String)
|
||||
case addMemberInfo(PresentationTheme, String)
|
||||
case inviteLink(PresentationTheme, String)
|
||||
case peerItem(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, RenderedChannelParticipant, ItemListPeerItemEditing, Bool)
|
||||
case contactsTitle(PresentationTheme, String)
|
||||
case peersTitle(PresentationTheme, String)
|
||||
case peerItem(Int32, PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, RenderedChannelParticipant, ItemListPeerItemEditing, Bool, Bool)
|
||||
|
||||
var section: ItemListSectionId {
|
||||
switch self {
|
||||
case .addMember, .addMemberInfo, .inviteLink:
|
||||
return ChannelMembersSection.addMembers.rawValue
|
||||
case .peerItem:
|
||||
case .contactsTitle:
|
||||
return ChannelMembersSection.contacts.rawValue
|
||||
case .peersTitle:
|
||||
return ChannelMembersSection.peers.rawValue
|
||||
case let .peerItem(_, _, _, _, _, _, _, _, isContact):
|
||||
return isContact ? ChannelMembersSection.contacts.rawValue : ChannelMembersSection.peers.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,9 +72,13 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
return .index(0)
|
||||
case .addMemberInfo:
|
||||
return .index(1)
|
||||
case .inviteLink:
|
||||
return .index(2)
|
||||
case let .peerItem(_, _, _, _, _, participant, _, _):
|
||||
case .inviteLink:
|
||||
return .index(2)
|
||||
case .contactsTitle:
|
||||
return .index(3)
|
||||
case .peersTitle:
|
||||
return .index(4)
|
||||
case let .peerItem(_, _, _, _, _, participant, _, _, _):
|
||||
return .peer(participant.peer.id)
|
||||
}
|
||||
}
|
||||
@ -86,14 +97,26 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .inviteLink(lhsTheme, lhsText):
|
||||
if case let .inviteLink(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .peerItem(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameOrder, lhsParticipant, lhsEditing, lhsEnabled):
|
||||
if case let .peerItem(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameOrder, rhsParticipant, rhsEditing, rhsEnabled) = rhs {
|
||||
case let .inviteLink(lhsTheme, lhsText):
|
||||
if case let .inviteLink(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .contactsTitle(lhsTheme, lhsText):
|
||||
if case let .contactsTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .peersTitle(lhsTheme, lhsText):
|
||||
if case let .peersTitle(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .peerItem(lhsIndex, lhsTheme, lhsStrings, lhsDateTimeFormat, lhsNameOrder, lhsParticipant, lhsEditing, lhsEnabled, lhsIsContact):
|
||||
if case let .peerItem(rhsIndex, rhsTheme, rhsStrings, rhsDateTimeFormat, rhsNameOrder, rhsParticipant, rhsEditing, rhsEnabled, rhsIsContact) = rhs {
|
||||
if lhsIndex != rhsIndex {
|
||||
return false
|
||||
}
|
||||
@ -118,6 +141,9 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
if lhsEnabled != rhsEnabled {
|
||||
return false
|
||||
}
|
||||
if lhsIsContact != rhsIsContact {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -143,11 +169,30 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
default:
|
||||
return true
|
||||
}
|
||||
|
||||
case let .peerItem(index, _, _, _, _, _, _, _):
|
||||
case .contactsTitle:
|
||||
switch rhs {
|
||||
case let .peerItem(rhsIndex, _, _, _, _, _, _, _):
|
||||
return index < rhsIndex
|
||||
case .addMember, .addMemberInfo, .inviteLink:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case .peersTitle:
|
||||
switch rhs {
|
||||
case .addMember, .addMemberInfo, .inviteLink, .contactsTitle:
|
||||
return false
|
||||
case let .peerItem(_, _, _, _, _, _, _, _, isContact):
|
||||
return !isContact
|
||||
default:
|
||||
return true
|
||||
}
|
||||
case let .peerItem(lhsIndex, _, _, _, _, _, _, _, lhsIsContact):
|
||||
switch rhs {
|
||||
case .contactsTitle:
|
||||
return false
|
||||
case .peersTitle:
|
||||
return lhsIsContact
|
||||
case let .peerItem(rhsIndex, _, _, _, _, _, _, _, _):
|
||||
return lhsIndex < rhsIndex
|
||||
case .addMember, .addMemberInfo, .inviteLink:
|
||||
return false
|
||||
}
|
||||
@ -167,7 +212,9 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
})
|
||||
case let .addMemberInfo(_, text):
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .peerItem(_, _, strings, dateTimeFormat, nameDisplayOrder, participant, editing, enabled):
|
||||
case let .contactsTitle(_, text), let .peersTitle(_, text):
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .peerItem(_, _, strings, dateTimeFormat, nameDisplayOrder, participant, editing, enabled, _):
|
||||
let text: ItemListPeerItemText
|
||||
if let user = participant.peer as? TelegramUser, let _ = user.botInfo {
|
||||
text = .text(strings.Bot_GenericBotStatus, .secondary)
|
||||
@ -238,7 +285,7 @@ private struct ChannelMembersControllerState: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func channelMembersControllerEntries(context: AccountContext, presentationData: PresentationData, view: PeerView, state: ChannelMembersControllerState, participants: [RenderedChannelParticipant]?, isGroup: Bool) -> [ChannelMembersEntry] {
|
||||
private func channelMembersControllerEntries(context: AccountContext, presentationData: PresentationData, view: PeerView, state: ChannelMembersControllerState, contacts: [RenderedChannelParticipant]?, participants: [RenderedChannelParticipant]?, isGroup: Bool) -> [ChannelMembersEntry] {
|
||||
if participants == nil || participants?.count == nil {
|
||||
return []
|
||||
}
|
||||
@ -251,6 +298,11 @@ private func channelMembersControllerEntries(context: AccountContext, presentati
|
||||
canAddMember = peer.hasPermission(.inviteMembers)
|
||||
}
|
||||
|
||||
var canEditMembers = false
|
||||
if let peer = view.peers[view.peerId] as? TelegramChannel {
|
||||
canEditMembers = peer.hasPermission(.banMembers)
|
||||
}
|
||||
|
||||
if canAddMember {
|
||||
entries.append(.addMember(presentationData.theme, isGroup ? presentationData.strings.Group_Members_AddMembers : presentationData.strings.Channel_Members_AddMembers))
|
||||
if let peer = view.peers[view.peerId] as? TelegramChannel, peer.addressName == nil {
|
||||
@ -267,14 +319,44 @@ private func channelMembersControllerEntries(context: AccountContext, presentati
|
||||
|
||||
|
||||
var index: Int32 = 0
|
||||
let sortedParticipants = participants
|
||||
for participant in sortedParticipants {
|
||||
var editable = true
|
||||
var canEditMembers = false
|
||||
if let peer = view.peers[view.peerId] as? TelegramChannel {
|
||||
canEditMembers = peer.hasPermission(.banMembers)
|
||||
var existingPeerIds = Set<PeerId>()
|
||||
|
||||
var addedContactsHeader = false
|
||||
if let contacts = contacts, !contacts.isEmpty {
|
||||
addedContactsHeader = true
|
||||
|
||||
entries.append(.contactsTitle(presentationData.theme, isGroup ? presentationData.strings.Group_Members_Contacts : presentationData.strings.Channel_Members_Contacts))
|
||||
|
||||
for participant in contacts {
|
||||
var editable = true
|
||||
if participant.peer.id == context.account.peerId {
|
||||
editable = false
|
||||
} else {
|
||||
switch participant.participant {
|
||||
case .creator:
|
||||
editable = false
|
||||
case .member:
|
||||
editable = canEditMembers
|
||||
}
|
||||
}
|
||||
entries.append(.peerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, participant, ItemListPeerItemEditing(editable: editable, editing: state.editing, revealed: participant.peer.id == state.peerIdWithRevealedOptions), state.removingPeerId != participant.peer.id, true))
|
||||
existingPeerIds.insert(participant.peer.id)
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
|
||||
var addedOtherHeader = false
|
||||
for participant in participants {
|
||||
if existingPeerIds.contains(participant.peer.id) {
|
||||
continue
|
||||
}
|
||||
|
||||
if addedContactsHeader && !addedOtherHeader {
|
||||
addedOtherHeader = true
|
||||
entries.append(.peersTitle(presentationData.theme, isGroup ? presentationData.strings.Group_Members_Other : presentationData.strings.Channel_Members_Other))
|
||||
}
|
||||
|
||||
var editable = true
|
||||
if participant.peer.id == context.account.peerId {
|
||||
editable = false
|
||||
} else {
|
||||
@ -285,7 +367,7 @@ private func channelMembersControllerEntries(context: AccountContext, presentati
|
||||
editable = canEditMembers
|
||||
}
|
||||
}
|
||||
entries.append(.peerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, participant, ItemListPeerItemEditing(editable: editable, editing: state.editing, revealed: participant.peer.id == state.peerIdWithRevealedOptions), state.removingPeerId != participant.peer.id))
|
||||
entries.append(.peerItem(index, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, participant, ItemListPeerItemEditing(editable: editable, editing: state.editing, revealed: participant.peer.id == state.peerIdWithRevealedOptions), state.removingPeerId != participant.peer.id, false))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -315,6 +397,7 @@ public func channelMembersController(context: AccountContext, updatedPresentatio
|
||||
actionsDisposable.add(removePeerDisposable)
|
||||
|
||||
let peersPromise = Promise<[RenderedChannelParticipant]?>(nil)
|
||||
let contactsPromise = Promise<[RenderedChannelParticipant]?>(nil)
|
||||
|
||||
let arguments = ChannelMembersControllerArguments(context: context, addMember: {
|
||||
actionsDisposable.add((peersPromise.get()
|
||||
@ -437,17 +520,22 @@ public func channelMembersController(context: AccountContext, updatedPresentatio
|
||||
|
||||
let peerView = context.account.viewTracker.peerView(peerId)
|
||||
|
||||
let (contactsDisposable, _) = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: { state in
|
||||
contactsPromise.set(.single(state.list))
|
||||
})
|
||||
let (disposable, loadMoreControl) = context.peerChannelMemberCategoriesContextsManager.recent(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, updated: { state in
|
||||
peersPromise.set(.single(state.list))
|
||||
})
|
||||
actionsDisposable.add(disposable)
|
||||
actionsDisposable.add(contactsDisposable)
|
||||
|
||||
var previousPeers: [RenderedChannelParticipant]?
|
||||
var currentContacts: [RenderedChannelParticipant]?
|
||||
var currentPeers: [RenderedChannelParticipant]?
|
||||
|
||||
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
|
||||
let signal = combineLatest(queue: .mainQueue(), presentationData, statePromise.get(), peerView, peersPromise.get())
|
||||
let signal = combineLatest(queue: .mainQueue(), presentationData, statePromise.get(), peerView, contactsPromise.get(), peersPromise.get())
|
||||
|> deliverOnMainQueue
|
||||
|> map { presentationData, state, view, peers -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
|> map { presentationData, state, view, contacts, peers -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
var isGroup = true
|
||||
if let peer = peerViewMainPeer(view) as? TelegramChannel, case .broadcast = peer.info {
|
||||
isGroup = false
|
||||
@ -455,7 +543,14 @@ public func channelMembersController(context: AccountContext, updatedPresentatio
|
||||
|
||||
var rightNavigationButton: ItemListNavigationButton?
|
||||
var secondaryRightNavigationButton: ItemListNavigationButton?
|
||||
if let peers = peers, !peers.isEmpty {
|
||||
|
||||
var isEmpty = true
|
||||
if let contacts = contacts, !contacts.isEmpty {
|
||||
isEmpty = false
|
||||
} else if let peers = peers, !peers.isEmpty {
|
||||
isEmpty = false
|
||||
}
|
||||
if !isEmpty {
|
||||
if state.editing {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: {
|
||||
updateState { state in
|
||||
@ -497,15 +592,26 @@ public func channelMembersController(context: AccountContext, updatedPresentatio
|
||||
}
|
||||
|
||||
var emptyStateItem: ItemListControllerEmptyStateItem?
|
||||
if peers == nil || peers?.count == 0 {
|
||||
if isEmpty {
|
||||
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
|
||||
}
|
||||
|
||||
let previous = previousPeers
|
||||
previousPeers = peers
|
||||
let previousContacts = currentContacts
|
||||
currentContacts = contacts
|
||||
|
||||
let previousPeers = currentPeers
|
||||
currentPeers = peers
|
||||
|
||||
var animateChanges = false
|
||||
if let previousContacts = previousContacts, let contacts = contacts, previousContacts.count >= contacts.count {
|
||||
animateChanges = true
|
||||
}
|
||||
if let previousPeers = previousPeers, let peers = peers, previousPeers.count >= peers.count {
|
||||
animateChanges = true
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(isGroup ? presentationData.strings.Group_Members_Title : presentationData.strings.Channel_Subscribers_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelMembersControllerEntries(context: context, presentationData: presentationData, view: view, state: state, participants: peers, isGroup: isGroup), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && peers != nil && previous!.count >= peers!.count)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelMembersControllerEntries(context: context, presentationData: presentationData, view: view, state: state, contacts: contacts, participants: peers, isGroup: isGroup), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: animateChanges)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -38,14 +38,14 @@ private enum ChannelMembersSearchEntryId: Hashable {
|
||||
|
||||
private enum ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
case copyInviteLink
|
||||
case peer(Int, RenderedChannelParticipant, ContactsPeerItemEditing, String?, Bool)
|
||||
case peer(Int, RenderedChannelParticipant, ContactsPeerItemEditing, String?, Bool, Bool, Bool)
|
||||
case contact(Int, Peer, TelegramUserPresence?)
|
||||
|
||||
var stableId: ChannelMembersSearchEntryId {
|
||||
switch self {
|
||||
case .copyInviteLink:
|
||||
return .copyInviteLink
|
||||
case let .peer(_, participant, _, _, _):
|
||||
case let .peer(_, participant, _, _, _, _, _):
|
||||
return .peer(participant.peer.id)
|
||||
case let .contact(_, peer, _):
|
||||
return .contact(peer.id)
|
||||
@ -60,8 +60,8 @@ private enum ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .peer(lhsIndex, lhsParticipant, lhsEditing, lhsLabel, lhsEnabled):
|
||||
if case .peer(lhsIndex, lhsParticipant, lhsEditing, lhsLabel, lhsEnabled) = rhs {
|
||||
case let .peer(lhsIndex, lhsParticipant, lhsEditing, lhsLabel, lhsEnabled, lhsIsChannel, lhsIsContact):
|
||||
if case .peer(lhsIndex, lhsParticipant, lhsEditing, lhsLabel, lhsEnabled, lhsIsChannel, lhsIsContact) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
@ -92,10 +92,10 @@ private enum ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
case let .peer(lhsIndex, _, _, _, _):
|
||||
case let .peer(lhsIndex, _, _, _, _, _, _):
|
||||
if case .copyInviteLink = rhs {
|
||||
return false
|
||||
} else if case let .peer(rhsIndex, _, _, _, _) = rhs {
|
||||
} else if case let .peer(rhsIndex, _, _, _, _, _, _) = rhs {
|
||||
return lhsIndex < rhsIndex
|
||||
} else if case .contact = rhs {
|
||||
return true
|
||||
@ -127,7 +127,7 @@ private enum ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: presentationData.strings.VoiceChat_CopyInviteLink, icon: icon, clearHighlightAutomatically: true, header: nil, action: {
|
||||
interaction.copyInviteLink()
|
||||
})
|
||||
case let .peer(_, participant, editing, label, enabled):
|
||||
case let .peer(_, participant, editing, label, enabled, isChannel, isContact):
|
||||
let status: ContactsPeerItemStatus
|
||||
if let label = label {
|
||||
status = .custom(string: label, multiline: false)
|
||||
@ -138,7 +138,14 @@ private enum ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
status = .none
|
||||
}
|
||||
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: EnginePeer(participant.peer), chatPeer: nil), status: status, enabled: enabled, selection: .none, editing: editing, index: nil, header: ChatListSearchItemHeader(type: .groupMembers, theme: presentationData.theme, strings: presentationData.strings), action: { _ in
|
||||
let headerType: ChatListSearchItemHeaderType
|
||||
if isContact {
|
||||
headerType = .contacts
|
||||
} else {
|
||||
headerType = isChannel ? .subscribers : .groupMembers
|
||||
}
|
||||
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, context: context, peerMode: .peer, peer: .peer(peer: EnginePeer(participant.peer), chatPeer: nil), status: status, enabled: enabled, selection: .none, editing: editing, index: nil, header: ChatListSearchItemHeader(type: headerType, theme: presentationData.theme, strings: presentationData.strings), action: { _ in
|
||||
interaction.openPeer(participant.peer, participant)
|
||||
})
|
||||
case let .contact(_, peer, presence):
|
||||
@ -239,6 +246,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
let previousEntries = Atomic<[ChannelMembersSearchEntry]?>(value: nil)
|
||||
|
||||
let disposableAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?)
|
||||
let contactsDisposableAndLoadMoreControl: (Disposable, PeerChannelMemberCategoryControl?)?
|
||||
let additionalDisposable = MetaDisposable()
|
||||
|
||||
if peerId.namespace == Namespaces.Peer.CloudGroup {
|
||||
@ -398,7 +406,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
renderedParticipant = RenderedChannelParticipant(participant: .member(id: peer.id, invitedAt: 0, adminInfo: nil, banInfo: nil, rank: nil), peer: peer, peers: peers, presences: peerView.peerPresences)
|
||||
}
|
||||
|
||||
entries.append(.peer(index, renderedParticipant, ContactsPeerItemEditing(editable: false, editing: false, revealed: false), label, enabled))
|
||||
entries.append(.peer(index, renderedParticipant, ContactsPeerItemEditing(editable: false, editing: false, revealed: false), label, enabled, false, false))
|
||||
index += 1
|
||||
}
|
||||
|
||||
@ -420,6 +428,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
strongSelf.enqueueTransition(preparedTransition(from: previous, to: entries, context: context, presentationData: strongSelf.presentationData, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, interaction: interaction))
|
||||
})
|
||||
disposableAndLoadMoreControl = (disposable, nil)
|
||||
contactsDisposableAndLoadMoreControl = nil
|
||||
} else {
|
||||
let membersState = Promise<ChannelMemberListState>()
|
||||
|
||||
@ -427,19 +436,26 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
membersState.set(.single(state))
|
||||
})
|
||||
|
||||
let contactsState = Promise<ChannelMemberListState>()
|
||||
contactsDisposableAndLoadMoreControl = context.peerChannelMemberCategoriesContextsManager.contacts(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, searchQuery: nil, updated: { state in
|
||||
contactsState.set(.single(state))
|
||||
})
|
||||
|
||||
additionalDisposable.set((combineLatest(queue: .mainQueue(),
|
||||
membersState.get(),
|
||||
contactsState.get(),
|
||||
context.account.postbox.peerView(id: peerId),
|
||||
context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Contacts.List(includePresences: true)
|
||||
)
|
||||
).start(next: { [weak self] state, peerView, contactsView in
|
||||
).start(next: { [weak self] state, contactsState, peerView, contactsView in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var entries: [ChannelMembersSearchEntry] = []
|
||||
|
||||
var canInviteByLink = false
|
||||
var isChannel = false
|
||||
if let peer = peerViewMainPeer(peerView) {
|
||||
if !(peer.addressName?.isEmpty ?? true) {
|
||||
canInviteByLink = true
|
||||
@ -447,6 +463,9 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
if peer.flags.contains(.isCreator) || (peer.adminRights?.rights.contains(.canInviteUsers) == true) {
|
||||
canInviteByLink = true
|
||||
}
|
||||
if case .broadcast = peer.info {
|
||||
isChannel = true
|
||||
}
|
||||
} else if let peer = peer as? TelegramGroup {
|
||||
if case .creator = peer.role {
|
||||
canInviteByLink = true
|
||||
@ -456,6 +475,8 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
var index = 0
|
||||
var existingPeersIds = Set<PeerId>()
|
||||
if case .inviteToCall = mode, canInviteByLink, !filters.contains(where: { filter in
|
||||
if case .excludeNonMembers = filter {
|
||||
return true
|
||||
@ -464,18 +485,53 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
}
|
||||
}) {
|
||||
entries.append(.copyInviteLink)
|
||||
} else {
|
||||
contactsLoop: for participant in contactsState.list {
|
||||
if participant.peer.isDeleted {
|
||||
continue contactsLoop
|
||||
}
|
||||
|
||||
var label: String?
|
||||
var enabled = true
|
||||
for filter in filters {
|
||||
switch filter {
|
||||
case let .exclude(ids):
|
||||
if ids.contains(participant.peer.id) {
|
||||
continue contactsLoop
|
||||
}
|
||||
case let .disable(ids):
|
||||
if ids.contains(participant.peer.id) {
|
||||
enabled = false
|
||||
}
|
||||
case .excludeNonMembers:
|
||||
break
|
||||
case .excludeBots:
|
||||
if let user = participant.peer as? TelegramUser, user.botInfo != nil {
|
||||
continue contactsLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
if case .promote = mode, case .creator = participant.participant {
|
||||
label = strongSelf.presentationData.strings.Channel_Management_LabelOwner
|
||||
enabled = false
|
||||
}
|
||||
|
||||
entries.append(.peer(index, participant, ContactsPeerItemEditing(editable: false, editing: false, revealed: false), label, enabled, isChannel, true))
|
||||
index += 1
|
||||
|
||||
existingPeersIds.insert(participant.peer.id)
|
||||
}
|
||||
}
|
||||
|
||||
var index = 0
|
||||
participantsLoop: for participant in state.list {
|
||||
if participant.peer.isDeleted {
|
||||
if participant.peer.isDeleted || existingPeersIds.contains(participant.peer.id) {
|
||||
continue participantsLoop
|
||||
}
|
||||
|
||||
var label: String?
|
||||
var enabled = true
|
||||
switch mode {
|
||||
case .ban:
|
||||
case .ban, .promote:
|
||||
if participant.peer.id == context.account.peerId {
|
||||
continue participantsLoop
|
||||
}
|
||||
@ -497,29 +553,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
case .promote:
|
||||
if participant.peer.id == context.account.peerId {
|
||||
continue
|
||||
}
|
||||
for filter in filters {
|
||||
switch filter {
|
||||
case let .exclude(ids):
|
||||
if ids.contains(participant.peer.id) {
|
||||
continue participantsLoop
|
||||
}
|
||||
case let .disable(ids):
|
||||
if ids.contains(participant.peer.id) {
|
||||
enabled = false
|
||||
}
|
||||
case .excludeNonMembers:
|
||||
break
|
||||
case .excludeBots:
|
||||
if let user = participant.peer as? TelegramUser, user.botInfo != nil {
|
||||
continue participantsLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
if case .creator = participant.participant {
|
||||
if case .promote = mode, case .creator = participant.participant {
|
||||
label = strongSelf.presentationData.strings.Channel_Management_LabelOwner
|
||||
enabled = false
|
||||
}
|
||||
@ -549,7 +583,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
}
|
||||
entries.append(.peer(index, participant, ContactsPeerItemEditing(editable: false, editing: false, revealed: false), label, enabled))
|
||||
entries.append(.peer(index, participant, ContactsPeerItemEditing(editable: false, editing: false, revealed: false), label, enabled, isChannel, false))
|
||||
index += 1
|
||||
}
|
||||
|
||||
@ -575,6 +609,9 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
let combinedDisposable = DisposableSet()
|
||||
combinedDisposable.add(disposableAndLoadMoreControl.0)
|
||||
combinedDisposable.add(additionalDisposable)
|
||||
if let disposable = contactsDisposableAndLoadMoreControl?.0 {
|
||||
combinedDisposable.add(disposable)
|
||||
}
|
||||
|
||||
self.disposable = combinedDisposable
|
||||
self.listControl = disposableAndLoadMoreControl.1
|
||||
|
Loading…
x
Reference in New Issue
Block a user