diff --git a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index ee65de32c0..1a2a01d2af 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -442,6 +442,12 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { self.targetSelectionIndex = nil icon = nil isUserInteractionEnabled = action != nil + case .videoProcessing: + self.action = nil + self.text = "The video will be published once converted and optimized." + self.targetSelectionIndex = nil + icon = nil + isUserInteractionEnabled = action != nil } self.iconNode = ASImageNode() diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index 05c6be0606..3209430d8a 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -2350,6 +2350,7 @@ public final class ContextController: ViewController, StandalonePresentableContr case animatedEmoji(text: String?, arguments: TextNodeWithEntities.Arguments?, file: TelegramMediaFile?, action: (() -> Void)?) case notificationTopicExceptions(text: String, action: (() -> Void)?) case starsReactions(topCount: Int) + case videoProcessing public static func ==(lhs: Tip, rhs: Tip) -> Bool { switch lhs { @@ -2401,6 +2402,12 @@ public final class ContextController: ViewController, StandalonePresentableContr } else { return false } + case .videoProcessing: + if case .videoProcessing = rhs { + return true + } else { + return false + } } } } diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift index 251d880612..cc3cfa49ba 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/StringForMessageTimestampStatus.swift @@ -70,7 +70,7 @@ public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Mess return strings.Message_RecommendedLabel } } - + var timestamp: Int32 if let scheduleTime = message.scheduleTime { timestamp = scheduleTime @@ -95,6 +95,20 @@ public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Mess dateText = " " } + //TODO:release + //TODO:localize + if "".isEmpty, let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info { + for media in message.media { + if let file = media as? TelegramMediaFile, file.isVideo, !file.isInstantVideo, !file.isAnimated { + if message.id.namespace == Namespaces.Message.ScheduledCloud { + return "appx. \(dateText)" + } else if message.id.namespace == Namespaces.Message.ScheduledLocal { + return "processing" + } + } + } + } + if displayFullDate { let dayText: String diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index 67f25070d3..83ffb93913 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -1120,9 +1120,16 @@ extension ChatControllerImpl { self.chatDisplayNode.setupSendActionOnViewUpdate = { [weak self] f, messageCorrelationId in //print("setup layoutActionOnViewTransition") - self?.chatDisplayNode.historyNode.layoutActionOnViewTransition = ({ [weak self] transition in + guard let self else { + return + } + self.layoutActionOnViewTransitionAction = f + + self.chatDisplayNode.historyNode.layoutActionOnViewTransition = ({ [weak self] transition in f() if let strongSelf = self, let validLayout = strongSelf.validLayout { + strongSelf.layoutActionOnViewTransitionAction = nil + var mappedTransition: (ChatHistoryListViewTransition, ListViewUpdateSizeAndInsets?)? let isScheduledMessages: Bool @@ -1262,35 +1269,127 @@ extension ChatControllerImpl { } } - let signal: Signal<[MessageId?], NoError> - if forwardSourcePeerIds.count > 1 { - var signals: [Signal<[MessageId?], NoError>] = [] - for messagesGroup in forwardedMessages { - signals.append(enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messagesGroup)) - } - signal = combineLatest(signals) - |> map { results in - var ids: [MessageId?] = [] - for result in results { - ids.append(contentsOf: result) + let _ = (strongSelf.shouldDivertMessagesToScheduled(messages: transformedMessages) + |> deliverOnMainQueue).start(next: { shouldDivert in + let signal: Signal<[MessageId?], NoError> + var stayInThisChat = false + var shouldOpenScheduledMessages = false + if forwardSourcePeerIds.count > 1 { + var forwardedMessages = forwardedMessages + if shouldDivert { + forwardedMessages = forwardedMessages.map { messageGroup -> [EnqueueMessage] in + return messageGroup.map { message -> EnqueueMessage in + return message.withUpdatedAttributes { attributes in + var attributes = attributes + attributes.removeAll(where: { $0 is OutgoingScheduleInfoMessageAttribute }) + attributes.append(OutgoingScheduleInfoMessageAttribute(scheduleTime: Int32(Date().timeIntervalSince1970) + 10 * 24 * 60 * 60)) + return attributes + } + } + } + shouldOpenScheduledMessages = true } - return ids + + var signals: [Signal<[MessageId?], NoError>] = [] + for messagesGroup in forwardedMessages { + signals.append(enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: messagesGroup)) + } + signal = combineLatest(signals) + |> map { results in + var ids: [MessageId?] = [] + for result in results { + ids.append(contentsOf: result) + } + return ids + } + stayInThisChat = true + } else { + var transformedMessages = transformedMessages + if shouldDivert { + transformedMessages = transformedMessages.map { message -> EnqueueMessage in + return message.withUpdatedAttributes { attributes in + var attributes = attributes + attributes.removeAll(where: { $0 is OutgoingScheduleInfoMessageAttribute }) + attributes.append(OutgoingScheduleInfoMessageAttribute(scheduleTime: Int32(Date().timeIntervalSince1970) + 10 * 24 * 60 * 60)) + return attributes + } + } + shouldOpenScheduledMessages = true + } + + signal = enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: transformedMessages) } - } else { - signal = enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: transformedMessages) - } - - let _ = (signal - |> deliverOnMainQueue).startStandalone(next: { messageIds in - if let strongSelf = self { + + let _ = (signal + |> deliverOnMainQueue).startStandalone(next: { messageIds in + guard let strongSelf = self else { + return + } if case .scheduledMessages = strongSelf.presentationInterfaceState.subject { } else { strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory() + + if shouldOpenScheduledMessages { + if let layoutActionOnViewTransitionAction = strongSelf.layoutActionOnViewTransitionAction { + strongSelf.layoutActionOnViewTransitionAction = nil + layoutActionOnViewTransitionAction() + } + + if stayInThisChat { + strongSelf.dismissAllUndoControllers() + + //TODO:localize + strongSelf.present( + UndoOverlayController( + presentationData: strongSelf.presentationData, + content: .info( + title: "Improving video...", + text: "The video will be published after it's optimized for the bese viewing experience.", + timeout: 8.0, + customUndoText: nil + ), + elevatedLayout: false, + position: .top, + action: { _ in + return true + } + ), + in: .current + ) + } else { + strongSelf.openScheduledMessages(force: true, completion: { c in + guard let self else { + return + } + + c.dismissAllUndoControllers() + + //TODO:localize + c.present( + UndoOverlayController( + presentationData: self.presentationData, + content: .info( + title: "Improving video...", + text: "The video will be published after it's optimized for the bese viewing experience.", + timeout: 8.0, + customUndoText: nil + ), + elevatedLayout: false, + position: .top, + action: { _ in + return true + } + ), + in: .current + ) + }) + } + } } - } + }) + + donateSendMessageIntent(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, intentContext: .chat, peerIds: [peerId]) }) - - donateSendMessageIntent(account: strongSelf.context.account, sharedContext: strongSelf.context.sharedContext, intentContext: .chat, peerIds: [peerId]) } else if case let .customChatContents(customChatContents) = strongSelf.subject { switch customChatContents.kind { case .hashTagSearch: diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift index 705b34fd36..897664d292 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift @@ -105,6 +105,16 @@ extension ChatControllerImpl { } } } + + //TODO:release + //TODO:localize + if "".isEmpty, let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info { + for media in message.media { + if let file = media as? TelegramMediaFile, file.isVideo, !file.isInstantVideo, !file.isAnimated { + tip = .videoProcessing + } + } + } if actions.tip == nil { actions.tip = tip diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 4cd76b306d..199bed6324 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -641,6 +641,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } + var layoutActionOnViewTransitionAction: (() -> Void)? + public init( context: AccountContext, chatLocation: ChatLocation, @@ -9114,6 +9116,55 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } + func shouldDivertMessagesToScheduled(targetPeer: EnginePeer? = nil, messages: [EnqueueMessage]) -> Signal { + guard let peer = targetPeer?._asPeer() ?? self.presentationInterfaceState.renderedPeer?.peer else { + return .single(false) + } + + if let channel = peer as? TelegramChannel, case .broadcast = channel.info { + } else { + return .single(false) + } + + //TODO:release + if !"".isEmpty { + return .single(false) + } + + var forwardMessageIds: [EngineMessage.Id] = [] + + for message in messages { + if case let .message(_, _, _, mediaReference, _, _, _, _, _, _) = message, let media = mediaReference?.media { + if let file = media as? TelegramMediaFile, file.isVideo && !file.isInstantVideo && !file.isAnimated { + return .single(true) + } + } else if case let .forward(sourceId, _, _, _, _) = message { + forwardMessageIds.append(sourceId) + } + } + + if forwardMessageIds.isEmpty { + return .single(false) + } else { + return self.context.engine.data.get( + EngineDataList(forwardMessageIds.map(TelegramEngine.EngineData.Item.Messages.Message.init(id:))) + ) + |> map { messages -> Bool in + for message in messages { + guard let message else { + continue + } + for media in message.media { + if let file = media as? TelegramMediaFile, file.isVideo && !file.isInstantVideo && !file.isAnimated { + return true + } + } + } + return false + } + } + } + func sendMessages(_ messages: [EnqueueMessage], media: Bool = false, commit: Bool = false) { if case let .customChatContents(customChatContents) = self.subject { customChatContents.enqueueMessages(messages: messages) @@ -9124,37 +9175,101 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } - var isScheduledMessages = false - if case .scheduledMessages = self.presentationInterfaceState.subject { - isScheduledMessages = true - } - - if commit || !isScheduledMessages { - self.commitPurposefulAction() + let _ = (self.shouldDivertMessagesToScheduled(messages: messages) + |> deliverOnMainQueue).startStandalone(next: { [weak self] shouldDivert in + guard let self else { + return + } - let _ = (enqueueMessages(account: self.context.account, peerId: peerId, messages: self.transformEnqueueMessages(messages)) - |> deliverOnMainQueue).startStandalone(next: { [weak self] _ in - if let strongSelf = self, strongSelf.presentationInterfaceState.subject != .scheduledMessages { - strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory() + var messages = messages + var shouldOpenScheduledMessages = false + + if shouldDivert { + messages = messages.map { message -> EnqueueMessage in + return message.withUpdatedAttributes { attributes in + var attributes = attributes + attributes.removeAll(where: { $0 is OutgoingScheduleInfoMessageAttribute }) + attributes.append(OutgoingScheduleInfoMessageAttribute(scheduleTime: Int32(Date().timeIntervalSince1970) + 10 * 24 * 60 * 60)) + return attributes + } } - }) + shouldOpenScheduledMessages = true + } - donateSendMessageIntent(account: self.context.account, sharedContext: self.context.sharedContext, intentContext: .chat, peerIds: [peerId]) + var isScheduledMessages = false + if case .scheduledMessages = self.presentationInterfaceState.subject { + isScheduledMessages = true + } - self.updateChatPresentationInterfaceState(interactive: true, { $0.updatedShowCommands(false) }) - } else { - self.presentScheduleTimePicker(style: media ? .media : .default, dismissByTapOutside: false, completion: { [weak self] time in - if let strongSelf = self { - strongSelf.sendMessages(strongSelf.transformEnqueueMessages(messages, silentPosting: false, scheduleTime: time), commit: true) + if commit || !isScheduledMessages { + self.commitPurposefulAction() + + let _ = (enqueueMessages(account: self.context.account, peerId: peerId, messages: self.transformEnqueueMessages(messages)) + |> deliverOnMainQueue).startStandalone(next: { [weak self] _ in + if let strongSelf = self, strongSelf.presentationInterfaceState.subject != .scheduledMessages { + strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory() + } + }) + + donateSendMessageIntent(account: self.context.account, sharedContext: self.context.sharedContext, intentContext: .chat, peerIds: [peerId]) + + self.updateChatPresentationInterfaceState(interactive: true, { $0.updatedShowCommands(false) }) + + if !isScheduledMessages && shouldOpenScheduledMessages { + if let layoutActionOnViewTransitionAction = self.layoutActionOnViewTransitionAction { + self.layoutActionOnViewTransitionAction = nil + layoutActionOnViewTransitionAction() + } + + self.openScheduledMessages(force: true, completion: { [weak self] c in + guard let self else { + return + } + c.dismissAllUndoControllers() + + //TODO:localize + c.present( + UndoOverlayController( + presentationData: self.presentationData, + content: .info( + title: "Improving video...", + text: "The video will be published after it's optimized for the bese viewing experience.", + timeout: 8.0, + customUndoText: nil + ), + elevatedLayout: false, + position: .top, + action: { _ in + return true + } + ), + in: .current + ) + }) } - }) - } + } else { + self.presentScheduleTimePicker(style: media ? .media : .default, dismissByTapOutside: false, completion: { [weak self] time in + if let strongSelf = self { + strongSelf.sendMessages(strongSelf.transformEnqueueMessages(messages, silentPosting: false, scheduleTime: time), commit: true) + } + }) + } + }) } func enqueueMediaMessages(signals: [Any]?, silentPosting: Bool, scheduleTime: Int32? = nil, parameters: ChatSendMessageActionSheetController.SendParameters? = nil, getAnimatedTransitionSource: ((String) -> UIView?)? = nil, completion: @escaping () -> Void = {}) { self.enqueueMediaMessageDisposable.set((legacyAssetPickerEnqueueMessages(context: self.context, account: self.context.account, signals: signals!) |> deliverOnMainQueue).startStrict(next: { [weak self] items in - if let strongSelf = self { + guard let strongSelf = self else { + return + } + + let _ = (strongSelf.shouldDivertMessagesToScheduled(messages: items.map(\.message)) + |> deliverOnMainQueue).startStandalone(next: { shouldDivert in + guard let strongSelf = self else { + return + } + var completionImpl: (() -> Void)? = completion var usedCorrelationId: Int64? @@ -9166,6 +9281,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var skipAddingTransitions = false + if shouldDivert { + skipAddingTransitions = true + } + for item in items { var message = item.message if message.groupingKey != nil { @@ -9289,7 +9408,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let _ = scheduleTime { completion() } - } + }) })) } @@ -10384,8 +10503,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - func openScheduledMessages() { - guard let navigationController = self.effectiveNavigationController, navigationController.topViewController == self else { + func openScheduledMessages(force: Bool = false, completion: @escaping (ChatControllerImpl) -> Void = { _ in }) { + guard let navigationController = self.effectiveNavigationController else { + return + } + if navigationController.topViewController == self || force { + } else { return } @@ -10396,7 +10519,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let controller = ChatControllerImpl(context: self.context, chatLocation: mappedChatLocation, subject: .scheduledMessages) controller.navigationPresentation = .modal - navigationController.pushViewController(controller) + navigationController.pushViewController(controller, completion: { [weak controller] in + if let controller { + completion(controller) + } + }) } func openPinnedMessages(at messageId: MessageId?) { diff --git a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift index 5157826e77..1992ca77e6 100644 --- a/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift +++ b/submodules/TelegramUI/Sources/ChatControllerForwardMessages.swift @@ -122,6 +122,9 @@ extension ChatControllerImpl { }) let commit: ([EnqueueMessage]) -> Void = { result in + guard let strongSelf = self else { + return + } var result = result strongSelf.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withoutSelectionState() }).updatedSearch(nil) }) @@ -133,96 +136,146 @@ extension ChatControllerImpl { result[i] = result[i].withUpdatedCorrelationId(correlationId) } - var displayPeers: [EnginePeer] = [] - for peer in peers { - let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result) - |> deliverOnMainQueue).startStandalone(next: { messageIds in - if let strongSelf = self { - let signals: [Signal] = messageIds.compactMap({ id -> Signal? in - guard let id = id else { - return nil - } - return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id) - |> mapToSignal { status, _ -> Signal in - if status != nil { - return .never() - } else { - return .single(true) - } - } - |> take(1) - }) - if strongSelf.shareStatusDisposable == nil { - strongSelf.shareStatusDisposable = MetaDisposable() - } - strongSelf.shareStatusDisposable?.set((combineLatest(signals) - |> deliverOnMainQueue).startStrict()) - } - }) - - if case let .secretChat(secretPeer) = peer { - if let peer = peerMap[secretPeer.regularPeerId] { - displayPeers.append(peer) - } - } else { - displayPeers.append(peer) + let targetPeersShouldDivertSignals: [Signal<(EnginePeer, Bool), NoError>] = peers.map { peer -> Signal<(EnginePeer, Bool), NoError> in + return strongSelf.shouldDivertMessagesToScheduled(targetPeer: peer, messages: result) + |> map { shouldDivert -> (EnginePeer, Bool) in + return (peer, shouldDivert) } } - - let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let text: String - var savedMessages = false - if displayPeers.count == 1, let peerId = displayPeers.first?.id, peerId == strongSelf.context.account.peerId { - text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many - savedMessages = true - } else { - if displayPeers.count == 1, let peer = displayPeers.first { - var peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - peerName = peerName.replacingOccurrences(of: "**", with: "") - text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string - } else if displayPeers.count == 2, let firstPeer = displayPeers.first, let secondPeer = displayPeers.last { - var firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - firstPeerName = firstPeerName.replacingOccurrences(of: "**", with: "") - var secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - secondPeerName = secondPeerName.replacingOccurrences(of: "**", with: "") - text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string - } else if let peer = displayPeers.first { - var peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - peerName = peerName.replacingOccurrences(of: "**", with: "") - text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(displayPeers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(displayPeers.count - 1)").string - } else { - text = "" - } - } - - let reactionItems: Signal<[ReactionItem], NoError> - if savedMessages && messages.count > 0 { - reactionItems = tagMessageReactions(context: strongSelf.context, subPeerId: nil) - } else { - reactionItems = .single([]) - } - - let _ = (reactionItems - |> deliverOnMainQueue).startStandalone(next: { [weak strongSelf] reactionItems in - guard let strongSelf else { + let targetPeersShouldDivert: Signal<[(EnginePeer, Bool)], NoError> = combineLatest(targetPeersShouldDivertSignals) + let _ = (targetPeersShouldDivert + |> deliverOnMainQueue).startStandalone(next: { targetPeersShouldDivert in + guard let strongSelf = self else { return } - strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, position: savedMessages && messages.count > 0 ? .top : .bottom, animateInAsReplacement: true, action: { action in - if savedMessages, let self, action == .info { - let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) - |> deliverOnMainQueue).start(next: { [weak self] peer in - guard let self, let peer else { - return + var displayConvertingTooltip = false + + var displayPeers: [EnginePeer] = [] + for (peer, shouldDivert) in targetPeersShouldDivert { + var peerMessages = result + if shouldDivert { + displayConvertingTooltip = true + peerMessages = peerMessages.map { message -> EnqueueMessage in + return message.withUpdatedAttributes { attributes in + var attributes = attributes + attributes.removeAll(where: { $0 is OutgoingScheduleInfoMessageAttribute }) + attributes.append(OutgoingScheduleInfoMessageAttribute(scheduleTime: Int32(Date().timeIntervalSince1970) + 10 * 24 * 60 * 60)) + return attributes } - guard let navigationController = self.navigationController as? NavigationController else { - return - } - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), forceOpenChat: true)) - }) + } } - return false - }, additionalView: (savedMessages && messages.count > 0) ? chatShareToSavedMessagesAdditionalView(strongSelf, reactionItems: reactionItems, correlationIds: correlationIds) : nil), in: .current) + + let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: peerMessages) + |> deliverOnMainQueue).startStandalone(next: { messageIds in + if let strongSelf = self { + let signals: [Signal] = messageIds.compactMap({ id -> Signal? in + guard let id = id else { + return nil + } + return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id) + |> mapToSignal { status, _ -> Signal in + if status != nil { + return .never() + } else { + return .single(true) + } + } + |> take(1) + }) + if strongSelf.shareStatusDisposable == nil { + strongSelf.shareStatusDisposable = MetaDisposable() + } + strongSelf.shareStatusDisposable?.set((combineLatest(signals) + |> deliverOnMainQueue).startStrict()) + } + }) + + if case let .secretChat(secretPeer) = peer { + if let peer = peerMap[secretPeer.regularPeerId] { + displayPeers.append(peer) + } + } else { + displayPeers.append(peer) + } + } + + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + let text: String + var savedMessages = false + if displayPeers.count == 1, let peerId = displayPeers.first?.id, peerId == strongSelf.context.account.peerId { + text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many + savedMessages = true + } else { + if displayPeers.count == 1, let peer = displayPeers.first { + var peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + peerName = peerName.replacingOccurrences(of: "**", with: "") + text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string + } else if displayPeers.count == 2, let firstPeer = displayPeers.first, let secondPeer = displayPeers.last { + var firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + firstPeerName = firstPeerName.replacingOccurrences(of: "**", with: "") + var secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + secondPeerName = secondPeerName.replacingOccurrences(of: "**", with: "") + text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string + } else if let peer = displayPeers.first { + var peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + peerName = peerName.replacingOccurrences(of: "**", with: "") + text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(displayPeers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(displayPeers.count - 1)").string + } else { + text = "" + } + } + + let reactionItems: Signal<[ReactionItem], NoError> + if savedMessages && messages.count > 0 { + reactionItems = tagMessageReactions(context: strongSelf.context, subPeerId: nil) + } else { + reactionItems = .single([]) + } + + let _ = (reactionItems + |> deliverOnMainQueue).startStandalone(next: { [weak strongSelf] reactionItems in + guard let strongSelf else { + return + } + + strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, position: savedMessages && messages.count > 0 ? .top : .bottom, animateInAsReplacement: true, action: { action in + if savedMessages, let self, action == .info { + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let peer else { + return + } + guard let navigationController = self.navigationController as? NavigationController else { + return + } + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), forceOpenChat: true)) + }) + } + return false + }, additionalView: (savedMessages && messages.count > 0) ? chatShareToSavedMessagesAdditionalView(strongSelf, reactionItems: reactionItems, correlationIds: correlationIds) : nil), in: .current) + }) + + if displayConvertingTooltip { + //TODO:localize + strongSelf.present( + UndoOverlayController( + presentationData: strongSelf.presentationData, + content: .info( + title: "Improving video...", + text: "The video will be published after it's optimized for the bese viewing experience.", + timeout: 8.0, + customUndoText: nil + ), + elevatedLayout: false, + position: .top, + action: { _ in + return true + } + ), + in: .current + ) + } }) }