diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 23eb11f7a3..9985b8aaa9 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -9052,3 +9052,8 @@ Sorry for the inconvenience."; "Login.Email.PremiumRequiredText" = "Due to high cost of SMS in your country, you need to have a **Telegram Premium** account to reset this email via an SMS code. You can ask a friend to a gift a Premium subscription for your account %@"; "ChatList.StartMessaging" = "Select a chat to start messaging"; + +"Conversation.ForwardOptions.RecipientsMessageForwardVisible" = "Recipients will see that it was forwarded"; +"Conversation.ForwardOptions.RecipientsMessageForwardHidden" = "Recipients won't see that it was forwarded"; +"Conversation.ForwardOptions.RecipientsMessagesForwardVisible" = "Recipients will see they were forwarded"; +"Conversation.ForwardOptions.RecipientsMessagesForwardHidden" = "Recipients won't see they were forwarded"; diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 2be2321fbf..61a80885d7 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -489,7 +489,7 @@ public enum ChatControllerSubject: Equatable { case message(id: MessageSubject, highlight: Bool, timecode: Double?) case scheduledMessages case pinnedMessages(id: EngineMessage.Id?) - case forwardedMessages(ids: [EngineMessage.Id], options: Signal) + case forwardedMessages(peerIds: [EnginePeer.Id], ids: [EngineMessage.Id], options: Signal) public static func ==(lhs: ChatControllerSubject, rhs: ChatControllerSubject) -> Bool { switch lhs { @@ -511,8 +511,8 @@ public enum ChatControllerSubject: Equatable { } else { return false } - case let .forwardedMessages(lhsIds, _): - if case let .forwardedMessages(rhsIds, _) = rhs, lhsIds == rhsIds { + case let .forwardedMessages(lhsPeerIds, lhsIds, _): + if case let .forwardedMessages(rhsPeerIds, rhsIds, _) = rhs, lhsPeerIds == rhsPeerIds, lhsIds == rhsIds { return true } else { return false diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 049a52efc1..752a2e7bed 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -4606,7 +4606,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return message?.totalCount } |> distinctUntilChanged - } else if case let .forwardedMessages(messageIds, options) = subject { + } else if case let .forwardedMessages(peerIds, messageIds, options) = subject { displayedCountSignal = self.presentationInterfaceStatePromise.get() |> map { state -> Int? in if let selectionState = state.interfaceState.selectionState { @@ -4617,50 +4617,71 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } |> distinctUntilChanged - subtitleTextSignal = combineLatest(self.presentationInterfaceStatePromise.get(), options, displayedCountSignal) - |> map { state, options, count in - if let peer = state.renderedPeer?.chatMainPeer { - if let peer = peer as? TelegramUser { - let displayName = EnginePeer(peer).compactDisplayTitle - if count == 1 { - if options.hideNames { - return state.strings.Conversation_ForwardOptions_UserMessageForwardHidden(displayName).string + let peers = self.context.account.postbox.multiplePeersView(peerIds) + |> take(1) + + let presentationData = self.presentationData + subtitleTextSignal = combineLatest(peers, options, displayedCountSignal) + |> map { peersView, options, count in + let peers = peersView.peers.values + if !peers.isEmpty { + if peers.count == 1, let peer = peers.first { + if let peer = peer as? TelegramUser { + let displayName = EnginePeer(peer).compactDisplayTitle + if count == 1 { + if options.hideNames { + return presentationData.strings.Conversation_ForwardOptions_UserMessageForwardHidden(displayName).string + } else { + return presentationData.strings.Conversation_ForwardOptions_UserMessageForwardVisible(displayName).string + } } else { - return state.strings.Conversation_ForwardOptions_UserMessageForwardVisible(displayName).string + if options.hideNames { + return presentationData.strings.Conversation_ForwardOptions_UserMessagesForwardHidden(displayName).string + } else { + return presentationData.strings.Conversation_ForwardOptions_UserMessagesForwardVisible(displayName).string + } + } + } else if let peer = peer as? TelegramChannel, case .broadcast = peer.info { + if count == 1 { + if options.hideNames { + return presentationData.strings.Conversation_ForwardOptions_ChannelMessageForwardHidden + } else { + return presentationData.strings.Conversation_ForwardOptions_ChannelMessageForwardVisible + } + } else { + if options.hideNames { + return presentationData.strings.Conversation_ForwardOptions_ChannelMessagesForwardHidden + } else { + return presentationData.strings.Conversation_ForwardOptions_ChannelMessagesForwardVisible + } } } else { - if options.hideNames { - return state.strings.Conversation_ForwardOptions_UserMessagesForwardHidden(displayName).string + if count == 1 { + if options.hideNames { + return presentationData.strings.Conversation_ForwardOptions_GroupMessageForwardHidden + } else { + return presentationData.strings.Conversation_ForwardOptions_GroupMessageForwardVisible + } } else { - return state.strings.Conversation_ForwardOptions_UserMessagesForwardVisible(displayName).string - } - } - } else if let peer = peer as? TelegramChannel, case .broadcast = peer.info { - if count == 1 { - if options.hideNames { - return state.strings.Conversation_ForwardOptions_ChannelMessageForwardHidden - } else { - return state.strings.Conversation_ForwardOptions_ChannelMessageForwardVisible - } - } else { - if options.hideNames { - return state.strings.Conversation_ForwardOptions_ChannelMessagesForwardHidden - } else { - return state.strings.Conversation_ForwardOptions_ChannelMessagesForwardVisible + if options.hideNames { + return presentationData.strings.Conversation_ForwardOptions_GroupMessagesForwardHidden + } else { + return presentationData.strings.Conversation_ForwardOptions_GroupMessagesForwardVisible + } } } } else { if count == 1 { if options.hideNames { - return state.strings.Conversation_ForwardOptions_GroupMessageForwardHidden + return presentationData.strings.Conversation_ForwardOptions_RecipientsMessageForwardHidden } else { - return state.strings.Conversation_ForwardOptions_GroupMessageForwardVisible + return presentationData.strings.Conversation_ForwardOptions_RecipientsMessageForwardVisible } } else { if options.hideNames { - return state.strings.Conversation_ForwardOptions_GroupMessagesForwardHidden + return presentationData.strings.Conversation_ForwardOptions_RecipientsMessagesForwardHidden } else { - return state.strings.Conversation_ForwardOptions_GroupMessagesForwardVisible + return presentationData.strings.Conversation_ForwardOptions_RecipientsMessagesForwardVisible } } } @@ -5948,6 +5969,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatTitleView?.networkState = state } }) + + if case let .forwardedMessages(_, messageIds, _) = self.subject, messageIds.count > 1 { + self.updateChatPresentationInterfaceState(interactive: false, { state in + return state.updatedInterfaceState({ $0.withUpdatedSelectedMessages(messageIds) }) + }) + } } required public init(coder aDecoder: NSCoder) { @@ -8100,7 +8127,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> distinctUntilChanged } - let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .forwardedMessages(ids: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], options: forwardOptions), botStart: nil, mode: .standard(previewing: true)) + let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: peerId), subject: .forwardedMessages(peerIds: [peerId], ids: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], options: forwardOptions), botStart: nil, mode: .standard(previewing: true)) chatController.canReadHistory.set(false) let messageIds = strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [] @@ -8132,7 +8159,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if !uniquePeerIds.contains(author.id) { uniquePeerIds.insert(author.id) } - if message.id.peerId == accountPeerId && message.forwardInfo == nil { } else { hasNotOwnMessages = true @@ -10635,12 +10661,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - if case let .forwardedMessages(messageIds, _) = self.subject, messageIds.count > 1 { - self.updateChatPresentationInterfaceState(interactive: false, { state in - return state.updatedInterfaceState({ $0.withUpdatedSelectedMessages(messageIds) }) - }) - } - self.displayNodeDidLoad() } @@ -18511,7 +18531,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent let sourceRect: CGRect? let navigationController: NavigationController? = nil - + let passthroughTouches: Bool init(controller: ViewController, sourceNode: ASDisplayNode?, sourceRect: CGRect? = nil, passthroughTouches: Bool) { diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index cf161a5fad..54aff54c94 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -336,7 +336,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputContextOverTextPanelContainer = ChatControllerTitlePanelNodeContainer() var source: ChatHistoryListSource - if case let .forwardedMessages(messageIds, options) = subject { + if case let .forwardedMessages(_, messageIds, options) = subject { let messages = combineLatest(context.account.postbox.messagesAtIds(messageIds), context.account.postbox.loadedPeerWithId(context.account.peerId), options) |> map { messages, accountPeer, options -> ([Message], Int32, Bool) in var messages = messages diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 54139e219f..4290a1aeb6 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -640,7 +640,14 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } else if self.emojiFile?.id != emojiFile?.id { if self.emojiFile != nil { self.didSetUpAnimationNode = false - item.controllerInteraction.seenOneTimeAnimatedMedia.remove(item.message.id) + item.controllerInteraction.seenOneTimeAnimatedMedia.remove(item.message.id) + + self.animationNode?.removeFromSupernode() + self.animationNode = nil + + self.contextSourceNode.contentNode.insertSubnode(self.placeholderNode, aboveSubnode: self.imageNode) + + self.setupNode(item: item) } self.emojiFile = emojiFile if let emojiFile = emojiFile { diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index d357fced28..70f0e5c6e9 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -21,6 +21,7 @@ import MultiAnimationRenderer import AnimatedStickerNode import TelegramAnimatedStickerNode import SolidRoundedButtonNode +import ContextUI final class PeerSelectionControllerNode: ASDisplayNode { private let context: AccountContext @@ -36,13 +37,11 @@ final class PeerSelectionControllerNode: ASDisplayNode { private let requestPeerType: [ReplyMarkupButtonRequestPeerType]? private var presentationInterfaceState: ChatPresentationInterfaceState + private let presentationInterfaceStatePromise = ValuePromise() + private var interfaceInteraction: ChatPanelInterfaceInteraction? - var inProgress: Bool = false { - didSet { - - } - } + var inProgress: Bool = false var navigationBar: NavigationBar? @@ -125,7 +124,8 @@ final class PeerSelectionControllerNode: ASDisplayNode { self.presentationInterfaceState = ChatPresentationInterfaceState(chatWallpaper: .builtin(WallpaperSettings()), theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameDisplayOrder: self.presentationData.nameDisplayOrder, limitsConfiguration: self.context.currentLimitsConfiguration.with { $0 }, fontSize: self.presentationData.chatFontSize, bubbleCorners: self.presentationData.chatBubbleCorners, accountPeerId: self.context.account.peerId, mode: .standard(previewing: false), chatLocation: .peer(id: PeerId(0)), subject: nil, peerNearbyData: nil, greetingData: nil, pendingUnpinnedAllMessages: false, activeGroupCallInfo: nil, hasActiveGroupCall: false, importState: nil, threadData: nil, isGeneralThreadClosed: nil) - self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds) } + self.presentationInterfaceState = self.presentationInterfaceState.updatedInterfaceState { $0.withUpdatedForwardMessageIds(forwardedMessageIds).withUpdatedForwardOptionsState(ChatInterfaceForwardOptionsState(hideNames: false, hideCaptions: false, unhideNamesOnCaptionChange: false)) } + self.presentationInterfaceStatePromise.set(self.presentationInterfaceState) if let _ = self.requestPeerType { self.requirementsBackgroundNode = NavigationBackgroundNode(color: self.presentationData.theme.rootController.navigationBar.blurredBackgroundColor) @@ -346,7 +346,190 @@ final class PeerSelectionControllerNode: ASDisplayNode { if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardOptionsState($0.forwardOptionsState) }) }) } - }, presentForwardOptions: { _ in + }, presentForwardOptions: { [weak self] sourceNode in + guard let strongSelf = self else { + return + } + + let presentationData = strongSelf.presentationData + + let peerIds = strongSelf.selectedPeers.0.map { $0.id } + + let forwardOptions: Signal + forwardOptions = strongSelf.presentationInterfaceStatePromise.get() + |> map { state -> ChatControllerSubject.ForwardOptions in + return ChatControllerSubject.ForwardOptions(hideNames: state.interfaceState.forwardOptionsState?.hideNames ?? false, hideCaptions: state.interfaceState.forwardOptionsState?.hideCaptions ?? false) + } + |> distinctUntilChanged + + let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: strongSelf.context.account.peerId), subject: .forwardedMessages(peerIds: peerIds, ids: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], options: forwardOptions), botStart: nil, mode: .standard(previewing: true)) + chatController.canReadHistory.set(false) + + let messageIds = strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [] + let messagesCount: Signal + if let chatController = chatController as? ChatControllerImpl, messageIds.count > 1 { + messagesCount = .single(messageIds.count) + |> then( + chatController.presentationInterfaceStatePromise.get() + |> map { state -> Int in + return state.interfaceState.selectionState?.selectedIds.count ?? 1 + } + ) + } else { + messagesCount = .single(1) + } + + let accountPeerId = strongSelf.context.account.peerId + let items = combineLatest(forwardOptions, strongSelf.context.account.postbox.messagesAtIds(messageIds), messagesCount) + |> map { forwardOptions, messages, messagesCount -> [ContextMenuItem] in + var items: [ContextMenuItem] = [] + + var hasCaptions = false + var uniquePeerIds = Set() + + var hasOther = false + var hasNotOwnMessages = false + for message in messages { + if let author = message.effectiveAuthor { + if !uniquePeerIds.contains(author.id) { + uniquePeerIds.insert(author.id) + } + if message.id.peerId == accountPeerId && message.forwardInfo == nil { + } else { + hasNotOwnMessages = true + } + } + + var isDice = false + var isMusic = false + for media in message.media { + if let media = media as? TelegramMediaFile, media.isMusic { + isMusic = true + } else if media is TelegramMediaDice { + isDice = true + } else { + if !message.text.isEmpty { + if media is TelegramMediaImage || media is TelegramMediaFile { + hasCaptions = true + } + } + } + } + if !isDice && !isMusic { + hasOther = true + } + } + + let canHideNames = hasNotOwnMessages && hasOther + + let hideNames = forwardOptions.hideNames + let hideCaptions = forwardOptions.hideCaptions + + if !"".isEmpty { // check if seecret chat + } else { + if canHideNames { + items.append(.action(ContextMenuActionItem(text: uniquePeerIds.count == 1 ? presentationData.strings.Conversation_ForwardOptions_ShowSendersName : presentationData.strings.Conversation_ForwardOptions_ShowSendersNames, icon: { theme in + if hideNames { + return nil + } else { + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + } + }, action: { [weak self] _, f in + self?.interfaceInteraction?.updateForwardOptionsState({ current in + var updated = current + updated.hideNames = false + updated.hideCaptions = false + updated.unhideNamesOnCaptionChange = false + return updated + }) + }))) + + items.append(.action(ContextMenuActionItem(text: uniquePeerIds.count == 1 ? presentationData.strings.Conversation_ForwardOptions_HideSendersName : presentationData.strings.Conversation_ForwardOptions_HideSendersNames, icon: { theme in + if hideNames { + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + } else { + return nil + } + }, action: { _, f in + self?.interfaceInteraction?.updateForwardOptionsState({ current in + var updated = current + updated.hideNames = true + updated.unhideNamesOnCaptionChange = false + return updated + }) + }))) + + items.append(.separator) + } + + if hasCaptions { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ForwardOptions_ShowCaption, icon: { theme in + if hideCaptions { + return nil + } else { + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + } + }, action: { [weak self] _, f in + self?.interfaceInteraction?.updateForwardOptionsState({ current in + var updated = current + updated.hideCaptions = false + if updated.unhideNamesOnCaptionChange { + updated.unhideNamesOnCaptionChange = false + updated.hideNames = false + } + return updated + }) + }))) + + items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ForwardOptions_HideCaption, icon: { theme in + if hideCaptions { + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) + } else { + return nil + } + }, action: { _, f in + self?.interfaceInteraction?.updateForwardOptionsState({ current in + var updated = current + updated.hideCaptions = true + if !updated.hideNames { + updated.hideNames = true + updated.unhideNamesOnCaptionChange = true + } + return updated + }) + }))) + + items.append(.separator) + } + } + + items.append(.action(ContextMenuActionItem(text: messagesCount == 1 ? presentationData.strings.Conversation_ForwardOptions_SendMessage : presentationData.strings.Conversation_ForwardOptions_SendMessages, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { [weak self, weak chatController] c, f in + guard let strongSelf = self else { + return + } + if let selectedMessageIds = (chatController as? ChatControllerImpl)?.selectedMessageIds { + var forwardMessageIds = strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [] + forwardMessageIds = forwardMessageIds.filter { selectedMessageIds.contains($0) } + strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(forwardMessageIds) }) }) + } + strongSelf.textInputPanelNode?.sendMessage(.generic) + + f(.default) + }))) + + return items + } + + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: sourceNode, passthroughTouches: true)), items: items |> map { ContextController.Items(content: .list($0)) }) + contextController.dismissedForCancel = { [weak chatController] in + if let selectedMessageIds = (chatController as? ChatControllerImpl)?.selectedMessageIds { + var forwardMessageIds = strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [] + forwardMessageIds = forwardMessageIds.filter { selectedMessageIds.contains($0) } + strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(forwardMessageIds) }) }) + } + } + contextController.immediateItemsTransitionAnimation = true + strongSelf.controller?.presentInGlobalOverlay(contextController) }, shareSelectedMessages: { }, updateTextInputStateAndMode: { [weak self] f in if let strongSelf = self { @@ -536,6 +719,7 @@ final class PeerSelectionControllerNode: ASDisplayNode { let updateInputTextState = self.presentationInterfaceState.interfaceState.effectiveInputState != presentationInterfaceState.interfaceState.effectiveInputState self.presentationInterfaceState = presentationInterfaceState + self.presentationInterfaceStatePromise.set(presentationInterfaceState) if let textInputPanelNode = self.textInputPanelNode, updateInputTextState { textInputPanelNode.updateInputTextState(presentationInterfaceState.interfaceState.effectiveInputState, animated: transition.isAnimated) @@ -546,6 +730,46 @@ final class PeerSelectionControllerNode: ASDisplayNode { } } + private var selectedPeers: ([Peer], [PeerId: Peer]) { + if self.contactListActive { + let selectedContactPeers = self.contactListNode?.selectedPeers ?? [] + + var selectedPeers: [Peer] = [] + var selectedPeerMap: [PeerId: Peer] = [:] + for contactPeer in selectedContactPeers { + if case let .peer(peer, _, _) = contactPeer { + selectedPeers.append(peer) + selectedPeerMap[peer.id] = peer + } + } + return (selectedPeers, selectedPeerMap) + } else { + var selectedPeerIds: [PeerId] = [] + var selectedPeerMap: [PeerId: Peer] = [:] + if let mainContainerNode = self.mainContainerNode { + mainContainerNode.currentItemNode.updateState { state in + selectedPeerIds = Array(state.selectedPeerIds) + selectedPeerMap = state.selectedPeerMap.mapValues({ $0._asPeer() }) + return state + } + } + if let chatListNode = self.chatListNode { + chatListNode.updateState { state in + selectedPeerIds = Array(state.selectedPeerIds) + selectedPeerMap = state.selectedPeerMap.mapValues({ $0._asPeer() }) + return state + } + } + var selectedPeers: [Peer] = [] + for peerId in selectedPeerIds { + if let peer = selectedPeerMap[peerId] { + selectedPeers.append(peer) + } + } + return (selectedPeers, selectedPeerMap) + } + } + func beginSelection() { if let _ = self.textInputPanelNode { } else { @@ -566,47 +790,9 @@ final class PeerSelectionControllerNode: ASDisplayNode { let effectiveInputText = strongSelf.presentationInterfaceState.interfaceState.composeInputState.inputText let forwardOptionsState = strongSelf.presentationInterfaceState.interfaceState.forwardOptionsState - if strongSelf.contactListActive { - strongSelf.contactListNode?.multipleSelection = true - let selectedContactPeers = strongSelf.contactListNode?.selectedPeers ?? [] - - var selectedPeers: [Peer] = [] - var selectedPeerMap: [PeerId: Peer] = [:] - for contactPeer in selectedContactPeers { - if case let .peer(peer, _, _) = contactPeer { - selectedPeers.append(peer) - selectedPeerMap[peer.id] = peer - } - } - if !selectedPeers.isEmpty { - strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode, forwardOptionsState) - } - } else { - var selectedPeerIds: [PeerId] = [] - var selectedPeerMap: [PeerId: Peer] = [:] - if let mainContainerNode = strongSelf.mainContainerNode { - mainContainerNode.currentItemNode.updateState { state in - selectedPeerIds = Array(state.selectedPeerIds) - selectedPeerMap = state.selectedPeerMap.mapValues({ $0._asPeer() }) - return state - } - } - if let chatListNode = strongSelf.chatListNode { - chatListNode.updateState { state in - selectedPeerIds = Array(state.selectedPeerIds) - selectedPeerMap = state.selectedPeerMap.mapValues({ $0._asPeer() }) - return state - } - } - if !selectedPeerIds.isEmpty { - var selectedPeers: [Peer] = [] - for peerId in selectedPeerIds { - if let peer = selectedPeerMap[peerId] { - selectedPeers.append(peer) - } - } - strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode, forwardOptionsState) - } + let (selectedPeers, selectedPeerMap) = strongSelf.selectedPeers + if !selectedPeers.isEmpty { + strongSelf.requestSend?(selectedPeers, selectedPeerMap, effectiveInputText, mode, forwardOptionsState) } } self.addSubnode(textInputPanelNode) @@ -1426,3 +1612,35 @@ private func stringForRequestPeerType(strings: PresentationStrings, peerType: Re return String(lines.joined(separator: "\n")) } } + +private final class ContextControllerContentSourceImpl: ContextControllerContentSource { + let controller: ViewController + weak var sourceNode: ASDisplayNode? + let sourceRect: CGRect? + + let navigationController: NavigationController? = nil + + let passthroughTouches: Bool + + init(controller: ViewController, sourceNode: ASDisplayNode?, sourceRect: CGRect? = nil, passthroughTouches: Bool) { + self.controller = controller + self.sourceNode = sourceNode + self.sourceRect = sourceRect + self.passthroughTouches = passthroughTouches + } + + func transitionInfo() -> ContextControllerTakeControllerInfo? { + let sourceNode = self.sourceNode + let sourceRect = self.sourceRect + return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in + if let sourceNode = sourceNode { + return (sourceNode.view, sourceRect ?? sourceNode.bounds) + } else { + return nil + } + }) + } + + func animatedIn() { + } +}