From 17fce2fdd2e52430353def859a9a9e2e2d0cb940 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Wed, 18 Apr 2018 12:48:31 -0400 Subject: [PATCH] Present calls using window manager. --- .../ViewControllers/CallViewController.swift | 12 ++++ Signal/src/util/OWSWindowManager.m | 65 +++++++++++++------ .../translations/en.lproj/Localizable.strings | 3 + 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 2a8a1ccf2..42e4bdb75 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -237,6 +237,9 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, if !remoteVideoView.isHidden { shouldRemoteVideoControlsBeHidden = !shouldRemoteVideoControlsBeHidden } + + // TODO: Until we have a proper design, use background taps to leave call view. + OWSWindowManager.shared().leaveCallView() } func createVideoViews() { @@ -1137,4 +1140,13 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver, updateLocalVideoTrack(localVideoTrack: localVideoTrack) updateRemoteVideoTrack(remoteVideoTrack: remoteVideoTrack) } + + // MARK: - Event Handlers + + func leaveCallViewTapped(sender: UIGestureRecognizer) { + guard sender.state == .recognized else { + return + } + OWSWindowManager.shared().leaveCallView() + } } diff --git a/Signal/src/util/OWSWindowManager.m b/Signal/src/util/OWSWindowManager.m index c46e2b9ef..f117efe99 100644 --- a/Signal/src/util/OWSWindowManager.m +++ b/Signal/src/util/OWSWindowManager.m @@ -10,24 +10,32 @@ 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 +// but behind the screen blocking window. const UIWindowLevel UIWindowLevel_ReturnToCall(void); const UIWindowLevel UIWindowLevel_ReturnToCall(void) { - return UIWindowLevelNormal + 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 + 2.f; + return UIWindowLevelNormal + 1.f; } +// In front of everything, including the status bar. const UIWindowLevel UIWindowLevel_ScreenBlocking(void); const UIWindowLevel UIWindowLevel_ScreenBlocking(void) { - return UIWindowLevelStatusBar + 1.f; + return UIWindowLevelStatusBar + 2.f; } -const int kReturnToCallWindowHeight = 40.f; +// TODO: Verify that this is the correct height for: +// CallKit, non-CallKit, incoming and outgoing calls. +const int kReturnToCallWindowHeight = 20.f; @implementation OWSWindowRootViewController @@ -47,9 +55,11 @@ const int kReturnToCallWindowHeight = 40.f; // UIWindowLevel_ReturnToCall @property (nonatomic) UIWindow *returnToCallWindow; +@property (nonatomic) UILabel *returnToCallLabel; // UIWindowLevel_CallView @property (nonatomic) UIWindow *callViewWindow; +@property (nonatomic) UINavigationController *callNavigationController; // UIWindowLevel_Background if inactive, // UIWindowLevel_ScreenBlocking() if active. @@ -105,13 +115,13 @@ const int kReturnToCallWindowHeight = 40.f; self.rootWindow = rootWindow; self.screenBlockingWindow = screenBlockingWindow; - self.returnToCallWindow = [OWSWindowManager createReturnToCallWindow:rootWindow]; - self.callViewWindow = [OWSWindowManager createCallViewWindow:rootWindow]; + self.returnToCallWindow = [self createReturnToCallWindow:rootWindow]; + self.callViewWindow = [self createCallViewWindow:rootWindow]; [self ensureWindowState]; } -+ (UIWindow *)createReturnToCallWindow:(UIWindow *)rootWindow +- (UIWindow *)createReturnToCallWindow:(UIWindow *)rootWindow { OWSAssertIsOnMainThread(); OWSAssert(rootWindow); @@ -125,13 +135,13 @@ const int kReturnToCallWindowHeight = 40.f; window.hidden = YES; window.windowLevel = UIWindowLevel_ReturnToCall(); window.opaque = YES; - // TODO: - window.backgroundColor = UIColor.ows_materialBlueColor; - window.backgroundColor = [UIColor redColor]; + // 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 = UIColor.ows_materialBlueColor; - viewController.view.backgroundColor = [UIColor redColor]; + viewController.view.backgroundColor = backgroundColor; UIView *rootView = viewController.view; rootView.userInteractionEnabled = YES; @@ -139,19 +149,20 @@ const int kReturnToCallWindowHeight = 40.f; action:@selector(returnToCallWasTapped:)]]; UILabel *label = [UILabel new]; - label.text = NSLocalizedString(@"CALL_WINDOW_RETURN_TO_CALL", @"Label for the 'return to call' indicator."); + label.text = NSLocalizedString(@"CALL_WINDOW_RETURN_TO_CALL", @"Label for the 'return to call' banner."); label.textColor = [UIColor whiteColor]; // TODO: Dynamic type? - label.font = [UIFont ows_mediumFontWithSize:18.f]; + label.font = [UIFont ows_regularFontWithSize:14.f]; [rootView addSubview:label]; [label autoCenterInSuperview]; + self.returnToCallLabel = label; window.rootViewController = viewController; return window; } -+ (UIWindow *)createCallViewWindow:(UIWindow *)rootWindow +- (UIWindow *)createCallViewWindow:(UIWindow *)rootWindow { OWSAssertIsOnMainThread(); OWSAssert(rootWindow); @@ -160,6 +171,7 @@ const int kReturnToCallWindowHeight = 40.f; window.hidden = YES; window.windowLevel = UIWindowLevel_CallView(); window.opaque = YES; + // TODO: What's the right color to use here? window.backgroundColor = [UIColor ows_materialBlueColor]; UIViewController *viewController = [OWSWindowRootViewController new]; @@ -168,6 +180,7 @@ const int kReturnToCallWindowHeight = 40.f; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController]; navigationController.navigationBarHidden = YES; + self.callNavigationController = navigationController; window.rootViewController = navigationController; @@ -193,9 +206,7 @@ const int kReturnToCallWindowHeight = 40.f; self.callViewController = callViewController; // Attach callViewController from window. - OWSAssert([self.callViewWindow.rootViewController isKindOfClass:[UINavigationController class]]); - UINavigationController *navigationController = (UINavigationController *)self.callViewWindow.rootViewController; - [navigationController pushViewController:callViewController animated:NO]; + [self.callNavigationController pushViewController:callViewController animated:NO]; self.isCallViewActive = YES; [self ensureWindowState]; @@ -213,9 +224,7 @@ const int kReturnToCallWindowHeight = 40.f; } // Dettach callViewController from window. - OWSAssert([self.callViewWindow.rootViewController isKindOfClass:[UINavigationController class]]); - UINavigationController *navigationController = (UINavigationController *)self.callViewWindow.rootViewController; - [navigationController popToRootViewControllerAnimated:NO]; + [self.callNavigationController popToRootViewControllerAnimated:NO]; self.callViewController = nil; self.isCallViewActive = NO; @@ -386,6 +395,19 @@ const int kReturnToCallWindowHeight = 40.f; 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; @@ -400,6 +422,7 @@ const int kReturnToCallWindowHeight = 40.f; } self.returnToCallWindow.hidden = YES; + [self.returnToCallLabel.layer removeAllAnimations]; } - (void)showCallViewWindowIfNecessary diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 0008b922b..24f9d1be8 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -319,6 +319,9 @@ /* Accessibility label to switch to video call */ "CALL_VIEW_SWITCH_TO_VIDEO_LABEL" = "Switch to video call"; +/* Label for the 'return to call' indicator. */ +"CALL_WINDOW_RETURN_TO_CALL" = "Touch to return to call"; + /* notification action */ "CALLBACK_BUTTON_TITLE" = "Call Back";