From 94323baba826c0b6a9da4ac3e4eca661cc314e49 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 10 May 2018 15:10:39 -0400 Subject: [PATCH 01/30] tmp - mute hides callscreen --- Signal/src/ViewControllers/CallViewController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 58b8d2538..27d5ae73a 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -814,6 +814,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, Logger.info("\(TAG) called \(#function)") muteButton.isSelected = !muteButton.isSelected + self.didTapLeaveCall() + callUIAdapter.setIsMuted(call: call, isMuted: muteButton.isSelected) } @@ -916,10 +918,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, preferences.setIsCallKitPrivacyEnabled(preferences.isCallKitPrivacyEnabled()) } - func didTapLeaveCall(sender: UIGestureRecognizer) { - guard sender.state == .recognized else { - return - } +// func didTapLeaveCall(sender: UIGestureRecognizer) { + func didTapLeaveCall() { OWSWindowManager.shared().leaveCallView() } From e62fe87b01ffc321fe57c16d86e07c0c8e290232 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 10:14:11 -0400 Subject: [PATCH 02/30] show status bar *above* call window --- Signal/src/util/OWSWindowManager.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index beda29b7e..114dc403c 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -13,19 +13,25 @@ NS_ASSUME_NONNULL_BEGIN // Behind everything, especially the root window. const UIWindowLevel UIWindowLevel_Background = -1.f; -// In front of the root window _and_ status bar +// MJK FIXME: this *looks* right, but then we can't receive taps that +// touch the status bar. We could: obscure status bar, but that looks wrong. +// have *another* transparent window? +// +// In front of the root window, behind the status bar // but behind the screen blocking window. const UIWindowLevel UIWindowLevel_ReturnToCall(void); const UIWindowLevel UIWindowLevel_ReturnToCall(void) { - return UIWindowLevelStatusBar + 1.f; + return UIWindowLevelStatusBar - 1.f; } + // In front of the root window, behind the screen blocking window. const UIWindowLevel UIWindowLevel_CallView(void); const UIWindowLevel UIWindowLevel_CallView(void) { return UIWindowLevelNormal + 1.f; } + // In front of everything, including the status bar. const UIWindowLevel UIWindowLevel_ScreenBlocking(void); const UIWindowLevel UIWindowLevel_ScreenBlocking(void) From 772af10e500d051aa7859b901d1677706d77d019 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 10 May 2018 15:10:47 -0400 Subject: [PATCH 03/30] Resizing call banner window problem is the navigation bar is now too tall, since it has room for status. We could shirnk the nav bar, but maybe it's easier to just have the call banner in the navbar? // FREEBIE --- Signal/src/util/OWSWindowManager.m | 31 ++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index 114dc403c..832623158 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -156,6 +156,13 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) label.font = [UIFont ows_regularFontWithSize:14.f]; [rootView addSubview:label]; + [label autoPinBottomToSuperviewMargin]; + [label setCompressionResistanceHigh]; + [label setContentHuggingHigh]; + [label autoHCenterInSuperview]; + + // TODO animate... + // returnToCallLabel uses manual layout. // // TODO: Is there a better way to do this? @@ -329,21 +336,21 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) } else if (self.callViewController) { // Show Root Window + "Return to Call". - [self ensureRootWindowShown]; + [self ensureRootWindowShownWithActiveCall:YES]; [self ensureReturnToCallWindowShown]; [self ensureCallViewWindowHidden]; [self ensureScreenBlockWindowHidden]; } else { // Show Root Window - [self ensureRootWindowShown]; + [self ensureRootWindowShownWithActiveCall:NO]; [self ensureReturnToCallWindowHidden]; [self ensureCallViewWindowHidden]; [self ensureScreenBlockWindowHidden]; } } -- (void)ensureRootWindowShown +- (void)ensureRootWindowShownWithActiveCall:(BOOL)isActiveCall { OWSAssertIsOnMainThread(); @@ -351,11 +358,27 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) DDLogInfo(@"%@ showing root window.", self.logTag); } + static CGRect defaultFrame; + static CGRect frameWithActiveCall; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + defaultFrame = self.rootWindow.frame; + + CGFloat callBannerHeight = self.returnToCallWindow.frame.size.height; + frameWithActiveCall + = CGRectMake(0, callBannerHeight, defaultFrame.size.width, defaultFrame.size.height - callBannerHeight); + }); + + if (isActiveCall) { + self.rootWindow.frame = frameWithActiveCall; + } else { + self.rootWindow.frame = defaultFrame; + } + // By calling makeKeyAndVisible we ensure the rootViewController becomes firt responder. // In the normal case, that means the SignalViewController will call `becomeFirstResponder` // on the vc on top of its navigation stack. [self.rootWindow makeKeyAndVisible]; - } - (void)ensureRootWindowHidden From a7252544b0b7c0acd33f8b7f4d711cb8ff857619 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 10 May 2018 15:29:45 -0400 Subject: [PATCH 04/30] WIP: custom navbar TODO: Use custom navcontroller everywhere - no more UINavigationController listen to notification for when call starts/ends and sizeToFit. --- Signal.xcodeproj/project.pbxproj | 4 ++ .../SignalsNavigationController.m | 11 +++- Signal/src/views/SignalNavigationBar.swift | 66 +++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 Signal/src/views/SignalNavigationBar.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 1224b37ce..dd0637e62 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -407,6 +407,7 @@ 45F659821E1BE77000444429 /* NonCallKitCallUIAdaptee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F659811E1BE77000444429 /* NonCallKitCallUIAdaptee.swift */; }; 45FBC5C81DF8575700E9B410 /* CallKitCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC59A1DF8575700E9B410 /* CallKitCallManager.swift */; }; 45FBC5D11DF8592E00E9B410 /* SignalCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */; }; + 45FDA43520A4D22700396358 /* SignalNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FDA43420A4D22700396358 /* SignalNavigationBar.swift */; }; 4AC4EA13C8A444455DAB351F /* Pods_SignalMessaging.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 264242150E87D10A357DB07B /* Pods_SignalMessaging.framework */; }; 70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70377AAA1918450100CAF501 /* MobileCoreServices.framework */; }; 768A1A2B17FC9CD300E00ED8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 768A1A2A17FC9CD300E00ED8 /* libz.dylib */; }; @@ -1060,6 +1061,7 @@ 45F659811E1BE77000444429 /* NonCallKitCallUIAdaptee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NonCallKitCallUIAdaptee.swift; sourceTree = ""; }; 45FBC59A1DF8575700E9B410 /* CallKitCallManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitCallManager.swift; sourceTree = ""; }; 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalCall.swift; sourceTree = ""; }; + 45FDA43420A4D22700396358 /* SignalNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalNavigationBar.swift; sourceTree = ""; }; 69349DE607F5BA6036C9AC60 /* Pods-SignalShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalShareExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension.debug.xcconfig"; sourceTree = ""; }; 70377AAA1918450100CAF501 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 748A5CAEDD7C919FC64C6807 /* Pods_SignalTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SignalTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -2145,6 +2147,7 @@ 45A6DAD51EBBF85500893231 /* ReminderView.swift */, 450D19111F85236600970622 /* RemoteVideoView.h */, 450D19121F85236600970622 /* RemoteVideoView.m */, + 45FDA43420A4D22700396358 /* SignalNavigationBar.swift */, ); name = Views; path = views; @@ -3298,6 +3301,7 @@ 34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */, 34D1F0C01F8EC1760066283D /* MessageRecipientStatusUtils.swift in Sources */, 45F659731E1BD99C00444429 /* CallKitCallUIAdaptee.swift in Sources */, + 45FDA43520A4D22700396358 /* SignalNavigationBar.swift in Sources */, 45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */, 34277A5E20751BDC006049F2 /* OWSQuotedMessageView.m in Sources */, 458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */, diff --git a/Signal/src/ViewControllers/SignalsNavigationController.m b/Signal/src/ViewControllers/SignalsNavigationController.m index 5314fd7dd..02e6a6bb5 100644 --- a/Signal/src/ViewControllers/SignalsNavigationController.m +++ b/Signal/src/ViewControllers/SignalsNavigationController.m @@ -1,8 +1,9 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "SignalsNavigationController.h" +#import "Signal-Swift.h" #import #import #import @@ -21,6 +22,14 @@ static double const STALLED_PROGRESS = 0.9; @implementation SignalsNavigationController +- (instancetype)initWithRootViewController:(UIViewController *)rootViewController +{ + self = [self initWithNavigationBarClass:[SignalNavigationBar class] toolbarClass:nil]; + [self pushViewController:rootViewController animated:NO]; + + return self; +} + - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. diff --git a/Signal/src/views/SignalNavigationBar.swift b/Signal/src/views/SignalNavigationBar.swift new file mode 100644 index 000000000..5f4fc04ec --- /dev/null +++ b/Signal/src/views/SignalNavigationBar.swift @@ -0,0 +1,66 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +import Foundation +import UIKit + +@objc +class SignalNavigationBar: UINavigationBar { +// var isCallActive: Bool = false { +// didSet { +// guard oldValue != isCallActive else { +// return +// } +// +// if isCallActive { +// self.addSubview(callBanner) +//// callBanner.autoPinEdge(toSuperviewEdge: .top) +// callBanner.autoPinEdge(toSuperviewEdge: .leading) +// callBanner.autoPinEdge(toSuperviewEdge: .trailing) +// } else { +// callBanner.removeFromSuperview() +// } +// } +// } +// +// let callBanner: UIView +// let callLabel: UILabel +// let callBannerHeight: CGFloat = 40 +// +// override init(frame: CGRect) { +// callBanner = UIView() +// callBanner.backgroundColor = .green +// callBanner.autoSetDimension(.height, toSize: callBannerHeight) +// +// callLabel = UILabel() +// callLabel.text = "Return to your call..." +// callLabel.textColor = .white +// +// callBanner.addSubview(callLabel) +// callLabel.autoPinBottomToSuperviewMargin() +// callLabel.autoHCenterInSuperview() +// callLabel.setCompressionResistanceHigh() +// callLabel.setContentHuggingHigh() +// +// super.init(frame: frame) +// +// let debugTap = UITapGestureRecognizer(target: self, action: #selector(didTap)) +// self.addGestureRecognizer(debugTap) +// } +// +// @objc +// func didTap(sender: UITapGestureRecognizer) { +// Logger.debug("\(self.logTag) in \(#function)") +// self.isCallActive = !self.isCallActive +// } +// +// + override func sizeThatFits(_ size: CGSize) -> CGSize { + if OWSWindowManager.shared().hasCall() { + return CGSize(width: UIScreen.main.bounds.width, height: 30) + } else { + return super.sizeThatFits(size) + } + } +} From 91cd1af3f9d5111b0c1ebe395c7868ec33f5ba06 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 10:02:08 -0400 Subject: [PATCH 05/30] Extract ReturnToCallViewController // FREEBIE --- Signal.xcodeproj/project.pbxproj | 4 + .../ReturnToCallViewController.swift | 70 ++++++++++ Signal/src/util/OWSWindowManager.h | 1 - Signal/src/util/OWSWindowManager.m | 128 +++--------------- 4 files changed, 94 insertions(+), 109 deletions(-) create mode 100644 Signal/src/ViewControllers/ReturnToCallViewController.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index dd0637e62..0cb6fc3e7 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -352,6 +352,7 @@ 459B775C207BA46C0071D0AB /* OWSQuotedReplyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 459B775A207BA3A80071D0AB /* OWSQuotedReplyModel.m */; }; 459B775D207BA4810071D0AB /* OWSQuotedReplyModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 459B7759207BA3A80071D0AB /* OWSQuotedReplyModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; 45A2F005204473A3002E978A /* NewMessage.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45A2F004204473A3002E978A /* NewMessage.aifc */; }; + 45A60E7320AC674100FB1ABF /* ReturnToCallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A60E7220AC674100FB1ABF /* ReturnToCallViewController.swift */; }; 45A663C51F92EC760027B59E /* GroupTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A663C41F92EC760027B59E /* GroupTableViewCell.swift */; }; 45A6DAD61EBBF85500893231 /* ReminderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A6DAD51EBBF85500893231 /* ReminderView.swift */; }; 45AE48511E0732D6004D96C2 /* TurnServerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AE48501E0732D6004D96C2 /* TurnServerInfo.swift */; }; @@ -998,6 +999,7 @@ 459B7759207BA3A80071D0AB /* OWSQuotedReplyModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OWSQuotedReplyModel.h; sourceTree = ""; }; 459B775A207BA3A80071D0AB /* OWSQuotedReplyModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OWSQuotedReplyModel.m; sourceTree = ""; }; 45A2F004204473A3002E978A /* NewMessage.aifc */ = {isa = PBXFileReference; lastKnownFileType = file; name = NewMessage.aifc; path = Signal/AudioFiles/NewMessage.aifc; sourceTree = SOURCE_ROOT; }; + 45A60E7220AC674100FB1ABF /* ReturnToCallViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReturnToCallViewController.swift; sourceTree = ""; }; 45A663C41F92EC760027B59E /* GroupTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupTableViewCell.swift; sourceTree = ""; }; 45A6DAD51EBBF85500893231 /* ReminderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReminderView.swift; sourceTree = ""; }; 45AE48501E0732D6004D96C2 /* TurnServerInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TurnServerInfo.swift; sourceTree = ""; }; @@ -1686,6 +1688,7 @@ 340FC897204DAC8D007AEB0F /* ThreadSettings */, 34D1F0BE1F8EC1760066283D /* Utils */, 452B998F20A34B6B006F2F9E /* AddContactShareToExistingContactViewController.swift */, + 45A60E7220AC674100FB1ABF /* ReturnToCallViewController.swift */, ); path = ViewControllers; sourceTree = ""; @@ -3331,6 +3334,7 @@ 340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */, 4579431E1E7C8CE9008ED0C0 /* Pastelog.m in Sources */, 340FC8B0204DAC8D007AEB0F /* AddToBlockListViewController.m in Sources */, + 45A60E7320AC674100FB1ABF /* ReturnToCallViewController.swift in Sources */, 340FC8B3204DAC8D007AEB0F /* AppSettingsViewController.m in Sources */, 346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */, 45E5A6991F61E6DE001E4A8A /* MarqueeLabel.swift in Sources */, diff --git a/Signal/src/ViewControllers/ReturnToCallViewController.swift b/Signal/src/ViewControllers/ReturnToCallViewController.swift new file mode 100644 index 000000000..2b5873d05 --- /dev/null +++ b/Signal/src/ViewControllers/ReturnToCallViewController.swift @@ -0,0 +1,70 @@ +// +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. +// + +import Foundation + +@objc +public protocol ReturnToCallViewControllerDelegate: class { + func returnToCallWasTapped(_ viewController: ReturnToCallViewController) +} + +@objc +public class ReturnToCallViewController: UIViewController { + + public weak var delegate: ReturnToCallViewControllerDelegate? + + let returnToCallLabel = UILabel() + + public func startAnimating() { + self.returnToCallLabel.layer.removeAllAnimations() + self.returnToCallLabel.alpha = 1 + UIView.animate(withDuration: 1, + delay: 0, + options: [.repeat, .autoreverse], + animations: { self.returnToCallLabel.alpha = 0 }, + completion: { _ in self.returnToCallLabel.alpha = 1 }) + } + + public func stopAnimating() { + self.returnToCallLabel.layer.removeAllAnimations() + } + + override public func loadView() { + self.view = UIView() + + // This is the color of the iOS "return to call" banner. + view.backgroundColor = UIColor(rgbHex: 0x4cd964) + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didTapView)) + view.addGestureRecognizer(tapGesture) + + view.addSubview(returnToCallLabel) + + // System UI doesn't use dynamic type for status bar; neither do we. + returnToCallLabel.font = UIFont.ows_regularFont(withSize: 14) + returnToCallLabel.text = NSLocalizedString("CALL_WINDOW_RETURN_TO_CALL", comment: "Label for the 'return to call' banner.") + returnToCallLabel.textColor = .white + + returnToCallLabel.autoPinEdge(toSuperviewEdge: .bottom, withInset: 2) + returnToCallLabel.setCompressionResistanceHigh() + returnToCallLabel.setContentHuggingHigh() + returnToCallLabel.autoHCenterInSuperview() + } + + @objc + public func didTapView(gestureRecognizer: UITapGestureRecognizer) { + self.delegate?.returnToCallWasTapped(self) + } + + override public func viewWillLayoutSubviews() { + Logger.debug("\(self.logTag) in \(#function)") + + super.viewWillLayoutSubviews() + } + + override public func viewDidLayoutSubviews() { + Logger.debug("\(self.logTag) in \(#function)") + + super.viewDidLayoutSubviews() + } +} diff --git a/Signal/src/util/OWSWindowManager.h b/Signal/src/util/OWSWindowManager.h index 15dde5100..6877c6514 100644 --- a/Signal/src/util/OWSWindowManager.h +++ b/Signal/src/util/OWSWindowManager.h @@ -29,7 +29,6 @@ extern const UIWindowLevel UIWindowLevel_Background; - (void)startCall:(UIViewController *)callViewController; - (void)endCall:(UIViewController *)callViewController; - (void)leaveCallView; -- (void)returnToCallView; - (BOOL)hasCall; @end diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index 832623158..0d5ba0e59 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -10,6 +10,8 @@ NS_ASSUME_NONNULL_BEGIN +const CGFloat OWSWindowManagerCallScreenHeight = 40; + // Behind everything, especially the root window. const UIWindowLevel UIWindowLevel_Background = -1.f; @@ -50,14 +52,14 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) #pragma mark - -@interface OWSWindowManager () +@interface OWSWindowManager () // UIWindowLevelNormal @property (nonatomic) UIWindow *rootWindow; // UIWindowLevel_ReturnToCall @property (nonatomic) UIWindow *returnToCallWindow; -@property (nonatomic) UILabel *returnToCallLabel; +@property (nonatomic) ReturnToCallViewController *returnToCallViewController; // UIWindowLevel_CallView @property (nonatomic) UIWindow *callViewWindow; @@ -117,8 +119,6 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) self.returnToCallWindow = [self createReturnToCallWindow:rootWindow]; self.callViewWindow = [self createCallViewWindow:rootWindow]; - [self updateReturnToCallWindowLayout]; - [self ensureWindowState]; } @@ -128,80 +128,22 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) OWSAssert(rootWindow); // "Return to call" should remain at the top of the screen. - CGRect windowFrame = rootWindow.bounds; - // Use zero height until updateReturnToCallWindowLayout. - windowFrame.size.height = 0; + CGRect windowFrame = UIScreen.mainScreen.bounds; + windowFrame.size.height = OWSWindowManagerCallScreenHeight; UIWindow *window = [[UIWindow alloc] initWithFrame:windowFrame]; window.hidden = YES; window.windowLevel = UIWindowLevel_ReturnToCall(); window.opaque = YES; - // This is the color of the iOS "return to call" banner. - // TODO: What's the right color to use here? - UIColor *backgroundColor = [UIColor colorWithRGBHex:0x4cd964]; - window.backgroundColor = backgroundColor; - - UIViewController *viewController = [OWSWindowRootViewController new]; - viewController.view.backgroundColor = backgroundColor; - UIView *rootView = viewController.view; - rootView.userInteractionEnabled = YES; - [rootView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self - action:@selector(returnToCallWasTapped:)]]; - rootView.layoutMargins = UIEdgeInsetsZero; - - UILabel *label = [UILabel new]; - label.text = NSLocalizedString(@"CALL_WINDOW_RETURN_TO_CALL", @"Label for the 'return to call' banner."); - label.textColor = [UIColor whiteColor]; - // System UI doesn't use dynamic type; neither do we. - label.font = [UIFont ows_regularFontWithSize:14.f]; - [rootView addSubview:label]; - - [label autoPinBottomToSuperviewMargin]; - [label setCompressionResistanceHigh]; - [label setContentHuggingHigh]; - [label autoHCenterInSuperview]; - - // TODO animate... - - // returnToCallLabel uses manual layout. - // - // TODO: Is there a better way to do this? - label.translatesAutoresizingMaskIntoConstraints = NO; - self.returnToCallLabel = label; + ReturnToCallViewController *viewController = [ReturnToCallViewController new]; + self.returnToCallViewController = viewController; + viewController.delegate = self; window.rootViewController = viewController; return window; } -- (void)updateReturnToCallWindowLayout -{ - OWSAssertIsOnMainThread(); - - CGRect statusBarFrame = UIApplication.sharedApplication.statusBarFrame; - CGFloat statusBarHeight = statusBarFrame.size.height; - - CGRect windowFrame = self.rootWindow.bounds; - windowFrame.size.height = statusBarHeight + 20.f; - self.returnToCallWindow.frame = windowFrame; - self.returnToCallWindow.rootViewController.view.frame = windowFrame; - - [self.returnToCallLabel sizeToFit]; - CGRect labelFrame = self.returnToCallLabel.frame; - labelFrame.origin.x = floor(windowFrame.size.width - labelFrame.size.width); - self.returnToCallLabel.frame = labelFrame; - - UIView *rootView = self.returnToCallWindow.rootViewController.view; - - [rootView setNeedsLayout]; - [rootView layoutIfNeeded]; - - for (UIView *subview in rootView.subviews) { - [subview setNeedsLayout]; - [subview layoutIfNeeded]; - } -} - - (UIWindow *)createCallViewWindow:(UIWindow *)rootWindow { OWSAssertIsOnMainThread(); @@ -251,8 +193,6 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) [self.callNavigationController pushViewController:callViewController animated:NO]; self.isCallViewActive = YES; - [self updateReturnToCallWindowLayout]; - [self ensureWindowState]; } @@ -286,7 +226,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) [self ensureWindowState]; } -- (void)returnToCallView +- (void)showCallView { OWSAssertIsOnMainThread(); OWSAssert(self.callViewController); @@ -358,18 +298,12 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) DDLogInfo(@"%@ showing root window.", self.logTag); } - static CGRect defaultFrame; - static CGRect frameWithActiveCall; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - defaultFrame = self.rootWindow.frame; - - CGFloat callBannerHeight = self.returnToCallWindow.frame.size.height; - frameWithActiveCall - = CGRectMake(0, callBannerHeight, defaultFrame.size.width, defaultFrame.size.height - callBannerHeight); - }); - + CGRect defaultFrame = [UIScreen mainScreen].bounds; if (isActiveCall) { + CGRect frameWithActiveCall = CGRectMake(0, + OWSWindowManagerCallScreenHeight, + defaultFrame.size.width, + defaultFrame.size.height - OWSWindowManagerCallScreenHeight); self.rootWindow.frame = frameWithActiveCall; } else { self.rootWindow.frame = defaultFrame; @@ -396,26 +330,8 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) { OWSAssertIsOnMainThread(); - if (self.returnToCallWindow.hidden) { - DDLogInfo(@"%@ showing 'return to call' window.", self.logTag); - - [self.returnToCallLabel.layer removeAllAnimations]; - self.returnToCallLabel.alpha = 1.f; - [UIView animateWithDuration:1.f - delay:0.f - options:(UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse - | UIViewAnimationOptionBeginFromCurrentState) - animations:^{ - self.returnToCallLabel.alpha = 0.f; - } - completion:^(BOOL finished) { - self.returnToCallLabel.alpha = 1.f; - }]; - } - self.returnToCallWindow.hidden = NO; - - [self updateReturnToCallWindowLayout]; + [self.returnToCallViewController startAnimating]; } - (void)ensureReturnToCallWindowHidden @@ -427,7 +343,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) } self.returnToCallWindow.hidden = YES; - [self.returnToCallLabel.layer removeAllAnimations]; + [self.returnToCallViewController stopAnimating]; } - (void)ensureCallViewWindowShown @@ -478,15 +394,11 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) self.screenBlockingWindow.windowLevel = UIWindowLevel_Background; } -#pragma mark - Events +#pragma mark - ReturnToCallViewControllerDelegate -- (void)returnToCallWasTapped:(UIGestureRecognizer *)sender +- (void)returnToCallWasTapped:(ReturnToCallViewController *)viewController { - if (sender.state != UIGestureRecognizerStateRecognized) { - return; - } - - [self returnToCallView]; + [self showCallView]; } @end From 2258e18d34c7d38b5cc3763c81c688f9ef8733f6 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 10:23:23 -0400 Subject: [PATCH 06/30] rename for clarity // FREEBIE --- Signal/src/util/OWSWindowManager.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index 0d5ba0e59..1609990d3 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -71,7 +71,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) @property (nonatomic) BOOL isScreenBlockActive; -@property (nonatomic) BOOL isCallViewActive; +@property (nonatomic) BOOL shouldShowCallView; @property (nonatomic, nullable) UIViewController *callViewController; @@ -191,7 +191,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) // Attach callViewController to window. [self.callNavigationController popToRootViewControllerAnimated:NO]; [self.callNavigationController pushViewController:callViewController animated:NO]; - self.isCallViewActive = YES; + self.shouldShowCallView = YES; [self ensureWindowState]; } @@ -210,7 +210,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) // Dettach callViewController from window. [self.callNavigationController popToRootViewControllerAnimated:NO]; self.callViewController = nil; - self.isCallViewActive = NO; + self.shouldShowCallView = NO; [self ensureWindowState]; } @@ -219,9 +219,9 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) { OWSAssertIsOnMainThread(); OWSAssert(self.callViewController); - OWSAssert(self.isCallViewActive); + OWSAssert(self.shouldShowCallView); - self.isCallViewActive = NO; + self.shouldShowCallView = NO; [self ensureWindowState]; } @@ -230,9 +230,9 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) { OWSAssertIsOnMainThread(); OWSAssert(self.callViewController); - OWSAssert(!self.isCallViewActive); + OWSAssert(!self.shouldShowCallView); - self.isCallViewActive = YES; + self.shouldShowCallView = YES; [self ensureWindowState]; } @@ -266,7 +266,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) [self ensureReturnToCallWindowHidden]; [self ensureCallViewWindowHidden]; [self ensureScreenBlockWindowShown]; - } else if (self.callViewController && self.isCallViewActive) { + } else if (self.callViewController && self.shouldShowCallView) { // Show Call View. [self ensureRootWindowHidden]; From ffe17a3fcc82d88b7e56ea2da5a46c320b2bcfd1 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 10:28:51 -0400 Subject: [PATCH 07/30] add guard to avoid redundant show, fix logic in existing guard when hiding. // FREEBIE --- Signal/src/util/OWSWindowManager.m | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index 1609990d3..dc7456d19 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -330,6 +330,11 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) { OWSAssertIsOnMainThread(); + if (!self.returnToCallWindow.hidden) { + return; + } + + DDLogInfo(@"%@ showing 'return to call' window.", self.logTag); self.returnToCallWindow.hidden = NO; [self.returnToCallViewController startAnimating]; } @@ -338,10 +343,11 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) { OWSAssertIsOnMainThread(); - if (!self.returnToCallWindow.hidden) { - DDLogInfo(@"%@ hiding 'return to call' window.", self.logTag); + if (self.returnToCallWindow.hidden) { + return; } + DDLogInfo(@"%@ hiding 'return to call' window.", self.logTag); self.returnToCallWindow.hidden = YES; [self.returnToCallViewController stopAnimating]; } From 0e87cbe7a53e8d9c04b8291ef8a73bae9aafd168 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 12:02:15 -0400 Subject: [PATCH 08/30] WIP navbar resize -[ ] CallScreen -[x] functional button -[ ] needs design -[ ] disable other contact call buttons while in call -[ ] iOS11 -[x] resize nav content -[ ] background showing at top of all vc's -[] iPhoneX -[x] use differently sized banner for now -[] mimic X system design -[ ] iOS10 -[x] resize nav content -[ ] animation glitch while push/pop -[ ] iOS9 // FREEBIE --- Signal.xcodeproj/project.pbxproj | 6 - Signal/src/UIDevice+featureSupport.swift | 21 ++- .../ViewControllers/CallViewController.swift | 19 ++- Signal/src/util/OWSWindowManager.h | 2 + Signal/src/util/OWSWindowManager.m | 29 ++++- Signal/src/util/UIDevice+TSHardwareVersion.h | 25 ---- Signal/src/util/UIDevice+TSHardwareVersion.m | 28 ---- Signal/src/views/SignalNavigationBar.swift | 120 ++++++++++-------- 8 files changed, 128 insertions(+), 122 deletions(-) delete mode 100644 Signal/src/util/UIDevice+TSHardwareVersion.h delete mode 100644 Signal/src/util/UIDevice+TSHardwareVersion.m diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 0cb6fc3e7..c1233a017 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -489,7 +489,6 @@ FC5CDF3A1A3393DD00B47253 /* warning_white@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC5CDF381A3393DD00B47253 /* warning_white@2x.png */; }; FC9120411A39EFB70074545C /* qr@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FC91203F1A39EFB70074545C /* qr@2x.png */; }; FCB11D8C1A129A76002F93FB /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCB11D8B1A129A76002F93FB /* CoreMedia.framework */; }; - FCC81A981A44558300DFEC7D /* UIDevice+TSHardwareVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1190,8 +1189,6 @@ FC5CDF381A3393DD00B47253 /* warning_white@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "warning_white@2x.png"; sourceTree = ""; }; FC91203F1A39EFB70074545C /* qr@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "qr@2x.png"; sourceTree = ""; }; FCB11D8B1A129A76002F93FB /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; - FCC81A961A44558300DFEC7D /* UIDevice+TSHardwareVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+TSHardwareVersion.h"; sourceTree = ""; }; - FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+TSHardwareVersion.m"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -2122,8 +2119,6 @@ 450DF2041E0D74AC003D14BE /* Platform.swift */, 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */, FCFA64B11A24F29E0007FB87 /* UI Categories */, - FCC81A961A44558300DFEC7D /* UIDevice+TSHardwareVersion.h */, - FCC81A971A44558300DFEC7D /* UIDevice+TSHardwareVersion.m */, ); path = util; sourceTree = ""; @@ -3314,7 +3309,6 @@ 457F671B20746193000EABCD /* QuotedReplyPreview.swift in Sources */, 34DBF004206BD5A500025978 /* OWSBubbleView.m in Sources */, 34E88D262098C5AE00A608F4 /* ContactViewController.swift in Sources */, - FCC81A981A44558300DFEC7D /* UIDevice+TSHardwareVersion.m in Sources */, 76EB054018170B33006006FC /* AppDelegate.m in Sources */, 34D1F0831F8678AA0066283D /* ConversationInputTextView.m in Sources */, 340FC8B6204DAC8D007AEB0F /* OWSQRCodeScanningViewController.m in Sources */, diff --git a/Signal/src/UIDevice+featureSupport.swift b/Signal/src/UIDevice+featureSupport.swift index 67c30fe90..eca3e0f54 100644 --- a/Signal/src/UIDevice+featureSupport.swift +++ b/Signal/src/UIDevice+featureSupport.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -8,4 +8,23 @@ extension UIDevice { var supportsCallKit: Bool { return ProcessInfo().isOperatingSystemAtLeast(OperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) } + + var isIPhoneX: Bool { + switch UIScreen.main.nativeBounds.height { + case 1136: + // iPhone 5 or 5S or 5C + return false + case 1334: + // iPhone 6/6S/7/8 + return false + case 1920, 2208: + // iPhone 6+/6S+/7+/8+// + return false + case 2436: + return true + default: + owsFail("\(logTag) in \(#function) unknown device format") + return false + } + } } diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 27d5ae73a..5c29886c7 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -43,6 +43,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, var contactAvatarContainerView: UIView! var callStatusLabel: UILabel! var callDurationTimer: Timer? + var leaveCallViewButton: UIButton! // MARK: - Ongoing Call Controls @@ -254,6 +255,14 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, } func createContactViews() { + + leaveCallViewButton = UIButton() + let backButtonImage = self.view.isRTL() ? #imageLiteral(resourceName: "NavBarBackRTL") : #imageLiteral(resourceName: "NavBarBack") + leaveCallViewButton.setImage(backButtonImage, for: .normal) + leaveCallViewButton.autoSetDimensions(to: CGSize(width: 40, height: 40)) + leaveCallViewButton.addTarget(self, action: #selector(didTapLeaveCall(sender:)), for: .touchUpInside) + self.view.addSubview(leaveCallViewButton) + contactNameLabel = MarqueeLabel() // marquee config @@ -500,7 +509,10 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, remoteVideoView.autoPinEdgesToSuperviewEdges() - contactNameLabel.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin) + leaveCallViewButton.autoPinEdge(toSuperviewMargin: .left) + leaveCallViewButton.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin) + + contactNameLabel.autoPinEdge(.top, to: .bottom, of: leaveCallViewButton, withOffset: 8) contactNameLabel.autoPinLeadingToSuperviewMargin() contactNameLabel.setContentHuggingVerticalHigh() contactNameLabel.setCompressionResistanceHigh() @@ -814,8 +826,6 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, Logger.info("\(TAG) called \(#function)") muteButton.isSelected = !muteButton.isSelected - self.didTapLeaveCall() - callUIAdapter.setIsMuted(call: call, isMuted: muteButton.isSelected) } @@ -918,8 +928,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, preferences.setIsCallKitPrivacyEnabled(preferences.isCallKitPrivacyEnabled()) } -// func didTapLeaveCall(sender: UIGestureRecognizer) { - func didTapLeaveCall() { + func didTapLeaveCall(sender: UIButton) { OWSWindowManager.shared().leaveCallView() } diff --git a/Signal/src/util/OWSWindowManager.h b/Signal/src/util/OWSWindowManager.h index 6877c6514..7122f27df 100644 --- a/Signal/src/util/OWSWindowManager.h +++ b/Signal/src/util/OWSWindowManager.h @@ -12,6 +12,8 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - +extern NSString *const OWSWindowManagerCallDidChangeNotification; + extern const UIWindowLevel UIWindowLevel_Background; @interface OWSWindowManager : NSObject diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index dc7456d19..ae42b87b0 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -10,7 +10,23 @@ NS_ASSUME_NONNULL_BEGIN -const CGFloat OWSWindowManagerCallScreenHeight = 40; +NSString *const OWSWindowManagerCallDidChangeNotification = @"OWSWindowManagerCallDidChangeNotification"; +// NSString *const OWSWindowManagerWillShowReturnToCallWindowNotification = +// @"OWSWindowManagerWillShowReturnToCallWindowNotification"; NSString *const +// OWSWindowManagerWillHideReturnToCallWindowNotification = @"OWSWindowManagerWillHideReturnToCallWindowNotification"; + + +const CGFloat OWSWindowManagerCallScreenHeight(void); +const CGFloat OWSWindowManagerCallScreenHeight(void) +{ + if ([UIDevice currentDevice].isIPhoneX) { + // TODO - rather than a bigger banner, we should stick with iPhoneX + // design changes, which only apply a green circle around the clock UI. + return 60; + } else { + return 40; + } +} // Behind everything, especially the root window. const UIWindowLevel UIWindowLevel_Background = -1.f; @@ -129,7 +145,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) // "Return to call" should remain at the top of the screen. CGRect windowFrame = UIScreen.mainScreen.bounds; - windowFrame.size.height = OWSWindowManagerCallScreenHeight; + windowFrame.size.height = OWSWindowManagerCallScreenHeight(); UIWindow *window = [[UIWindow alloc] initWithFrame:windowFrame]; window.hidden = YES; window.windowLevel = UIWindowLevel_ReturnToCall(); @@ -188,6 +204,9 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) OWSAssert(!self.callViewController); self.callViewController = callViewController; + // TODO move to setter? + [NSNotificationCenter.defaultCenter postNotificationName:OWSWindowManagerCallDidChangeNotification object:nil]; + // Attach callViewController to window. [self.callNavigationController popToRootViewControllerAnimated:NO]; [self.callNavigationController pushViewController:callViewController animated:NO]; @@ -210,6 +229,8 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) // Dettach callViewController from window. [self.callNavigationController popToRootViewControllerAnimated:NO]; self.callViewController = nil; + [NSNotificationCenter.defaultCenter postNotificationName:OWSWindowManagerCallDidChangeNotification object:nil]; + self.shouldShowCallView = NO; [self ensureWindowState]; @@ -301,9 +322,9 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) CGRect defaultFrame = [UIScreen mainScreen].bounds; if (isActiveCall) { CGRect frameWithActiveCall = CGRectMake(0, - OWSWindowManagerCallScreenHeight, + OWSWindowManagerCallScreenHeight(), defaultFrame.size.width, - defaultFrame.size.height - OWSWindowManagerCallScreenHeight); + defaultFrame.size.height - OWSWindowManagerCallScreenHeight()); self.rootWindow.frame = frameWithActiveCall; } else { self.rootWindow.frame = defaultFrame; diff --git a/Signal/src/util/UIDevice+TSHardwareVersion.h b/Signal/src/util/UIDevice+TSHardwareVersion.h deleted file mode 100644 index 1424c1992..000000000 --- a/Signal/src/util/UIDevice+TSHardwareVersion.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// UIDevice+TSHardwareVersion.h -// Signal -// -// Created by Dylan Bourgeois on 19/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// -// Original Source : -// Erica Sadun, http://ericasadun.com -// iPhone Developer's Cookbook, 6.x Edition -// BSD License, Use at your own risk -// -// - -#import - - -@interface UIDevice (TSHardwareVersion) - -/* - * Returns true if device is iPhone 6 or 6+ - */ -- (BOOL)isiPhoneVersionSixOrMore; - -@end diff --git a/Signal/src/util/UIDevice+TSHardwareVersion.m b/Signal/src/util/UIDevice+TSHardwareVersion.m deleted file mode 100644 index fa87f631a..000000000 --- a/Signal/src/util/UIDevice+TSHardwareVersion.m +++ /dev/null @@ -1,28 +0,0 @@ -// -// UIDevice+TSHardwareVersion.m -// Signal -// -// Created by Dylan Bourgeois on 19/12/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. -// -// Original Source : -// Erica Sadun, http://ericasadun.com -// iPhone Developer's Cookbook, 6.x Edition -// BSD License, Use at your own risk -// -// - -#include -#import "UIDevice+TSHardwareVersion.h" - -@implementation UIDevice (TSHardwareVersion) - -// Look for phone-type devices with a width greater than or equal to the width -// of the original iPhone 6. Hopefully, this is somewhat future proof -- (BOOL)isiPhoneVersionSixOrMore { - return - self.userInterfaceIdiom == UIUserInterfaceIdiomPhone && - ([[UIScreen mainScreen] scale] * [[UIScreen mainScreen] bounds].size.width) >= 750; -} - -@end diff --git a/Signal/src/views/SignalNavigationBar.swift b/Signal/src/views/SignalNavigationBar.swift index 5f4fc04ec..dbeed4801 100644 --- a/Signal/src/views/SignalNavigationBar.swift +++ b/Signal/src/views/SignalNavigationBar.swift @@ -7,60 +7,74 @@ import UIKit @objc class SignalNavigationBar: UINavigationBar { -// var isCallActive: Bool = false { -// didSet { -// guard oldValue != isCallActive else { -// return -// } -// -// if isCallActive { -// self.addSubview(callBanner) -//// callBanner.autoPinEdge(toSuperviewEdge: .top) -// callBanner.autoPinEdge(toSuperviewEdge: .leading) -// callBanner.autoPinEdge(toSuperviewEdge: .trailing) -// } else { -// callBanner.removeFromSuperview() -// } -// } -// } -// -// let callBanner: UIView -// let callLabel: UILabel -// let callBannerHeight: CGFloat = 40 -// -// override init(frame: CGRect) { -// callBanner = UIView() -// callBanner.backgroundColor = .green -// callBanner.autoSetDimension(.height, toSize: callBannerHeight) -// -// callLabel = UILabel() -// callLabel.text = "Return to your call..." -// callLabel.textColor = .white -// -// callBanner.addSubview(callLabel) -// callLabel.autoPinBottomToSuperviewMargin() -// callLabel.autoHCenterInSuperview() -// callLabel.setCompressionResistanceHigh() -// callLabel.setContentHuggingHigh() -// -// super.init(frame: frame) -// -// let debugTap = UITapGestureRecognizer(target: self, action: #selector(didTap)) -// self.addGestureRecognizer(debugTap) -// } -// -// @objc -// func didTap(sender: UITapGestureRecognizer) { -// Logger.debug("\(self.logTag) in \(#function)") -// self.isCallActive = !self.isCallActive -// } -// -// - override func sizeThatFits(_ size: CGSize) -> CGSize { - if OWSWindowManager.shared().hasCall() { - return CGSize(width: UIScreen.main.bounds.width, height: 30) + + // TODO - get a more precise value + // TODO - test with other heights, e.g. w/ hotspot, w/ call in other app + let navbarHeight: CGFloat = 44 + + override init(frame: CGRect) { + super.init(frame: frame) + + // TODO better place to observe? + NotificationCenter.default.addObserver(forName: .OWSWindowManagerCallDidChange, object: nil, queue: nil) { _ in + Logger.debug("\(self.logTag) in \(#function) OWSWindowManagerCallDidChange") + + self.callDidChange() + } + } + + private func callDidChange() { + if #available(iOS 11, *) { + self.layoutSubviews() } else { - return super.sizeThatFits(size) + self.sizeToFit() + } + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func sizeThatFits(_ size: CGSize) -> CGSize { + // pre iOS11, sizeThatFits is repeatedly called to size the navbar, which is pretty straight forward + // as of iOS11, this is not true and we have to do things in layoutSubviews. + // FIXME: pre-iOS11, though the size is right, there's a glitch on the titleView while push/popping items. + let result: CGSize = { + if OWSWindowManager.shared().hasCall() { + // status bar height gets re-added + return CGSize(width: UIScreen.main.bounds.width, height: navbarHeight - UIApplication.shared.statusBarFrame.size.height) + } else { + return super.sizeThatFits(size) + } + }() + + Logger.debug("\(self.logTag) in \(#function): \(result)") + + return result + } + + override func layoutSubviews() { + Logger.debug("\(self.logTag) in \(#function)") + + guard #available(iOS 11.0, *), OWSWindowManager.shared().hasCall() else { + super.layoutSubviews() + return + } + +// let rect = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: self.navbarHeightWithoutStatusBar) +// self.frame = CGRect(x: 0, y: 20, width: UI Screen.main.bounds.width, height: ios11NavbarHeight) + self.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarHeight) + self.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarHeight) + + super.layoutSubviews() + + for subview in self.subviews { + let stringFromClass = NSStringFromClass(subview.classForCoder) + if stringFromClass.contains("BarBackground") { + subview.frame = self.bounds + } else if stringFromClass.contains("BarContentView") { + subview.frame = self.bounds + } } } } From 4dbd14ac417744c7b20748bddf5c52aef029ffbe Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 16:20:14 -0400 Subject: [PATCH 09/30] WIP navbar resize -[ ] CallScreen -[x] functional button -[ ] needs design -[x] disable conversation view call buttons while in call -[ ] iOS11 -[x] resize nav content -[ ] background showing at top of all vc's -[] iPhoneX -[x] use differently sized banner for now -[] mimic X system design -[ ] iOS10 -[x] resize nav content -[ ] animation glitch while push/pop -[ ] iOS9 // FREEBIE --- .../ConversationViewController.m | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 771c97735..b6ddfc198 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -289,6 +289,10 @@ typedef enum : NSUInteger { selector:@selector(blockedPhoneNumbersDidChange:) name:kNSNotificationName_BlockedPhoneNumbersDidChange object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowManagerCallDidChange:) + name:OWSWindowManagerCallDidChangeNotification + object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(identityStateDidChange:) name:kNSNotificationName_IdentityStateDidChange @@ -1225,6 +1229,11 @@ typedef enum : NSUInteger { self.navigationItem.leftBarButtonItem = backItem; } +- (void)windowManagerCallDidChange:(NSNotification *)notification +{ + [self updateBarButtonItems]; +} + - (void)updateBarButtonItems { if (self.userLeftGroup) { @@ -1239,9 +1248,21 @@ typedef enum : NSUInteger { // UIBarButtonItem in order to ensure that these buttons are spaced tightly. // The contents of the navigation bar are cramped in this view. UIButton *callButton = [UIButton buttonWithType:UIButtonTypeCustom]; - UIImage *image = [UIImage imageNamed:@"button_phone_white"]; + UIImage *image = [[UIImage imageNamed:@"button_phone_white"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [callButton setImage:image forState:UIControlStateNormal]; + + if (OWSWindowManager.sharedManager.hasCall) { + callButton.enabled = NO; + callButton.userInteractionEnabled = NO; + callButton.tintColor = UIColor.lightGrayColor; + } else { + callButton.enabled = YES; + callButton.userInteractionEnabled = YES; + callButton.tintColor = UIColor.whiteColor; + } + UIEdgeInsets imageEdgeInsets = UIEdgeInsetsZero; + // We normally would want to use left and right insets that ensure the button // is square and the icon is centered. However UINavigationBar doesn't offer us // control over the margins and spacing of its content, and the buttons end up From 3a9391f4fb4f3a77c4bda1f220863b047d3073de Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 17:54:54 -0400 Subject: [PATCH 10/30] notes on what didn't work --- Signal/src/AppDelegate.m | 4 + .../ConversationViewController.m | 19 ++++ .../SignalsNavigationController.m | 99 ++++++++++++++++++- Signal/src/util/OWSWindowManager.m | 3 + Signal/src/views/SignalNavigationBar.swift | 24 +++++ 5 files changed, 148 insertions(+), 1 deletion(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 83ddd3635..42201aec1 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1099,6 +1099,10 @@ static NSTimeInterval launchStartedAt; // Resume lazy restore. [OWSBackupLazyRestoreJob runAsync]; #endif + + + OutboundCallInitiator *outboundCallInitiator = SignalApp.sharedApp.outboundCallInitiator; + [outboundCallInitiator initiateCallWithHandle:@"+14158181337"]; } - (void)registrationStateDidChange diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index b6ddfc198..ca4eddba5 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -266,6 +266,22 @@ typedef enum : NSUInteger { return self; } +- (CGSize)sizeForChildContentContainer:(id)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)coordinator +{ + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; +} + - (void)commonInit { _contactsManager = [Environment current].contactsManager; @@ -484,6 +500,7 @@ typedef enum : NSUInteger { { [super viewDidLoad]; + // self.topLayoutGuide [self createContents]; [self.navigationController.navigationBar setTranslucent:NO]; @@ -510,6 +527,8 @@ typedef enum : NSUInteger { { [super loadView]; + // extendedLayoutIncludesOpaqueBars + self.extendedLayoutIncludesOpaqueBars = YES; self.view.backgroundColor = [UIColor ows_toolbarBackgroundColor]; } diff --git a/Signal/src/ViewControllers/SignalsNavigationController.m b/Signal/src/ViewControllers/SignalsNavigationController.m index 02e6a6bb5..96337e540 100644 --- a/Signal/src/ViewControllers/SignalsNavigationController.m +++ b/Signal/src/ViewControllers/SignalsNavigationController.m @@ -24,19 +24,115 @@ static double const STALLED_PROGRESS = 0.9; - (instancetype)initWithRootViewController:(UIViewController *)rootViewController { + // Attempt 1: negative additionalSafeArea + // Failure: additionalSafeArea insets cannot be negative + // UIEdgeInsets newSafeArea = UIEdgeInsetsMake(-50, 30, 20, 30); + // rootViewController.additionalSafeAreaInsets = newSafeArea; + + // Attempt 2: safeAreaInsets on vc.view + // failure. they're already 0 + // UIEdgeInsets existingInsets = rootViewController.view.safeAreaInsets; + + // Attempt 3: override topLayoutGuide? + // Failure - not called. + // overriding it does no good - it's not called by default layout code. + // presumably it just existing if you want to use it as an anchor. + + // Attemp 4: sizeForChildContentConainer? + // Failure - not called. + + // Attempt 5: autoSetDimension on navbar + // Failure: no effect on rendered size + + // Attempt 6: manually set child frames in will/didLayoutSubviews + + + // Attempt 7: Since we can't seem to *shrink* the navbar, maybe we can grow it. + // make additionalSafeAreaInsets +// self.additionalSafeAreaInsets = UIEdgeInsetsMake(100, 0, 0, 0); + + self = [self initWithNavigationBarClass:[SignalNavigationBar class] toolbarClass:nil]; [self pushViewController:rootViewController animated:NO]; - + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowManagerCallDidChange:) + name:OWSWindowManagerCallDidChangeNotification + object:nil]; + return self; } +- (CGSize)sizeForChildContentContainer:(id)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)coordinator +{ + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; +} + +- (void)windowManagerCallDidChange:(NSNotification *)notification +{ + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + if (OWSWindowManager.sharedManager.hasCall) { + + } else { + } +} + +- (id)topLayoutGuide +{ + id result = [super topLayoutGuide]; + + DDLogDebug(@"%@ result: %@", self.logTag, result); + return result; +} + - (void)viewDidLoad { [super viewDidLoad]; + + // self.view.safeAreaInsets = // Do any additional setup after loading the view. [self initializeObserver]; [self updateSocketStatusView]; } + +- (void)viewDidAppear:(BOOL)animated +{ + [super viewDidAppear:animated]; + + // UIEdgeInsets newSafeArea = UIEdgeInsetsMake(50, 10, 20, 30); + // // Adjust the safe area insets of the + // // embedded child view controller. + // UIViewController *child = self.childViewControllers[0]; + // child.additionalSafeAreaInsets = newSafeArea; +} + +- (void)viewWillLayoutSubviews +{ + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + [super viewWillLayoutSubviews]; +} + +- (void)viewDidLayoutSubviews +{ + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + [super viewDidLayoutSubviews]; + // if (OWSWindowManager.sharedManager.hasCall) { + // self.topViewController.view.frame = CGRectMake(0, 44, 375, 583); + // self.topViewController.view.bounds = CGRectMake(0, 0, 375, 583); + // } +} + - (void)initializeSocketStatusBar { if (!_socketStatusView) { _socketStatusView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; @@ -52,6 +148,7 @@ static double const STALLED_PROGRESS = 0.9; } } + - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index ae42b87b0..887324729 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -275,6 +275,9 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) OWSAssert(self.callViewWindow); OWSAssert(self.screenBlockingWindow); + // MJK remove + self.rootWindow.backgroundColor = UIColor.yellowColor; + // To avoid bad frames, we never want to hide the blocking window, so we manipulate // its window level to "hide" it behind other windows. The other windows have fixed // window level and are shown/hidden as necessary. diff --git a/Signal/src/views/SignalNavigationBar.swift b/Signal/src/views/SignalNavigationBar.swift index dbeed4801..78b8c28ff 100644 --- a/Signal/src/views/SignalNavigationBar.swift +++ b/Signal/src/views/SignalNavigationBar.swift @@ -53,6 +53,30 @@ class SignalNavigationBar: UINavigationBar { return result } + // seems unused. +// override var intrinsicContentSize: CGSize { +// return CGSize(width: UIScreen.main.bounds.width, height: navbarHeight) +// 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)") From a2b1793262ebe35cb23b85dd35b3eeb44a57437d Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 21:24:55 -0400 Subject: [PATCH 11/30] initial render is wrong, but settles somewhere nice -[x] fix initial placement -[x] add additional top safe area? // FREEBIE --- .../ConversationViewController.m | 2 +- .../SignalsNavigationController.m | 14 ++++++--- Signal/src/util/OWSWindowManager.m | 18 ++++++------ Signal/src/views/SignalNavigationBar.swift | 29 +++++++++++++++++-- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index ca4eddba5..89e9d8e81 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -528,7 +528,7 @@ typedef enum : NSUInteger { [super loadView]; // extendedLayoutIncludesOpaqueBars - self.extendedLayoutIncludesOpaqueBars = YES; + // self.extendedLayoutIncludesOpaqueBars = YES; self.view.backgroundColor = [UIColor ows_toolbarBackgroundColor]; } diff --git a/Signal/src/ViewControllers/SignalsNavigationController.m b/Signal/src/ViewControllers/SignalsNavigationController.m index 96337e540..dc263b4e2 100644 --- a/Signal/src/ViewControllers/SignalsNavigationController.m +++ b/Signal/src/ViewControllers/SignalsNavigationController.m @@ -49,9 +49,9 @@ static double const STALLED_PROGRESS = 0.9; // Attempt 7: Since we can't seem to *shrink* the navbar, maybe we can grow it. // make additionalSafeAreaInsets -// self.additionalSafeAreaInsets = UIEdgeInsetsMake(100, 0, 0, 0); - - + + [self updateAdditionalSafeAreaInsets]; + self = [self initWithNavigationBarClass:[SignalNavigationBar class] toolbarClass:nil]; [self pushViewController:rootViewController animated:NO]; @@ -82,9 +82,15 @@ static double const STALLED_PROGRESS = 0.9; - (void)windowManagerCallDidChange:(NSNotification *)notification { DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - if (OWSWindowManager.sharedManager.hasCall) { + [self updateAdditionalSafeAreaInsets]; +} +- (void)updateAdditionalSafeAreaInsets +{ + if (OWSWindowManager.sharedManager.hasCall) { + self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0); } else { + self.additionalSafeAreaInsets = UIEdgeInsetsZero; } } diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index 887324729..7ca9ebe03 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -323,15 +323,15 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) } CGRect defaultFrame = [UIScreen mainScreen].bounds; - if (isActiveCall) { - CGRect frameWithActiveCall = CGRectMake(0, - OWSWindowManagerCallScreenHeight(), - defaultFrame.size.width, - defaultFrame.size.height - OWSWindowManagerCallScreenHeight()); - self.rootWindow.frame = frameWithActiveCall; - } else { - self.rootWindow.frame = defaultFrame; - } + // if (isActiveCall) { + // CGRect frameWithActiveCall = CGRectMake(0, + // OWSWindowManagerCallScreenHeight(), + // defaultFrame.size.width, + // defaultFrame.size.height - OWSWindowManagerCallScreenHeight()); + // self.rootWindow.frame = frameWithActiveCall; + // } else { + self.rootWindow.frame = defaultFrame; + // } // By calling makeKeyAndVisible we ensure the rootViewController becomes firt responder. // In the normal case, that means the SignalViewController will call `becomeFirstResponder` diff --git a/Signal/src/views/SignalNavigationBar.swift b/Signal/src/views/SignalNavigationBar.swift index 78b8c28ff..017178c39 100644 --- a/Signal/src/views/SignalNavigationBar.swift +++ b/Signal/src/views/SignalNavigationBar.swift @@ -11,6 +11,7 @@ class SignalNavigationBar: UINavigationBar { // TODO - get a more precise value // TODO - test with other heights, e.g. w/ hotspot, w/ call in other app let navbarHeight: CGFloat = 44 + let callBannerHeight: CGFloat = 40 override init(frame: CGRect) { super.init(frame: frame) @@ -24,6 +25,11 @@ class SignalNavigationBar: UINavigationBar { } private func callDidChange() { +// if OWSWindowManager.shared().hasCall() { +// self.bounds.origin.y = -20 +// } else { +// self.bounds.origin.y = 0 +// } if #available(iOS 11, *) { self.layoutSubviews() } else { @@ -53,6 +59,23 @@ class SignalNavigationBar: UINavigationBar { return result } +// 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: navbarHeight) @@ -87,7 +110,7 @@ class SignalNavigationBar: UINavigationBar { // let rect = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: self.navbarHeightWithoutStatusBar) // self.frame = CGRect(x: 0, y: 20, width: UI Screen.main.bounds.width, height: ios11NavbarHeight) - self.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarHeight) + self.frame = CGRect(x: 0, y: callBannerHeight, width: UIScreen.main.bounds.width, height: navbarHeight) self.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarHeight) super.layoutSubviews() @@ -95,9 +118,9 @@ class SignalNavigationBar: UINavigationBar { for subview in self.subviews { let stringFromClass = NSStringFromClass(subview.classForCoder) if stringFromClass.contains("BarBackground") { - subview.frame = self.bounds + subview.frame = self.bounds//.offsetBy(dx: 0, dy: 20) } else if stringFromClass.contains("BarContentView") { - subview.frame = self.bounds + subview.frame = self.bounds//.offsetBy(dx: 0, dy: 20) } } } From 12c98f434007928360060364a3ab7b23873cf981 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 21:37:04 -0400 Subject: [PATCH 12/30] cleanup and move to OWSNavigationController // FREEBIE --- .../ViewControllers/OWSNavigationController.m | 59 +++++++++- .../SignalsNavigationController.m | 109 ------------------ 2 files changed, 58 insertions(+), 110 deletions(-) diff --git a/Signal/src/ViewControllers/OWSNavigationController.m b/Signal/src/ViewControllers/OWSNavigationController.m index 87bdffd41..9ad78b627 100644 --- a/Signal/src/ViewControllers/OWSNavigationController.m +++ b/Signal/src/ViewControllers/OWSNavigationController.m @@ -1,8 +1,9 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSNavigationController.h" +#import "Signal-Swift.h" // We use a category to expose UINavigationController's private // UINavigationBarDelegate methods. @@ -20,6 +21,62 @@ @implementation OWSNavigationController +- (instancetype)initWithRootViewController:(UIViewController *)rootViewController +{ + // Attempt 1: negative additionalSafeArea + // Failure: additionalSafeArea insets cannot be negative + // UIEdgeInsets newSafeArea = UIEdgeInsetsMake(-50, 30, 20, 30); + // rootViewController.additionalSafeAreaInsets = newSafeArea; + + // Attempt 2: safeAreaInsets on vc.view + // failure. they're already 0 + // UIEdgeInsets existingInsets = rootViewController.view.safeAreaInsets; + + // Attempt 3: override topLayoutGuide? + // Failure - not called. + // overriding it does no good - it's not called by default layout code. + // presumably it just existing if you want to use it as an anchor. + + // Attemp 4: sizeForChildContentConainer? + // Failure - not called. + + // Attempt 5: autoSetDimension on navbar + // Failure: no effect on rendered size + + // Attempt 6: manually set child frames in will/didLayoutSubviews + // glitchy, and viewcontrollers re-layout themselves afterwards anyway + + // Attempt 7: Since we can't seem to *shrink* the navbar, maybe we can grow it. + // make additionalSafeAreaInsets + + [self updateAdditionalSafeAreaInsets]; + + self = [self initWithNavigationBarClass:[SignalNavigationBar class] toolbarClass:nil]; + [self pushViewController:rootViewController animated:NO]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(windowManagerCallDidChange:) + name:OWSWindowManagerCallDidChangeNotification + object:nil]; + + return self; +} + +- (void)windowManagerCallDidChange:(NSNotification *)notification +{ + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + [self updateAdditionalSafeAreaInsets]; +} + +- (void)updateAdditionalSafeAreaInsets +{ + if (OWSWindowManager.sharedManager.hasCall) { + self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0); + } else { + self.additionalSafeAreaInsets = UIEdgeInsetsZero; + } +} + - (void)viewDidLoad { [super viewDidLoad]; diff --git a/Signal/src/ViewControllers/SignalsNavigationController.m b/Signal/src/ViewControllers/SignalsNavigationController.m index dc263b4e2..3225978e2 100644 --- a/Signal/src/ViewControllers/SignalsNavigationController.m +++ b/Signal/src/ViewControllers/SignalsNavigationController.m @@ -22,123 +22,14 @@ static double const STALLED_PROGRESS = 0.9; @implementation SignalsNavigationController -- (instancetype)initWithRootViewController:(UIViewController *)rootViewController -{ - // Attempt 1: negative additionalSafeArea - // Failure: additionalSafeArea insets cannot be negative - // UIEdgeInsets newSafeArea = UIEdgeInsetsMake(-50, 30, 20, 30); - // rootViewController.additionalSafeAreaInsets = newSafeArea; - - // Attempt 2: safeAreaInsets on vc.view - // failure. they're already 0 - // UIEdgeInsets existingInsets = rootViewController.view.safeAreaInsets; - - // Attempt 3: override topLayoutGuide? - // Failure - not called. - // overriding it does no good - it's not called by default layout code. - // presumably it just existing if you want to use it as an anchor. - - // Attemp 4: sizeForChildContentConainer? - // Failure - not called. - - // Attempt 5: autoSetDimension on navbar - // Failure: no effect on rendered size - - // Attempt 6: manually set child frames in will/didLayoutSubviews - - - // Attempt 7: Since we can't seem to *shrink* the navbar, maybe we can grow it. - // make additionalSafeAreaInsets - - [self updateAdditionalSafeAreaInsets]; - - self = [self initWithNavigationBarClass:[SignalNavigationBar class] toolbarClass:nil]; - [self pushViewController:rootViewController animated:NO]; - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(windowManagerCallDidChange:) - name:OWSWindowManagerCallDidChangeNotification - object:nil]; - - return self; -} - -- (CGSize)sizeForChildContentContainer:(id)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)coordinator -{ - DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator]; -} - -- (void)windowManagerCallDidChange:(NSNotification *)notification -{ - DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - [self updateAdditionalSafeAreaInsets]; -} - -- (void)updateAdditionalSafeAreaInsets -{ - if (OWSWindowManager.sharedManager.hasCall) { - self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0); - } else { - self.additionalSafeAreaInsets = UIEdgeInsetsZero; - } -} - -- (id)topLayoutGuide -{ - id result = [super topLayoutGuide]; - - DDLogDebug(@"%@ result: %@", self.logTag, result); - return result; -} - - (void)viewDidLoad { [super viewDidLoad]; - // self.view.safeAreaInsets = // Do any additional setup after loading the view. [self initializeObserver]; [self updateSocketStatusView]; } - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - - // UIEdgeInsets newSafeArea = UIEdgeInsetsMake(50, 10, 20, 30); - // // Adjust the safe area insets of the - // // embedded child view controller. - // UIViewController *child = self.childViewControllers[0]; - // child.additionalSafeAreaInsets = newSafeArea; -} - -- (void)viewWillLayoutSubviews -{ - DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - [super viewWillLayoutSubviews]; -} - -- (void)viewDidLayoutSubviews -{ - DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - [super viewDidLayoutSubviews]; - // if (OWSWindowManager.sharedManager.hasCall) { - // self.topViewController.view.frame = CGRectMake(0, 44, 375, 583); - // self.topViewController.view.bounds = CGRectMake(0, 0, 375, 583); - // } -} - - (void)initializeSocketStatusBar { if (!_socketStatusView) { _socketStatusView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault]; From 33eb4c38cd7ef629001bef15024c3c7c9ad02185 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 21:51:34 -0400 Subject: [PATCH 13/30] Centralize translucency configuration // FREEBIE --- .../AppSettings/AppSettingsViewController.m | 1 - .../AppSettings/BlockListViewController.m | 6 ------ .../AppSettings/DomainFrontingCountryViewController.m | 1 - .../ConversationView/ConversationViewController.m | 5 ----- Signal/src/ViewControllers/HomeView/HomeViewController.m | 1 - .../src/ViewControllers/NewContactThreadViewController.m | 2 -- Signal/src/ViewControllers/NewGroupViewController.m | 7 ------- Signal/src/ViewControllers/ProfileViewController.m | 3 +-- .../ThreadSettings/ShowGroupMembersViewController.m | 5 ----- .../ThreadSettings/UpdateGroupViewController.m | 9 +-------- Signal/src/views/SignalNavigationBar.swift | 2 ++ SignalMessaging/ViewControllers/OWSTableViewController.m | 7 ------- SignalMessaging/contacts/CountryCodeViewController.m | 1 - SignalMessaging/contacts/SelectRecipientViewController.m | 1 - SignalMessaging/contacts/SelectThreadViewController.m | 6 ------ 15 files changed, 4 insertions(+), 53 deletions(-) diff --git a/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m index 241459a56..51de91328 100644 --- a/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m @@ -80,7 +80,6 @@ OWSAssert([self.navigationController isKindOfClass:[OWSNavigationController class]]); - [self.navigationController.navigationBar setTranslucent:NO]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self diff --git a/Signal/src/ViewControllers/AppSettings/BlockListViewController.m b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m index a0d30979d..e064028ac 100644 --- a/Signal/src/ViewControllers/AppSettings/BlockListViewController.m +++ b/Signal/src/ViewControllers/AppSettings/BlockListViewController.m @@ -47,12 +47,6 @@ NS_ASSUME_NONNULL_BEGIN [self updateTableContents]; } -- (void)viewDidLoad -{ - [super viewDidLoad]; - [self.navigationController.navigationBar setTranslucent:NO]; -} - #pragma mark - Table view data source - (void)updateTableContents diff --git a/Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.m b/Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.m index a5f2ccf8b..06028daf5 100644 --- a/Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.m +++ b/Signal/src/ViewControllers/AppSettings/DomainFrontingCountryViewController.m @@ -31,7 +31,6 @@ NS_ASSUME_NONNULL_BEGIN @"CENSORSHIP_CIRCUMVENTION_COUNTRY_VIEW_TITLE", @"Title for the 'censorship circumvention country' view."); self.view.backgroundColor = [UIColor whiteColor]; - [self.navigationController.navigationBar setTranslucent:NO]; [self createViews]; } diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 89e9d8e81..c954eae7b 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -500,11 +500,8 @@ typedef enum : NSUInteger { { [super viewDidLoad]; - // self.topLayoutGuide [self createContents]; - [self.navigationController.navigationBar setTranslucent:NO]; - [self registerCellClasses]; [self createConversationScrollButtons]; @@ -527,8 +524,6 @@ typedef enum : NSUInteger { { [super loadView]; - // extendedLayoutIncludesOpaqueBars - // self.extendedLayoutIncludesOpaqueBars = YES; self.view.backgroundColor = [UIColor ows_toolbarBackgroundColor]; } diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index 9b3b6d81c..e68963b39 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -252,7 +252,6 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations - (void)viewDidLoad { [super viewDidLoad]; - [self.navigationController.navigationBar setTranslucent:NO]; self.editingDbConnection = OWSPrimaryStorage.sharedManager.newDatabaseConnection; diff --git a/Signal/src/ViewControllers/NewContactThreadViewController.m b/Signal/src/ViewControllers/NewContactThreadViewController.m index bf1c145c7..bc531085a 100644 --- a/Signal/src/ViewControllers/NewContactThreadViewController.m +++ b/Signal/src/ViewControllers/NewContactThreadViewController.m @@ -269,8 +269,6 @@ NS_ASSUME_NONNULL_BEGIN // a message. [self.contactsViewHelper.contactsManager requestSystemContactsOnce]; - [self.navigationController.navigationBar setTranslucent:NO]; - [self showContactAppropriateViews]; } diff --git a/Signal/src/ViewControllers/NewGroupViewController.m b/Signal/src/ViewControllers/NewGroupViewController.m index 3fac30bd9..2482f23ff 100644 --- a/Signal/src/ViewControllers/NewGroupViewController.m +++ b/Signal/src/ViewControllers/NewGroupViewController.m @@ -420,13 +420,6 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; #pragma mark - Methods -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [self.navigationController.navigationBar setTranslucent:NO]; -} - - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; diff --git a/Signal/src/ViewControllers/ProfileViewController.m b/Signal/src/ViewControllers/ProfileViewController.m index eeaf5881c..bc661c815 100644 --- a/Signal/src/ViewControllers/ProfileViewController.m +++ b/Signal/src/ViewControllers/ProfileViewController.m @@ -75,7 +75,6 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat { [super loadView]; - [self.navigationController.navigationBar setTranslucent:NO]; self.title = NSLocalizedString(@"PROFILE_VIEW_TITLE", @"Title for the profile view."); _avatarViewHelper = [AvatarViewHelper new]; @@ -94,7 +93,7 @@ NSString *const kProfileView_LastPresentedDate = @"kProfileView_LastPresentedDat UIView *contentView = [UIView containerView]; contentView.backgroundColor = [UIColor whiteColor]; [self.view addSubview:contentView]; - [contentView autoPinEdgeToSuperviewEdge:ALEdgeTop]; + [contentView autoPinToTopLayoutGuideOfViewController:self withInset:0]; [contentView autoPinWidthToSuperview]; const CGFloat fontSizePoints = ScaleFromIPhone5To7Plus(16.f, 20.f); diff --git a/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m index f22e16e5b..757520e7f 100644 --- a/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m @@ -97,11 +97,6 @@ NS_ASSUME_NONNULL_BEGIN OWSAssert([self.navigationController isKindOfClass:[OWSNavigationController class]]); - // HACK otherwise CNContactViewController Navbar is shown as black. - // RADAR rdar://28433898 http://www.openradar.me/28433898 - // CNContactViewController incompatible with opaque navigation bar - [self.navigationController.navigationBar setTranslucent:YES]; - self.title = _thread.groupModel.groupName; [self updateTableContents]; diff --git a/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m b/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m index a67d5e7ae..4b5a03c17 100644 --- a/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/UpdateGroupViewController.m @@ -113,7 +113,7 @@ NS_ASSUME_NONNULL_BEGIN [self.view addSubview:firstSection]; [firstSection autoSetDimension:ALDimensionHeight toSize:100.f]; [firstSection autoPinWidthToSuperview]; - [firstSection autoPinEdgeToSuperviewEdge:ALEdgeTop]; + [firstSection autoPinToTopLayoutGuideOfViewController:self withInset:0]; _tableViewController = [OWSTableViewController new]; _tableViewController.delegate = self; @@ -125,13 +125,6 @@ NS_ASSUME_NONNULL_BEGIN [self updateTableContents]; } -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [self.navigationController.navigationBar setTranslucent:NO]; -} - - (void)setHasUnsavedChanges:(BOOL)hasUnsavedChanges { _hasUnsavedChanges = hasUnsavedChanges; diff --git a/Signal/src/views/SignalNavigationBar.swift b/Signal/src/views/SignalNavigationBar.swift index 017178c39..43c75353e 100644 --- a/Signal/src/views/SignalNavigationBar.swift +++ b/Signal/src/views/SignalNavigationBar.swift @@ -16,6 +16,8 @@ class SignalNavigationBar: UINavigationBar { override init(frame: CGRect) { super.init(frame: frame) + self.isTranslucent = false + // TODO better place to observe? NotificationCenter.default.addObserver(forName: .OWSWindowManagerCallDidChange, object: nil, queue: nil) { _ in Logger.debug("\(self.logTag) in \(#function) OWSWindowManagerCallDidChange") diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.m b/SignalMessaging/ViewControllers/OWSTableViewController.m index cce54fc89..21e273034 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.m +++ b/SignalMessaging/ViewControllers/OWSTableViewController.m @@ -463,13 +463,6 @@ NSString *const kOWSTableCellIdentifier = @"kOWSTableCellIdentifier"; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kOWSTableCellIdentifier]; } -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [self.navigationController.navigationBar setTranslucent:NO]; -} - - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; diff --git a/SignalMessaging/contacts/CountryCodeViewController.m b/SignalMessaging/contacts/CountryCodeViewController.m index 8b81bfacd..e5e488d7b 100644 --- a/SignalMessaging/contacts/CountryCodeViewController.m +++ b/SignalMessaging/contacts/CountryCodeViewController.m @@ -26,7 +26,6 @@ [super loadView]; self.view.backgroundColor = [UIColor whiteColor]; - [self.navigationController.navigationBar setTranslucent:NO]; self.title = NSLocalizedString(@"COUNTRYCODE_SELECT_TITLE", @""); self.countryCodes = [PhoneNumberUtil countryCodesForSearchTerm:nil]; diff --git a/SignalMessaging/contacts/SelectRecipientViewController.m b/SignalMessaging/contacts/SelectRecipientViewController.m index 1a681849c..84e7ebb88 100644 --- a/SignalMessaging/contacts/SelectRecipientViewController.m +++ b/SignalMessaging/contacts/SelectRecipientViewController.m @@ -55,7 +55,6 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien [super loadView]; self.view.backgroundColor = [UIColor whiteColor]; - [self.navigationController.navigationBar setTranslucent:NO]; _contactsViewHelper = [[ContactsViewHelper alloc] initWithDelegate:self]; diff --git a/SignalMessaging/contacts/SelectThreadViewController.m b/SignalMessaging/contacts/SelectThreadViewController.m index 18e84e81a..ae90b6cfe 100644 --- a/SignalMessaging/contacts/SelectThreadViewController.m +++ b/SignalMessaging/contacts/SelectThreadViewController.m @@ -81,12 +81,6 @@ NS_ASSUME_NONNULL_BEGIN [self updateTableContents]; } -- (void)viewDidLoad -{ - [super viewDidLoad]; - [self.navigationController.navigationBar setTranslucent:NO]; -} - - (void)createViews { OWSAssert(self.selectThreadViewDelegate); From 29d08545e21f5a6caefb836151f7649e9eecd525 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 16 May 2018 22:42:00 -0400 Subject: [PATCH 14/30] Use OWSNavigationController instead of UINavigationController - [ ] document picker - [ ] camera picker - [ ] image picker - [ ] restore "confirm to go back" behavior (interactive pop gesture?) // FREEBIE --- Signal.xcodeproj/project.pbxproj | 40 ++++--- Signal/src/AppDelegate.m | 10 +- .../ContactShareViewHelper.swift | 2 +- .../ConversationViewController.m | 7 +- .../src/ViewControllers/DebugUI/DebugUIMisc.m | 2 +- Signal/src/ViewControllers/InviteFlow.swift | 4 +- .../MediaGalleryViewController.swift | 6 +- .../ViewControllers/NewGroupViewController.m | 2 +- .../OWS2FAReminderViewController.swift | 4 +- .../ViewControllers/ProfileViewController.m | 1 + .../Registration/RegistrationViewController.m | 8 +- .../FingerprintViewController.m | 4 +- .../OWSConversationSettingsViewController.m | 3 +- Signal/src/environment/SignalApp.h | 3 +- SignalMessaging/SignalMessaging.h | 2 + .../ViewControllers/OWSNavigationController.h | 6 +- .../ViewControllers/OWSNavigationController.m | 111 ++++++++++-------- .../ViewControllers/OWSTableViewController.m | 3 +- .../ReturnToCallViewController.swift | 0 SignalMessaging/Views/ContactsViewHelper.m | 4 +- .../Views/OWSNavigationBar.swift | 7 +- .../categories}/UIDevice+featureSupport.swift | 2 +- .../contacts/SelectRecipientViewController.m | 4 +- SignalMessaging/environment/Environment.h | 4 +- .../utils}/OWSWindowManager.h | 0 .../utils}/OWSWindowManager.m | 14 +-- .../ShareViewController.swift | 2 +- 27 files changed, 141 insertions(+), 114 deletions(-) rename {Signal/src => SignalMessaging}/ViewControllers/OWSNavigationController.h (85%) rename {Signal/src => SignalMessaging}/ViewControllers/OWSNavigationController.m (54%) rename {Signal/src => SignalMessaging}/ViewControllers/ReturnToCallViewController.swift (100%) rename Signal/src/views/SignalNavigationBar.swift => SignalMessaging/Views/OWSNavigationBar.swift (93%) rename {Signal/src => SignalMessaging/categories}/UIDevice+featureSupport.swift (96%) rename {Signal/src/util => SignalMessaging/utils}/OWSWindowManager.h (100%) rename {Signal/src/util => SignalMessaging/utils}/OWSWindowManager.m (97%) diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index c1233a017..bca9ed4e9 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -144,7 +144,6 @@ 34612A011FD5F31400532771 /* OWS104CreateRecipientIdentities.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129F41FD5F31400532771 /* OWS104CreateRecipientIdentities.h */; }; 34612A061FD7238600532771 /* OWSContactsSyncing.h in Headers */ = {isa = PBXBuildFile; fileRef = 34612A041FD7238500532771 /* OWSContactsSyncing.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34612A071FD7238600532771 /* OWSContactsSyncing.m in Sources */ = {isa = PBXBuildFile; fileRef = 34612A051FD7238500532771 /* OWSContactsSyncing.m */; }; - 34641E1220878FB000E2EDE5 /* OWSWindowManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 34641E1020878FAF00E2EDE5 /* OWSWindowManager.m */; }; 34641E182088D7E900E2EDE5 /* OWSScreenLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34641E172088D7E900E2EDE5 /* OWSScreenLock.swift */; }; 34641E1B2088DA4100E2EDE5 /* ScreenLockViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34641E192088DA3F00E2EDE5 /* ScreenLockViewController.m */; }; 34641E1C2088DA4100E2EDE5 /* ScreenLockViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 34641E1A2088DA4000E2EDE5 /* ScreenLockViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -189,7 +188,6 @@ 34C3C78F2040A4F70000134C /* sonarping.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 34C3C78E2040A4F70000134C /* sonarping.mp3 */; }; 34C3C7922040B0DD0000134C /* OWSAudioPlayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 34C3C7902040B0DC0000134C /* OWSAudioPlayer.h */; settings = {ATTRIBUTES = (Public, ); }; }; 34C3C7932040B0DD0000134C /* OWSAudioPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C3C7912040B0DC0000134C /* OWSAudioPlayer.m */; }; - 34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */; }; 34C6B0A91FA0E46F00D35993 /* test-gif.gif in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0A51FA0E46F00D35993 /* test-gif.gif */; }; 34C6B0AB1FA0E46F00D35993 /* test-mp3.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0A71FA0E46F00D35993 /* test-mp3.mp3 */; }; 34C6B0AC1FA0E46F00D35993 /* test-mp4.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 34C6B0A81FA0E46F00D35993 /* test-mp4.mp4 */; }; @@ -249,6 +247,13 @@ 450998681FD8C0FF00D89EB3 /* AttachmentSharing.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B3F83A1E8DF1700035BE1A /* AttachmentSharing.m */; }; 450998691FD8C10200D89EB3 /* AttachmentSharing.h in Headers */ = {isa = PBXBuildFile; fileRef = 34B3F8391E8DF1700035BE1A /* AttachmentSharing.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4509E79A1DD653700025A59F /* WebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4509E7991DD653700025A59F /* WebRTC.framework */; }; + 450C800C20AD191E00F3A091 /* OWSNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */; }; + 450C800D20AD193100F3A091 /* OWSNavigationController.h in Headers */ = {isa = PBXBuildFile; fileRef = 34C42D591F45F7A80072EC04 /* OWSNavigationController.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 450C800E20AD1A6500F3A091 /* OWSNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FDA43420A4D22700396358 /* OWSNavigationBar.swift */; }; + 450C800F20AD1AB900F3A091 /* OWSWindowManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 34641E1020878FAF00E2EDE5 /* OWSWindowManager.m */; }; + 450C801020AD1AE400F3A091 /* OWSWindowManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 34641E1120878FB000E2EDE5 /* OWSWindowManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 450C801120AD1CDB00F3A091 /* ReturnToCallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A60E7220AC674100FB1ABF /* ReturnToCallViewController.swift */; }; + 450C801220AD1D5B00F3A091 /* UIDevice+featureSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BB93371E688E14001E3939 /* UIDevice+featureSupport.swift */; }; 450D19131F85236600970622 /* RemoteVideoView.m in Sources */ = {isa = PBXBuildFile; fileRef = 450D19121F85236600970622 /* RemoteVideoView.m */; }; 450DF2051E0D74AC003D14BE /* Platform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450DF2041E0D74AC003D14BE /* Platform.swift */; }; 450DF2091E0DD2C6003D14BE /* UserNotificationsAdaptee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450DF2081E0DD2C6003D14BE /* UserNotificationsAdaptee.swift */; }; @@ -352,7 +357,6 @@ 459B775C207BA46C0071D0AB /* OWSQuotedReplyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 459B775A207BA3A80071D0AB /* OWSQuotedReplyModel.m */; }; 459B775D207BA4810071D0AB /* OWSQuotedReplyModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 459B7759207BA3A80071D0AB /* OWSQuotedReplyModel.h */; settings = {ATTRIBUTES = (Public, ); }; }; 45A2F005204473A3002E978A /* NewMessage.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45A2F004204473A3002E978A /* NewMessage.aifc */; }; - 45A60E7320AC674100FB1ABF /* ReturnToCallViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A60E7220AC674100FB1ABF /* ReturnToCallViewController.swift */; }; 45A663C51F92EC760027B59E /* GroupTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A663C41F92EC760027B59E /* GroupTableViewCell.swift */; }; 45A6DAD61EBBF85500893231 /* ReminderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45A6DAD51EBBF85500893231 /* ReminderView.swift */; }; 45AE48511E0732D6004D96C2 /* TurnServerInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45AE48501E0732D6004D96C2 /* TurnServerInfo.swift */; }; @@ -382,7 +386,6 @@ 45B74A892044AAB600CD42F8 /* circles-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45B74A702044AAB500CD42F8 /* circles-quiet.aifc */; }; 45B74A8B2044AAB600CD42F8 /* synth.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45B74A722044AAB600CD42F8 /* synth.aifc */; }; 45B74A8C2044AAB600CD42F8 /* input-quiet.aifc in Resources */ = {isa = PBXBuildFile; fileRef = 45B74A732044AAB600CD42F8 /* input-quiet.aifc */; }; - 45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BB93371E688E14001E3939 /* UIDevice+featureSupport.swift */; }; 45BC829D1FD9C4B400011CF3 /* ShareViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BC829C1FD9C4B400011CF3 /* ShareViewDelegate.swift */; }; 45BD60821DE9547E00A8F436 /* Contacts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 45BD60811DE9547E00A8F436 /* Contacts.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 45BE4EA22012AD2000935E59 /* DisappearingTimerConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45BE4EA12012AD2000935E59 /* DisappearingTimerConfigurationView.swift */; }; @@ -408,7 +411,6 @@ 45F659821E1BE77000444429 /* NonCallKitCallUIAdaptee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45F659811E1BE77000444429 /* NonCallKitCallUIAdaptee.swift */; }; 45FBC5C81DF8575700E9B410 /* CallKitCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC59A1DF8575700E9B410 /* CallKitCallManager.swift */; }; 45FBC5D11DF8592E00E9B410 /* SignalCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */; }; - 45FDA43520A4D22700396358 /* SignalNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 45FDA43420A4D22700396358 /* SignalNavigationBar.swift */; }; 4AC4EA13C8A444455DAB351F /* Pods_SignalMessaging.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 264242150E87D10A357DB07B /* Pods_SignalMessaging.framework */; }; 70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70377AAA1918450100CAF501 /* MobileCoreServices.framework */; }; 768A1A2B17FC9CD300E00ED8 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 768A1A2A17FC9CD300E00ED8 /* libz.dylib */; }; @@ -1062,7 +1064,7 @@ 45F659811E1BE77000444429 /* NonCallKitCallUIAdaptee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NonCallKitCallUIAdaptee.swift; sourceTree = ""; }; 45FBC59A1DF8575700E9B410 /* CallKitCallManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallKitCallManager.swift; sourceTree = ""; }; 45FBC5D01DF8592E00E9B410 /* SignalCall.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalCall.swift; sourceTree = ""; }; - 45FDA43420A4D22700396358 /* SignalNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalNavigationBar.swift; sourceTree = ""; }; + 45FDA43420A4D22700396358 /* OWSNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OWSNavigationBar.swift; sourceTree = ""; }; 69349DE607F5BA6036C9AC60 /* Pods-SignalShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SignalShareExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension.debug.xcconfig"; sourceTree = ""; }; 70377AAA1918450100CAF501 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 748A5CAEDD7C919FC64C6807 /* Pods_SignalTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SignalTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1453,6 +1455,8 @@ 34480B4F1FD0A7A300BC14EF /* OWSScrubbingLogFormatter.h */, 34480B511FD0A7A400BC14EF /* OWSScrubbingLogFormatter.m */, 346129331FD1A88700532771 /* OWSSwiftUtils.swift */, + 34641E1120878FB000E2EDE5 /* OWSWindowManager.h */, + 34641E1020878FAF00E2EDE5 /* OWSWindowManager.m */, 45360B8C1F9521F800FA666C /* Searcher.swift */, 347850581FD9972E007B8332 /* SwiftSingletons.swift */, 346129BD1FD2068600532771 /* ThreadUtil.h */, @@ -1468,6 +1472,7 @@ 34480B5C1FD0A98800BC14EF /* categories */ = { isa = PBXGroup; children = ( + 45BB93371E688E14001E3939 /* UIDevice+featureSupport.swift */, 4551DB59205C562300C8AE75 /* Collection+OWS.swift */, 346129C51FD2072D00532771 /* NSAttributedString+OWS.h */, 346129C11FD2072D00532771 /* NSAttributedString+OWS.m */, @@ -1604,6 +1609,7 @@ 451573952061B49500803601 /* GradientView.swift */, 346129CF1FD207F200532771 /* OWSAlerts.swift */, 454A965E1FD60EA2008D2A0E /* OWSFlatButton.swift */, + 45FDA43420A4D22700396358 /* OWSNavigationBar.swift */, 348BB258209CF8E40047AEC2 /* TappableStackView.swift */, 348BB259209CF8E50047AEC2 /* TappableView.swift */, 3400C7971EAFB772008A8584 /* ThreadViewHelper.h */, @@ -1674,8 +1680,6 @@ 45D2AC01204885170033C692 /* OWS2FAReminderViewController.swift */, 345BC30A2047030600257B7C /* OWS2FASettingsViewController.h */, 345BC30B2047030600257B7C /* OWS2FASettingsViewController.m */, - 34C42D591F45F7A80072EC04 /* OWSNavigationController.h */, - 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */, 34CE88E51F2FB9A10098030F /* ProfileViewController.h */, 34CE88E61F2FB9A10098030F /* ProfileViewController.m */, 340FC875204DAC8C007AEB0F /* Registration */, @@ -1685,7 +1689,6 @@ 340FC897204DAC8D007AEB0F /* ThreadSettings */, 34D1F0BE1F8EC1760066283D /* Utils */, 452B998F20A34B6B006F2F9E /* AddContactShareToExistingContactViewController.swift */, - 45A60E7220AC674100FB1ABF /* ReturnToCallViewController.swift */, ); path = ViewControllers; sourceTree = ""; @@ -1855,10 +1858,13 @@ 451F8A361FD7115D005CB9DA /* ViewControllers */ = { isa = PBXGroup; children = ( + 34C42D591F45F7A80072EC04 /* OWSNavigationController.h */, + 34C42D5A1F45F7A80072EC04 /* OWSNavigationController.m */, 34B3F89D1E8DF5490035BE1A /* OWSTableViewController.h */, 34B3F89E1E8DF5490035BE1A /* OWSTableViewController.m */, 34D99C8A1F27B13B00D284D6 /* OWSViewController.h */, 34D99C8B1F27B13B00D284D6 /* OWSViewController.m */, + 45A60E7220AC674100FB1ABF /* ReturnToCallViewController.swift */, ); path = ViewControllers; sourceTree = ""; @@ -2112,8 +2118,6 @@ 34D2CCD120618B2F00CB1A14 /* OWSBackupLazyRestoreJob.swift */, 34D2CCD82062E7D000CB1A14 /* OWSScreenLockUI.h */, 34D2CCD92062E7D000CB1A14 /* OWSScreenLockUI.m */, - 34641E1120878FB000E2EDE5 /* OWSWindowManager.h */, - 34641E1020878FAF00E2EDE5 /* OWSWindowManager.m */, 4579431C1E7C8CE9008ED0C0 /* Pastelog.h */, 4579431D1E7C8CE9008ED0C0 /* Pastelog.m */, 450DF2041E0D74AC003D14BE /* Platform.swift */, @@ -2145,7 +2149,6 @@ 45A6DAD51EBBF85500893231 /* ReminderView.swift */, 450D19111F85236600970622 /* RemoteVideoView.h */, 450D19121F85236600970622 /* RemoteVideoView.m */, - 45FDA43420A4D22700396358 /* SignalNavigationBar.swift */, ); name = Views; path = views; @@ -2387,7 +2390,6 @@ children = ( 45638BDE1F3DDB2200128435 /* MessageSender+Promise.swift */, 45C0DC1A1E68FE9000E04C47 /* UIApplication+OWS.swift */, - 45BB93371E688E14001E3939 /* UIDevice+featureSupport.swift */, 45C0DC1D1E69011F00E04C47 /* UIStoryboard+OWS.swift */, EF764C331DB67CC5000D9A87 /* UIViewController+Permissions.h */, EF764C341DB67CC5000D9A87 /* UIViewController+Permissions.m */, @@ -2415,6 +2417,7 @@ 34612A001FD5F31400532771 /* OWS105AttachmentFilePaths.h in Headers */, 346129F61FD5F31400532771 /* OWS103EnableVideoCalling.h in Headers */, 344F248A20069F0600CFB4F4 /* ViewControllerUtils.h in Headers */, + 450C800D20AD193100F3A091 /* OWSNavigationController.h in Headers */, 346129A91FD1F0E000532771 /* OWSFormat.h in Headers */, 34480B551FD0A7A400BC14EF /* DebugLogger.h in Headers */, 344F248420069E9C00CFB4F4 /* CountryCodeViewController.h in Headers */, @@ -2439,6 +2442,7 @@ 34480B611FD0A98800BC14EF /* UIColor+OWS.h in Headers */, 453518961FC63DBF00210559 /* SignalMessaging.h in Headers */, 3461295A1FD1D74C00532771 /* Environment.h in Headers */, + 450C801020AD1AE400F3A091 /* OWSWindowManager.h in Headers */, 34D58730208E2C4200D2255A /* OWS109OutgoingMessageState.h in Headers */, 4598198E204E2F28009414F2 /* OWS108CallLoggingPreference.h in Headers */, 34480B631FD0A98800BC14EF /* UIView+OWS.h in Headers */, @@ -3121,6 +3125,7 @@ 45194F8F1FD71FF500333B2C /* ThreadUtil.m in Sources */, 451F8A3B1FD71297005CB9DA /* UIUtil.m in Sources */, 451F8A331FD71083005CB9DA /* SelectThreadViewController.m in Sources */, + 450C800F20AD1AB900F3A091 /* OWSWindowManager.m in Sources */, 454A965A1FD6017E008D2A0E /* SignalAttachment.swift in Sources */, 454A965B1FD601BF008D2A0E /* MediaMessageView.swift in Sources */, 45BC829D1FD9C4B400011CF3 /* ShareViewDelegate.swift in Sources */, @@ -3147,17 +3152,21 @@ 45F59A082028E4FB00E8D2B0 /* OWSAudioSession.swift in Sources */, 34612A071FD7238600532771 /* OWSContactsSyncing.m in Sources */, 346129DF1FD5C02A00532771 /* LockInteractionController.m in Sources */, + 450C801220AD1D5B00F3A091 /* UIDevice+featureSupport.swift in Sources */, 451F8A471FD715BA005CB9DA /* OWSAvatarBuilder.m in Sources */, 344D6CEB20069E070042AF96 /* SelectRecipientViewController.m in Sources */, 34480B591FD0A7A400BC14EF /* OWSScrubbingLogFormatter.m in Sources */, 451F8A441FD7156B005CB9DA /* BlockListUIUtils.m in Sources */, 34641E182088D7E900E2EDE5 /* OWSScreenLock.swift in Sources */, 451F8A381FD7117E005CB9DA /* OWSViewController.m in Sources */, + 450C801120AD1CDB00F3A091 /* ReturnToCallViewController.swift in Sources */, + 450C800C20AD191E00F3A091 /* OWSNavigationController.m in Sources */, 346129721FD1D74C00532771 /* SignalKeyingStorage.m in Sources */, 34480B561FD0A7A400BC14EF /* DebugLogger.m in Sources */, 459B775C207BA46C0071D0AB /* OWSQuotedReplyModel.m in Sources */, 34ABB2C42090C59700C727A6 /* OWSResaveCollectionDBMigration.m in Sources */, 4551DB5A205C562300C8AE75 /* Collection+OWS.swift in Sources */, + 450C800E20AD1A6500F3A091 /* OWSNavigationBar.swift in Sources */, 3461293C1FD1D46A00532771 /* OWSMath.m in Sources */, 451F8A391FD711D6005CB9DA /* ContactsViewHelper.m in Sources */, 346129AF1FD1F5D900532771 /* SystemContactsFetcher.swift in Sources */, @@ -3276,7 +3285,6 @@ 45D308AD2049A439000189E4 /* PinEntryView.m in Sources */, 340FC8B1204DAC8D007AEB0F /* BlockListViewController.m in Sources */, 45B5360E206DD8BB00D61655 /* UIResponder+OWS.swift in Sources */, - 34641E1220878FB000E2EDE5 /* OWSWindowManager.m in Sources */, 45F659821E1BE77000444429 /* NonCallKitCallUIAdaptee.swift in Sources */, 45AE48511E0732D6004D96C2 /* TurnServerInfo.swift in Sources */, 34B3F8771E8DF1700035BE1A /* ContactsPicker.swift in Sources */, @@ -3299,8 +3307,6 @@ 34BECE2E1F7ABCE000D7438D /* GifPickerViewController.swift in Sources */, 34D1F0C01F8EC1760066283D /* MessageRecipientStatusUtils.swift in Sources */, 45F659731E1BD99C00444429 /* CallKitCallUIAdaptee.swift in Sources */, - 45FDA43520A4D22700396358 /* SignalNavigationBar.swift in Sources */, - 45BB93381E688E14001E3939 /* UIDevice+featureSupport.swift in Sources */, 34277A5E20751BDC006049F2 /* OWSQuotedMessageView.m in Sources */, 458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */, 45DDA6242090CEB500DE97F8 /* ConversationHeaderView.swift in Sources */, @@ -3315,7 +3321,6 @@ 34D1F0B11F867BFC0066283D /* OWSUnreadIndicatorCell.m in Sources */, 340FC8B5204DAC8D007AEB0F /* AboutTableViewController.m in Sources */, 34BECE2B1F74C12700D7438D /* DebugUIStress.m in Sources */, - 34C42D5B1F45F7A80072EC04 /* OWSNavigationController.m in Sources */, 340FC8B9204DAC8D007AEB0F /* UpdateGroupViewController.m in Sources */, B609597C1C2C0FC6004E8797 /* iRate.m in Sources */, 4574A5D61DD6704700C6B692 /* CallService.swift in Sources */, @@ -3328,7 +3333,6 @@ 340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */, 4579431E1E7C8CE9008ED0C0 /* Pastelog.m in Sources */, 340FC8B0204DAC8D007AEB0F /* AddToBlockListViewController.m in Sources */, - 45A60E7320AC674100FB1ABF /* ReturnToCallViewController.swift in Sources */, 340FC8B3204DAC8D007AEB0F /* AppSettingsViewController.m in Sources */, 346B66311F4E29B200E5122F /* CropScaleImageViewController.swift in Sources */, 45E5A6991F61E6DE001E4A8A /* MarqueeLabel.swift in Sources */, diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 42201aec1..cd1d2dd04 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -12,7 +12,6 @@ #import "NotificationsManager.h" #import "OWS2FASettingsViewController.h" #import "OWSBackup.h" -#import "OWSNavigationController.h" #import "OWSScreenLockUI.h" #import "Pastelog.h" #import "PushManager.h" @@ -28,6 +27,7 @@ #import #import #import +#import #import #import #import @@ -483,9 +483,9 @@ static NSTimeInterval launchStartedAt; if ([url.scheme isEqualToString:kURLSchemeSGNLKey]) { if ([url.host hasPrefix:kURLHostVerifyPrefix] && ![TSAccountManager isRegistered]) { id signupController = SignalApp.sharedApp.signUpFlowNavigationController; - if ([signupController isKindOfClass:[UINavigationController class]]) { - UINavigationController *navController = (UINavigationController *)signupController; - UIViewController *controller = [navController.childViewControllers lastObject]; + if ([signupController isKindOfClass:[OWSNavigationController class]]) { + OWSNavigationController *navController = (OWSNavigationController *)signupController; + UIViewController *controller = [navController.childViewControllers lastObject]; if ([controller isKindOfClass:[CodeVerificationViewController class]]) { CodeVerificationViewController *cvvc = (CodeVerificationViewController *)controller; NSString *verificationCode = [url.path substringFromIndex:1]; @@ -628,7 +628,7 @@ static NSTimeInterval launchStartedAt; @"%@ Skipping 2FA reminder since there isn't yet an initial view controller", self.logTag); } else { UIViewController *rootViewController = self.window.rootViewController; - UINavigationController *reminderNavController = + OWSNavigationController *reminderNavController = [OWS2FAReminderViewController wrappedInNavController]; [rootViewController presentViewController:reminderNavController animated:YES completion:nil]; diff --git a/Signal/src/ViewControllers/ContactShareViewHelper.swift b/Signal/src/ViewControllers/ContactShareViewHelper.swift index 200c8e4ca..0323f2006 100644 --- a/Signal/src/ViewControllers/ContactShareViewHelper.swift +++ b/Signal/src/ViewControllers/ContactShareViewHelper.swift @@ -168,7 +168,7 @@ public class ContactShareViewHelper: NSObject, CNContactViewControllerDelegate { // CNContactViewController incompatible with opaque navigation bar UIUtil.applyDefaultSystemAppearence() - let modal = UINavigationController(rootViewController: contactViewController) + let modal = OWSNavigationController(rootViewController: contactViewController) fromViewController.present(modal, animated: true) } diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index c954eae7b..351223ccc 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -60,6 +60,7 @@ #import #import #import +#import #import #import #import @@ -2614,8 +2615,8 @@ typedef enum : NSUInteger { contactsPicker.title = NSLocalizedString(@"CONTACT_PICKER_TITLE", @"navbar title for contact picker when sharing a contact"); - UINavigationController *navigationController = - [[UINavigationController alloc] initWithRootViewController:contactsPicker]; + OWSNavigationController *navigationController = + [[OWSNavigationController alloc] initWithRootViewController:contactsPicker]; [self dismissKeyBoard]; [self presentViewController:navigationController animated:YES completion:nil]; } @@ -2656,7 +2657,7 @@ typedef enum : NSUInteger { GifPickerViewController *view = [[GifPickerViewController alloc] initWithThread:self.thread messageSender:self.messageSender]; view.delegate = self; - UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:view]; + OWSNavigationController *navigationController = [[OWSNavigationController alloc] initWithRootViewController:view]; [self dismissKeyBoard]; [self presentViewController:navigationController animated:YES completion:nil]; diff --git a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m index 228f9a6e7..f47d4a32d 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUIMisc.m @@ -109,7 +109,7 @@ NS_ASSUME_NONNULL_BEGIN [items addObject:[OWSTableItem itemWithTitle:@"Show 2FA Reminder" actionBlock:^() { - UINavigationController *navController = + OWSNavigationController *navController = [OWS2FAReminderViewController wrappedInNavController]; [[[UIApplication sharedApplication] frontmostViewController] presentViewController:navController diff --git a/Signal/src/ViewControllers/InviteFlow.swift b/Signal/src/ViewControllers/InviteFlow.swift index 323167a7c..1517d91ea 100644 --- a/Signal/src/ViewControllers/InviteFlow.swift +++ b/Signal/src/ViewControllers/InviteFlow.swift @@ -154,7 +154,7 @@ class InviteFlow: NSObject, MFMessageComposeViewControllerDelegate, MFMailCompos let picker = ContactsPicker(allowsMultipleSelection: true, subtitleCellType: .phoneNumber) picker.contactsPickerDelegate = self picker.title = NSLocalizedString("INVITE_FRIENDS_PICKER_TITLE", comment: "Navbar title") - let navigationController = UINavigationController(rootViewController: picker) + let navigationController = OWSNavigationController(rootViewController: picker) self.presentingViewController.present(navigationController, animated: true) } } @@ -218,7 +218,7 @@ class InviteFlow: NSObject, MFMessageComposeViewControllerDelegate, MFMailCompos let picker = ContactsPicker(allowsMultipleSelection: true, subtitleCellType: .email) picker.contactsPickerDelegate = self picker.title = NSLocalizedString("INVITE_FRIENDS_PICKER_TITLE", comment: "Navbar title") - let navigationController = UINavigationController(rootViewController: picker) + let navigationController = OWSNavigationController(rootViewController: picker) self.presentingViewController.present(navigationController, animated: true) } } diff --git a/Signal/src/ViewControllers/MediaGalleryViewController.swift b/Signal/src/ViewControllers/MediaGalleryViewController.swift index 9d8e47122..71741244e 100644 --- a/Signal/src/ViewControllers/MediaGalleryViewController.swift +++ b/Signal/src/ViewControllers/MediaGalleryViewController.swift @@ -184,7 +184,7 @@ protocol MediaGalleryDataSourceDelegate: class { func mediaGalleryDataSource(_ mediaGalleryDataSource: MediaGalleryDataSource, deletedSections: IndexSet, deletedItems: [IndexPath]) } -class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource, MediaTileViewControllerDelegate { +class MediaGalleryViewController: OWSNavigationController, MediaGalleryDataSource, MediaTileViewControllerDelegate { private var pageViewController: MediaPageViewController? @@ -395,9 +395,9 @@ class MediaGalleryViewController: UINavigationController, MediaGalleryDataSource // If we're using a navigationController other than self to present the views // e.g. the conversation settings view controller - var fromNavController: UINavigationController? + var fromNavController: OWSNavigationController? - func pushTileView(fromNavController: UINavigationController) { + func pushTileView(fromNavController: OWSNavigationController) { var mostRecentItem: MediaGalleryItem? self.uiDatabaseConnection.read { transaction in if let message = self.mediaGalleryFinder.mostRecentMediaMessage(transaction: transaction) { diff --git a/Signal/src/ViewControllers/NewGroupViewController.m b/Signal/src/ViewControllers/NewGroupViewController.m index 2482f23ff..6ed0f1ac1 100644 --- a/Signal/src/ViewControllers/NewGroupViewController.m +++ b/Signal/src/ViewControllers/NewGroupViewController.m @@ -117,7 +117,7 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; [self.view addSubview:firstSection]; [firstSection autoSetDimension:ALDimensionHeight toSize:100.f]; [firstSection autoPinWidthToSuperview]; - [firstSection autoPinEdgeToSuperviewEdge:ALEdgeTop]; + [firstSection autoPinToTopLayoutGuideOfViewController:self withInset:0]; _tableViewController = [OWSTableViewController new]; _tableViewController.delegate = self; diff --git a/Signal/src/ViewControllers/OWS2FAReminderViewController.swift b/Signal/src/ViewControllers/OWS2FAReminderViewController.swift index 58dc312e4..588721f34 100644 --- a/Signal/src/ViewControllers/OWS2FAReminderViewController.swift +++ b/Signal/src/ViewControllers/OWS2FAReminderViewController.swift @@ -14,8 +14,8 @@ public class OWS2FAReminderViewController: UIViewController, PinEntryViewDelegat var pinEntryView: PinEntryView! @objc - public class func wrappedInNavController() -> UINavigationController { - let navController = UINavigationController() + public class func wrappedInNavController() -> OWSNavigationController { + let navController = OWSNavigationController() navController.pushViewController(OWS2FAReminderViewController(), animated: false) return navController diff --git a/Signal/src/ViewControllers/ProfileViewController.m b/Signal/src/ViewControllers/ProfileViewController.m index bc661c815..56d96d18f 100644 --- a/Signal/src/ViewControllers/ProfileViewController.m +++ b/Signal/src/ViewControllers/ProfileViewController.m @@ -13,6 +13,7 @@ #import "UIFont+OWS.h" #import "UIView+OWS.h" #import +#import #import #import #import diff --git a/Signal/src/ViewControllers/Registration/RegistrationViewController.m b/Signal/src/ViewControllers/Registration/RegistrationViewController.m index 0aae5902d..5484a492b 100644 --- a/Signal/src/ViewControllers/Registration/RegistrationViewController.m +++ b/Signal/src/ViewControllers/Registration/RegistrationViewController.m @@ -14,6 +14,7 @@ #import #import #import +#import NS_ASSUME_NONNULL_BEGIN @@ -50,7 +51,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi // Do any additional setup after loading the view. [self populateDefaultCountryNameAndCode]; - [SignalApp.sharedApp setSignUpFlowNavigationController:self.navigationController]; + OWSAssert([self.navigationController isKindOfClass:[OWSNavigationController class]]); + [SignalApp.sharedApp setSignUpFlowNavigationController:(OWSNavigationController *)self.navigationController]; } - (void)viewDidLoad @@ -354,8 +356,8 @@ NSString *const kKeychainKey_LastRegisteredPhoneNumber = @"kKeychainKey_LastRegi { CountryCodeViewController *countryCodeController = [CountryCodeViewController new]; countryCodeController.countryCodeDelegate = self; - UINavigationController *navigationController = - [[UINavigationController alloc] initWithRootViewController:countryCodeController]; + OWSNavigationController *navigationController = + [[OWSNavigationController alloc] initWithRootViewController:countryCodeController]; [self presentViewController:navigationController animated:YES completion:[UIUtil modalCompletionBlock]]; } diff --git a/Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.m b/Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.m index e33a6362a..d731f0f56 100644 --- a/Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/FingerprintViewController.m @@ -105,8 +105,8 @@ typedef void (^CustomLayoutBlock)(void); FingerprintViewController *fingerprintViewController = [FingerprintViewController new]; [fingerprintViewController configureWithRecipientId:recipientId]; - UINavigationController *navigationController = - [[UINavigationController alloc] initWithRootViewController:fingerprintViewController]; + OWSNavigationController *navigationController = + [[OWSNavigationController alloc] initWithRootViewController:fingerprintViewController]; [viewController presentViewController:navigationController animated:YES completion:nil]; } diff --git a/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m index 2e2fa9c7a..d5881fe43 100644 --- a/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/OWSConversationSettingsViewController.m @@ -1173,7 +1173,8 @@ NS_ASSUME_NONNULL_BEGIN // reference to it until we're dismissed. self.mediaGalleryViewController = vc; - [vc pushTileViewFromNavController:self.navigationController]; + OWSAssert([self.navigationController isKindOfClass:[OWSNavigationController class]]); + [vc pushTileViewFromNavController:(OWSNavigationController *)self.navigationController]; } #pragma mark - Notifications diff --git a/Signal/src/environment/SignalApp.h b/Signal/src/environment/SignalApp.h index f09bece9a..05231e32a 100644 --- a/Signal/src/environment/SignalApp.h +++ b/Signal/src/environment/SignalApp.h @@ -10,6 +10,7 @@ @class HomeViewController; @class NotificationsManager; @class OWSMessageFetcherJob; +@class OWSNavigationController; @class OWSWebRTCCallMessageHandler; @class OutboundCallInitiator; @class TSThread; @@ -17,7 +18,7 @@ @interface SignalApp : NSObject @property (nonatomic, weak) HomeViewController *homeViewController; -@property (nonatomic, weak) UINavigationController *signUpFlowNavigationController; +@property (nonatomic, weak) OWSNavigationController *signUpFlowNavigationController; // TODO: Convert to singletons? @property (nonatomic, readonly) OWSWebRTCCallMessageHandler *callMessageHandler; diff --git a/SignalMessaging/SignalMessaging.h b/SignalMessaging/SignalMessaging.h index 1204fdc46..976e86006 100644 --- a/SignalMessaging/SignalMessaging.h +++ b/SignalMessaging/SignalMessaging.h @@ -29,11 +29,13 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[]; #import #import #import +#import #import #import #import #import #import +#import #import #import #import diff --git a/Signal/src/ViewControllers/OWSNavigationController.h b/SignalMessaging/ViewControllers/OWSNavigationController.h similarity index 85% rename from Signal/src/ViewControllers/OWSNavigationController.h rename to SignalMessaging/ViewControllers/OWSNavigationController.h index 26900edde..533a5b4d0 100644 --- a/Signal/src/ViewControllers/OWSNavigationController.h +++ b/SignalMessaging/ViewControllers/OWSNavigationController.h @@ -1,9 +1,11 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import +NS_ASSUME_NONNULL_BEGIN + // Any view controller which wants to be able cancel back button // presses and back gestures should implement this protocol. @protocol OWSNavigationView @@ -22,3 +24,5 @@ @interface OWSNavigationController : UINavigationController @end + +NS_ASSUME_NONNULL_END diff --git a/Signal/src/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m similarity index 54% rename from Signal/src/ViewControllers/OWSNavigationController.m rename to SignalMessaging/ViewControllers/OWSNavigationController.m index 9ad78b627..f938ac700 100644 --- a/Signal/src/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -3,11 +3,12 @@ // #import "OWSNavigationController.h" -#import "Signal-Swift.h" +#import -// We use a category to expose UINavigationController's private -// UINavigationBarDelegate methods. -@interface UINavigationController (OWSNavigationController) +NS_ASSUME_NONNULL_BEGIN + + +@interface OWSNavigationController (OWSNavigationController) @end @@ -27,38 +28,38 @@ // Failure: additionalSafeArea insets cannot be negative // UIEdgeInsets newSafeArea = UIEdgeInsetsMake(-50, 30, 20, 30); // rootViewController.additionalSafeAreaInsets = newSafeArea; - + // Attempt 2: safeAreaInsets on vc.view // failure. they're already 0 // UIEdgeInsets existingInsets = rootViewController.view.safeAreaInsets; - + // Attempt 3: override topLayoutGuide? // Failure - not called. // overriding it does no good - it's not called by default layout code. // presumably it just existing if you want to use it as an anchor. - + // Attemp 4: sizeForChildContentConainer? // Failure - not called. - + // Attempt 5: autoSetDimension on navbar // Failure: no effect on rendered size - + // Attempt 6: manually set child frames in will/didLayoutSubviews // glitchy, and viewcontrollers re-layout themselves afterwards anyway - + // Attempt 7: Since we can't seem to *shrink* the navbar, maybe we can grow it. // make additionalSafeAreaInsets - + [self updateAdditionalSafeAreaInsets]; - - self = [self initWithNavigationBarClass:[SignalNavigationBar class] toolbarClass:nil]; + + self = [self initWithNavigationBarClass:[OWSNavigationBar class] toolbarClass:nil]; [self pushViewController:rootViewController animated:NO]; - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowManagerCallDidChange:) name:OWSWindowManagerCallDidChangeNotification object:nil]; - + return self; } @@ -81,54 +82,60 @@ { [super viewDidLoad]; - self.interactivePopGestureRecognizer.delegate = self; + // self.interactivePopGestureRecognizer.delegate = self; } #pragma mark - UINavigationBarDelegate -// All UINavigationController serve as the UINavigationBarDelegate for their navbar. +// All OWSNavigationController serve as the UINavigationBarDelegate for their navbar. // We override shouldPopItem: in order to cancel some back button presses - for example, // if a view has unsaved changes. -- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item -{ - OWSAssert(self.interactivePopGestureRecognizer.delegate == self); - UIViewController *topViewController = self.topViewController; - - // wasBackButtonClicked is YES if the back button was pressed but not - // if a back gesture was performed or if the view is popped programmatically. - BOOL wasBackButtonClicked = topViewController.navigationItem == item; - BOOL result = YES; - if (wasBackButtonClicked) { - if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { - id navigationView = (id)topViewController; - result = ![navigationView shouldCancelNavigationBack]; - } - } - - // If we're not going to cancel the pop/back, we need to call the super - // implementation since it has important side effects. - if (result) { - // NOTE: result might end up NO if the super implementation cancels the - // the pop/back. - result = [super navigationBar:navigationBar shouldPopItem:item]; - } - return result; -} +//- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item +//{ +// OWSAssert(self.interactivePopGestureRecognizer.delegate == self); +// UIViewController *topViewController = self.topViewController; +// +// // wasBackButtonClicked is YES if the back button was pressed but not +// // if a back gesture was performed or if the view is popped programmatically. +// BOOL wasBackButtonClicked = topViewController.navigationItem == item; +// BOOL result = YES; +// if (wasBackButtonClicked) { +// if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { +// id navigationView = (id)topViewController; +// result = ![navigationView shouldCancelNavigationBack]; +// } +// } +// +// // If we're not going to cancel the pop/back, we need to call the super +// // implementation since it has important side effects. +// if (result) { +// // NOTE: result might end up NO if the super implementation cancels the +// // the pop/back. +// +// // MJK WTF?? This seems super broken. It won't compile now, but how could it ever +// // have? This is a delegate method, so how are we calling it on super? +// // [super navigationBar:navigationBar shouldPopItem:item]; +// result = YES; +// } +// return result; +//} #pragma mark - UIGestureRecognizerDelegate // We serve as the UIGestureRecognizerDelegate of the interactivePopGestureRecognizer // in order to cancel some "back" gestures - for example, // if a view has unsaved changes. -- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer -{ - UIViewController *topViewController = self.topViewController; - if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { - id navigationView = (id)topViewController; - return ![navigationView shouldCancelNavigationBack]; - } else { - return YES; - } -} +//- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer +//{ +// UIViewController *topViewController = self.topViewController; +// if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { +// id navigationView = (id)topViewController; +// return ![navigationView shouldCancelNavigationBack]; +// } else { +// return YES; +// } +//} @end + +NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.m b/SignalMessaging/ViewControllers/OWSTableViewController.m index 21e273034..187b9ff76 100644 --- a/SignalMessaging/ViewControllers/OWSTableViewController.m +++ b/SignalMessaging/ViewControllers/OWSTableViewController.m @@ -3,6 +3,7 @@ // #import "OWSTableViewController.h" +#import "OWSNavigationController.h" #import "UIFont+OWS.h" #import "UIView+OWS.h" @@ -652,7 +653,7 @@ NSString *const kOWSTableCellIdentifier = @"kOWSTableCellIdentifier"; { OWSAssert(fromViewController); - UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self]; + OWSNavigationController *navigationController = [[OWSNavigationController alloc] initWithRootViewController:self]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self diff --git a/Signal/src/ViewControllers/ReturnToCallViewController.swift b/SignalMessaging/ViewControllers/ReturnToCallViewController.swift similarity index 100% rename from Signal/src/ViewControllers/ReturnToCallViewController.swift rename to SignalMessaging/ViewControllers/ReturnToCallViewController.swift diff --git a/SignalMessaging/Views/ContactsViewHelper.m b/SignalMessaging/Views/ContactsViewHelper.m index d1afa28db..dc444ec83 100644 --- a/SignalMessaging/Views/ContactsViewHelper.m +++ b/SignalMessaging/Views/ContactsViewHelper.m @@ -392,8 +392,8 @@ NS_ASSUME_NONNULL_BEGIN target:fromViewController action:@selector(didFinishEditingContact)]; - UINavigationController *navigationController = - [[UINavigationController alloc] initWithRootViewController:contactViewController]; + OWSNavigationController *navigationController = + [[OWSNavigationController alloc] initWithRootViewController:contactViewController]; // We want the presentation to imply a "replacement" in this case. if (shouldEditImmediately) { diff --git a/Signal/src/views/SignalNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift similarity index 93% rename from Signal/src/views/SignalNavigationBar.swift rename to SignalMessaging/Views/OWSNavigationBar.swift index 43c75353e..cc80768b4 100644 --- a/Signal/src/views/SignalNavigationBar.swift +++ b/SignalMessaging/Views/OWSNavigationBar.swift @@ -6,7 +6,7 @@ import Foundation import UIKit @objc -class SignalNavigationBar: UINavigationBar { +class OWSNavigationBar: UINavigationBar { // TODO - get a more precise value // TODO - test with other heights, e.g. w/ hotspot, w/ call in other app @@ -47,10 +47,13 @@ class SignalNavigationBar: UINavigationBar { // pre iOS11, sizeThatFits is repeatedly called to size the navbar, which is pretty straight forward // as of iOS11, this is not true and we have to do things in layoutSubviews. // FIXME: pre-iOS11, though the size is right, there's a glitch on the titleView while push/popping items. + + // MJK safe to hardcode? Do we even need this approach anymore? + let statusBarHeight: CGFloat = 20 let result: CGSize = { if OWSWindowManager.shared().hasCall() { // status bar height gets re-added - return CGSize(width: UIScreen.main.bounds.width, height: navbarHeight - UIApplication.shared.statusBarFrame.size.height) + return CGSize(width: CurrentAppContext().mainWindow!.bounds.width, height: navbarHeight - statusBarHeight) } else { return super.sizeThatFits(size) } diff --git a/Signal/src/UIDevice+featureSupport.swift b/SignalMessaging/categories/UIDevice+featureSupport.swift similarity index 96% rename from Signal/src/UIDevice+featureSupport.swift rename to SignalMessaging/categories/UIDevice+featureSupport.swift index eca3e0f54..24f60bfda 100644 --- a/Signal/src/UIDevice+featureSupport.swift +++ b/SignalMessaging/categories/UIDevice+featureSupport.swift @@ -4,7 +4,7 @@ import Foundation -extension UIDevice { +public extension UIDevice { var supportsCallKit: Bool { return ProcessInfo().isOperatingSystemAtLeast(OperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) } diff --git a/SignalMessaging/contacts/SelectRecipientViewController.m b/SignalMessaging/contacts/SelectRecipientViewController.m index 84e7ebb88..22b899f9e 100644 --- a/SignalMessaging/contacts/SelectRecipientViewController.m +++ b/SignalMessaging/contacts/SelectRecipientViewController.m @@ -266,8 +266,8 @@ NSString *const kSelectRecipientViewControllerCellIdentifier = @"kSelectRecipien if (self.isPresentedInNavigationController) { [self.navigationController pushViewController:countryCodeController animated:YES]; } else { - UINavigationController *navigationController = - [[UINavigationController alloc] initWithRootViewController:countryCodeController]; + OWSNavigationController *navigationController = + [[OWSNavigationController alloc] initWithRootViewController:countryCodeController]; [self presentViewController:navigationController animated:YES completion:[UIUtil modalCompletionBlock]]; } } diff --git a/SignalMessaging/environment/Environment.h b/SignalMessaging/environment/Environment.h index 07067dd14..7df6b0c7d 100644 --- a/SignalMessaging/environment/Environment.h +++ b/SignalMessaging/environment/Environment.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // #import "OWSPreferences.h" @@ -16,10 +16,10 @@ @class ContactsUpdater; @class OWSContactsManager; @class OWSMessageSender; +@class OWSNavigationController; @class TSGroupThread; @class TSNetworkManager; @class TSThread; -@class UINavigationController; @interface Environment : NSObject diff --git a/Signal/src/util/OWSWindowManager.h b/SignalMessaging/utils/OWSWindowManager.h similarity index 100% rename from Signal/src/util/OWSWindowManager.h rename to SignalMessaging/utils/OWSWindowManager.h diff --git a/Signal/src/util/OWSWindowManager.m b/SignalMessaging/utils/OWSWindowManager.m similarity index 97% rename from Signal/src/util/OWSWindowManager.m rename to SignalMessaging/utils/OWSWindowManager.m index 7ca9ebe03..204ac9f58 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/SignalMessaging/utils/OWSWindowManager.m @@ -3,10 +3,10 @@ // #import "OWSWindowManager.h" -#import "Signal-Swift.h" -#import -#import -#import +#import "UIColor+OWS.h" +#import "UIFont+OWS.h" +#import "UIView+OWS.h" +#import NS_ASSUME_NONNULL_BEGIN @@ -79,7 +79,7 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) // UIWindowLevel_CallView @property (nonatomic) UIWindow *callViewWindow; -@property (nonatomic) UINavigationController *callNavigationController; +@property (nonatomic) OWSNavigationController *callNavigationController; // UIWindowLevel_Background if inactive, // UIWindowLevel_ScreenBlocking() if active. @@ -175,8 +175,8 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) UIViewController *viewController = [OWSWindowRootViewController new]; viewController.view.backgroundColor = [UIColor ows_materialBlueColor]; - UINavigationController *navigationController = - [[UINavigationController alloc] initWithRootViewController:viewController]; + OWSNavigationController *navigationController = + [[OWSNavigationController alloc] initWithRootViewController:viewController]; navigationController.navigationBarHidden = YES; OWSAssert(!self.callNavigationController); self.callNavigationController = navigationController; diff --git a/SignalShareExtension/ShareViewController.swift b/SignalShareExtension/ShareViewController.swift index 81891c543..12a65e588 100644 --- a/SignalShareExtension/ShareViewController.swift +++ b/SignalShareExtension/ShareViewController.swift @@ -26,7 +26,7 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed private var progressPoller: ProgressPoller? var loadViewController: SAELoadViewController? - let shareViewNavigationController: UINavigationController = UINavigationController() + let shareViewNavigationController: OWSNavigationController = OWSNavigationController() override open func loadView() { super.loadView() From 6c7af671bc55fe9e1a6d99316d8f221a5b17a72a Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 11:50:30 -0400 Subject: [PATCH 15/30] call banner above status bar for now --- SignalMessaging/utils/OWSWindowManager.m | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/SignalMessaging/utils/OWSWindowManager.m b/SignalMessaging/utils/OWSWindowManager.m index 204ac9f58..ee2747962 100644 --- a/SignalMessaging/utils/OWSWindowManager.m +++ b/SignalMessaging/utils/OWSWindowManager.m @@ -31,16 +31,15 @@ const CGFloat OWSWindowManagerCallScreenHeight(void) // Behind everything, especially the root window. const UIWindowLevel UIWindowLevel_Background = -1.f; -// MJK FIXME: this *looks* right, but then we can't receive taps that -// touch the status bar. We could: obscure status bar, but that looks wrong. -// have *another* transparent window? -// -// In front of the root window, behind the status bar -// but behind the screen blocking window. +// Putting the call banner above the status bar is not ideal. +// It obscures status bar content like the system clock +// But being behind the status bar introduces two worse problems that'd we'd need to address +// 1. Tap target is too small, only the 20px below the status bar are tappable +// 2. hot-spot connected banner obscure our return-to-call banner, so the user can't see that they're in a call. const UIWindowLevel UIWindowLevel_ReturnToCall(void); const UIWindowLevel UIWindowLevel_ReturnToCall(void) { - return UIWindowLevelStatusBar - 1.f; + return UIWindowLevelStatusBar + 1.f; } // In front of the root window, behind the screen blocking window. From 319a6ff765fad2918630ca195b7707356e52fb2c Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 14:52:46 -0400 Subject: [PATCH 16/30] fixup behavior on iOS10 --- Signal/src/AppDelegate.m | 4 +- .../ViewControllers/OWSNavigationController.m | 28 +++++--- SignalMessaging/Views/OWSNavigationBar.swift | 67 ++++++++++--------- 3 files changed, 56 insertions(+), 43 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index cd1d2dd04..4f041a9d3 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1099,8 +1099,8 @@ static NSTimeInterval launchStartedAt; // Resume lazy restore. [OWSBackupLazyRestoreJob runAsync]; #endif - - + + // MJK FIXME OutboundCallInitiator *outboundCallInitiator = SignalApp.sharedApp.outboundCallInitiator; [outboundCallInitiator initiateCallWithHandle:@"+14158181337"]; } diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index f938ac700..46f29e8e0 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -7,7 +7,6 @@ NS_ASSUME_NONNULL_BEGIN - @interface OWSNavigationController (OWSNavigationController) @end @@ -50,10 +49,10 @@ NS_ASSUME_NONNULL_BEGIN // Attempt 7: Since we can't seem to *shrink* the navbar, maybe we can grow it. // make additionalSafeAreaInsets - [self updateAdditionalSafeAreaInsets]; - self = [self initWithNavigationBarClass:[OWSNavigationBar class] toolbarClass:nil]; [self pushViewController:rootViewController animated:NO]; + + [self updateNavbarCallBannerLayout]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowManagerCallDidChange:) @@ -66,15 +65,28 @@ NS_ASSUME_NONNULL_BEGIN - (void)windowManagerCallDidChange:(NSNotification *)notification { DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - [self updateAdditionalSafeAreaInsets]; + [self updateNavbarCallBannerLayout]; } -- (void)updateAdditionalSafeAreaInsets +- (void)updateNavbarCallBannerLayout { - if (OWSWindowManager.sharedManager.hasCall) { - self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0); + if (@available(iOS 11.0, *)) { + if (OWSWindowManager.sharedManager.hasCall) { + self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0); + } else { + self.additionalSafeAreaInsets = UIEdgeInsetsZero; + } } else { - self.additionalSafeAreaInsets = UIEdgeInsetsZero; + if (![self.navigationBar isKindOfClass:[OWSNavigationBar class]]) { + OWSFail(@"%@ in %s navigationBar was unexpected class", self.logTag, __PRETTY_FUNCTION__); + return; + } + + 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; } } diff --git a/SignalMessaging/Views/OWSNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift index cc80768b4..113816a31 100644 --- a/SignalMessaging/Views/OWSNavigationBar.swift +++ b/SignalMessaging/Views/OWSNavigationBar.swift @@ -10,32 +10,34 @@ class OWSNavigationBar: UINavigationBar { // TODO - get a more precise value // TODO - test with other heights, e.g. w/ hotspot, w/ call in other app - let navbarHeight: CGFloat = 44 + let navbarWithoutStatusHeight: CGFloat = 44 let callBannerHeight: CGFloat = 40 + // MJK safe to hardcode? Do we even need this approach anymore? + var statusBarHeight: CGFloat { + // TODO? plumb through CurrentAppContext() + return 20 + } + override init(frame: CGRect) { super.init(frame: frame) self.isTranslucent = false - // TODO better place to observe? - NotificationCenter.default.addObserver(forName: .OWSWindowManagerCallDidChange, object: nil, queue: nil) { _ in - Logger.debug("\(self.logTag) in \(#function) OWSWindowManagerCallDidChange") - - self.callDidChange() - } + NotificationCenter.default.addObserver(self, selector: #selector(callDidChange), name: .OWSWindowManagerCallDidChange, object: nil) } - private func callDidChange() { -// if OWSWindowManager.shared().hasCall() { -// self.bounds.origin.y = -20 -// } else { -// self.bounds.origin.y = 0 -// } + @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() } } @@ -44,24 +46,22 @@ class OWSNavigationBar: UINavigationBar { } override func sizeThatFits(_ size: CGSize) -> CGSize { - // pre iOS11, sizeThatFits is repeatedly called to size the navbar, which is pretty straight forward - // as of iOS11, this is not true and we have to do things in layoutSubviews. - // FIXME: pre-iOS11, though the size is right, there's a glitch on the titleView while push/popping items. - - // MJK safe to hardcode? Do we even need this approach anymore? - let statusBarHeight: CGFloat = 20 - let result: CGSize = { - if OWSWindowManager.shared().hasCall() { - // status bar height gets re-added - return CGSize(width: CurrentAppContext().mainWindow!.bounds.width, height: navbarHeight - statusBarHeight) - } else { - return super.sizeThatFits(size) - } - }() + guard OWSWindowManager.shared().hasCall() else { + return super.sizeThatFits(size) + } - Logger.debug("\(self.logTag) in \(#function): \(result)") + 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. + let result = CGSize(width: CurrentAppContext().mainWindow!.bounds.width, height: navbarWithoutStatusHeight + statusBarHeight) + + Logger.debug("\(self.logTag) in \(#function): \(result)") - return result + return result + } } // override var center: CGPoint { @@ -83,7 +83,7 @@ class OWSNavigationBar: UINavigationBar { // seems unused. // override var intrinsicContentSize: CGSize { -// return CGSize(width: UIScreen.main.bounds.width, height: navbarHeight) +// return CGSize(width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) // return CGSize(width: UIScreen.main.bounds.width, height: 20) // } @@ -108,15 +108,16 @@ class OWSNavigationBar: UINavigationBar { override func layoutSubviews() { Logger.debug("\(self.logTag) in \(#function)") - guard #available(iOS 11.0, *), OWSWindowManager.shared().hasCall() else { + guard OWSWindowManager.shared().hasCall() else { +// guard #available(iOS 11.0, *), OWSWindowManager.shared().hasCall() else { super.layoutSubviews() return } // let rect = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: self.navbarHeightWithoutStatusBar) // self.frame = CGRect(x: 0, y: 20, width: UI Screen.main.bounds.width, height: ios11NavbarHeight) - self.frame = CGRect(x: 0, y: callBannerHeight, width: UIScreen.main.bounds.width, height: navbarHeight) - self.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarHeight) + self.frame = CGRect(x: 0, y: callBannerHeight, width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) + self.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) super.layoutSubviews() From d9d0227ce52d18f4d5b83ec8b34a28541249d8b0 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 14:52:57 -0400 Subject: [PATCH 17/30] Align search bar to safe area insets // FREEBIE --- Signal/src/ViewControllers/ContactsPicker.xib | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Signal/src/ViewControllers/ContactsPicker.xib b/Signal/src/ViewControllers/ContactsPicker.xib index f25c4fbb9..a78eca718 100644 --- a/Signal/src/ViewControllers/ContactsPicker.xib +++ b/Signal/src/ViewControllers/ContactsPicker.xib @@ -1,8 +1,12 @@ - - + + + + + - + + @@ -15,10 +19,11 @@ - + + @@ -26,6 +31,7 @@ + @@ -38,7 +44,7 @@ - + From 1b6071675936658fa0367dbca326774936642911 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 15:45:48 -0400 Subject: [PATCH 18/30] 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)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)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) +@interface OWSNavigationController (OWSNavigationController) @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") { From 49c652ad1463acb49d8806be8199df4652350a42 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 16:12:51 -0400 Subject: [PATCH 19/30] Comment cleanup // FREEBIE --- SignalMessaging/Views/OWSNavigationBar.swift | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/SignalMessaging/Views/OWSNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift index 0342968c7..77cdf5fe9 100644 --- a/SignalMessaging/Views/OWSNavigationBar.swift +++ b/SignalMessaging/Views/OWSNavigationBar.swift @@ -15,14 +15,10 @@ 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 let callBannerHeight: CGFloat = 40 - // MJK safe to hardcode? Do we even need this approach anymore? var statusBarHeight: CGFloat { - // TODO? plumb through CurrentAppContext() return 20 } @@ -71,8 +67,6 @@ class OWSNavigationBar: UINavigationBar { return } -// let rect = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: self.navbarHeightWithoutStatusBar) -// self.frame = CGRect(x: 0, y: 20, width: UI Screen.main.bounds.width, height: ios11NavbarHeight) self.frame = CGRect(x: 0, y: callBannerHeight, width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) self.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) @@ -82,13 +76,15 @@ class OWSNavigationBar: UINavigationBar { return } - // This is only necessary on iOS11, which has some private views within the navbar + // This is only necessary on iOS11, which has some private views within that lay outside of the navbar. + // They aren't actually visible behind the call status bar, but they looks strange during present/dismiss + // animations for modal VC's for subview in self.subviews { let stringFromClass = NSStringFromClass(subview.classForCoder) if stringFromClass.contains("BarBackground") { - subview.frame = self.bounds//.offsetBy(dx: 0, dy: 20) + subview.frame = self.bounds } else if stringFromClass.contains("BarContentView") { - subview.frame = self.bounds//.offsetBy(dx: 0, dy: 20) + subview.frame = self.bounds } } } From 7ad5f154483640c0cab9da30d153ce1f7c8299fd Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 16:22:14 -0400 Subject: [PATCH 20/30] Restore cancleable back gesture for those VC's that use it // FREEBIE --- .../ViewControllers/OWSNavigationController.m | 79 +++++++++---------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index 8557d3155..ef85024cd 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface OWSNavigationController (OWSNavigationController) +@interface UINavigationController (OWSNavigationController) @end @@ -106,7 +106,7 @@ NS_ASSUME_NONNULL_BEGIN { [super viewDidLoad]; - // self.interactivePopGestureRecognizer.delegate = self; + self.interactivePopGestureRecognizer.delegate = self; } #pragma mark - UINavigationBarDelegate @@ -114,51 +114,48 @@ NS_ASSUME_NONNULL_BEGIN // All OWSNavigationController serve as the UINavigationBarDelegate for their navbar. // We override shouldPopItem: in order to cancel some back button presses - for example, // if a view has unsaved changes. -//- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item -//{ -// OWSAssert(self.interactivePopGestureRecognizer.delegate == self); -// UIViewController *topViewController = self.topViewController; -// -// // wasBackButtonClicked is YES if the back button was pressed but not -// // if a back gesture was performed or if the view is popped programmatically. -// BOOL wasBackButtonClicked = topViewController.navigationItem == item; -// BOOL result = YES; -// if (wasBackButtonClicked) { -// if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { -// id navigationView = (id)topViewController; -// result = ![navigationView shouldCancelNavigationBack]; -// } -// } -// -// // If we're not going to cancel the pop/back, we need to call the super -// // implementation since it has important side effects. -// if (result) { -// // NOTE: result might end up NO if the super implementation cancels the -// // the pop/back. -// -// // MJK WTF?? This seems super broken. It won't compile now, but how could it ever -// // have? This is a delegate method, so how are we calling it on super? -// // [super navigationBar:navigationBar shouldPopItem:item]; -// result = YES; -// } -// return result; -//} +- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item +{ + OWSAssert(self.interactivePopGestureRecognizer.delegate == self); + UIViewController *topViewController = self.topViewController; + + // wasBackButtonClicked is YES if the back button was pressed but not + // if a back gesture was performed or if the view is popped programmatically. + BOOL wasBackButtonClicked = topViewController.navigationItem == item; + BOOL result = YES; + if (wasBackButtonClicked) { + if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { + id navigationView = (id)topViewController; + result = ![navigationView shouldCancelNavigationBack]; + } + } + + // If we're not going to cancel the pop/back, we need to call the super + // implementation since it has important side effects. + if (result) { + // NOTE: result might end up NO if the super implementation cancels the + // the pop/back. + [super navigationBar:navigationBar shouldPopItem:item]; + result = YES; + } + return result; +} #pragma mark - UIGestureRecognizerDelegate // We serve as the UIGestureRecognizerDelegate of the interactivePopGestureRecognizer // in order to cancel some "back" gestures - for example, // if a view has unsaved changes. -//- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer -//{ -// UIViewController *topViewController = self.topViewController; -// if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { -// id navigationView = (id)topViewController; -// return ![navigationView shouldCancelNavigationBack]; -// } else { -// return YES; -// } -//} +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer +{ + UIViewController *topViewController = self.topViewController; + if ([topViewController conformsToProtocol:@protocol(OWSNavigationView)]) { + id navigationView = (id)topViewController; + return ![navigationView shouldCancelNavigationBack]; + } else { + return YES; + } +} @end From 778e11c2c32a2d5506fb8954086592e197c761bf Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 16:26:17 -0400 Subject: [PATCH 21/30] cleanup ahead of PR // FREEBIE --- Signal/src/AppDelegate.m | 3 --- .../ViewControllers/OWSNavigationController.m | 26 ------------------- SignalMessaging/utils/OWSWindowManager.m | 25 +++--------------- 3 files changed, 3 insertions(+), 51 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 4f041a9d3..71eefb5a3 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1100,9 +1100,6 @@ static NSTimeInterval launchStartedAt; [OWSBackupLazyRestoreJob runAsync]; #endif - // MJK FIXME - OutboundCallInitiator *outboundCallInitiator = SignalApp.sharedApp.outboundCallInitiator; - [outboundCallInitiator initiateCallWithHandle:@"+14158181337"]; } - (void)registrationStateDidChange diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index ef85024cd..b44cf0ee7 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -23,32 +23,6 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithRootViewController:(UIViewController *)rootViewController { - // Attempt 1: negative additionalSafeArea - // Failure: additionalSafeArea insets cannot be negative - // UIEdgeInsets newSafeArea = UIEdgeInsetsMake(-50, 30, 20, 30); - // rootViewController.additionalSafeAreaInsets = newSafeArea; - - // Attempt 2: safeAreaInsets on vc.view - // failure. they're already 0 - // UIEdgeInsets existingInsets = rootViewController.view.safeAreaInsets; - - // Attempt 3: override topLayoutGuide? - // Failure - not called. - // overriding it does no good - it's not called by default layout code. - // presumably it just existing if you want to use it as an anchor. - - // Attemp 4: sizeForChildContentConainer? - // Failure - not called. - - // Attempt 5: autoSetDimension on navbar - // Failure: no effect on rendered size - - // Attempt 6: manually set child frames in will/didLayoutSubviews - // glitchy, and viewcontrollers re-layout themselves afterwards anyway - - // Attempt 7: Since we can't seem to *shrink* the navbar, maybe we can grow it. - // make additionalSafeAreaInsets - self = [self initWithNavigationBarClass:[OWSNavigationBar class] toolbarClass:nil]; [self pushViewController:rootViewController animated:NO]; diff --git a/SignalMessaging/utils/OWSWindowManager.m b/SignalMessaging/utils/OWSWindowManager.m index ee2747962..8773318ca 100644 --- a/SignalMessaging/utils/OWSWindowManager.m +++ b/SignalMessaging/utils/OWSWindowManager.m @@ -11,17 +11,12 @@ NS_ASSUME_NONNULL_BEGIN NSString *const OWSWindowManagerCallDidChangeNotification = @"OWSWindowManagerCallDidChangeNotification"; -// NSString *const OWSWindowManagerWillShowReturnToCallWindowNotification = -// @"OWSWindowManagerWillShowReturnToCallWindowNotification"; NSString *const -// OWSWindowManagerWillHideReturnToCallWindowNotification = @"OWSWindowManagerWillHideReturnToCallWindowNotification"; const CGFloat OWSWindowManagerCallScreenHeight(void); const CGFloat OWSWindowManagerCallScreenHeight(void) { if ([UIDevice currentDevice].isIPhoneX) { - // TODO - rather than a bigger banner, we should stick with iPhoneX - // design changes, which only apply a green circle around the clock UI. return 60; } else { return 40; @@ -274,9 +269,6 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) OWSAssert(self.callViewWindow); OWSAssert(self.screenBlockingWindow); - // MJK remove - self.rootWindow.backgroundColor = UIColor.yellowColor; - // To avoid bad frames, we never want to hide the blocking window, so we manipulate // its window level to "hide" it behind other windows. The other windows have fixed // window level and are shown/hidden as necessary. @@ -299,21 +291,21 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) } else if (self.callViewController) { // Show Root Window + "Return to Call". - [self ensureRootWindowShownWithActiveCall:YES]; + [self ensureRootWindowShown]; [self ensureReturnToCallWindowShown]; [self ensureCallViewWindowHidden]; [self ensureScreenBlockWindowHidden]; } else { // Show Root Window - [self ensureRootWindowShownWithActiveCall:NO]; + [self ensureRootWindowShown]; [self ensureReturnToCallWindowHidden]; [self ensureCallViewWindowHidden]; [self ensureScreenBlockWindowHidden]; } } -- (void)ensureRootWindowShownWithActiveCall:(BOOL)isActiveCall +- (void)ensureRootWindowShown { OWSAssertIsOnMainThread(); @@ -321,17 +313,6 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) DDLogInfo(@"%@ showing root window.", self.logTag); } - CGRect defaultFrame = [UIScreen mainScreen].bounds; - // if (isActiveCall) { - // CGRect frameWithActiveCall = CGRectMake(0, - // OWSWindowManagerCallScreenHeight(), - // defaultFrame.size.width, - // defaultFrame.size.height - OWSWindowManagerCallScreenHeight()); - // self.rootWindow.frame = frameWithActiveCall; - // } else { - self.rootWindow.frame = defaultFrame; - // } - // By calling makeKeyAndVisible we ensure the rootViewController becomes firt responder. // In the normal case, that means the SignalViewController will call `becomeFirstResponder` // on the vc on top of its navigation stack. From 3383c5e80c344afa6a76980e9ea71a7187a408c8 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 17 May 2018 17:58:43 -0400 Subject: [PATCH 22/30] Fixup for iPhoneX // FREEBIE --- .../ViewControllers/OWSNavigationController.m | 3 ++- SignalMessaging/Views/OWSNavigationBar.swift | 14 +++++++++----- SignalMessaging/utils/OWSWindowManager.h | 1 + SignalMessaging/utils/OWSWindowManager.m | 3 +-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index b44cf0ee7..189fef258 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -53,9 +53,10 @@ NS_ASSUME_NONNULL_BEGIN } else { self.additionalSafeAreaInsets = UIEdgeInsetsZero; } + // in iOS11 we have to ensure the position *in* layoutSubviews. [navbar layoutSubviews]; } else { - // Pre iOS11 we have to position the frame manually + // Pre iOS11 we size the navbar, and position it vertically once. [navbar sizeToFit]; if (OWSWindowManager.sharedManager.hasCall) { diff --git a/SignalMessaging/Views/OWSNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift index 77cdf5fe9..6b458adb8 100644 --- a/SignalMessaging/Views/OWSNavigationBar.swift +++ b/SignalMessaging/Views/OWSNavigationBar.swift @@ -16,12 +16,16 @@ class OWSNavigationBar: UINavigationBar { weak var navBarLayoutDelegate: NavBarLayoutDelegate? let navbarWithoutStatusHeight: CGFloat = 44 - let callBannerHeight: CGFloat = 40 + let callBannerHeight: CGFloat = OWSWindowManagerCallScreenHeight() var statusBarHeight: CGFloat { return 20 } + var fullWidth: CGFloat { + return UIScreen.main.bounds.size.width + } + override init(frame: CGRect) { super.init(frame: frame) @@ -51,7 +55,7 @@ class OWSNavigationBar: UINavigationBar { // 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) + let result = CGSize(width: fullWidth, height: navbarWithoutStatusHeight + statusBarHeight) Logger.debug("\(self.logTag) in \(#function): \(result)") @@ -60,15 +64,15 @@ class OWSNavigationBar: UINavigationBar { } override func layoutSubviews() { - Logger.debug("\(self.logTag) in \(#function)") + Logger.debug("\(self.logTag) in \(#function) with frame: \(frame)") guard OWSWindowManager.shared().hasCall() else { super.layoutSubviews() return } - self.frame = CGRect(x: 0, y: callBannerHeight, width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) - self.bounds = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: navbarWithoutStatusHeight) + self.frame = CGRect(x: 0, y: callBannerHeight, width: fullWidth, height: navbarWithoutStatusHeight) + self.bounds = CGRect(x: 0, y: 0, width: fullWidth, height: navbarWithoutStatusHeight) super.layoutSubviews() diff --git a/SignalMessaging/utils/OWSWindowManager.h b/SignalMessaging/utils/OWSWindowManager.h index 7122f27df..6d7046d15 100644 --- a/SignalMessaging/utils/OWSWindowManager.h +++ b/SignalMessaging/utils/OWSWindowManager.h @@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - extern NSString *const OWSWindowManagerCallDidChangeNotification; +const CGFloat OWSWindowManagerCallScreenHeight(void); extern const UIWindowLevel UIWindowLevel_Background; diff --git a/SignalMessaging/utils/OWSWindowManager.m b/SignalMessaging/utils/OWSWindowManager.m index 8773318ca..b5f75518c 100644 --- a/SignalMessaging/utils/OWSWindowManager.m +++ b/SignalMessaging/utils/OWSWindowManager.m @@ -13,11 +13,10 @@ NS_ASSUME_NONNULL_BEGIN NSString *const OWSWindowManagerCallDidChangeNotification = @"OWSWindowManagerCallDidChangeNotification"; -const CGFloat OWSWindowManagerCallScreenHeight(void); const CGFloat OWSWindowManagerCallScreenHeight(void) { if ([UIDevice currentDevice].isIPhoneX) { - return 60; + return 64; } else { return 40; } From 4c9808d1a13ab88e4e02c63db3703c3cdaa2343a Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 18 May 2018 09:12:01 -0400 Subject: [PATCH 23/30] Fix iPhoneX layout show status bar above call banner // FREEBIE --- Signal/src/util/MainAppContext.m | 5 ++++ .../ViewControllers/OWSNavigationController.m | 10 +++++-- SignalMessaging/Views/OWSNavigationBar.swift | 18 ++++++++++--- SignalMessaging/utils/OWSWindowManager.m | 27 ++++++++++++++++--- SignalServiceKit/src/Util/AppContext.h | 2 ++ .../utils/ShareAppExtensionContext.m | 6 +++++ 6 files changed, 59 insertions(+), 9 deletions(-) diff --git a/Signal/src/util/MainAppContext.m b/Signal/src/util/MainAppContext.m index 1199d698a..5d7f708e1 100644 --- a/Signal/src/util/MainAppContext.m +++ b/Signal/src/util/MainAppContext.m @@ -128,6 +128,11 @@ NS_ASSUME_NONNULL_BEGIN [[UIApplication sharedApplication] setStatusBarHidden:isHidden animated:isAnimated]; } +- (CGFloat)statusBarHeight +{ + return [UIApplication sharedApplication].statusBarFrame.size.height; +} + - (BOOL)isInBackground { return [UIApplication sharedApplication].applicationState == UIApplicationStateBackground; diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index 189fef258..cd85fc451 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -49,11 +49,17 @@ NS_ASSUME_NONNULL_BEGIN if (@available(iOS 11.0, *)) { if (OWSWindowManager.sharedManager.hasCall) { - self.additionalSafeAreaInsets = UIEdgeInsetsMake(64, 0, 0, 0); + if (UIDevice.currentDevice.isIPhoneX) { + // iPhoneX computes status bar height differently. + self.additionalSafeAreaInsets = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + 20, 0, 0, 0); + } else { + self.additionalSafeAreaInsets + = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + CurrentAppContext().statusBarHeight, 0, 0, 0); + } } else { self.additionalSafeAreaInsets = UIEdgeInsetsZero; } - // in iOS11 we have to ensure the position *in* layoutSubviews. + // in iOS11 we have to ensure the navbar frame *in* layoutSubviews. [navbar layoutSubviews]; } else { // Pre iOS11 we size the navbar, and position it vertically once. diff --git a/SignalMessaging/Views/OWSNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift index 6b458adb8..04be1803a 100644 --- a/SignalMessaging/Views/OWSNavigationBar.swift +++ b/SignalMessaging/Views/OWSNavigationBar.swift @@ -16,22 +16,30 @@ class OWSNavigationBar: UINavigationBar { weak var navBarLayoutDelegate: NavBarLayoutDelegate? let navbarWithoutStatusHeight: CGFloat = 44 - let callBannerHeight: CGFloat = OWSWindowManagerCallScreenHeight() + + var callBannerHeight: CGFloat { + return OWSWindowManagerCallScreenHeight() + } var statusBarHeight: CGFloat { - return 20 + return CurrentAppContext().statusBarHeight } var fullWidth: CGFloat { return UIScreen.main.bounds.size.width } + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + override init(frame: CGRect) { super.init(frame: frame) self.isTranslucent = false NotificationCenter.default.addObserver(self, selector: #selector(callDidChange), name: .OWSWindowManagerCallDidChange, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(didChangeStatusBarFrame), name: .UIApplicationDidChangeStatusBarFrame, object: nil) } @objc @@ -40,8 +48,10 @@ class OWSNavigationBar: UINavigationBar { self.navBarLayoutDelegate?.navBarCallLayoutDidChange(navbar: self) } - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") + @objc + public func didChangeStatusBarFrame() { + Logger.debug("\(self.logTag) in \(#function)") + self.navBarLayoutDelegate?.navBarCallLayoutDidChange(navbar: self) } override func sizeThatFits(_ size: CGSize) -> CGSize { diff --git a/SignalMessaging/utils/OWSWindowManager.m b/SignalMessaging/utils/OWSWindowManager.m index b5f75518c..a1ede3eae 100644 --- a/SignalMessaging/utils/OWSWindowManager.m +++ b/SignalMessaging/utils/OWSWindowManager.m @@ -16,9 +16,12 @@ NSString *const OWSWindowManagerCallDidChangeNotification = @"OWSWindowManagerCa const CGFloat OWSWindowManagerCallScreenHeight(void) { if ([UIDevice currentDevice].isIPhoneX) { + // On an iPhoneX, the system return-to-call banner has been replaced by a much subtler green + // circle behind the system clock. Instead, we mimic the old system call banner as on older devices, + // but it has to be taller to fit beneath the notch. return 64; } else { - return 40; + return CurrentAppContext().statusBarHeight + 20; } } @@ -29,11 +32,10 @@ const UIWindowLevel UIWindowLevel_Background = -1.f; // It obscures status bar content like the system clock // But being behind the status bar introduces two worse problems that'd we'd need to address // 1. Tap target is too small, only the 20px below the status bar are tappable -// 2. hot-spot connected banner obscure our return-to-call banner, so the user can't see that they're in a call. const UIWindowLevel UIWindowLevel_ReturnToCall(void); const UIWindowLevel UIWindowLevel_ReturnToCall(void) { - return UIWindowLevelStatusBar + 1.f; + return UIWindowLevelStatusBar - 1; } // In front of the root window, behind the screen blocking window. @@ -122,15 +124,34 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) OWSAssert(screenBlockingWindow); OWSAssert(!self.screenBlockingWindow); + // MJK FIXME + rootWindow.backgroundColor = UIColor.yellowColor; + self.rootWindow = rootWindow; self.screenBlockingWindow = screenBlockingWindow; self.returnToCallWindow = [self createReturnToCallWindow:rootWindow]; self.callViewWindow = [self createCallViewWindow:rootWindow]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(didChangeStatusBarFrame:) + name:UIApplicationDidChangeStatusBarFrameNotification + object:nil]; + [self ensureWindowState]; } +- (void)didChangeStatusBarFrame:(NSNotification *)notification +{ + CGRect newFrame = self.returnToCallWindow.frame; + newFrame.size.height = OWSWindowManagerCallScreenHeight(); + + DDLogDebug(@"%@ StatusBar changed frames - updating returnToCallWindowFrame: %@", + self.logTag, + NSStringFromCGRect(newFrame)); + self.returnToCallWindow.frame = newFrame; +} + - (UIWindow *)createReturnToCallWindow:(UIWindow *)rootWindow { OWSAssertIsOnMainThread(); diff --git a/SignalServiceKit/src/Util/AppContext.h b/SignalServiceKit/src/Util/AppContext.h index 78c77df50..1feea801e 100755 --- a/SignalServiceKit/src/Util/AppContext.h +++ b/SignalServiceKit/src/Util/AppContext.h @@ -59,6 +59,8 @@ NSString *NSStringForUIApplicationState(UIApplicationState value); - (void)setStatusBarStyle:(UIStatusBarStyle)statusBarStyle; - (void)setStatusBarHidden:(BOOL)isHidden animated:(BOOL)isAnimated; +@property (nonatomic, readonly) CGFloat statusBarHeight; + // Returns the VC that should be used to present alerts, modals, etc. - (nullable UIViewController *)frontmostViewController; diff --git a/SignalShareExtension/utils/ShareAppExtensionContext.m b/SignalShareExtension/utils/ShareAppExtensionContext.m index 0b926a223..6bf57d5b0 100644 --- a/SignalShareExtension/utils/ShareAppExtensionContext.m +++ b/SignalShareExtension/utils/ShareAppExtensionContext.m @@ -135,6 +135,12 @@ NS_ASSUME_NONNULL_BEGIN DDLogInfo(@"Ignoring request to show/hide status bar style since we're in an app extension"); } +- (CGFloat)statusBarHeight +{ + OWSFail(@"%@ in %s unexpected for share extension", self.logTag, __PRETTY_FUNCTION__); + return 20; +} + - (BOOL)isInBackground { return self.isSAEInBackground; From 4f8010023460bdbf6726a22023c9958047ffb1fd Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 18 May 2018 09:37:59 -0400 Subject: [PATCH 24/30] Tapping on status bar returns to call We want to render the return-to-call banner behind the status bar, so the user can see the system clock, etc. But normally, doing so would mean we wouldn't receive touches in the top 20px of the screen. // FREEBIE --- Signal/src/AppDelegate.m | 13 +++++++++++++ .../ReturnToCallViewController.swift | 7 +++++++ SignalMessaging/contacts/ViewControllerUtils.h | 1 + SignalMessaging/contacts/ViewControllerUtils.m | 2 ++ 4 files changed, 23 insertions(+) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 71eefb5a3..49e60c194 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1162,4 +1162,17 @@ static NSTimeInterval launchStartedAt; [AppUpdateNag.sharedInstance showAppUpgradeNagIfNecessary]; } +#pragma mark - status bar touches + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + [super touchesBegan:touches withEvent:event]; + CGPoint location = [[[event allTouches] anyObject] locationInView:[self window]]; + CGRect statusBarFrame = [UIApplication sharedApplication].statusBarFrame; + if (CGRectContainsPoint(statusBarFrame, location)) { + DDLogDebug(@"%@ touched status bar", self.logTag); + [[NSNotificationCenter defaultCenter] postNotificationName:TappedStatusBarNotification object:nil]; + } +} + @end diff --git a/SignalMessaging/ViewControllers/ReturnToCallViewController.swift b/SignalMessaging/ViewControllers/ReturnToCallViewController.swift index 2b5873d05..92e0d2292 100644 --- a/SignalMessaging/ViewControllers/ReturnToCallViewController.swift +++ b/SignalMessaging/ViewControllers/ReturnToCallViewController.swift @@ -17,6 +17,7 @@ public class ReturnToCallViewController: UIViewController { let returnToCallLabel = UILabel() public func startAnimating() { + NotificationCenter.default.addObserver(self, selector: #selector(didTapStatusBar(notification:)), name: .TappedStatusBar, object: nil) self.returnToCallLabel.layer.removeAllAnimations() self.returnToCallLabel.alpha = 1 UIView.animate(withDuration: 1, @@ -27,6 +28,7 @@ public class ReturnToCallViewController: UIViewController { } public func stopAnimating() { + NotificationCenter.default.removeObserver(self, name: .TappedStatusBar, object: nil) self.returnToCallLabel.layer.removeAllAnimations() } @@ -56,6 +58,11 @@ public class ReturnToCallViewController: UIViewController { self.delegate?.returnToCallWasTapped(self) } + @objc + public func didTapStatusBar(notification: Notification) { + self.delegate?.returnToCallWasTapped(self) + } + override public func viewWillLayoutSubviews() { Logger.debug("\(self.logTag) in \(#function)") diff --git a/SignalMessaging/contacts/ViewControllerUtils.h b/SignalMessaging/contacts/ViewControllerUtils.h index 168c3d553..bedba7671 100644 --- a/SignalMessaging/contacts/ViewControllerUtils.h +++ b/SignalMessaging/contacts/ViewControllerUtils.h @@ -8,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN extern const NSUInteger kMin2FAPinLength; extern const NSUInteger kMax2FAPinLength; +extern NSString *const TappedStatusBarNotification; @interface ViewControllerUtils : NSObject diff --git a/SignalMessaging/contacts/ViewControllerUtils.m b/SignalMessaging/contacts/ViewControllerUtils.m index eb9406cea..6215e4c3e 100644 --- a/SignalMessaging/contacts/ViewControllerUtils.m +++ b/SignalMessaging/contacts/ViewControllerUtils.m @@ -11,6 +11,8 @@ NS_ASSUME_NONNULL_BEGIN +NSString *const TappedStatusBarNotification = @"TappedStatusBarNotification"; + const NSUInteger kMin2FAPinLength = 4; const NSUInteger kMax2FAPinLength = 16; From 2709a91b5e054d77f1cbb83c8cb5908ee52d2778 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 18 May 2018 12:55:33 -0400 Subject: [PATCH 25/30] Fixup attachment approval vis-a-vis call banner // FREEBIE --- .../ConversationViewController.m | 5 +- .../AttachmentApprovalViewController.swift | 45 +++++++++--------- .../MessageApprovalViewController.swift | 46 ++++++------------- .../SharingThreadPickerViewController.m | 13 ++---- 4 files changed, 41 insertions(+), 68 deletions(-) diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 502345336..bdbc5e3b8 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -4038,8 +4038,9 @@ typedef enum : NSUInteger { } else if (skipApprovalDialog) { [self sendMessageAttachment:attachment]; } else { - AttachmentApprovalViewController *approvalVC = [[AttachmentApprovalViewController alloc] initWithAttachment:attachment delegate:self]; - [self presentViewController:approvalVC animated:YES completion:nil]; + OWSNavigationController *modal = + [AttachmentApprovalViewController wrappedInNavControllerWithAttachment:attachment delegate:self]; + [self presentViewController:modal animated:YES completion:nil]; } }); } diff --git a/SignalMessaging/attachments/AttachmentApprovalViewController.swift b/SignalMessaging/attachments/AttachmentApprovalViewController.swift index e869c0175..22a444f65 100644 --- a/SignalMessaging/attachments/AttachmentApprovalViewController.swift +++ b/SignalMessaging/attachments/AttachmentApprovalViewController.swift @@ -55,7 +55,26 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool override public func viewDidLoad() { super.viewDidLoad() - self.navigationItem.title = dialogTitle() + self.navigationItem.title = nil + + let cancelButton = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(cancelPressed)) + cancelButton.tintColor = .white + self.navigationItem.leftBarButtonItem = cancelButton + } + + @objc + public class func wrappedInNavController(attachment: SignalAttachment, delegate: AttachmentApprovalViewControllerDelegate) -> OWSNavigationController { + let vc = AttachmentApprovalViewController(attachment: attachment, delegate: delegate) + let navController = OWSNavigationController(rootViewController: vc) + + // Make navigationBar clear + navController.navigationBar.backgroundColor = .clear + navController.navigationBar.setBackgroundImage(UIImage(), for: .default) + navController.navigationBar.isTranslucent = true + navController.navigationBar.shadowImage = UIImage() + navController.navigationBar.clipsToBounds = true + + return navController } override public func viewWillLayoutSubviews() { @@ -66,14 +85,6 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool updateMinZoomScaleForSize(view.bounds.size) } - private func dialogTitle() -> String { - guard let filename = mediaMessageView.formattedFileName() else { - return NSLocalizedString("ATTACHMENT_APPROVAL_DIALOG_TITLE", - comment: "Title for the 'attachment approval' dialog.") - } - return filename - } - override public func viewWillAppear(_ animated: Bool) { Logger.debug("\(logTag) in \(#function)") super.viewWillAppear(animated) @@ -150,19 +161,6 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool topGradient.autoSetDimension(.height, toSize: ScaleFromIPhone5(60)) } - // Top Toolbar - let topToolbar = makeClearToolbar() - - self.view.addSubview(topToolbar) - topToolbar.autoPinWidthToSuperview() - topToolbar.autoPin(toTopLayoutGuideOf: self, withInset: 0) - topToolbar.setContentHuggingVerticalHigh() - topToolbar.setCompressionResistanceVerticalHigh() - - let cancelButton = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(cancelPressed)) - cancelButton.tintColor = UIColor.white - topToolbar.items = [cancelButton] - // Bottom Toolbar let captioningToolbar = CaptioningToolbar() captioningToolbar.captioningToolbarDelegate = self @@ -198,7 +196,7 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool // pops the keyboard. contentContainer.addSubview(progressBar) - progressBar.autoPinEdge(.top, to: .bottom, of: topToolbar) + progressBar.autoPin(toTopLayoutGuideOf: self, withInset: 0) progressBar.autoPinWidthToSuperview() progressBar.autoSetDimension(.height, toSize: 44) @@ -320,7 +318,6 @@ public class AttachmentApprovalViewController: OWSViewController, CaptioningTool } public func playerProgressBarDidStartScrubbing(_ playerProgressBar: PlayerProgressBar) { - // [self.videoPlayer pause]; guard let videoPlayer = self.videoPlayer else { owsFail("\(TAG) video player was unexpectedly nil") return diff --git a/SignalMessaging/attachments/MessageApprovalViewController.swift b/SignalMessaging/attachments/MessageApprovalViewController.swift index ccaebf347..084c53e9d 100644 --- a/SignalMessaging/attachments/MessageApprovalViewController.swift +++ b/SignalMessaging/attachments/MessageApprovalViewController.swift @@ -23,7 +23,13 @@ public class MessageApprovalViewController: OWSViewController, UITextViewDelegat let contactsManager: OWSContactsManager private(set) var textView: UITextView! - private(set) var topToolbar: UIToolbar! + private var sendButton: UIBarButtonItem = { + return UIBarButtonItem(title: NSLocalizedString("SEND_BUTTON_TITLE", + comment: "Label for the send button in the conversation view."), + style: .plain, + target: self, + action: #selector(sendPressed)) + }() // MARK: Initializers @@ -48,26 +54,13 @@ public class MessageApprovalViewController: OWSViewController, UITextViewDelegat super.viewDidLoad() self.navigationItem.title = NSLocalizedString("MESSAGE_APPROVAL_DIALOG_TITLE", comment: "Title for the 'message approval' dialog.") - } - private func updateToolbar() { - var items = [UIBarButtonItem]() - - let cancelButton = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(cancelPressed)) - items.append(cancelButton) - - if textView.text.count > 0 { - let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) - items.append(spacer) - let sendButton = UIBarButtonItem(title: NSLocalizedString("SEND_BUTTON_TITLE", - comment: "Label for the send button in the conversation view."), - style: .plain, - target: self, - action: #selector(sendPressed)) - items.append(sendButton) - } + self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .stop, target: self, action: #selector(cancelPressed)) + self.navigationItem.rightBarButtonItem = sendButton + } - topToolbar.items = items + private func updateSendButton() { + sendButton.isEnabled = textView.text.count > 0 } // MARK: - Create Views @@ -77,20 +70,11 @@ public class MessageApprovalViewController: OWSViewController, UITextViewDelegat self.view = UIView.container() self.view.backgroundColor = UIColor.white - // Top Toolbar - topToolbar = UIToolbar() - topToolbar.backgroundColor = UIColor.ows_toolbarBackground - self.view.addSubview(topToolbar) - topToolbar.autoPinWidthToSuperview() - topToolbar.autoPin(toTopLayoutGuideOf: self, withInset: 0) - topToolbar.setContentHuggingVerticalHigh() - topToolbar.setCompressionResistanceVerticalHigh() - // Recipient Row let recipientRow = createRecipientRow() view.addSubview(recipientRow) recipientRow.autoPinWidthToSuperview() - recipientRow.autoPinEdge(.top, to: .bottom, of: topToolbar) + recipientRow.autoPin(toTopLayoutGuideOf: self, withInset: 0) // Text View textView = UITextView() @@ -105,8 +89,6 @@ public class MessageApprovalViewController: OWSViewController, UITextViewDelegat textView.autoPinWidthToSuperview() textView.autoPinEdge(.top, to: .bottom, of: recipientRow) textView.autoPin(toBottomLayoutGuideOf: self, withInset: 0) - - updateToolbar() } private func createRecipientRow() -> UIView { @@ -223,6 +205,6 @@ public class MessageApprovalViewController: OWSViewController, UITextViewDelegat // MARK: - UITextViewDelegate public func textViewDidChange(_ textView: UITextView) { - updateToolbar() + updateSendButton() } } diff --git a/SignalMessaging/attachments/SharingThreadPickerViewController.m b/SignalMessaging/attachments/SharingThreadPickerViewController.m index 65de3f7d1..5b9c20b6c 100644 --- a/SignalMessaging/attachments/SharingThreadPickerViewController.m +++ b/SignalMessaging/attachments/SharingThreadPickerViewController.m @@ -185,12 +185,6 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); NSString *_Nullable messageText = [self convertAttachmentToMessageTextIfPossible]; - // Hide the navigation bar before presenting the approval view. - // - // Note that cancelling in the approval views will dismiss the entire - // share extension, so there is no "back" button. - self.navigationController.navigationBarHidden = YES; - if (messageText) { MessageApprovalViewController *approvalVC = [[MessageApprovalViewController alloc] initWithMessageText:messageText @@ -200,10 +194,9 @@ typedef void (^SendMessageBlock)(SendCompletionBlock completion); [self.navigationController pushViewController:approvalVC animated:YES]; } else { - AttachmentApprovalViewController *approvalVC = - [[AttachmentApprovalViewController alloc] initWithAttachment:self.attachment delegate:self]; - - [self.navigationController pushViewController:approvalVC animated:YES]; + OWSNavigationController *approvalModal = + [AttachmentApprovalViewController wrappedInNavControllerWithAttachment:self.attachment delegate:self]; + [self presentViewController:approvalModal animated:YES completion:nil]; } } From fe62a6ac924bc90a4fb2042e733832a04d46b377 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 18 May 2018 16:17:45 -0400 Subject: [PATCH 26/30] CNContactController needs to be presented in a navcontroller with a translucent navbar. In cases where we were presenting modally, we can easily modify the modal to have a translucent navbar. In the one place we were pushing onto the SignalsNavigationController, rather than modifying the SNC.isTranslucent and having to clean it up, I've opted to convert to a modal presentation. // FREEBIE --- Signal/src/AppDelegate.m | 1 - ...ShareToExistingContactViewController.swift | 31 ++++++++++++++++--- .../ContactShareViewHelper.swift | 13 +++++--- SignalMessaging/Views/ContactsViewHelper.m | 22 +++++++------ 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 49e60c194..6a6cbe549 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -1099,7 +1099,6 @@ static NSTimeInterval launchStartedAt; // Resume lazy restore. [OWSBackupLazyRestoreJob runAsync]; #endif - } - (void)registrationStateDidChange diff --git a/Signal/src/ViewControllers/AddContactShareToExistingContactViewController.swift b/Signal/src/ViewControllers/AddContactShareToExistingContactViewController.swift index 327de07ab..0f5c1a3eb 100644 --- a/Signal/src/ViewControllers/AddContactShareToExistingContactViewController.swift +++ b/Signal/src/ViewControllers/AddContactShareToExistingContactViewController.swift @@ -74,11 +74,19 @@ class AddContactShareToExistingContactViewController: ContactsPicker, ContactsPi contactViewController.allowsEditing = true contactViewController.delegate = self - guard let navigationController = self.navigationController else { - owsFail("\(logTag) in \(#function) navigationController was unexpectedly nil") - return + let modal = OWSNavigationController(rootViewController: contactViewController) + + // HACK otherwise CNContactViewController Navbar is shows window background color. + // RADAR rdar://28433898 http://www.openradar.me/28433898 + // CNContactViewController incompatible with opaque navigation bar + modal.navigationBar.isTranslucent = true + if #available(iOS 10, *) { + // Contact navbar is blue in iOS9, so our white text works, + // but gray on iOS10+, in which case we want the system default black text. + UIUtil.applyDefaultSystemAppearence() } - navigationController.pushViewController(contactViewController, animated: true) + + self.present(modal, animated: true) } func contactsPicker(_: ContactsPicker, didSelectMultipleContacts contacts: [Contact]) { @@ -126,8 +134,21 @@ class AddContactShareToExistingContactViewController: ContactsPicker, ContactsPi return } + // HACK otherwise CNContactViewController Navbar is shows window background color. + // RADAR rdar://28433898 http://www.openradar.me/28433898 + // CNContactViewController incompatible with opaque navigation bar + navigationController.navigationBar.isTranslucent = false + if #available(iOS 10, *) { + // Contact navbar is blue in iOS9, so our white text works, + // but gray on iOS10+, in which case we want the system default black text. + UIUtil.applySignalAppearence() + } + let previousViewControllerIndex = navigationController.viewControllers.index(before: myIndex) let previousViewController = navigationController.viewControllers[previousViewControllerIndex] - navigationController.popToViewController(previousViewController, animated: true) + + self.dismiss(animated: false) { + navigationController.popToViewController(previousViewController, animated: true) + } } } diff --git a/Signal/src/ViewControllers/ContactShareViewHelper.swift b/Signal/src/ViewControllers/ContactShareViewHelper.swift index 0323f2006..c4c31b35b 100644 --- a/Signal/src/ViewControllers/ContactShareViewHelper.swift +++ b/Signal/src/ViewControllers/ContactShareViewHelper.swift @@ -163,12 +163,17 @@ public class ContactShareViewHelper: NSObject, CNContactViewControllerDelegate { target: self, action: #selector(didFinishEditingContact)) - // HACK otherwise CNContactViewController Navbar is shown as black. + let modal = OWSNavigationController(rootViewController: contactViewController) + // HACK otherwise CNContactViewController Navbar is shows window background color. // RADAR rdar://28433898 http://www.openradar.me/28433898 // CNContactViewController incompatible with opaque navigation bar - UIUtil.applyDefaultSystemAppearence() + modal.navigationBar.isTranslucent = true + if #available(iOS 10, *) { + // Contact navbar is blue in iOS9, so our white text works, + // but gray on iOS10+, in which case we want the system default black text. + UIUtil.applyDefaultSystemAppearence() + } - let modal = OWSNavigationController(rootViewController: contactViewController) fromViewController.present(modal, animated: true) } @@ -189,7 +194,7 @@ public class ContactShareViewHelper: NSObject, CNContactViewControllerDelegate { } let viewController = AddContactShareToExistingContactViewController(contactShare: contactShare) - + UIUtil.applySignalAppearence() navigationController.pushViewController(viewController, animated: true) } diff --git a/SignalMessaging/Views/ContactsViewHelper.m b/SignalMessaging/Views/ContactsViewHelper.m index dc444ec83..60820ae6a 100644 --- a/SignalMessaging/Views/ContactsViewHelper.m +++ b/SignalMessaging/Views/ContactsViewHelper.m @@ -392,19 +392,23 @@ NS_ASSUME_NONNULL_BEGIN target:fromViewController action:@selector(didFinishEditingContact)]; - OWSNavigationController *navigationController = - [[OWSNavigationController alloc] initWithRootViewController:contactViewController]; + OWSNavigationController *modal = [[OWSNavigationController alloc] initWithRootViewController:contactViewController]; + + // HACK otherwise CNContactViewController Navbar is shows window background color. + // RADAR rdar://28433898 http://www.openradar.me/28433898 + // CNContactViewController incompatible with opaque navigation bar + modal.navigationBar.translucent = YES; + if (@available(iOS 10, *)) { + // Contact navbar is blue in iOS9, so our white tex works, + // but gray on iOS10+, in which case we want the system default black text. + [UIUtil applyDefaultSystemAppearence]; + } // We want the presentation to imply a "replacement" in this case. if (shouldEditImmediately) { - navigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; + modal.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; } - [fromViewController presentViewController:navigationController animated:YES completion:nil]; - - // HACK otherwise CNContactViewController Navbar is shown as black. - // RADAR rdar://28433898 http://www.openradar.me/28433898 - // CNContactViewController incompatible with opaque navigation bar - [UIUtil applyDefaultSystemAppearence]; + [fromViewController presentViewController:modal animated:YES completion:nil]; } @end From 20424d9a7e1e0014739e4ba5f2ae8e9c4cfc3761 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 21 May 2018 16:00:35 -0400 Subject: [PATCH 27/30] remove debug code, reorder for clarity // FREEBIE --- .../ViewControllers/OWSNavigationController.m | 93 ++++++++++--------- SignalMessaging/Views/OWSNavigationBar.swift | 8 +- SignalMessaging/utils/OWSWindowManager.m | 23 +++-- 3 files changed, 62 insertions(+), 62 deletions(-) diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index cd85fc451..23a2e1571 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -38,51 +38,6 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (void)navBarCallLayoutDidChangeWithNavbar:(OWSNavigationBar *)navbar -{ - [self updateLayoutForNavbar:navbar]; -} - -- (void)updateLayoutForNavbar:(OWSNavigationBar *)navbar -{ - DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); - - if (@available(iOS 11.0, *)) { - if (OWSWindowManager.sharedManager.hasCall) { - if (UIDevice.currentDevice.isIPhoneX) { - // iPhoneX computes status bar height differently. - self.additionalSafeAreaInsets = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + 20, 0, 0, 0); - } else { - self.additionalSafeAreaInsets - = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + CurrentAppContext().statusBarHeight, 0, 0, 0); - } - } else { - self.additionalSafeAreaInsets = UIEdgeInsetsZero; - } - // in iOS11 we have to ensure the navbar frame *in* layoutSubviews. - [navbar layoutSubviews]; - } else { - // Pre iOS11 we size the navbar, and position it vertically once. - [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; - } - - // Since the navbar's frame was updated, we need to be sure our child VC's - // container view is updated. - [self.view setNeedsLayout]; - } -} - - (void)viewDidLoad { [super viewDidLoad]; @@ -138,6 +93,54 @@ NS_ASSUME_NONNULL_BEGIN } } + +#pragma mark - NavBarLayoutDelegate + +- (void)navBarCallLayoutDidChangeWithNavbar:(OWSNavigationBar *)navbar +{ + [self updateLayoutForNavbar:navbar]; +} + +- (void)updateLayoutForNavbar:(OWSNavigationBar *)navbar +{ + DDLogDebug(@"%@ in %s", self.logTag, __PRETTY_FUNCTION__); + + if (@available(iOS 11.0, *)) { + if (OWSWindowManager.sharedManager.hasCall) { + if (UIDevice.currentDevice.isIPhoneX) { + // iPhoneX computes status bar height differently. + self.additionalSafeAreaInsets = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + 20, 0, 0, 0); + } else { + self.additionalSafeAreaInsets + = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + CurrentAppContext().statusBarHeight, 0, 0, 0); + } + } else { + self.additionalSafeAreaInsets = UIEdgeInsetsZero; + } + // in iOS11 we have to ensure the navbar frame *in* layoutSubviews. + [navbar layoutSubviews]; + } else { + // Pre iOS11 we size the navbar, and position it vertically once. + [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; + } + + // Since the navbar's frame was updated, we need to be sure our child VC's + // container view is updated. + [self.view setNeedsLayout]; + } +} + @end NS_ASSUME_NONNULL_END diff --git a/SignalMessaging/Views/OWSNavigationBar.swift b/SignalMessaging/Views/OWSNavigationBar.swift index 04be1803a..f1250afc6 100644 --- a/SignalMessaging/Views/OWSNavigationBar.swift +++ b/SignalMessaging/Views/OWSNavigationBar.swift @@ -65,17 +65,11 @@ class OWSNavigationBar: UINavigationBar { // 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: fullWidth, height: navbarWithoutStatusHeight + statusBarHeight) - - Logger.debug("\(self.logTag) in \(#function): \(result)") - - return result + return CGSize(width: fullWidth, height: navbarWithoutStatusHeight + statusBarHeight) } } override func layoutSubviews() { - Logger.debug("\(self.logTag) in \(#function) with frame: \(frame)") - guard OWSWindowManager.shared().hasCall() else { super.layoutSubviews() return diff --git a/SignalMessaging/utils/OWSWindowManager.m b/SignalMessaging/utils/OWSWindowManager.m index a1ede3eae..8beae7885 100644 --- a/SignalMessaging/utils/OWSWindowManager.m +++ b/SignalMessaging/utils/OWSWindowManager.m @@ -28,10 +28,6 @@ const CGFloat OWSWindowManagerCallScreenHeight(void) // Behind everything, especially the root window. const UIWindowLevel UIWindowLevel_Background = -1.f; -// Putting the call banner above the status bar is not ideal. -// It obscures status bar content like the system clock -// But being behind the status bar introduces two worse problems that'd we'd need to address -// 1. Tap target is too small, only the 20px below the status bar are tappable const UIWindowLevel UIWindowLevel_ReturnToCall(void); const UIWindowLevel UIWindowLevel_ReturnToCall(void) { @@ -124,9 +120,6 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) OWSAssert(screenBlockingWindow); OWSAssert(!self.screenBlockingWindow); - // MJK FIXME - rootWindow.backgroundColor = UIColor.yellowColor; - self.rootWindow = rootWindow; self.screenBlockingWindow = screenBlockingWindow; @@ -211,6 +204,19 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) #pragma mark - Calls +- (void)setCallViewController:(nullable UIViewController *)callViewController +{ + OWSAssertIsOnMainThread(); + + if (callViewController == _callViewController) { + return; + } + + _callViewController = callViewController; + + [NSNotificationCenter.defaultCenter postNotificationName:OWSWindowManagerCallDidChangeNotification object:nil]; +} + - (void)startCall:(UIViewController *)callViewController { OWSAssertIsOnMainThread(); @@ -218,8 +224,6 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) OWSAssert(!self.callViewController); self.callViewController = callViewController; - // TODO move to setter? - [NSNotificationCenter.defaultCenter postNotificationName:OWSWindowManagerCallDidChangeNotification object:nil]; // Attach callViewController to window. [self.callNavigationController popToRootViewControllerAnimated:NO]; @@ -243,7 +247,6 @@ const UIWindowLevel UIWindowLevel_ScreenBlocking(void) // Dettach callViewController from window. [self.callNavigationController popToRootViewControllerAnimated:NO]; self.callViewController = nil; - [NSNotificationCenter.defaultCenter postNotificationName:OWSWindowManagerCallDidChangeNotification object:nil]; self.shouldShowCallView = NO; From b8707b6fa4e30077eda73f032e20da51a32e655b Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Mon, 21 May 2018 17:59:59 -0400 Subject: [PATCH 28/30] WIP: call view changes --- .../ViewControllers/CallViewController.swift | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 5c29886c7..d446a5143 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -227,8 +227,6 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, blurView.isUserInteractionEnabled = false self.view.addSubview(blurView) - self.view.setHLayoutMargins(0) - // Create the video views first, as they are under the other views. createVideoViews() createContactViews() @@ -276,7 +274,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, contactNameLabel.trailingBuffer = ScaleFromIPhone5(80.0) // label config - contactNameLabel.font = UIFont.ows_lightFont(withSize: ScaleFromIPhone5To7Plus(32, 40)) + contactNameLabel.font = UIFont.ows_dynamicTypeTitle1 + contactNameLabel.textAlignment = .center contactNameLabel.textColor = UIColor.white contactNameLabel.layer.shadowOffset = CGSize.zero contactNameLabel.layer.shadowOpacity = 0.35 @@ -285,11 +284,13 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, self.view.addSubview(contactNameLabel) callStatusLabel = UILabel() - callStatusLabel.font = UIFont.ows_regularFont(withSize: ScaleFromIPhone5To7Plus(19, 25)) + callStatusLabel.font = UIFont.ows_dynamicTypeBody + callStatusLabel.textAlignment = .center callStatusLabel.textColor = UIColor.white callStatusLabel.layer.shadowOffset = CGSize.zero callStatusLabel.layer.shadowOpacity = 0.35 callStatusLabel.layer.shadowRadius = 4 + self.view.addSubview(callStatusLabel) contactAvatarContainerView = UIView.container() @@ -358,8 +359,6 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, func createOngoingCallControls() { -// textMessageButton = createButton(imageName:"message-active-wide", -// action:#selector(didPressTextMessage)) audioSourceButton = createButton(image: #imageLiteral(resourceName: "audio-call-speaker-inactive"), action: #selector(didPressAudioSource)) audioSourceButton.accessibilityLabel = NSLocalizedString("CALL_VIEW_AUDIO_SOURCE_LABEL", @@ -482,8 +481,10 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, // MARK: - Layout + var localVideoViewTopConstraint: NSLayoutConstraint! + func createViewConstraints() { - let topMargin = CGFloat(40) + let contactVSpacing = CGFloat(3) let settingsNagHMargin = CGFloat(30) let ongoingBottomMargin = ScaleFromIPhone5To7Plus(23, 41) @@ -501,27 +502,30 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, // Dark blurred background. blurView.autoPinEdgesToSuperviewEdges() - localVideoView.autoPinTrailingToSuperviewMargin(withInset: videoPreviewHMargin) - localVideoView.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin) - let localVideoSize = ScaleFromIPhone5To7Plus(80, 100) - localVideoView.autoSetDimension(.width, toSize: localVideoSize) - localVideoView.autoSetDimension(.height, toSize: localVideoSize) - - remoteVideoView.autoPinEdgesToSuperviewEdges() - - leaveCallViewButton.autoPinEdge(toSuperviewMargin: .left) - leaveCallViewButton.autoPinEdge(toSuperviewEdge: .top, withInset: topMargin) + leaveCallViewButton.autoPinEdge(toSuperviewMargin: .leading) + leaveCallViewButton.autoPinEdge(toSuperviewMargin: .top) - contactNameLabel.autoPinEdge(.top, to: .bottom, of: leaveCallViewButton, withOffset: 8) - contactNameLabel.autoPinLeadingToSuperviewMargin() + // MJK TODO height of contact name label should be ~same as back button + contactNameLabel.autoPinEdge(toSuperviewMargin: .top) + contactNameLabel.autoPinEdge(.leading, to: .trailing, of: leaveCallViewButton, withOffset: 8, relation: .greaterThanOrEqual) + contactNameLabel.autoHCenterInSuperview() contactNameLabel.setContentHuggingVerticalHigh() contactNameLabel.setCompressionResistanceHigh() callStatusLabel.autoPinEdge(.top, to: .bottom, of: contactNameLabel, withOffset: contactVSpacing) - callStatusLabel.autoPinLeadingToSuperviewMargin() + callStatusLabel.autoHCenterInSuperview() callStatusLabel.setContentHuggingVerticalHigh() callStatusLabel.setCompressionResistanceHigh() + localVideoView.autoPinTrailingToSuperviewMargin(withInset: videoPreviewHMargin) + // MJK TODO, depends on whether contactNameLabel is visible + self.localVideoViewTopConstraint = localVideoView.autoPinEdge(.top, to: .bottom, of: callStatusLabel, withOffset: 4) + let localVideoSize = ScaleFromIPhone5To7Plus(80, 100) + localVideoView.autoSetDimension(.width, toSize: localVideoSize) + localVideoView.autoSetDimension(.height, toSize: localVideoSize) + + remoteVideoView.autoPinEdgesToSuperviewEdges() + contactAvatarContainerView.autoPinEdge(.top, to: .bottom, of: callStatusLabel, withOffset: +avatarTopSpacing) contactAvatarContainerView.autoPinEdge(.bottom, to: .top, of: ongoingCallControls, withOffset: -avatarBottomSpacing) contactAvatarContainerView.autoPinWidthToSuperview(withMargin: avatarTopSpacing) @@ -577,12 +581,12 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, if localVideoView.isHidden { let contactHMargin = CGFloat(5) - constraints.append(contactNameLabel.autoPinTrailingToSuperviewMargin(withInset: contactHMargin)) - constraints.append(callStatusLabel.autoPinTrailingToSuperviewMargin(withInset: contactHMargin)) +// constraints.append(contactNameLabel.autoPinTrailingToSuperviewMargin(withInset: contactHMargin)) +// constraints.append(callStatusLabel.autoPinTrailingToSuperviewMargin(withInset: contactHMargin)) } else { let spacing = CGFloat(10) - constraints.append(localVideoView.autoPinLeading(toTrailingEdgeOf: contactNameLabel, offset: spacing)) - constraints.append(localVideoView.autoPinLeading(toTrailingEdgeOf: callStatusLabel, offset: spacing)) +// constraints.append(localVideoView.autoPinLeading(toTrailingEdgeOf: contactNameLabel, offset: spacing)) +// constraints.append(localVideoView.autoPinLeading(toTrailingEdgeOf: callStatusLabel, offset: spacing)) } self.localVideoConstraints = constraints From 36ee6af62102c3b591b6c62b2747673426000f89 Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 23 May 2018 08:48:51 -0400 Subject: [PATCH 29/30] respond to CR --- .../ViewControllers/OWSNavigationController.m | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index 23a2e1571..10cdf6e44 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -13,6 +13,9 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - +// Expose that UINavigationController already secretly implements UIGestureRecognizerDelegate +// so we can call [super navigationBar:shouldPopItem] in our own implementation to take advantage +// of the important side effects of that method. @interface OWSNavigationController () @end @@ -24,6 +27,10 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithRootViewController:(UIViewController *)rootViewController { self = [self initWithNavigationBarClass:[OWSNavigationBar class] toolbarClass:nil]; + if (!self) { + return self; + } + [self pushViewController:rootViewController animated:NO]; if (![self.navigationBar isKindOfClass:[OWSNavigationBar class]]) { @@ -125,8 +132,8 @@ NS_ASSUME_NONNULL_BEGIN if (OWSWindowManager.sharedManager.hasCall) { CGRect oldFrame = navbar.frame; - CGRect newFrame - = CGRectMake(oldFrame.origin.x, navbar.callBannerHeight, oldFrame.size.width, oldFrame.size.height); + CGRect newFrame = oldFrame; + newFrame.size.height = navbar.callBannerHeight; navbar.frame = newFrame; } else { CGRect oldFrame = navbar.frame; From fc34a0643c27f93b7a00d53e1808665f797c4f3d Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Wed, 23 May 2018 20:03:55 -0400 Subject: [PATCH 30/30] CR: annotate device constants // FREEBIE --- SignalMessaging/ViewControllers/OWSNavigationController.m | 2 ++ SignalMessaging/categories/UIDevice+featureSupport.swift | 1 + SignalMessaging/utils/OWSWindowManager.m | 2 ++ 3 files changed, 5 insertions(+) diff --git a/SignalMessaging/ViewControllers/OWSNavigationController.m b/SignalMessaging/ViewControllers/OWSNavigationController.m index 10cdf6e44..27fb190dd 100644 --- a/SignalMessaging/ViewControllers/OWSNavigationController.m +++ b/SignalMessaging/ViewControllers/OWSNavigationController.m @@ -116,7 +116,9 @@ NS_ASSUME_NONNULL_BEGIN if (OWSWindowManager.sharedManager.hasCall) { if (UIDevice.currentDevice.isIPhoneX) { // iPhoneX computes status bar height differently. + // IOS_DEVICE_CONSTANT self.additionalSafeAreaInsets = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + 20, 0, 0, 0); + } else { self.additionalSafeAreaInsets = UIEdgeInsetsMake(navbar.navbarWithoutStatusHeight + CurrentAppContext().statusBarHeight, 0, 0, 0); diff --git a/SignalMessaging/categories/UIDevice+featureSupport.swift b/SignalMessaging/categories/UIDevice+featureSupport.swift index 24f60bfda..b38b04763 100644 --- a/SignalMessaging/categories/UIDevice+featureSupport.swift +++ b/SignalMessaging/categories/UIDevice+featureSupport.swift @@ -23,6 +23,7 @@ public extension UIDevice { case 2436: return true default: + // Verify all our IOS_DEVICE_CONSTANT tags make sense when adding a new device size. owsFail("\(logTag) in \(#function) unknown device format") return false } diff --git a/SignalMessaging/utils/OWSWindowManager.m b/SignalMessaging/utils/OWSWindowManager.m index 8beae7885..a42c17892 100644 --- a/SignalMessaging/utils/OWSWindowManager.m +++ b/SignalMessaging/utils/OWSWindowManager.m @@ -19,8 +19,10 @@ const CGFloat OWSWindowManagerCallScreenHeight(void) // On an iPhoneX, the system return-to-call banner has been replaced by a much subtler green // circle behind the system clock. Instead, we mimic the old system call banner as on older devices, // but it has to be taller to fit beneath the notch. + // IOS_DEVICE_CONSTANT, we'll want to revisit this when new device dimensions are introduced. return 64; } else { + return CurrentAppContext().statusBarHeight + 20; } }