import Foundation import TelegramPresentationData import AccountContext import Postbox import TelegramCore import SwiftSignalKit import PresentationDataUtils import Display extension ChatControllerImpl { func openMessageReplies(messageId: MessageId, displayProgressInMessage: MessageId?, isChannelPost: Bool, atMessage atMessageId: MessageId?, displayModalProgress: Bool) { guard let navigationController = self.effectiveNavigationController else { return } if let displayProgressInMessage = displayProgressInMessage, self.controllerInteraction?.currentMessageWithLoadingReplyThread == displayProgressInMessage { return } let _ = self.presentVoiceMessageDiscardAlert(action: { let progressSignal: Signal = Signal { [weak self] _ in guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else { return EmptyDisposable } if let displayProgressInMessage = displayProgressInMessage, controllerInteraction.currentMessageWithLoadingReplyThread != displayProgressInMessage { let previousId = controllerInteraction.currentMessageWithLoadingReplyThread controllerInteraction.currentMessageWithLoadingReplyThread = displayProgressInMessage strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage) if let previousId = previousId { strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(previousId) } } return ActionDisposable { Queue.mainQueue().async { guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else { return } if let displayProgressInMessage = displayProgressInMessage, controllerInteraction.currentMessageWithLoadingReplyThread == displayProgressInMessage { controllerInteraction.currentMessageWithLoadingReplyThread = nil strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(displayProgressInMessage) } } } } |> runOn(.mainQueue()) let progress = (progressSignal |> delay(0.15, queue: .mainQueue())).startStrict() self.navigationActionDisposable.set((ChatControllerImpl.openMessageReplies(context: self.context, updatedPresentationData: self.updatedPresentationData, navigationController: navigationController, present: { [weak self] c, a in self?.present(c, in: .window(.root), with: a) }, messageId: messageId, isChannelPost: isChannelPost, atMessage: atMessageId, displayModalProgress: displayModalProgress) |> afterDisposed { progress.dispose() }).startStrict()) }) } static func openMessageReplies(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, navigationController: NavigationController, present: @escaping (ViewController, Any?) -> Void, messageId: MessageId, isChannelPost: Bool, atMessage atMessageId: MessageId?, displayModalProgress: Bool) -> Signal { return Signal { subscriber in let presentationData = context.sharedContext.currentPresentationData.with { $0 } var cancelImpl: (() -> Void)? let statusController = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { cancelImpl?() })) if displayModalProgress { present(statusController, nil) } let disposable = (fetchAndPreloadReplyThreadInfo(context: context, subject: isChannelPost ? .channelPost(messageId) : .groupMessage(messageId), atMessageId: atMessageId, preload: true) |> deliverOnMainQueue).startStrict(next: { [weak statusController] result in if displayModalProgress { statusController?.dismiss() } let chatLocation: NavigateToChatControllerParams.Location = .replyThread(result.message) let subject: ChatControllerSubject? if let atMessageId = atMessageId { subject = .message(id: .id(atMessageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil) } else if let index = result.scrollToLowerBoundMessage { subject = .message(id: .id(index.id), highlight: nil, timecode: nil) } else { subject = nil } context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: chatLocation, chatLocationContextHolder: result.contextHolder, subject: subject, activateInput: result.isEmpty ? .text : nil, keepStack: .always)) subscriber.putCompletion() }, error: { _ in let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 } present(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Channel_DiscussionMessageUnavailable, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil) }) cancelImpl = { [weak statusController] in disposable.dispose() statusController?.dismiss() subscriber.putCompletion() } return ActionDisposable { cancelImpl?() } } |> runOn(.mainQueue()) } }