From e5a229cd7a37d0d5cd0574a013f987ca9c0c054c Mon Sep 17 00:00:00 2001 From: Pete Walters Date: Thu, 16 May 2024 09:33:06 -0500 Subject: [PATCH] Coordinate dismiss of ComposeVC with presentation of ConversationVC --- .../ComposeViewController.swift | 34 +++++++------------ 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/Signal/src/ViewControllers/RecipientPicker/ComposeViewController.swift b/Signal/src/ViewControllers/RecipientPicker/ComposeViewController.swift index 96c1f7db46b..a51f6deb3b7 100644 --- a/Signal/src/ViewControllers/RecipientPicker/ComposeViewController.swift +++ b/Signal/src/ViewControllers/RecipientPicker/ComposeViewController.swift @@ -47,28 +47,20 @@ class ComposeViewController: RecipientPickerContainerViewController { /// Presents the conversation for the given thread and dismisses this /// controller such that the conversation is visible. - /// - /// - Note - /// In practice, the view controller dismissing us here is the same one - /// (a ``ConversationSplitViewController``) that will ultimately present the - /// conversation. To that end, there be dragons in potential races between - /// the two actions, which seem to particularly be prominent when this - /// method is called from a `DispatchQueue.main` block. (This happens, for - /// example, when doing some asynchronous work, such as a lookup, which - /// completes in a `DispatchQueue.main` block that calls this method.) - /// - /// Some example dragons found at the time of writing include user - /// interaction being disabled on the nav bar, incorrect nav bar layout, - /// keyboards refusing to pop, and the conversation input toolbar being - /// hidden behind the keyboard if it does pop. - /// - /// Ensuring that the presentation and dismissal are in separate dispatch - /// blocks seems to dodge the dragons. func newConversation(thread: TSThread) { - SignalApp.shared.presentConversationForThread(thread, action: .compose, animated: false) - - DispatchQueue.main.async { [weak self] in - self?.presentingViewController?.dismiss(animated: true) + presentingViewController?.dismiss(animated: true) + if let transitionCoordinator = presentingViewController?.transitionCoordinator { + // When transitionCoordinator is present, coordinate the immediate presentation of + // the conversationVC with the animated dismissal of the compose VC + transitionCoordinator.animate { _ in + UIView.performWithoutAnimation { + SignalApp.shared.presentConversationForThread(thread, action: .compose, animated: false) + } + } + } else { + // There isn't a transition coordinator present for some reason, revert to displaying + // the conversation VC in parallel with the animated dismissal of the compose VC + SignalApp.shared.presentConversationForThread(thread, action: .compose, animated: false) } }