From 1b6071675936658fa0367dbca326774936642911 Mon Sep 17 00:00:00 2001
From: Michael Kirk <michael@signal.org>
Date: Thu, 17 May 2018 15:45:48 -0400
Subject: [PATCH] Stop worrying about notification order by using delegate
 pattern

// FREEBIE
---
 .../ConversationViewController.m              | 16 -----
 .../SignalsNavigationController.m             |  1 -
 .../ViewControllers/OWSNavigationController.m | 50 ++++++++-----
 SignalMessaging/Views/OWSNavigationBar.swift  | 72 +++++--------------
 4 files changed, 48 insertions(+), 91 deletions(-)

diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m
index 351223ccc..502345336 100644
--- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m
+++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m
@@ -267,22 +267,6 @@ typedef enum : NSUInteger {
     return self;
 }
 
-- (CGSize)sizeForChildContentContainer:(id<UIContentContainer>)container
-               withParentContainerSize:(CGSize)parentSize NS_AVAILABLE_IOS(8_0);
-{
-    CGSize result = [super sizeForChildContentContainer:container withParentContainerSize:parentSize];
-    DDLogDebug(@"%@ in %s result: %@", self.logTag, __PRETTY_FUNCTION__, NSStringFromCGSize(result));
-
-    return result;
-}
-
-- (void)viewWillTransitionToSize:(CGSize)size
-       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
-{
-    DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
-    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
-}
-
 - (void)commonInit
 {
     _contactsManager = [Environment current].contactsManager;
diff --git a/Signal/src/ViewControllers/SignalsNavigationController.m b/Signal/src/ViewControllers/SignalsNavigationController.m
index 3225978e2..1ef76a540 100644
--- a/Signal/src/ViewControllers/SignalsNavigationController.m
+++ b/Signal/src/ViewControllers/SignalsNavigationController.m
@@ -45,7 +45,6 @@ static double const STALLED_PROGRESS = 0.9;
     }
 }
 
-
 - (void)dealloc
 {
     [[NSNotificationCenter defaultCenter] removeObserver:self];
diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m
index 46f29e8e0..8557d3155 100644
--- a/SignalMessaging/ViewControllers/OWSNavigationController.m
+++ b/SignalMessaging/ViewControllers/OWSNavigationController.m
@@ -7,7 +7,7 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface OWSNavigationController (OWSNavigationController) <UINavigationBarDelegate>
+@interface OWSNavigationController (OWSNavigationController) <UINavigationBarDelegate, NavBarLayoutDelegate>
 
 @end
 
@@ -51,42 +51,54 @@ NS_ASSUME_NONNULL_BEGIN
 
     self = [self initWithNavigationBarClass:[OWSNavigationBar class] toolbarClass:nil];
     [self pushViewController:rootViewController animated:NO];
-    
-    [self updateNavbarCallBannerLayout];
 
-    [[NSNotificationCenter defaultCenter] addObserver:self
-                                             selector:@selector(windowManagerCallDidChange:)
-                                                 name:OWSWindowManagerCallDidChangeNotification
-                                               object:nil];
+    if (![self.navigationBar isKindOfClass:[OWSNavigationBar class]]) {
+        OWSFail(@"%@ navigationBar was unexpected class: %@", self.logTag, self.navigationBar);
+        return self;
+    }
+
+    OWSNavigationBar *navbar = (OWSNavigationBar *)self.navigationBar;
+    navbar.navBarLayoutDelegate = self;
+    [self updateLayoutForNavbar:navbar];
 
     return self;
 }
 
-- (void)windowManagerCallDidChange:(NSNotification *)notification
+- (void)navBarCallLayoutDidChangeWithNavbar:(OWSNavigationBar *)navbar
 {
-    DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
-    [self updateNavbarCallBannerLayout];
+    [self updateLayoutForNavbar:navbar];
 }
 
-- (void)updateNavbarCallBannerLayout
+- (void)updateLayoutForNavbar:(OWSNavigationBar *)navbar
 {
+    DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__);
+
     if (@available(iOS 11.0, *)) {
         if (OWSWindowManager.sharedManager.hasCall) {
             self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0);
         } else {
             self.additionalSafeAreaInsets = UIEdgeInsetsZero;
         }
+        [navbar layoutSubviews];
     } else {
-        if (![self.navigationBar isKindOfClass:[OWSNavigationBar class]]) {
-            OWSFail(@"%@ in %s navigationBar was unexpected class", self.logTag, __PRETTY_FUNCTION__);
-            return;
+        // Pre iOS11 we have to position the frame manually
+        [navbar sizeToFit];
+
+        if (OWSWindowManager.sharedManager.hasCall) {
+            CGRect oldFrame = navbar.frame;
+            CGRect newFrame
+                = CGRectMake(oldFrame.origin.x, navbar.callBannerHeight, oldFrame.size.width, oldFrame.size.height);
+            navbar.frame = newFrame;
+        } else {
+            CGRect oldFrame = navbar.frame;
+            CGRect newFrame
+                = CGRectMake(oldFrame.origin.x, navbar.statusBarHeight, oldFrame.size.width, oldFrame.size.height);
+            navbar.frame = newFrame;
         }
 
-        OWSNavigationBar *navBar = (OWSNavigationBar *)self.navigationBar;
-        CGRect oldFrame = navBar.frame;
-        CGRect newFrame
-            = CGRectMake(oldFrame.origin.x, navBar.statusBarHeight, oldFrame.size.width, oldFrame.size.height);
-        navBar.frame = newFrame;
+        // Since the navbar's frame was updated, we need to be sure our child VC's
+        // container view is updated.
+        [self.view setNeedsLayout];
     }
 }
 
diff --git a/SignalMessaging/Views/OWSNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift
index 113816a31..0342968c7 100644
--- a/SignalMessaging/Views/OWSNavigationBar.swift
+++ b/SignalMessaging/Views/OWSNavigationBar.swift
@@ -5,9 +5,16 @@
 import Foundation
 import UIKit
 
+@objc
+protocol NavBarLayoutDelegate: class {
+    func navBarCallLayoutDidChange(navbar: OWSNavigationBar)
+}
+
 @objc
 class OWSNavigationBar: UINavigationBar {
 
+    weak var navBarLayoutDelegate: NavBarLayoutDelegate?
+
     // TODO - get a more precise value
     // TODO - test with other heights, e.g. w/ hotspot, w/ call in other app
     let navbarWithoutStatusHeight: CGFloat = 44
@@ -29,16 +36,8 @@ class OWSNavigationBar: UINavigationBar {
 
     @objc
     public func callDidChange() {
-        Logger.debug("\(self.logTag) in \(#function) OWSWindowManagerCallDidChange")
-
-        if #available(iOS 11, *) {
-            self.layoutSubviews()
-        } else {
-            self.sizeToFit()
-            self.frame.origin.y = statusBarHeight
-
-            self.layoutSubviews()
-        }
+        Logger.debug("\(self.logTag) in \(#function)")
+        self.navBarLayoutDelegate?.navBarCallLayoutDidChange(navbar: self)
     }
 
     required init?(coder aDecoder: NSCoder) {
@@ -53,9 +52,9 @@ class OWSNavigationBar: UINavigationBar {
         if #available(iOS 11, *) {
             return super.sizeThatFits(size)
         } else {
-            // pre iOS11, sizeThatFits is repeatedly called to size the navbar
-            // as of iOS11, this is not true and we have to size things in layoutSubviews.
-            // FIXME: pre-iOS11, though the size is right, there's a glitch on the titleView while push/popping items.
+            // pre iOS11, sizeThatFits is repeatedly called to determine how much space to reserve for that navbar.
+            // That is, increasing this causes the child view controller to be pushed down.
+            // (as of iOS11, this is not used and instead we use additionalSafeAreaInsets)
             let result = CGSize(width: CurrentAppContext().mainWindow!.bounds.width, height: navbarWithoutStatusHeight + statusBarHeight)
 
             Logger.debug("\(self.logTag) in \(#function): \(result)")
@@ -64,52 +63,10 @@ class OWSNavigationBar: UINavigationBar {
         }
     }
 
-//    override var center: CGPoint {
-//        get {
-//            Logger.debug("\(self.logTag) in \(#function)")
-//            return super.center
-//        }
-//        set {
-//            Logger.debug("\(self.logTag) in \(#function)")
-//            if OWSWindowManager.shared().hasCall() {
-//                var translated = newValue
-////                translated.y -= 20
-//                super.center = translated
-//            } else {
-//                super.center = newValue
-//            }
-//        }
-//    }
-
-    // seems unused.
-//    override var intrinsicContentSize: CGSize {
-//        return CGSize(width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight)
-//        return CGSize(width: UIScreen.main.bounds.width, height: 20)
-//    }
-
-//    override var bounds: CGRect {
-//        get {
-//            return super.bounds
-//        }
-//        set {
-//            super.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: ios11NavbarHeight)
-//        }
-//    }
-//
-//    override var frame: CGRect {
-//        get {
-//            return super.frame
-//        }
-//        set {
-//            super.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: ios11NavbarHeight)
-//        }
-//    }
-
     override func layoutSubviews() {
         Logger.debug("\(self.logTag) in \(#function)")
 
         guard OWSWindowManager.shared().hasCall() else {
-//        guard #available(iOS 11.0, *), OWSWindowManager.shared().hasCall() else {
             super.layoutSubviews()
             return
         }
@@ -121,6 +78,11 @@ class OWSNavigationBar: UINavigationBar {
 
         super.layoutSubviews()
 
+        guard #available(iOS 11, *) else {
+            return
+        }
+
+        // This is only necessary on iOS11, which has some private views within the navbar
         for subview in self.subviews {
             let stringFromClass = NSStringFromClass(subview.classForCoder)
             if stringFromClass.contains("BarBackground") {