-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[iOS] Add account picker sheet, configuration, layout delegate
This CL is the first step to add the account picker UI for the Save to Photos feature. This code is essentially copy-pasted from `i/c/b/ui/**/consistency_promo_signin/consistency_sheet/`. Fixed: 1474414 Change-Id: I0418d964c647e300506688d9048a9129beec339b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4798155 Reviewed-by: Sylvain Defresne <sdefresne@chromium.org> Commit-Queue: Quentin Pubert <qpubert@google.com> Reviewed-by: Jérôme Lebel <jlebel@chromium.org> Cr-Commit-Position: refs/heads/main@{#1187854}
- Loading branch information
Quentin Pubert
authored and
Chromium LUCI CQ
committed
Aug 24, 2023
1 parent
cc1382b
commit 0edc57a
Showing
15 changed files
with
759 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Copyright 2023 The Chromium Authors | ||
# Use of this source code is governed by a BSD-style license that can be | ||
# found in the LICENSE file. | ||
|
||
source_set("account_picker_configuration") { | ||
sources = [ | ||
"account_picker_configuration.h", | ||
"account_picker_configuration.mm", | ||
] | ||
} | ||
|
||
source_set("account_picker_layout") { | ||
sources = [ "account_picker_layout_delegate.h" ] | ||
deps = [ "//ui/base" ] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
jlebel@chromium.org |
29 changes: 29 additions & 0 deletions
29
ios/chrome/browser/ui/account_picker/account_picker_configuration.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_CONFIGURATION_H_ | ||
#define IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_CONFIGURATION_H_ | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
// Configuration for the AccountPickerCoordinator. | ||
@interface AccountPickerConfiguration : NSObject | ||
|
||
// Title of the account picker confirmation screen. | ||
@property(nonatomic, copy) NSString* titleText; | ||
|
||
// Body of the account picker confirmation screen which explains what the | ||
// account will be used for. | ||
@property(nonatomic, copy) NSString* bodyText; | ||
|
||
// Title of the account picker confirmation screen submit button. | ||
@property(nonatomic, copy) NSString* submitButtonTitle; | ||
|
||
// The label of the "Ask every time" switch. If left nil, the switch will not be | ||
// shown. | ||
@property(nonatomic, copy) NSString* askEveryTimeSwitchLabelText; | ||
|
||
@end | ||
|
||
#endif // IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_CONFIGURATION_H_ |
9 changes: 9 additions & 0 deletions
9
ios/chrome/browser/ui/account_picker/account_picker_configuration.mm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#import "ios/chrome/browser/ui/account_picker/account_picker_configuration.h" | ||
|
||
@implementation AccountPickerConfiguration | ||
|
||
@end |
26 changes: 26 additions & 0 deletions
26
ios/chrome/browser/ui/account_picker/account_picker_layout_delegate.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_LAYOUT_DELEGATE_H_ | ||
#define IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_LAYOUT_DELEGATE_H_ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
// Style to display the account picker sheet. | ||
enum AccountPickerSheetDisplayStyle { | ||
// Bottom sheet at the bottom of the screen (for compact size). | ||
kAccountPickerSheetDisplayStyleBottom, | ||
// Bottom sheet centered in the middle of the screen (for regular size). | ||
kAccountPickerSheetDisplayStyleCentered, | ||
}; | ||
|
||
@protocol AccountPickerLayoutDelegate <NSObject> | ||
|
||
// Display style according to the trait collection. | ||
@property(nonatomic, assign, readonly) | ||
AccountPickerSheetDisplayStyle displayStyle; | ||
|
||
@end | ||
|
||
#endif // IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_LAYOUT_DELEGATE_H_ |
24 changes: 24 additions & 0 deletions
24
ios/chrome/browser/ui/account_picker/account_picker_screen/BUILD.gn
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Copyright 2023 The Chromium Authors | ||
# Use of this source code is governed by a BSD-style license that can be | ||
# found in the LICENSE file. | ||
|
||
source_set("account_picker_screen") { | ||
sources = [ | ||
"account_picker_screen_constants.h", | ||
"account_picker_screen_constants.mm", | ||
"account_picker_screen_navigation_controller.h", | ||
"account_picker_screen_navigation_controller.mm", | ||
"account_picker_screen_presentation_controller.h", | ||
"account_picker_screen_presentation_controller.mm", | ||
"account_picker_screen_slide_transition_animator.h", | ||
"account_picker_screen_slide_transition_animator.mm", | ||
"account_picker_screen_view_controller.h", | ||
] | ||
deps = [ | ||
"//base", | ||
"//ios/chrome/browser/shared/ui/util", | ||
"//ios/chrome/browser/shared/ui/util/image", | ||
"//ios/chrome/browser/ui/account_picker:account_picker_layout", | ||
"//ios/chrome/common/ui/util", | ||
] | ||
} |
17 changes: 17 additions & 0 deletions
17
ios/chrome/browser/ui/account_picker/account_picker_screen/account_picker_screen_constants.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_SCREEN_ACCOUNT_PICKER_SCREEN_CONSTANTS_H_ | ||
#define IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_SCREEN_ACCOUNT_PICKER_SCREEN_CONSTANTS_H_ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
// Maximum height ratio for the bottom sheet container view. | ||
extern const CGFloat kMaxPickAccountHeightRatioWithWindow; | ||
|
||
// AccountPickerScreenNavigationController accessibility identifier. | ||
extern NSString* const | ||
kAccountPickerScreenNavigationControllerAccessibilityIdentifier; | ||
|
||
#endif // IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_SCREEN_ACCOUNT_PICKER_SCREEN_CONSTANTS_H_ |
11 changes: 11 additions & 0 deletions
11
...chrome/browser/ui/account_picker/account_picker_screen/account_picker_screen_constants.mm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#import "ios/chrome/browser/ui/account_picker/account_picker_screen/account_picker_screen_constants.h" | ||
|
||
const CGFloat kMaxPickAccountHeightRatioWithWindow = 0.75; | ||
|
||
NSString* const | ||
kAccountPickerScreenNavigationControllerAccessibilityIdentifier = | ||
@"AccountPickerScreenNavigationControllerAccessibilityIdentifier"; |
48 changes: 48 additions & 0 deletions
48
...ser/ui/account_picker/account_picker_screen/account_picker_screen_navigation_controller.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_SCREEN_ACCOUNT_PICKER_SCREEN_NAVIGATION_CONTROLLER_H_ | ||
#define IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_SCREEN_ACCOUNT_PICKER_SCREEN_NAVIGATION_CONTROLLER_H_ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
#import "ios/chrome/browser/ui/account_picker/account_picker_layout_delegate.h" | ||
|
||
// Delegate for updating navigation controller content. | ||
@protocol AccountPickerScreenNavigationControllerLayoutDelegate <NSObject> | ||
|
||
// Performs updates due to changes in preferred content size. | ||
- (void)preferredContentSizeDidChangeForAccountPickerScreenViewController; | ||
|
||
@end | ||
|
||
// Navigation controller presented from the bottom. The pushed view controllers | ||
// view have to be UIScrollView. This is required to support high font size | ||
// (related to accessibility) with small devices (like iPhone SE). | ||
// The view is automatically sized according to the last child view controller. | ||
// This class works with AccountPickerScreenPresentationController and | ||
// AccountPickerScreenSlideTransitionAnimator. | ||
// Child view controller are required to implement | ||
// AccountPickerScreenViewController protocol. | ||
@interface AccountPickerScreenNavigationController | ||
: UINavigationController <AccountPickerLayoutDelegate> | ||
|
||
// Returns the desired size related to the current view controller shown by | ||
// `AccountPickerScreenNavigationController`, based on `width`. | ||
- (CGSize)layoutFittingSizeForWidth:(CGFloat)width; | ||
|
||
// Updates internal views according to the consistency sheet view position. | ||
- (void)didUpdateControllerViewFrame; | ||
|
||
// Delegate for layout. | ||
@property(nonatomic, weak) | ||
id<AccountPickerScreenNavigationControllerLayoutDelegate> | ||
layoutDelegate; | ||
// Interaction transition to swipe from left to right to pop a view controller. | ||
@property(nonatomic, strong, readonly) | ||
UIPercentDrivenInteractiveTransition* interactionTransition; | ||
|
||
@end | ||
|
||
#endif // IOS_CHROME_BROWSER_UI_ACCOUNT_PICKER_ACCOUNT_PICKER_SCREEN_ACCOUNT_PICKER_SCREEN_NAVIGATION_CONTROLLER_H_ |
185 changes: 185 additions & 0 deletions
185
...er/ui/account_picker/account_picker_screen/account_picker_screen_navigation_controller.mm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#import "ios/chrome/browser/ui/account_picker/account_picker_screen/account_picker_screen_navigation_controller.h" | ||
|
||
#import <algorithm> | ||
|
||
#import "base/check.h" | ||
#import "base/notreached.h" | ||
#import "ios/chrome/browser/ui/account_picker/account_picker_screen/account_picker_screen_constants.h" | ||
#import "ios/chrome/browser/ui/account_picker/account_picker_screen/account_picker_screen_view_controller.h" | ||
#import "ios/chrome/common/ui/util/background_util.h" | ||
|
||
namespace { | ||
|
||
// Corner radius for centered style dialog. | ||
constexpr CGFloat kCornerRadius = 12.; | ||
|
||
} // namespace | ||
|
||
@interface AccountPickerScreenNavigationController () | ||
|
||
// View to get transparent blurred background. | ||
@property(nonatomic, strong, readwrite) UIView* backgroundView; | ||
@property(nonatomic, strong, readwrite) | ||
UIPercentDrivenInteractiveTransition* interactionTransition; | ||
|
||
@end | ||
|
||
@implementation AccountPickerScreenNavigationController | ||
|
||
- (CGSize)layoutFittingSizeForWidth:(CGFloat)width { | ||
UINavigationController* navigationController = | ||
self.childViewControllers.lastObject; | ||
DCHECK([navigationController | ||
conformsToProtocol:@protocol(AccountPickerScreenViewController)]); | ||
UIViewController<AccountPickerScreenViewController>* | ||
childNavigationController = | ||
static_cast<UIViewController<AccountPickerScreenViewController>*>( | ||
navigationController); | ||
|
||
// If the child controller updates its view due to an external action such | ||
// as adding or removing an identity then force a layout to ensure the child | ||
// height is up-to-date. | ||
[childNavigationController.view setNeedsLayout]; | ||
[childNavigationController.view layoutIfNeeded]; | ||
|
||
CGFloat height = | ||
[childNavigationController layoutFittingHeightForWidth:width]; | ||
CGFloat maxViewHeight = | ||
self.view.window.frame.size.height * kMaxPickAccountHeightRatioWithWindow; | ||
return CGSizeMake(width, std::min(height, maxViewHeight)); | ||
} | ||
|
||
- (void)didUpdateControllerViewFrame { | ||
self.backgroundView.frame = self.view.bounds; | ||
} | ||
|
||
- (void)preferredContentSizeDidChangeForChildContentContainer: | ||
(id<UIContentContainer>)container { | ||
[super preferredContentSizeDidChangeForChildContentContainer:container]; | ||
[self.layoutDelegate | ||
preferredContentSizeDidChangeForAccountPickerScreenViewController]; | ||
} | ||
|
||
#pragma mark - AccountPickerLayoutDelegate | ||
|
||
- (AccountPickerSheetDisplayStyle)displayStyle { | ||
return [self displayStyleWithTraitCollection:self.traitCollection]; | ||
} | ||
|
||
#pragma mark - UIViewController | ||
|
||
- (void)viewDidLoad { | ||
[super viewDidLoad]; | ||
self.backgroundView = PrimaryBackgroundBlurView(); | ||
[self.view insertSubview:self.backgroundView atIndex:0]; | ||
self.backgroundView.frame = self.view.bounds; | ||
self.view.layer.masksToBounds = YES; | ||
self.view.clipsToBounds = YES; | ||
self.view.accessibilityIdentifier = | ||
kAccountPickerScreenNavigationControllerAccessibilityIdentifier; | ||
UIScreenEdgePanGestureRecognizer* edgeSwipeGesture = | ||
[[UIScreenEdgePanGestureRecognizer alloc] | ||
initWithTarget:self | ||
action:@selector(swipeAction:)]; | ||
edgeSwipeGesture.edges = UIRectEdgeLeft; | ||
[self.view addGestureRecognizer:edgeSwipeGesture]; | ||
} | ||
|
||
- (void)viewWillAppear:(BOOL)animated { | ||
[super viewWillAppear:animated]; | ||
[self.navigationBar setBackgroundImage:[[UIImage alloc] init] | ||
forBarMetrics:UIBarMetricsDefault]; | ||
[self updateViewWithTraitCollection:self.traitCollection]; | ||
} | ||
|
||
- (void)viewDidLayoutSubviews { | ||
[super viewDidLayoutSubviews]; | ||
[self didUpdateControllerViewFrame]; | ||
} | ||
|
||
#pragma mark - UINavigationController | ||
|
||
- (void)pushViewController:(UIViewController*)viewController | ||
animated:(BOOL)animated { | ||
DCHECK([viewController | ||
conformsToProtocol:@protocol(AccountPickerScreenViewController)]); | ||
[super pushViewController:viewController animated:animated]; | ||
} | ||
|
||
#pragma mark - UIContentContainer | ||
|
||
- (void)willTransitionToTraitCollection:(UITraitCollection*)newCollection | ||
withTransitionCoordinator: | ||
(id<UIViewControllerTransitionCoordinator>)coordinator { | ||
[self updateViewWithTraitCollection:newCollection]; | ||
} | ||
|
||
#pragma mark - SwipeGesture | ||
|
||
// Called when the swipe gesture is active. This method controls the sliding | ||
// between two view controls in `self`. | ||
- (void)swipeAction:(UIScreenEdgePanGestureRecognizer*)gestureRecognizer { | ||
if (!gestureRecognizer.view) { | ||
self.interactionTransition = nil; | ||
return; | ||
} | ||
UIView* view = gestureRecognizer.view; | ||
CGFloat percentage = | ||
[gestureRecognizer translationInView:view].x / view.bounds.size.width; | ||
switch (gestureRecognizer.state) { | ||
case UIGestureRecognizerStateBegan: | ||
self.interactionTransition = | ||
[[UIPercentDrivenInteractiveTransition alloc] init]; | ||
[self popViewControllerAnimated:YES]; | ||
[self.interactionTransition updateInteractiveTransition:percentage]; | ||
break; | ||
case UIGestureRecognizerStateChanged: | ||
[self.interactionTransition updateInteractiveTransition:percentage]; | ||
break; | ||
case UIGestureRecognizerStateEnded: | ||
if (percentage > .5 && | ||
gestureRecognizer.state != UIGestureRecognizerStateCancelled) { | ||
[self.interactionTransition finishInteractiveTransition]; | ||
} else { | ||
[self.interactionTransition cancelInteractiveTransition]; | ||
} | ||
self.interactionTransition = nil; | ||
break; | ||
case UIGestureRecognizerStatePossible: | ||
case UIGestureRecognizerStateCancelled: | ||
case UIGestureRecognizerStateFailed: | ||
break; | ||
} | ||
} | ||
|
||
#pragma mark - Private | ||
|
||
// Updates the view according to the trait collection. | ||
- (void)updateViewWithTraitCollection:(UITraitCollection*)collection { | ||
switch ([self displayStyleWithTraitCollection:collection]) { | ||
case kAccountPickerSheetDisplayStyleBottom: | ||
self.view.layer.cornerRadius = 0; | ||
break; | ||
case kAccountPickerSheetDisplayStyleCentered: | ||
self.view.layer.cornerRadius = kCornerRadius; | ||
break; | ||
} | ||
} | ||
|
||
// Returns the display style based on the trait collection. | ||
- (AccountPickerSheetDisplayStyle)displayStyleWithTraitCollection: | ||
(UITraitCollection*)collection { | ||
// If one trait dimension is compact, the returned style is bottom. | ||
// Otherwise, the returned style is centered. | ||
BOOL hasAtLeastOneCompactSize = | ||
(collection.horizontalSizeClass == UIUserInterfaceSizeClassCompact) || | ||
(collection.verticalSizeClass == UIUserInterfaceSizeClassCompact); | ||
return hasAtLeastOneCompactSize ? kAccountPickerSheetDisplayStyleBottom | ||
: kAccountPickerSheetDisplayStyleCentered; | ||
} | ||
|
||
@end |
Oops, something went wrong.