From 72b602c3d8cc91a6789c2e7c3d5542e7dd036d72 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 27 Mar 2018 17:46:05 -0400 Subject: [PATCH] Respond to CR. --- Signal/src/util/OWSScreenLock.swift | 3 +- Signal/src/util/OWSScreenLockUI.m | 129 ++++++++++++++++++---------- 2 files changed, 84 insertions(+), 48 deletions(-) diff --git a/Signal/src/util/OWSScreenLock.swift b/Signal/src/util/OWSScreenLock.swift index fdb95fe51..d8ae13f3b 100644 --- a/Signal/src/util/OWSScreenLock.swift +++ b/Signal/src/util/OWSScreenLock.swift @@ -316,7 +316,8 @@ import LocalAuthentication let context = LAContext() // If user has set any non-zero timeout, recycle biometric auth - // in the same period as our normal screen lock timeout. + // in the same period as our normal screen lock timeout, up to + // max of 10 seconds. context.touchIDAuthenticationAllowableReuseDuration = TimeInterval(min(10.0, screenLockTimeout())) if #available(iOS 11.0, *) { diff --git a/Signal/src/util/OWSScreenLockUI.m b/Signal/src/util/OWSScreenLockUI.m index eec61e972..41e24c563 100644 --- a/Signal/src/util/OWSScreenLockUI.m +++ b/Signal/src/util/OWSScreenLockUI.m @@ -13,6 +13,10 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) UIWindow *screenBlockingWindow; @property (nonatomic) UIViewController *screenBlockingViewController; +@property (nonatomic) UIView *screenBlockingImageView; +@property (nonatomic) UIView *screenBlockingButton; +@property (nonatomic) NSArray *screenBlockingConstraints; +@property (nonatomic) NSString *screenBlockingSignature; // Unlike UIApplication.applicationState, this state is // updated conservatively, e.g. the flag is cleared during @@ -156,7 +160,7 @@ NS_ASSUME_NONNULL_BEGIN if (self.screenBlockingWindow.hidden != !shouldShowBlockWindow) { DDLogInfo(@"%@, %@.", self.logTag, shouldShowBlockWindow ? @"showing block window" : @"hiding block window"); } - [self updateScreenBlockingWindow:shouldShowBlockWindow shouldHaveScreenLock:shouldHaveScreenLock]; + [self updateScreenBlockingWindow:shouldShowBlockWindow shouldHaveScreenLock:shouldHaveScreenLock animated:YES]; if (shouldHaveScreenLock && !self.didLastUnlockAttemptFail) { [self tryToPresentScreenLockUI]; @@ -208,6 +212,8 @@ NS_ASSUME_NONNULL_BEGIN // Re-show the unlock UI. [self ensureScreenProtection]; }]; + + [self ensureScreenProtection]; } - (BOOL)shouldHaveScreenProtection @@ -318,12 +324,52 @@ NS_ASSUME_NONNULL_BEGIN UIViewController *viewController = [UIViewController new]; viewController.view.backgroundColor = UIColor.ows_materialBlueColor; + + UIView *rootView = viewController.view; + + UIView *edgesView = [UIView containerView]; + [rootView addSubview:edgesView]; + [edgesView autoPinEdgeToSuperviewEdge:ALEdgeTop]; + [edgesView autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + [edgesView autoPinWidthToSuperview]; + + UIImage *image = [UIImage imageNamed:@"logoSignal"]; + UIImageView *imageView = [UIImageView new]; + imageView.image = image; + [edgesView addSubview:imageView]; + [imageView autoHCenterInSuperview]; + + const CGSize screenSize = UIScreen.mainScreen.bounds.size; + const CGFloat shortScreenDimension = MIN(screenSize.width, screenSize.height); + const CGFloat imageSize = round(shortScreenDimension / 3.f); + [imageView autoSetDimension:ALDimensionWidth toSize:imageSize]; + [imageView autoSetDimension:ALDimensionHeight toSize:imageSize]; + + const CGFloat kButtonHeight = 40.f; + OWSFlatButton *button = + [OWSFlatButton buttonWithTitle:NSLocalizedString(@"SCREEN_LOCK_UNLOCK_SIGNAL", + @"Label for button on lock screen that lets users unlock Signal.") + font:[OWSFlatButton fontForHeight:kButtonHeight] + titleColor:[UIColor ows_materialBlueColor] + backgroundColor:[UIColor whiteColor] + target:self + selector:@selector(showUnlockUI)]; + [edgesView addSubview:button]; + + [button autoSetDimension:ALDimensionHeight toSize:kButtonHeight]; + [button autoPinLeadingToSuperviewWithMargin:50.f]; + [button autoPinTrailingToSuperviewWithMargin:50.f]; + const CGFloat kVMargin = 65.f; + [button autoPinBottomToSuperviewWithMargin:kVMargin]; + window.rootViewController = viewController; self.screenBlockingWindow = window; self.screenBlockingViewController = viewController; + self.screenBlockingImageView = imageView; + self.screenBlockingButton = button; - [self updateScreenBlockingWindow:YES shouldHaveScreenLock:NO]; + [self updateScreenBlockingWindow:YES shouldHaveScreenLock:NO animated:NO]; } // The "screen blocking" window has three possible states: @@ -333,26 +379,19 @@ NS_ASSUME_NONNULL_BEGIN // * "Screen Lock, local auth UI presented". Move the Signal logo so that it is visible. // * "Screen Lock, local auth UI not presented". Move the Signal logo so that it is visible, // show "unlock" button. -- (void)updateScreenBlockingWindow:(BOOL)shouldShowBlockWindow shouldHaveScreenLock:(BOOL)shouldHaveScreenLock +- (void)updateScreenBlockingWindow:(BOOL)shouldShowBlockWindow + shouldHaveScreenLock:(BOOL)shouldHaveScreenLock + animated:(BOOL)animated { OWSAssertIsOnMainThread(); self.screenBlockingWindow.hidden = !shouldShowBlockWindow; UIView *rootView = self.screenBlockingViewController.view; - for (UIView *subview in rootView.subviews) { - [subview removeFromSuperview]; - } - UIImage *image = [UIImage imageNamed:@"logoSignal"]; - UIImageView *imageView = [UIImageView new]; - imageView.image = image; + [NSLayoutConstraint deactivateConstraints:self.screenBlockingConstraints]; - const CGSize screenSize = UIScreen.mainScreen.bounds.size; - const CGFloat shortScreenDimension = MIN(screenSize.width, screenSize.height); - const CGFloat imageSize = round(shortScreenDimension / 3.f); - [imageView autoSetDimension:ALDimensionWidth toSize:imageSize]; - [imageView autoSetDimension:ALDimensionHeight toSize:imageSize]; + NSMutableArray *screenBlockingConstraints = [NSMutableArray new]; BOOL shouldShowUnlockButton = (!self.appIsInactive && !self.appIsInBackground && self.didLastUnlockAttemptFail); @@ -363,40 +402,35 @@ NS_ASSUME_NONNULL_BEGIN shouldHaveScreenLock, shouldShowUnlockButton); - if (shouldHaveScreenLock) { - const CGFloat kVMargin = 50.f; - [rootView addSubview:imageView]; - [imageView autoHCenterInSuperview]; - [imageView autoPinTopToSuperviewWithMargin:kVMargin]; - - const CGFloat kButtonHeight = 40.f; - OWSFlatButton *button = - [OWSFlatButton buttonWithTitle:NSLocalizedString(@"SCREEN_LOCK_UNLOCK_SIGNAL", - @"Label for button on lock screen that lets users unlock Signal.") - font:[OWSFlatButton fontForHeight:kButtonHeight] - titleColor:[UIColor ows_materialBlueColor] - backgroundColor:[UIColor whiteColor] - target:self - selector:@selector(showUnlockUI)]; - [rootView addSubview:button]; - [button autoVCenterInSuperview]; - [button autoSetDimension:ALDimensionHeight toSize:kButtonHeight]; - [button autoPinLeadingToSuperviewWithMargin:50.f]; - [button autoPinTrailingToSuperviewWithMargin:50.f]; - - button.hidden = !shouldShowUnlockButton; + NSString *signature = [NSString stringWithFormat:@"%d %d", shouldHaveScreenLock, self.isShowingScreenLockUI]; + if ([NSObject isNullableObject:self.screenBlockingSignature equalTo:signature]) { + // Skip redundant work to avoid interfering with ongoing animations. + return; + } + + self.screenBlockingButton.hidden = !shouldHaveScreenLock; + + if (self.isShowingScreenLockUI) { + const CGFloat kVMargin = 60.f; + [screenBlockingConstraints addObject:[self.screenBlockingImageView autoPinEdge:ALEdgeTop + toEdge:ALEdgeTop + ofView:rootView + withOffset:kVMargin]]; } else { - UIView *edgesView = [UIView containerView]; - [rootView addSubview:edgesView]; - [edgesView autoPinEdgeToSuperviewEdge:ALEdgeTop]; - [edgesView autoPinEdgeToSuperviewEdge:ALEdgeBottom]; - [edgesView autoPinWidthToSuperview]; - - [edgesView addSubview:imageView]; - [imageView autoCenterInSuperview]; + [screenBlockingConstraints addObject:[self.screenBlockingImageView autoVCenterInSuperview]]; } - [rootView layoutIfNeeded]; + self.screenBlockingConstraints = screenBlockingConstraints; + self.screenBlockingSignature = signature; + + if (animated) { + [UIView animateWithDuration:0.35f + animations:^{ + [rootView layoutIfNeeded]; + }]; + } else { + [rootView layoutIfNeeded]; + } } - (void)showUnlockUI @@ -434,17 +468,18 @@ NS_ASSUME_NONNULL_BEGIN self.shouldClearAuthUIWhenActive = YES; } else { self.isShowingScreenLockUI = NO; + [self ensureScreenProtection]; } } - (void)applicationDidBecomeActive:(NSNotification *)notification { - self.appIsInactive = NO; - if (self.shouldClearAuthUIWhenActive) { self.shouldClearAuthUIWhenActive = NO; self.isShowingScreenLockUI = NO; } + + self.appIsInactive = NO; } - (void)applicationWillResignActive:(NSNotification *)notification