Signal-iOS/SignalUI/ViewControllers/ScreenLockViewController.m
Max Radermacher 823c3d11a7 Fix Screen Lock error when no passcode is set
In abf556fb7a, we passed all presented
view controllers to the app’s main UI. However, screen lock errors don’t
immediately dismiss the screen lock UI, so they weren’t ever shown.

In 6ca4bfeff9, we adopted the new limited
photo picker APIs, and manually presenting the photo picker allows us to
specify the view controller from which it should be presented. That
eliminates the root cause that necessitated the workaround.
2022-12-20 13:52:15 -08:00

155 lines
5.3 KiB
Objective-C

//
// Copyright 2018 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
#import "ScreenLockViewController.h"
#import "UIFont+OWS.h"
#import "UIView+SignalUI.h"
#import <SignalUI/SignalUI-Swift.h>
NSString *NSStringForScreenLockUIState(ScreenLockUIState value)
{
switch (value) {
case ScreenLockUIStateNone:
return @"ScreenLockUIStateNone";
case ScreenLockUIStateScreenProtection:
return @"ScreenLockUIStateScreenProtection";
case ScreenLockUIStateScreenLock:
return @"ScreenLockUIStateScreenLock";
}
}
@interface ScreenLockViewController ()
@property (nonatomic) UIView *screenBlockingImageView;
@property (nonatomic) UIView *screenBlockingButton;
@property (nonatomic) NSArray<NSLayoutConstraint *> *screenBlockingConstraints;
@property (nonatomic) NSString *screenBlockingSignature;
@end
#pragma mark -
@implementation ScreenLockViewController
- (void)loadView
{
[super loadView];
self.view.backgroundColor = Theme.launchScreenBackgroundColor;
UIView *edgesView = [UIView containerView];
[self.view addSubview:edgesView];
[edgesView autoPinEdgeToSuperviewEdge:ALEdgeTop];
[edgesView autoPinEdgeToSuperviewEdge:ALEdgeBottom];
[edgesView autoPinWidthToSuperview];
UIImage *image = [UIImage imageNamed:@"signal-logo-128-launch-screen"];
UIImageView *imageView = [UIImageView new];
imageView.image = image;
[edgesView addSubview:imageView];
[imageView autoHCenterInSuperview];
[imageView autoSetDimensionsToSize:CGSizeMake(128, 128)];
const CGFloat kButtonHeight = 40.f;
OWSFlatButton *button =
[OWSFlatButton buttonWithTitle:OWSLocalizedString(@"SCREEN_LOCK_UNLOCK_SIGNAL",
@"Label for button on lock screen that lets users unlock Signal.")
font:[OWSFlatButton fontForHeight:kButtonHeight]
titleColor:Theme.accentBlueColor
backgroundColor:[UIColor whiteColor]
target:self
selector:@selector(showUnlockUI)];
[edgesView addSubview:button];
[button autoSetDimension:ALDimensionHeight toSize:kButtonHeight];
[button autoPinLeadingToSuperviewMarginWithInset:50.f];
[button autoPinTrailingToSuperviewMarginWithInset:50.f];
const CGFloat kVMargin = 65.f;
[button autoPinBottomToSuperviewMarginWithInset:kVMargin];
self.screenBlockingImageView = imageView;
self.screenBlockingButton = button;
[self updateUIWithState:ScreenLockUIStateScreenProtection isLogoAtTop:NO animated:NO];
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(themeDidChange)
name:ThemeDidChangeNotification
object:nil];
}
- (void)themeDidChange
{
self.view.backgroundColor = Theme.launchScreenBackgroundColor;
}
// The "screen blocking" window has three possible states:
//
// * "Just a logo". Used when app is launching and in app switcher. Must match the "Launch Screen"
// storyboard pixel-for-pixel.
// * "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)updateUIWithState:(ScreenLockUIState)uiState isLogoAtTop:(BOOL)isLogoAtTop animated:(BOOL)animated
{
OWSAssertIsOnMainThread();
if (!self.isViewLoaded) {
return;
}
BOOL shouldShowBlockWindow = uiState != ScreenLockUIStateNone;
BOOL shouldHaveScreenLock = uiState == ScreenLockUIStateScreenLock;
self.screenBlockingImageView.hidden = !shouldShowBlockWindow;
NSString *signature = [NSString stringWithFormat:@"%d %d", shouldHaveScreenLock, isLogoAtTop];
if ([NSObject isNullableObject:self.screenBlockingSignature equalTo:signature]) {
// Skip redundant work to avoid interfering with ongoing animations.
return;
}
[NSLayoutConstraint deactivateConstraints:self.screenBlockingConstraints];
NSMutableArray<NSLayoutConstraint *> *screenBlockingConstraints = [NSMutableArray new];
self.screenBlockingButton.hidden = !shouldHaveScreenLock;
if (isLogoAtTop) {
const CGFloat kVMargin = 60.f;
[screenBlockingConstraints addObject:[self.screenBlockingImageView autoPinEdge:ALEdgeTop
toEdge:ALEdgeTop
ofView:self.view
withOffset:kVMargin]];
} else {
[screenBlockingConstraints addObject:[self.screenBlockingImageView autoVCenterInSuperview]];
}
self.screenBlockingConstraints = screenBlockingConstraints;
self.screenBlockingSignature = signature;
if (animated) {
[UIView animateWithDuration:0.35f animations:^{ [self.view layoutIfNeeded]; }];
} else {
[self.view layoutIfNeeded];
}
}
- (void)showUnlockUI
{
OWSAssertIsOnMainThread();
[self.delegate unlockButtonWasTapped];
}
#pragma mark - Orientation
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIDevice.currentDevice.defaultSupportedOrientations;
}
@end