blob: 538e5e1891bb4ca3c1c9f08d7f94f25f81264456 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// 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/authentication/unified_consent/identity_picker_view.h"
#import <MaterialComponents/MaterialRipple.h>
#include "base/check.h"
#import "ios/chrome/browser/ui/authentication/authentication_constants.h"
#import "ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_view.h"
#import "ios/chrome/browser/ui/authentication/unified_consent/unified_consent_constants.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h"
#import "ios/chrome/common/ui/util/constraints_ui_util.h"
#import "ios/chrome/common/ui/util/pointer_interaction_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
const CGFloat kIdentityPickerViewRadius = 8.;
// Sizes.
const CGFloat kArrowDownSize = 24.;
// Distances/margins.
const CGFloat kArrowDownMargin = 12.;
} // namespace
@interface IdentityPickerView ()
@property(nonatomic, strong) IdentityView* identityView;
// Ripple effect when the user starts or stop a touch in the view.
@property(nonatomic, strong) MDCRippleView* rippleView;
// Image View for the down arrow, letting the user know that more profiles can
// be selected.
@property(nonatomic, strong) UIImageView* arrowDownImageView;
@end
@implementation IdentityPickerView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.accessibilityIdentifier = kIdentityPickerViewIdentifier;
self.layer.cornerRadius = kIdentityPickerViewRadius;
self.backgroundColor = UIColor.cr_secondarySystemBackgroundColor;
// Adding view elements inside.
// Ink view.
_rippleView = [[MDCRippleView alloc] initWithFrame:CGRectZero];
_rippleView.layer.cornerRadius = kIdentityPickerViewRadius;
_rippleView.rippleStyle = MDCRippleStyleBounded;
_rippleView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_rippleView];
// Arrow down.
_arrowDownImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
_arrowDownImageView.translatesAutoresizingMaskIntoConstraints = NO;
_arrowDownImageView.image =
[[UIImage imageNamed:@"identity_picker_view_arrow_down"]
imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
_arrowDownImageView.tintColor = UIColor.cr_labelColor;
[self addSubview:_arrowDownImageView];
// Main view with avatar, name and email.
_identityView = [[IdentityView alloc] initWithFrame:CGRectZero];
_identityView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_identityView];
// Layout constraints.
NSDictionary* views = @{
@"identityview" : _identityView,
@"arrow" : _arrowDownImageView,
};
NSDictionary* metrics = @{
@"ArrowMargin" : @(kArrowDownMargin),
@"ArrowSize" : @(kArrowDownSize),
};
NSArray* constraints = @[
// Horizontal constraints.
@"H:|[identityview]-(ArrowMargin)-[arrow]-(ArrowMargin)-|",
// Vertical constraints.
@"V:|[identityview]|",
// Size constraints.
@"H:[arrow(ArrowSize)]",
@"V:[arrow(ArrowSize)]",
];
AddSameCenterYConstraint(self, _arrowDownImageView);
ApplyVisualConstraintsWithMetrics(constraints, views, metrics);
#if defined(__IPHONE_13_4)
if (@available(iOS 13.4, *)) {
[self addInteraction:[[ViewPointerInteraction alloc] init]];
}
#endif // defined(__IPHONE_13_4)
// Accessibility.
self.isAccessibilityElement = YES;
self.accessibilityTraits = UIAccessibilityTraitButton;
}
return self;
}
#pragma mark - Setter
- (void)setIdentityAvatar:(UIImage*)identityAvatar {
[self.identityView setAvatar:identityAvatar];
}
- (void)setIdentityName:(NSString*)name email:(NSString*)email {
DCHECK(email);
if (!name.length) {
[self.identityView setTitle:email subtitle:nil];
self.accessibilityLabel = email;
} else {
[self.identityView setTitle:name subtitle:email];
self.accessibilityLabel =
[NSString stringWithFormat:@"%@, %@", name, email];
}
}
#pragma mark - Private
- (CGPoint)locationFromTouches:(NSSet*)touches {
UITouch* touch = [touches anyObject];
return [touch locationInView:self];
}
#pragma mark - UIResponder
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
[super touchesBegan:touches withEvent:event];
CGPoint location = [self locationFromTouches:touches];
[self.rippleView beginRippleTouchDownAtPoint:location
animated:YES
completion:nil];
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
[super touchesEnded:touches withEvent:event];
[self.rippleView beginRippleTouchUpAnimated:YES completion:nil];
}
- (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event {
[super touchesCancelled:touches withEvent:event];
[self.rippleView beginRippleTouchUpAnimated:YES completion:nil];
}
@end