Various Improvements

This commit is contained in:
Ilya Laktyushin 2021-11-24 11:43:48 +04:00
parent a76672896e
commit 45018fdd27
12 changed files with 216 additions and 44 deletions

View File

@ -147,11 +147,13 @@ public struct ChatAvailableMessageActions {
public var options: ChatAvailableMessageActionOptions
public var banAuthor: Peer?
public var disableDelete: Bool
public var isCopyProtected: Bool
public init(options: ChatAvailableMessageActionOptions, banAuthor: Peer?, disableDelete: Bool) {
public init(options: ChatAvailableMessageActionOptions, banAuthor: Peer?, disableDelete: Bool, isCopyProtected: Bool) {
self.options = options
self.banAuthor = banAuthor
self.disableDelete = disableDelete
self.isCopyProtected = isCopyProtected
}
}

View File

@ -115,6 +115,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
private var selectedFilterKeyPromise = Promise<ChatListSearchFilterEntryId?>()
private var transitionFraction: CGFloat = 0.0
private weak var copyProtectionTooltipController: TooltipController?
private var didSetReady: Bool = false
private let _ready = Promise<Void>()
public override func ready() -> Signal<Void, NoError> {
@ -417,6 +419,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
self.presentationDataDisposable?.dispose()
self.suggestedFiltersDisposable.dispose()
self.shareStatusDisposable?.dispose()
self.copyProtectionTooltipController?.dismiss()
}
private func updateState(_ f: (ChatListSearchContainerNodeSearchState) -> ChatListSearchContainerNodeSearchState) {
@ -588,6 +592,53 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
return
}
strongSelf.forwardMessages(messageIds: nil)
}, displayCopyProtectionTip: { [weak self] node, save in
guard let strongSelf = self, let messageIds = strongSelf.stateValue.selectedMessageIds, !messageIds.isEmpty else {
return
}
let _ = (strongSelf.context.account.postbox.transaction { transaction -> [EngineMessage] in
var messages: [EngineMessage] = []
for id in messageIds {
if let message = transaction.getMessage(id) {
messages.append(EngineMessage(message))
}
}
return messages
}
|> deliverOnMainQueue).start(next: { messages in
if let strongSelf = self, !messages.isEmpty {
var isChannel = false
for message in messages {
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info {
isChannel = true
break
}
}
let text: String
if save {
text = isChannel ? strongSelf.presentationData.strings.Conversation_CopyProtectionSavingDisabledChannel : strongSelf.presentationData.strings.Conversation_CopyProtectionSavingDisabledGroup
} else {
text = isChannel ? strongSelf.presentationData.strings.Conversation_CopyProtectionForwardingDisabledChannel : strongSelf.presentationData.strings.Conversation_CopyProtectionForwardingDisabledGroup
}
strongSelf.copyProtectionTooltipController?.dismiss()
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
strongSelf.copyProtectionTooltipController = tooltipController
tooltipController.dismissed = { [weak tooltipController] _ in
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.copyProtectionTooltipController === tooltipController {
strongSelf.copyProtectionTooltipController = nil
}
}
strongSelf.present?(tooltipController, TooltipControllerPresentationArguments(sourceNodeAndRect: {
if let strongSelf = self {
let rect = node.view.convert(node.view.bounds, to: strongSelf.view).offsetBy(dx: 0.0, dy: 3.0)
return (strongSelf, rect)
}
return nil
}))
}
})
})
selectionPanelNode.chatAvailableMessageActions = { [weak self] messageIds -> Signal<ChatAvailableMessageActions, NoError> in
guard let strongSelf = self else {

View File

@ -17,6 +17,7 @@ final class ChatListSearchMessageSelectionPanelNode: ASDisplayNode {
private let deleteMessages: () -> Void
private let shareMessages: () -> Void
private let forwardMessages: () -> Void
private let displayCopyProtectionTip: (ASDisplayNode, Bool) -> Void
private let separatorNode: ASDisplayNode
private let backgroundNode: NavigationBackgroundNode
@ -60,11 +61,12 @@ final class ChatListSearchMessageSelectionPanelNode: ASDisplayNode {
}
}
init(context: AccountContext, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void) {
init(context: AccountContext, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void, displayCopyProtectionTip: @escaping (ASDisplayNode, Bool) -> Void) {
self.context = context
self.deleteMessages = deleteMessages
self.shareMessages = shareMessages
self.forwardMessages = forwardMessages
self.displayCopyProtectionTip = displayCopyProtectionTip
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
self.theme = presentationData.theme
@ -102,8 +104,8 @@ final class ChatListSearchMessageSelectionPanelNode: ASDisplayNode {
self.addSubnode(self.separatorNode)
self.deleteButton.isEnabled = false
self.forwardButton.isEnabled = false
self.shareButton.isEnabled = false
self.forwardButton.isImplicitlyDisabled = true
self.shareButton.isImplicitlyDisabled = true
self.deleteButton.addTarget(self, action: #selector(self.deleteButtonPressed), forControlEvents: .touchUpInside)
self.forwardButton.addTarget(self, action: #selector(self.forwardButtonPressed), forControlEvents: .touchUpInside)
@ -144,15 +146,15 @@ final class ChatListSearchMessageSelectionPanelNode: ASDisplayNode {
if let actions = self.actions {
self.deleteButton.isEnabled = false
self.forwardButton.isEnabled = actions.options.contains(.forward)
self.shareButton.isEnabled = false
self.forwardButton.isImplicitlyDisabled = !actions.options.contains(.forward)
self.deleteButton.isEnabled = !actions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty
self.shareButton.isEnabled = !actions.options.intersection([.forward]).isEmpty
self.shareButton.isImplicitlyDisabled = actions.options.intersection([.forward]).isEmpty
} else {
self.deleteButton.isEnabled = false
self.forwardButton.isEnabled = false
self.shareButton.isEnabled = false
self.forwardButton.isImplicitlyDisabled = true
self.shareButton.isImplicitlyDisabled = true
}
self.deleteButton.frame = CGRect(origin: CGPoint(x: leftInset, y: 0.0), size: CGSize(width: 57.0, height: panelHeight))
@ -173,10 +175,18 @@ final class ChatListSearchMessageSelectionPanelNode: ASDisplayNode {
}
@objc func forwardButtonPressed() {
self.forwardMessages()
if let actions = self.actions, actions.isCopyProtected {
self.displayCopyProtectionTip(self.forwardButton, false)
} else {
self.forwardMessages()
}
}
@objc func shareButtonPressed() {
self.shareMessages()
if let actions = self.actions, actions.isCopyProtected {
self.displayCopyProtectionTip(self.shareButton, true)
} else {
self.shareMessages()
}
}
}

View File

@ -89,7 +89,7 @@ open class HighlightableButtonNode: HighlightTrackingButtonNode {
super.init(pointerStyle: pointerStyle)
self.highligthedChanged = { [weak self] highlighted in
if let strongSelf = self {
if let strongSelf = self, !strongSelf.isImplicitlyDisabled {
if highlighted {
strongSelf.layer.removeAnimation(forKey: "opacity")
strongSelf.alpha = 0.4

View File

@ -298,8 +298,9 @@ open class ASButtonNode: ASControlNode {
override open var isHighlighted: Bool {
didSet {
if self.isHighlighted != oldValue {
if self.isHighlighted {
if self.isHighlighted != oldValue && !self.isImplicitlyDisabled {
let isHighlighted = self.isHighlighted
if isHighlighted {
if self.highlightedTitleNode.attributedText != nil {
self.highlightedTitleNode.isHidden = false
self.titleNode.isHidden = true
@ -349,28 +350,42 @@ open class ASButtonNode: ASControlNode {
}
}
open var isImplicitlyDisabled: Bool = false {
didSet {
if self.isImplicitlyDisabled != oldValue {
self.updateIsEnabled()
}
}
}
override open var isEnabled: Bool {
didSet {
if self.isEnabled != oldValue {
if self.isEnabled || self.disabledTitleNode.attributedText == nil {
self.titleNode.isHidden = false
self.disabledTitleNode.isHidden = true
} else {
self.titleNode.isHidden = true
self.disabledTitleNode.isHidden = false
}
if self.isEnabled || self.disabledImageNode.image == nil {
self.imageNode.isHidden = false
self.disabledImageNode.isHidden = true
} else {
self.imageNode.isHidden = true
self.disabledImageNode.isHidden = false
}
self.updateIsEnabled()
}
}
}
private func updateIsEnabled() {
let isEnabled = self.isEnabled && !self.isImplicitlyDisabled
if isEnabled || self.disabledTitleNode.attributedText == nil {
self.titleNode.isHidden = false
self.disabledTitleNode.isHidden = true
} else {
self.titleNode.isHidden = true
self.disabledTitleNode.isHidden = false
}
if isEnabled || self.disabledImageNode.image == nil {
self.imageNode.isHidden = false
self.disabledImageNode.isHidden = true
} else {
self.imageNode.isHidden = true
self.disabledImageNode.isHidden = false
}
}
override open func layout() {
let size = self.bounds.size

View File

@ -411,6 +411,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
private weak var mediaRestrictedTooltipController: TooltipController?
private var mediaRestrictedTooltipControllerMode = true
private weak var checksTooltipController: TooltipController?
private weak var copyProtectionTooltipController: TooltipController?
private var currentMessageTooltipScreens: [(TooltipScreen, ListViewItemNode)] = []
@ -7685,6 +7686,37 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})
}, presentChatRequestAdminInfo: { [weak self] in
self?.presentChatRequestAdminInfo()
}, displayCopyProtectionTip: { [weak self] node, save in
if let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer {
let isChannel: Bool
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
isChannel = true
} else {
isChannel = false
}
let text: String
if save {
text = isChannel ? strongSelf.presentationInterfaceState.strings.Conversation_CopyProtectionSavingDisabledChannel : strongSelf.presentationInterfaceState.strings.Conversation_CopyProtectionSavingDisabledGroup
} else {
text = isChannel ? strongSelf.presentationInterfaceState.strings.Conversation_CopyProtectionForwardingDisabledChannel : strongSelf.presentationInterfaceState.strings.Conversation_CopyProtectionForwardingDisabledGroup
}
strongSelf.copyProtectionTooltipController?.dismiss()
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
strongSelf.copyProtectionTooltipController = tooltipController
tooltipController.dismissed = { [weak tooltipController] _ in
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.copyProtectionTooltipController === tooltipController {
strongSelf.copyProtectionTooltipController = nil
}
}
strongSelf.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: {
if let strongSelf = self {
let rect = node.view.convert(node.view.bounds, to: strongSelf.chatDisplayNode.view).offsetBy(dx: 0.0, dy: 3.0)
return (strongSelf.chatDisplayNode, rect)
}
return nil
}))
}
}, statuses: ChatPanelInterfaceInteractionStatuses(editingMessage: self.editingMessage.get(), startingBot: self.startingBot.get(), unblockingPeer: self.unblockingPeer.get(), searching: self.searching.get(), loadingMessage: self.loadingMessage.get(), inlineSearch: self.performingInlineSearch.get()))
do {
@ -13548,6 +13580,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.mediaRecordingModeTooltipController?.dismiss()
self.mediaRestrictedTooltipController?.dismiss()
self.checksTooltipController?.dismiss()
self.copyProtectionTooltipController?.dismiss()
self.window?.forEachController({ controller in
if let controller = controller as? UndoOverlayController {

View File

@ -1285,6 +1285,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
var hadPersonalIncoming = false
var hadBanPeerId = false
var disableDelete = false
var isCopyProtected = false
func getPeer(_ peerId: PeerId) -> Peer? {
if let peer = transaction.getPeer(peerId) {
@ -1306,12 +1307,16 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
}
}
for id in messageIds {
let isScheduled = id.namespace == Namespaces.Message.ScheduledCloud
if optionsMap[id] == nil {
optionsMap[id] = []
}
if let message = getMessage(id) {
if message.isCopyProtected() {
isCopyProtected = true
}
for media in message.media {
if let file = media as? TelegramMediaFile, file.isSticker {
for case let .Sticker(_, packReference, _) in file.attributes {
@ -1501,9 +1506,9 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
if hadPersonalIncoming && optionsMap.values.contains(where: { $0.contains(.deleteGlobally) }) && !reducedOptions.contains(.deleteGlobally) {
reducedOptions.insert(.unsendPersonal)
}
return ChatAvailableMessageActions(options: reducedOptions, banAuthor: banPeer, disableDelete: disableDelete)
return ChatAvailableMessageActions(options: reducedOptions, banAuthor: banPeer, disableDelete: disableDelete, isCopyProtected: isCopyProtected)
} else {
return ChatAvailableMessageActions(options: [], banAuthor: nil, disableDelete: false)
return ChatAvailableMessageActions(options: [], banAuthor: nil, disableDelete: false, isCopyProtected: isCopyProtected)
}
}
}

View File

@ -93,8 +93,8 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
self.addSubnode(self.shareButton)
self.addSubnode(self.separatorNode)
self.forwardButton.isEnabled = false
self.shareButton.isEnabled = false
self.forwardButton.isImplicitlyDisabled = true
self.shareButton.isImplicitlyDisabled = true
self.deleteButton.addTarget(self, action: #selector(self.deleteButtonPressed), forControlEvents: .touchUpInside)
self.reportButton.addTarget(self, action: #selector(self.reportButtonPressed), forControlEvents: .touchUpInside)
@ -132,11 +132,19 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
}
@objc func forwardButtonPressed() {
self.interfaceInteraction?.forwardSelectedMessages()
if let actions = self.actions, actions.isCopyProtected {
self.interfaceInteraction?.displayCopyProtectionTip(self.forwardButton, false)
} else {
self.interfaceInteraction?.forwardSelectedMessages()
}
}
@objc func shareButtonPressed() {
self.interfaceInteraction?.shareSelectedMessages()
if let actions = self.actions, actions.isCopyProtected {
self.interfaceInteraction?.displayCopyProtectionTip(self.shareButton, true)
} else {
self.interfaceInteraction?.shareSelectedMessages()
}
}
override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat {
@ -150,14 +158,14 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
if let actions = self.actions {
self.deleteButton.isEnabled = false
self.reportButton.isEnabled = false
self.forwardButton.isEnabled = actions.options.contains(.forward)
self.forwardButton.isImplicitlyDisabled = !actions.options.contains(.forward)
if self.peerMedia {
self.deleteButton.isEnabled = !actions.options.intersection([.deleteLocally, .deleteGlobally]).isEmpty
} else {
self.deleteButton.isEnabled = !actions.disableDelete
}
self.shareButton.isEnabled = !actions.options.intersection([.forward]).isEmpty
self.shareButton.isImplicitlyDisabled = actions.options.intersection([.forward]).isEmpty
self.reportButton.isEnabled = !actions.options.intersection([.report]).isEmpty
if self.peerMedia {
@ -171,8 +179,8 @@ final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
self.deleteButton.isHidden = self.peerMedia
self.reportButton.isEnabled = false
self.reportButton.isHidden = true
self.forwardButton.isEnabled = false
self.shareButton.isEnabled = false
self.forwardButton.isImplicitlyDisabled = true
self.shareButton.isImplicitlyDisabled = true
}
if self.reportButton.isHidden || (self.peerMedia && self.deleteButton.isHidden && self.reportButton.isHidden) {

View File

@ -136,6 +136,7 @@ final class ChatPanelInterfaceInteraction {
let openInviteRequests: () -> Void
let openSendAsPeer: (ASDisplayNode, ContextGesture?) -> Void
let presentChatRequestAdminInfo: () -> Void
let displayCopyProtectionTip: (ASDisplayNode, Bool) -> Void
let statuses: ChatPanelInterfaceInteractionStatuses?
init(
@ -226,6 +227,7 @@ final class ChatPanelInterfaceInteraction {
openInviteRequests: @escaping () -> Void,
openSendAsPeer: @escaping (ASDisplayNode, ContextGesture?) -> Void,
presentChatRequestAdminInfo: @escaping () -> Void,
displayCopyProtectionTip: @escaping (ASDisplayNode, Bool) -> Void,
statuses: ChatPanelInterfaceInteractionStatuses?
) {
self.setupReplyMessage = setupReplyMessage
@ -315,6 +317,7 @@ final class ChatPanelInterfaceInteraction {
self.openInviteRequests = openInviteRequests
self.openSendAsPeer = openSendAsPeer
self.presentChatRequestAdminInfo = presentChatRequestAdminInfo
self.displayCopyProtectionTip = displayCopyProtectionTip
self.statuses = statuses
}
@ -411,6 +414,7 @@ final class ChatPanelInterfaceInteraction {
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { _, _ in
}, statuses: nil)
}
}

View File

@ -148,7 +148,9 @@ final class ChatRecentActionsController: TelegramBaseController {
}, updateShowSendAsPeers: { _ in
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {}, statuses: nil)
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { _, _ in
}, statuses: nil)
self.navigationItem.titleView = self.titleView

View File

@ -222,18 +222,20 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
private let shareMessages: () -> Void
private let forwardMessages: () -> Void
private let reportMessages: () -> Void
private let displayCopyProtectionTip: (ASDisplayNode, Bool) -> Void
let selectionPanel: ChatMessageSelectionInputPanelNode
let separatorNode: ASDisplayNode
let backgroundNode: NavigationBackgroundNode
init(context: AccountContext, presentationData: PresentationData, peerId: PeerId, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void, reportMessages: @escaping () -> Void) {
init(context: AccountContext, presentationData: PresentationData, peerId: PeerId, deleteMessages: @escaping () -> Void, shareMessages: @escaping () -> Void, forwardMessages: @escaping () -> Void, reportMessages: @escaping () -> Void, displayCopyProtectionTip: @escaping (ASDisplayNode, Bool) -> Void) {
self.context = context
self.peerId = peerId
self.deleteMessages = deleteMessages
self.shareMessages = shareMessages
self.forwardMessages = forwardMessages
self.reportMessages = reportMessages
self.displayCopyProtectionTip = displayCopyProtectionTip
let presentationData = presentationData
@ -337,7 +339,10 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
}, updateShowSendAsPeers: { _ in
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {}, statuses: nil)
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { node, save in
displayCopyProtectionTip(node, save)
}, statuses: nil)
self.selectionPanel.interfaceInteraction = interfaceInteraction
@ -1507,6 +1512,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
private let tipsPeerDisposable = MetaDisposable()
private let cachedFaq = Promise<ResolvedUrl?>(nil)
private weak var copyProtectionTooltipController: TooltipController?
private let _ready = Promise<Bool>()
var ready: Promise<Bool> {
return self._ready
@ -2877,6 +2884,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
self.shareStatusDisposable?.dispose()
self.customStatusDisposable?.dispose()
self.refreshMessageTagStatsDisposable?.dispose()
self.copyProtectionTooltipController?.dismiss()
}
override func didLoad() {
@ -6477,6 +6486,37 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}, push: { c in
self?.controller?.push(c)
}, completion: { _, _ in }), in: .window(.root))
}, displayCopyProtectionTip: { [weak self] node, save in
if let strongSelf = self, let peer = strongSelf.data?.peer {
let isChannel: Bool
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
isChannel = true
} else {
isChannel = false
}
let text: String
if save {
text = isChannel ? strongSelf.presentationData.strings.Conversation_CopyProtectionSavingDisabledChannel : strongSelf.presentationData.strings.Conversation_CopyProtectionSavingDisabledGroup
} else {
text = isChannel ? strongSelf.presentationData.strings.Conversation_CopyProtectionForwardingDisabledChannel : strongSelf.presentationData.strings.Conversation_CopyProtectionForwardingDisabledGroup
}
strongSelf.copyProtectionTooltipController?.dismiss()
let tooltipController = TooltipController(content: .text(text), baseFontSize: strongSelf.presentationData.listsFontSize.baseDisplaySize, dismissByTapOutside: true, dismissImmediatelyOnLayoutUpdate: true)
strongSelf.copyProtectionTooltipController = tooltipController
tooltipController.dismissed = { [weak tooltipController] _ in
if let strongSelf = self, let tooltipController = tooltipController, strongSelf.copyProtectionTooltipController === tooltipController {
strongSelf.copyProtectionTooltipController = nil
}
}
strongSelf.controller?.present(tooltipController, in: .window(.root), with: TooltipControllerPresentationArguments(sourceNodeAndRect: {
if let strongSelf = self {
let rect = node.view.convert(node.view.bounds, to: strongSelf.view).offsetBy(dx: 0.0, dy: 3.0)
return (strongSelf, rect)
}
return nil
}))
}
})
self.paneContainerNode.selectionPanelNode = selectionPanelNode
self.paneContainerNode.addSubnode(selectionPanelNode)
@ -6856,7 +6896,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen {
private let activeSessionsContextAndCount = Promise<(ActiveSessionsContext, Int, WebSessionsContext)?>(nil)
private var tabBarItemDisposable: Disposable?
fileprivate var controllerNode: PeerInfoScreenNode {
return self.displayNode as! PeerInfoScreenNode
}

View File

@ -304,7 +304,9 @@ final class PeerSelectionControllerNode: ASDisplayNode {
}, updateShowSendAsPeers: { _ in
}, openInviteRequests: {
}, openSendAsPeer: { _, _ in
}, presentChatRequestAdminInfo: {}, statuses: nil)
}, presentChatRequestAdminInfo: {
}, displayCopyProtectionTip: { _, _ in
}, statuses: nil)
self.readyValue.set(self.chatListNode.ready)
}