mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Chat moderation improvements
This commit is contained in:
parent
c85315e756
commit
59f4ec2cdd
@ -165,6 +165,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
|
||||
public let peer: ContactsPeerItemPeer
|
||||
let status: ContactsPeerItemStatus
|
||||
let badge: ContactsPeerItemBadge?
|
||||
let rightLabelText: String?
|
||||
let requiresPremiumForMessaging: Bool
|
||||
let enabled: Bool
|
||||
let selection: ContactsPeerItemSelection
|
||||
@ -202,6 +203,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
|
||||
peer: ContactsPeerItemPeer,
|
||||
status: ContactsPeerItemStatus,
|
||||
badge: ContactsPeerItemBadge? = nil,
|
||||
rightLabelText: String? = nil,
|
||||
requiresPremiumForMessaging: Bool = false,
|
||||
enabled: Bool,
|
||||
selection: ContactsPeerItemSelection,
|
||||
@ -233,6 +235,7 @@ public class ContactsPeerItem: ItemListItem, ListViewItemWithHeader {
|
||||
self.peer = peer
|
||||
self.status = status
|
||||
self.badge = badge
|
||||
self.rightLabelText = rightLabelText
|
||||
self.requiresPremiumForMessaging = requiresPremiumForMessaging
|
||||
self.enabled = enabled
|
||||
self.selection = selection
|
||||
@ -421,6 +424,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
private var actionButtonNodes: [HighlightableButtonNode]?
|
||||
private var moreButtonNode: MoreButtonNode?
|
||||
private var arrowButtonNode: HighlightableButtonNode?
|
||||
private var rightLabelTextNode: TextNode?
|
||||
|
||||
private var avatarTapRecognizer: UITapGestureRecognizer?
|
||||
|
||||
@ -579,6 +583,10 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateFrame(node: strongSelf.extractedBackgroundImageNode, frame: rect)
|
||||
}
|
||||
|
||||
if let rightLabelTextNode = strongSelf.rightLabelTextNode {
|
||||
transition.updateTransform(node: rightLabelTextNode, transform: CGAffineTransformMakeTranslation(isExtracted ? -24.0 : 0.0, 0.0))
|
||||
}
|
||||
|
||||
transition.updateSublayerTransformOffset(layer: strongSelf.offsetContainerNode.layer, offset: CGPoint(x: isExtracted ? 12.0 : 0.0, y: 0.0))
|
||||
transition.updateAlpha(node: strongSelf.extractedBackgroundImageNode, alpha: isExtracted ? 1.0 : 0.0, completion: { _ in
|
||||
if !isExtracted {
|
||||
@ -588,6 +596,20 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.updateEnableGestures()
|
||||
}
|
||||
|
||||
private func updateEnableGestures() {
|
||||
if let item = self.layoutParams?.0, !item.options.isEmpty {
|
||||
self.view.disablesInteractiveTransitionGestureRecognizer = false
|
||||
} else {
|
||||
self.view.disablesInteractiveTransitionGestureRecognizer = false
|
||||
}
|
||||
}
|
||||
|
||||
public override func secondaryAction(at point: CGPoint) {
|
||||
guard let item = self.item, let contextAction = item.contextAction else {
|
||||
return
|
||||
@ -665,6 +687,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
let currentSelectionNode = self.selectionNode
|
||||
|
||||
let makeBadgeTextLayout = TextNode.asyncLayout(self.badgeTextNode)
|
||||
let makeRightLabelTextLayout = TextNode.asyncLayout(self.rightLabelTextNode)
|
||||
|
||||
let currentItem = self.layoutParams?.0
|
||||
|
||||
@ -712,6 +735,13 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
var rightLabelTextLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||
if let rightLabelText = item.rightLabelText {
|
||||
let rightLabelTextLayoutAndApplyValue = makeRightLabelTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: rightLabelText, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - 20.0, height: 100.0)))
|
||||
rightLabelTextLayoutAndApply = rightLabelTextLayoutAndApplyValue
|
||||
rightInset -= 6.0 + rightLabelTextLayoutAndApplyValue.0.size.width
|
||||
}
|
||||
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||
|
||||
var credibilityIcon: EmojiStatusComponent.Content?
|
||||
@ -1117,7 +1147,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
transition = .immediate
|
||||
}
|
||||
|
||||
let revealOffset = strongSelf.revealOffset
|
||||
let revealOffset: CGFloat = 0.0
|
||||
|
||||
if let _ = updatedTheme {
|
||||
switch item.style {
|
||||
@ -1479,6 +1509,28 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
if let (rightLabelTextLayout, rightLabelTextApply) = rightLabelTextLayoutAndApply {
|
||||
let rightLabelTextNode = rightLabelTextApply()
|
||||
var rightLabelTextTransition = transition
|
||||
if rightLabelTextNode !== strongSelf.rightLabelTextNode {
|
||||
strongSelf.rightLabelTextNode?.removeFromSupernode()
|
||||
strongSelf.rightLabelTextNode = rightLabelTextNode
|
||||
strongSelf.offsetContainerNode.addSubnode(rightLabelTextNode)
|
||||
rightLabelTextTransition = .immediate
|
||||
}
|
||||
|
||||
var rightLabelTextFrame = CGRect(x: revealOffset + params.width - params.rightInset - 8.0 - rightLabelTextLayout.size.width, y: floor((nodeLayout.contentSize.height - rightLabelTextLayout.size.height) / 2.0), width: rightLabelTextLayout.size.width, height: rightLabelTextLayout.size.height)
|
||||
if let arrowButtonImage = arrowButtonImage {
|
||||
rightLabelTextFrame.origin.x -= arrowButtonImage.size.width + 6.0
|
||||
}
|
||||
|
||||
rightLabelTextNode.bounds = CGRect(origin: CGPoint(), size: rightLabelTextFrame.size)
|
||||
rightLabelTextTransition.updatePosition(node: rightLabelTextNode, position: rightLabelTextFrame.center)
|
||||
} else if let rightLabelTextNode = strongSelf.rightLabelTextNode {
|
||||
strongSelf.rightLabelTextNode = nil
|
||||
rightLabelTextNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
if let updatedSelectionNode = updatedSelectionNode {
|
||||
let hadSelectionNode = strongSelf.selectionNode != nil
|
||||
if strongSelf.selectionNode !== updatedSelectionNode {
|
||||
@ -1533,6 +1585,8 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.setRevealOptions((left: [], right: peerRevealOptions))
|
||||
strongSelf.setRevealOptionsOpened(item.editing.revealed, animated: animated)
|
||||
}
|
||||
|
||||
strongSelf.updateEnableGestures()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -1553,57 +1607,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
override public func updateRevealOffset(offset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
super.updateRevealOffset(offset: offset, transition: transition)
|
||||
|
||||
if let item = self.item, let params = self.layoutParams?.1 {
|
||||
var leftInset: CGFloat = 65.0 + params.leftInset
|
||||
|
||||
switch item.selection {
|
||||
case .none:
|
||||
break
|
||||
case .selectable:
|
||||
leftInset += 28.0
|
||||
}
|
||||
|
||||
var avatarFrame = self.avatarNode.frame
|
||||
avatarFrame.origin.x = offset + leftInset - 50.0
|
||||
transition.updateFrame(node: self.avatarNode, frame: avatarFrame)
|
||||
|
||||
var titleFrame = self.titleNode.frame
|
||||
titleFrame.origin.x = leftInset + offset
|
||||
transition.updateFrame(node: self.titleNode, frame: titleFrame)
|
||||
|
||||
var statusFrame = self.statusNode.frame
|
||||
let previousStatusFrame = statusFrame
|
||||
statusFrame.origin.x = leftInset + offset
|
||||
if let statusIconImage = self.statusIconNode?.image {
|
||||
statusFrame.origin.x += statusIconImage.size.width + 1.0
|
||||
}
|
||||
self.statusNode.frame = statusFrame
|
||||
transition.animatePositionAdditive(node: self.statusNode, offset: CGPoint(x: previousStatusFrame.minX - statusFrame.minX, y: 0))
|
||||
|
||||
var nextIconX = titleFrame.maxX
|
||||
if let credibilityIconView = self.credibilityIconView {
|
||||
var iconFrame = credibilityIconView.frame
|
||||
iconFrame.origin.x = nextIconX + 4.0
|
||||
nextIconX += 4.0 + iconFrame.width
|
||||
transition.updateFrame(view: credibilityIconView, frame: iconFrame)
|
||||
}
|
||||
if let verifiedIconView = self.verifiedIconView {
|
||||
var iconFrame = verifiedIconView.frame
|
||||
iconFrame.origin.x = nextIconX + 4.0
|
||||
nextIconX += 4.0 + iconFrame.width
|
||||
transition.updateFrame(view: verifiedIconView, frame: iconFrame)
|
||||
}
|
||||
|
||||
if let badgeBackgroundNode = self.badgeBackgroundNode, let badgeTextNode = self.badgeTextNode {
|
||||
var badgeBackgroundFrame = badgeBackgroundNode.frame
|
||||
badgeBackgroundFrame.origin.x = offset + params.width - params.rightInset - badgeBackgroundFrame.width - 6.0
|
||||
var badgeTextFrame = badgeTextNode.frame
|
||||
badgeTextFrame.origin.x = badgeBackgroundFrame.midX - badgeTextFrame.width / 2.0
|
||||
|
||||
transition.updateFrame(node: badgeBackgroundNode, frame: badgeBackgroundFrame)
|
||||
transition.updateFrame(node: badgeTextNode, frame: badgeTextFrame)
|
||||
}
|
||||
}
|
||||
var offsetContainerBounds = self.offsetContainerNode.bounds
|
||||
offsetContainerBounds.origin.x = -offset
|
||||
transition.updateBounds(node: self.offsetContainerNode, bounds: offsetContainerBounds)
|
||||
}
|
||||
|
||||
override public func revealOptionsInteractivelyOpened() {
|
||||
|
@ -616,6 +616,10 @@ private final class AdminUserActionsSheetComponent: Component {
|
||||
canBanEveryone = false
|
||||
continue
|
||||
}
|
||||
if let banInfo = peer.participant.banInfo, !banInfo.isMember {
|
||||
canBanEveryone = false
|
||||
continue
|
||||
}
|
||||
|
||||
switch peer.participant {
|
||||
case .creator:
|
||||
|
@ -144,6 +144,7 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/Settings/BirthdayPickerScreen",
|
||||
"//submodules/TelegramUI/Components/Settings/PeerSelectionScreen",
|
||||
"//submodules/ConfettiEffect",
|
||||
"//submodules/ContactsPeerItem",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -14,6 +14,7 @@ import MergeLists
|
||||
import ItemListUI
|
||||
import PeerInfoVisualMediaPaneNode
|
||||
import PeerInfoPaneNode
|
||||
import ContactsPeerItem
|
||||
|
||||
private struct PeerMembersListTransaction {
|
||||
let deletions: [ListViewDeleteItem]
|
||||
@ -84,7 +85,7 @@ private enum PeerMembersListEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
func item(context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) -> ListViewItem {
|
||||
func item(context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void, contextAction: ((PeerInfoMember, ASDisplayNode, ContextGesture?) -> Void)?) -> ListViewItem {
|
||||
switch self {
|
||||
case let .addMember(_, text):
|
||||
return ItemListPeerActionItem(presentationData: ItemListPresentationData(presentationData), icon: PresentationResourcesItemList.addPersonIcon(presentationData.theme), title: text, alwaysPlain: true, sectionId: 0, height: .compactPeerList, color: .accent, editing: false, action: {
|
||||
@ -123,24 +124,104 @@ private enum PeerMembersListEntry: Comparable, Identifiable {
|
||||
action(member, .remove)
|
||||
}))
|
||||
}
|
||||
|
||||
let presence: EnginePeer.Presence
|
||||
if member.peer.id == context.account.peerId {
|
||||
presence = EnginePeer.Presence(status: .present(until: Int32.max), lastActivity: 0)
|
||||
} else if let value = member.presence {
|
||||
presence = EnginePeer.Presence(value)
|
||||
} else {
|
||||
presence = EnginePeer.Presence(status: .longTimeAgo, lastActivity: 0)
|
||||
}
|
||||
|
||||
return ContactsPeerItem(
|
||||
presentationData: ItemListPresentationData(presentationData),
|
||||
style: .plain,
|
||||
sectionId: 0,
|
||||
sortOrder: presentationData.nameSortOrder,
|
||||
displayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
peerMode: .peer,
|
||||
peer: .peer(peer: EnginePeer(member.peer), chatPeer: EnginePeer(member.peer)),
|
||||
status: .presence(presence, presentationData.dateTimeFormat),
|
||||
rightLabelText: label,
|
||||
enabled: true,
|
||||
selection: .none,
|
||||
editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false),
|
||||
options: options,
|
||||
additionalActions: [],
|
||||
actionIcon: .none,
|
||||
index: nil,
|
||||
header: nil,
|
||||
action: { _ in
|
||||
action(member, .open)
|
||||
},
|
||||
disabledAction: nil,
|
||||
setPeerIdWithRevealedOptions: { _, _ in
|
||||
},
|
||||
deletePeer: nil,
|
||||
itemHighlighting: nil,
|
||||
contextAction: contextAction == nil ? nil : { node, gesture, _ in
|
||||
contextAction?(member, node, gesture)
|
||||
},
|
||||
animationCache: context.animationCache,
|
||||
animationRenderer: context.animationRenderer,
|
||||
storyStats: member.storyStats.flatMap { storyStats in
|
||||
return (
|
||||
total: storyStats.totalCount,
|
||||
unseen: storyStats.unseenCount,
|
||||
hasUnseenCloseFriends: storyStats.hasUnseenCloseFriends
|
||||
)
|
||||
},
|
||||
openStories: { _, sourceNode in
|
||||
action(member, .openStories(sourceView: sourceNode.view))
|
||||
}
|
||||
)
|
||||
|
||||
return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: EnginePeer(member.peer), presence: member.presence.flatMap(EnginePeer.Presence.init), text: .presence, label: label == nil ? .none : .text(label!, .standard), editing: ItemListPeerItemEditing(editable: !options.isEmpty, editing: false, revealed: false), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, selectable: member.id != context.account.peerId, sectionId: 0, action: {
|
||||
action(member, .open)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in
|
||||
}, removePeer: { _ in
|
||||
}, contextAction: nil, hasTopStripe: false, noInsets: true, noCorners: true, disableInteractiveTransitionIfNecessary: true, storyStats: member.storyStats, openStories: { sourceView in
|
||||
action(member, .openStories(sourceView: sourceView))
|
||||
})
|
||||
/*return ItemListPeerItem(
|
||||
presentationData: ItemListPresentationData(presentationData),
|
||||
dateTimeFormat: presentationData.dateTimeFormat,
|
||||
nameDisplayOrder: presentationData.nameDisplayOrder,
|
||||
context: context,
|
||||
peer: EnginePeer(member.peer),
|
||||
presence: member.presence.flatMap(EnginePeer.Presence.init),
|
||||
text: .presence,
|
||||
label: label == nil ? .none : .text(label!, .standard),
|
||||
editing: ItemListPeerItemEditing(editable: !options.isEmpty, editing: false, revealed: false),
|
||||
revealOptions: ItemListPeerItemRevealOptions(options: options),
|
||||
switchValue: nil,
|
||||
enabled: true,
|
||||
selectable: member.id != context.account.peerId,
|
||||
sectionId: 0,
|
||||
action: {
|
||||
action(member, .open)
|
||||
},
|
||||
setPeerIdWithRevealedOptions: { _, _ in
|
||||
},
|
||||
removePeer: { _ in
|
||||
},
|
||||
contextAction: contextAction == nil ? nil : { node, gesture in
|
||||
contextAction?(member, node, gesture)
|
||||
},
|
||||
hasTopStripe: false,
|
||||
noInsets: true,
|
||||
noCorners: true,
|
||||
disableInteractiveTransitionIfNecessary: true,
|
||||
storyStats: member.storyStats,
|
||||
openStories: { sourceView in
|
||||
action(member, .openStories(sourceView: sourceView))
|
||||
}
|
||||
)*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func preparedTransition(from fromEntries: [PeerMembersListEntry], to toEntries: [PeerMembersListEntry], context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) -> PeerMembersListTransaction {
|
||||
private func preparedTransition(from fromEntries: [PeerMembersListEntry], to toEntries: [PeerMembersListEntry], context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void, contextAction: ((PeerInfoMember, ASDisplayNode, ContextGesture?) -> Void)?) -> PeerMembersListTransaction {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: addMemberAction, action: action), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: addMemberAction, action: action), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: addMemberAction, action: action, contextAction: contextAction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: addMemberAction, action: action, contextAction: contextAction), directionHint: nil) }
|
||||
|
||||
return PeerMembersListTransaction(deletions: deletions, insertions: insertions, updates: updates, animated: toEntries.count < fromEntries.count)
|
||||
}
|
||||
@ -276,7 +357,79 @@ final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||
let transaction = preparedTransition(from: self.currentEntries, to: entries, context: self.context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: { [weak self] in
|
||||
self?.addMemberAction()
|
||||
}, action: { [weak self] member, action in
|
||||
self?.action(member, action)
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
if case .open = action {
|
||||
self.listNode.clearHighlightAnimated(true)
|
||||
}
|
||||
|
||||
self.action(member, action)
|
||||
}, contextAction: { [weak self] member, sourceNode, gesture in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
var node: ContextExtractedContentContainingNode?
|
||||
if let sourceNode = sourceNode as? ContextExtractedContentContainingNode {
|
||||
node = sourceNode
|
||||
} else {
|
||||
for subnode in sourceNode.subnodes ?? [] {
|
||||
if let subnode = subnode as? ContextExtractedContentContainingNode {
|
||||
node = subnode
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
guard let node else {
|
||||
gesture?.cancel()
|
||||
return
|
||||
}
|
||||
|
||||
let actions = availableActionsForMemberOfPeer(accountPeerId: self.context.account.peerId, peer: enclosingPeer, member: member)
|
||||
|
||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
var items: [ContextMenuItem] = []
|
||||
let action = self.action
|
||||
|
||||
if actions.contains(.promote) && enclosingPeer is TelegramChannel {
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.GroupInfo_ActionPromote, icon: { _ in
|
||||
return nil
|
||||
}, action: { c, _ in
|
||||
c.dismiss(completion: {
|
||||
action(member, .promote)
|
||||
})
|
||||
})))
|
||||
}
|
||||
if actions.contains(.restrict) {
|
||||
if enclosingPeer is TelegramChannel {
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.GroupInfo_ActionRestrict, icon: { _ in
|
||||
return nil
|
||||
}, action: { c, _ in
|
||||
c.dismiss(completion: {
|
||||
action(member, .restrict)
|
||||
})
|
||||
})))
|
||||
}
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Common_Delete, textColor: .destructive, icon: { _ in
|
||||
return nil
|
||||
}, action: { c, _ in
|
||||
c.dismiss(completion: {
|
||||
action(member, .remove)
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
if items.isEmpty {
|
||||
gesture?.cancel()
|
||||
return
|
||||
}
|
||||
|
||||
let dismissPromise = ValuePromise<Bool>(false)
|
||||
let source = PeerInfoMemberExtractedContentSource(sourceNode: node, keepInPlace: false, blurBackground: true, centerVertically: false, shouldBeDismissed: dismissPromise.get())
|
||||
|
||||
let contextController = ContextController(presentationData: presentationData, source: .extracted(source), items: .single(ContextController.Items(content: .list(items))), gesture: gesture)
|
||||
self.parentController?.presentInGlobalOverlay(contextController)
|
||||
})
|
||||
self.enclosingPeer = enclosingPeer
|
||||
self.currentEntries = entries
|
||||
@ -335,3 +488,30 @@ final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||
func updateSelectedMessages(animated: Bool) {
|
||||
}
|
||||
}
|
||||
|
||||
final class PeerInfoMemberExtractedContentSource: ContextExtractedContentSource {
|
||||
var keepInPlace: Bool
|
||||
let ignoreContentTouches: Bool = false
|
||||
let blurBackground: Bool
|
||||
|
||||
private let sourceNode: ContextExtractedContentContainingNode
|
||||
|
||||
var centerVertically: Bool
|
||||
var shouldBeDismissed: Signal<Bool, NoError>
|
||||
|
||||
init(sourceNode: ContextExtractedContentContainingNode, keepInPlace: Bool, blurBackground: Bool, centerVertically: Bool, shouldBeDismissed: Signal<Bool, NoError>) {
|
||||
self.sourceNode = sourceNode
|
||||
self.keepInPlace = keepInPlace
|
||||
self.blurBackground = blurBackground
|
||||
self.centerVertically = centerVertically
|
||||
self.shouldBeDismissed = shouldBeDismissed
|
||||
}
|
||||
|
||||
func takeView() -> ContextControllerTakeViewInfo? {
|
||||
return ContextControllerTakeViewInfo(containingItem: .node(self.sourceNode), contentAreaInScreenSpace: UIScreen.main.bounds)
|
||||
}
|
||||
|
||||
func putBack() -> ContextControllerPutBackViewInfo? {
|
||||
return ContextControllerPutBackViewInfo(contentAreaInScreenSpace: UIScreen.main.bounds)
|
||||
}
|
||||
}
|
||||
|
@ -648,6 +648,12 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
||||
}
|
||||
return [.leftCenter, .rightCenter]
|
||||
}
|
||||
if case .members = currentPaneKey {
|
||||
if index == 0 {
|
||||
return .leftCenter
|
||||
}
|
||||
return [.leftCenter, .rightCenter]
|
||||
}
|
||||
if strongSelf.currentPane?.node.navigationContentNode != nil {
|
||||
return []
|
||||
}
|
||||
|
@ -28,6 +28,9 @@ extension ChatControllerImpl {
|
||||
|
||||
//TODO:localize
|
||||
var title: String? = messageIds.count == 1 ? "Message Deleted" : "Messages Deleted"
|
||||
if !result.deleteAllFromPeers.isEmpty {
|
||||
title = "Messages Deleted"
|
||||
}
|
||||
var text: String = ""
|
||||
var undoRights: [EnginePeer.Id: InitialBannedRights] = [:]
|
||||
|
||||
@ -95,6 +98,9 @@ extension ChatControllerImpl {
|
||||
|
||||
if text.isEmpty {
|
||||
text = messageIds.count == 1 ? "Message Deleted." : "Messages Deleted."
|
||||
if !result.deleteAllFromPeers.isEmpty {
|
||||
text = "Messages Deleted."
|
||||
}
|
||||
title = nil
|
||||
}
|
||||
|
||||
@ -134,6 +140,9 @@ extension ChatControllerImpl {
|
||||
|
||||
var signal = combineLatest(authors.map { author in
|
||||
self.context.engine.peers.fetchChannelParticipant(peerId: peerId, participantId: author.id)
|
||||
|> map { result -> (Peer, ChannelParticipant?) in
|
||||
return (author, result)
|
||||
}
|
||||
})
|
||||
let disposables = MetaDisposable()
|
||||
self.navigationActionDisposable.set(disposables)
|
||||
@ -166,7 +175,7 @@ extension ChatControllerImpl {
|
||||
}
|
||||
|
||||
disposables.set((signal
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] participants in
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] authorsAndParticipants in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
@ -179,13 +188,23 @@ extension ChatControllerImpl {
|
||||
}
|
||||
var renderedParticipants: [RenderedChannelParticipant] = []
|
||||
var initialUserBannedRights: [EnginePeer.Id: InitialBannedRights] = [:]
|
||||
for maybeParticipant in participants {
|
||||
guard let participant = maybeParticipant else {
|
||||
continue
|
||||
}
|
||||
guard let peer = authors.first(where: { $0.id == participant.peerId }) else {
|
||||
continue
|
||||
for (author, maybeParticipant) in authorsAndParticipants {
|
||||
let participant: ChannelParticipant
|
||||
if let maybeParticipant {
|
||||
participant = maybeParticipant
|
||||
} else {
|
||||
participant = .member(id: author.id, invitedAt: 0, adminInfo: nil, banInfo: ChannelParticipantBannedInfo(
|
||||
rights: TelegramChatBannedRights(
|
||||
flags: [.banReadMessages],
|
||||
untilDate: Int32.max
|
||||
),
|
||||
restrictedBy: self.context.account.peerId,
|
||||
timestamp: 0,
|
||||
isMember: false
|
||||
), rank: nil)
|
||||
}
|
||||
|
||||
let peer = author
|
||||
renderedParticipants.append(RenderedChannelParticipant(
|
||||
participant: participant,
|
||||
peer: peer
|
||||
@ -254,10 +273,26 @@ extension ChatControllerImpl {
|
||||
}
|
||||
|
||||
disposables.set((signal
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] participant in
|
||||
guard let self, let participant else {
|
||||
|> deliverOnMainQueue).startStrict(next: { [weak self] maybeParticipant in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
let participant: ChannelParticipant
|
||||
if let maybeParticipant {
|
||||
participant = maybeParticipant
|
||||
} else {
|
||||
participant = .member(id: author.id, invitedAt: 0, adminInfo: nil, banInfo: ChannelParticipantBannedInfo(
|
||||
rights: TelegramChatBannedRights(
|
||||
flags: [.banReadMessages],
|
||||
untilDate: Int32.max
|
||||
),
|
||||
restrictedBy: self.context.account.peerId,
|
||||
timestamp: 0,
|
||||
isMember: false
|
||||
), rank: nil)
|
||||
}
|
||||
|
||||
let _ = (self.context.engine.data.get(
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: peerId),
|
||||
TelegramEngine.EngineData.Item.Peer.Peer(id: author.id)
|
||||
|
Loading…
x
Reference in New Issue
Block a user