Commit 37d6dae3 authored by Jérôme Lebel's avatar Jérôme Lebel Committed by Commit Bot

[iOS] Creating IdentityView

This patch extracts code to display an avatar with an email and an
optional name from IdentityPickerView into IdentityView.

This code can be share between IdentityPickerView and the identity
chooser dialog in this mock:
https://gallery.googleplex.com/projects/MCHbtQVoQ2HCZQNtxfU4ytJv/files/MCHtA7U1iMGr62Mmhjs3q0iDhQHgIuNdWV0

Bug: 827072
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: Ib7df934aa678c35b42b8a37c71dfac6fd52ca5c4
Reviewed-on: https://chromium-review.googlesource.com/1044373
Commit-Queue: Jérôme Lebel <jlebel@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#557219}
parent 11ef1ec8
......@@ -218,11 +218,22 @@ class ChromeSigninViewControllerTest
NSString* view_name = NSStringFromClass([view class]);
// Views that don't display strings.
NSArray* other_views = @[
@"AccountControlCell", @"CollectionViewFooterCell", @"UIButtonLabel",
@"UICollectionView", @"UICollectionViewControllerWrapperView",
@"UIImageView", @"UIView", @"MDCActivityIndicator", @"MDCButtonBar",
@"MDCFlexibleHeaderView", @"MDCHeaderStackView", @"MDCInkView",
@"MDCNavigationBar", @"UIScrollView", @"IdentityPickerView"
@"AccountControlCell",
@"CollectionViewFooterCell",
@"IdentityPickerView",
@"IdentityView",
@"UIButtonLabel",
@"MDCActivityIndicator",
@"MDCButtonBar",
@"MDCFlexibleHeaderView",
@"MDCHeaderStackView",
@"MDCInkView",
@"MDCNavigationBar",
@"UICollectionView",
@"UICollectionViewControllerWrapperView",
@"UIImageView",
@"UIScrollView",
@"UIView",
];
// If this test fails, the unknown class should be added in other_views if
// it doesn't display any strings, otherwise the strings diplay by this
......
......@@ -26,6 +26,8 @@ source_set("unified_consent_ui") {
sources = [
"identity_picker_view.h",
"identity_picker_view.mm",
"identity_view.h",
"identity_view.mm",
"unified_consent_view_controller.h",
"unified_consent_view_controller.mm",
]
......
......@@ -5,6 +5,7 @@
#import "ios/chrome/browser/ui/authentication/unified_consent/identity_picker_view.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/authentication/unified_consent/identity_view.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#import "ios/chrome/browser/ui/util/constraints_ui_util.h"
#import "ios/third_party/material_components_ios/src/components/Ink/src/MaterialInk.h"
......@@ -17,43 +18,27 @@ namespace {
const CGFloat kIdentityPickerViewRadius = 8.;
// Sizes.
const CGFloat kIdentityAvatarSize = 40.;
const CGFloat kTitleFontSize = 14.;
const CGFloat kSubtitleFontSize = 12.;
const CGFloat kArrowDownSize = 24.;
// Distances/margins.
const CGFloat kTitleOffset = 2;
const CGFloat kArrowDownMargin = 12.;
const CGFloat kHorizontalAvatarMargin = 16.;
const CGFloat kVerticalMargin = 12.;
// Colors
const int kHeaderBackgroundColor = 0xf1f3f4;
const CGFloat kTitleTextColorAlpha = .87;
const CGFloat kSubtitleTextColorAlpha = .54;
} // namespace
@interface IdentityPickerView ()
@property(nonatomic) UIImageView* avatarImageView;
@property(nonatomic) UILabel* title;
@property(nonatomic) UILabel* subtitle;
@property(nonatomic) MDCInkView* inkView;
@property(nonatomic) NSLayoutConstraint* titleConstraintForNameAndEmail;
@property(nonatomic) NSLayoutConstraint* titleConstraintForEmailOnly;
@property(nonatomic, strong) IdentityView* identityView;
@property(nonatomic, strong) MDCInkView* inkView;
@end
@implementation IdentityPickerView
@synthesize avatarImageView = _avatarImageView;
@synthesize title = _title;
@synthesize subtitle = _subtitle;
@synthesize identityView = _identityView;
@synthesize inkView = _inkView;
// Constraints when email and name are available.
@synthesize titleConstraintForNameAndEmail = _titleConstraintForNameAndEmail;
// Constraints when only the email is avaiable.
@synthesize titleConstraintForEmailOnly = _titleConstraintForEmailOnly;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
......@@ -68,11 +53,6 @@ const CGFloat kSubtitleTextColorAlpha = .54;
_inkView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_inkView];
// Avatar view.
_avatarImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
_avatarImageView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_avatarImageView];
// Arrow down.
UIImageView* arrowDownImageView =
[[UIImageView alloc] initWithFrame:CGRectZero];
......@@ -81,61 +61,33 @@ const CGFloat kSubtitleTextColorAlpha = .54;
[UIImage imageNamed:@"identity_picker_view_arrow_down"];
[self addSubview:arrowDownImageView];
// Title.
_title = [[UILabel alloc] initWithFrame:CGRectZero];
_title.translatesAutoresizingMaskIntoConstraints = NO;
_title.textColor = [UIColor colorWithWhite:0 alpha:kTitleTextColorAlpha];
_title.font = [UIFont systemFontOfSize:kTitleFontSize];
[self addSubview:_title];
// Subtitle.
_subtitle = [[UILabel alloc] initWithFrame:CGRectZero];
_subtitle.translatesAutoresizingMaskIntoConstraints = NO;
_subtitle.textColor =
[UIColor colorWithWhite:0 alpha:kSubtitleTextColorAlpha];
_subtitle.font = [UIFont systemFontOfSize:kSubtitleFontSize];
[self addSubview:_subtitle];
// Main view with avatar, name and email.
_identityView = [[IdentityView alloc] initWithFrame:CGRectZero];
_identityView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_identityView];
// Layout constraints.
NSDictionary* views = @{
@"avatar" : _avatarImageView,
@"title" : _title,
@"subtitle" : _subtitle,
@"identityview" : _identityView,
@"arrow" : arrowDownImageView,
};
NSDictionary* metrics = @{
@"ArMrg" : @(kArrowDownMargin),
@"ArrowMargin" : @(kArrowDownMargin),
@"ArrowSize" : @(kArrowDownSize),
@"AvatarSize" : @(kIdentityAvatarSize),
@"HAvatMrg" : @(kHorizontalAvatarMargin),
@"VMargin" : @(kVerticalMargin),
};
NSArray* constraints = @[
// Horizontal constraints.
@"H:|-(HAvatMrg)-[avatar]-(HAvatMrg)-[title]-(ArMrg)-[arrow]-(ArMrg)-|",
@"H:|[identityview]-(ArrowMargin)-[arrow]-(ArrowMargin)-|",
// Vertical constraints.
@"V:|-(>=VMargin)-[avatar]-(>=VMargin)-|",
@"V:|-(>=VMargin)-[title]",
@"V:[subtitle]-(>=VMargin)-|",
@"V:|[identityview]|",
// Size constraints.
@"H:[avatar(AvatarSize)]",
@"V:[avatar(AvatarSize)]",
@"H:[arrow(ArrowSize)]",
@"V:[arrow(ArrowSize)]",
];
AddSameCenterYConstraint(self, _avatarImageView);
AddSameCenterYConstraint(self, arrowDownImageView);
ApplyVisualConstraintsWithMetrics(constraints, views, metrics);
AddSameConstraintsToSides(_title, _subtitle,
LayoutSides::kLeading | LayoutSides::kTrailing);
_titleConstraintForNameAndEmail =
[self.centerYAnchor constraintEqualToAnchor:_title.bottomAnchor
constant:kTitleOffset];
_titleConstraintForEmailOnly =
[self.centerYAnchor constraintEqualToAnchor:_title.centerYAnchor];
[self.centerYAnchor constraintEqualToAnchor:_subtitle.topAnchor
constant:-kTitleOffset]
.active = YES;
}
return self;
}
......@@ -143,24 +95,12 @@ const CGFloat kSubtitleTextColorAlpha = .54;
#pragma mark - Setter
- (void)setIdentityAvatar:(UIImage*)identityAvatar {
_avatarImageView.image =
CircularImageFromImage(identityAvatar, kIdentityAvatarSize);
[self.identityView setAvatar:identityAvatar];
}
- (void)setIdentityName:(NSString*)name email:(NSString*)email {
DCHECK(email);
if (!name || name.length == 0) {
self.titleConstraintForNameAndEmail.active = NO;
self.titleConstraintForEmailOnly.active = YES;
self.subtitle.hidden = YES;
self.title.text = email;
} else {
self.titleConstraintForEmailOnly.active = NO;
self.titleConstraintForNameAndEmail.active = YES;
self.subtitle.hidden = NO;
self.title.text = name;
self.subtitle.text = email;
}
[self.identityView setName:name email:email];
}
#pragma mark - Private
......
// 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.
#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_UNIFIED_CONSENT_IDENTITY_VIEW_H_
#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_UNIFIED_CONSENT_IDENTITY_VIEW_H_
#import <UIKit/UIKit.h>
// View with the avatar on the leading side, the name and the email address of
// an identity.
// The email address is required. The name and the avatar are optional.
// If the name is empty (or nil), then the email address is vertically centered.
// The avatar is displayed as a round image.
// +--------------------------------+
// | +------+ |
// | | | Full Name |
// | |Avatar| Email address |
// | +------+ |
// +--------------------------------+
@interface IdentityView : UIView
// Initialises IdentityView.
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
// See -[IdentityView initWithFrame:].
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
// Sets the avatar shown. The image is resized (40px) and shaped as a round
// image.
- (void)setAvatar:(UIImage*)avatar;
// Sets the name and the email address. |name| can be nil.
- (void)setName:(NSString*)name email:(NSString*)email;
@end
#endif // IOS_CHROME_BROWSER_UI_AUTHENTICATION_UNIFIED_CONSENT_IDENTITY_VIEW_H_
// 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_view.h"
#include "base/logging.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#import "ios/chrome/browser/ui/util/constraints_ui_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Sizes.
const CGFloat kAvatarSize = 40.;
const CGFloat kTitleFontSize = 14.;
const CGFloat kSubtitleFontSize = 12.;
// Distances/margins.
const CGFloat kTitleOffset = 2;
const CGFloat kHorizontalAvatarMargin = 16.;
const CGFloat kVerticalMargin = 12.;
// Colors
const CGFloat kTitleTextColorAlpha = .87;
const CGFloat kSubtitleTextColorAlpha = .54;
} // namespace
@interface IdentityView ()
// Avatar.
@property(nonatomic, strong) UIImageView* avatarView;
// Contains the name if it exists, otherwise it contains the email.
@property(nonatomic, strong) UILabel* title;
// Contains the email if the name exists, otherwise it is hidden.
@property(nonatomic, strong) UILabel* subtitle;
// Constraints if the name exists.
@property(nonatomic, strong) NSLayoutConstraint* titleConstraintForNameAndEmail;
// Constraints if the name doesn't exist.
@property(nonatomic, strong) NSLayoutConstraint* titleConstraintForEmailOnly;
@end
@implementation IdentityView
@synthesize avatarView = _avatarView;
@synthesize title = _title;
@synthesize subtitle = _subtitle;
// Constraints when email and name are available.
@synthesize titleConstraintForNameAndEmail = _titleConstraintForNameAndEmail;
// Constraints when only the email is available.
@synthesize titleConstraintForEmailOnly = _titleConstraintForEmailOnly;
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Avatar view.
_avatarView = [[UIImageView alloc] init];
_avatarView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_avatarView];
// Title.
_title = [[UILabel alloc] init];
_title.translatesAutoresizingMaskIntoConstraints = NO;
_title.textColor = [UIColor colorWithWhite:0 alpha:kTitleTextColorAlpha];
_title.font = [UIFont systemFontOfSize:kTitleFontSize];
[self addSubview:_title];
// Subtitle.
_subtitle = [[UILabel alloc] init];
_subtitle.translatesAutoresizingMaskIntoConstraints = NO;
_subtitle.textColor =
[UIColor colorWithWhite:0 alpha:kSubtitleTextColorAlpha];
_subtitle.font = [UIFont systemFontOfSize:kSubtitleFontSize];
[self addSubview:_subtitle];
// Layout constraints.
NSDictionary* views = @{
@"avatar" : _avatarView,
@"title" : _title,
@"subtitle" : _subtitle,
};
NSDictionary* metrics = @{
@"AvatarSize" : @(kAvatarSize),
@"HAvatarMargin" : @(kHorizontalAvatarMargin),
@"VMargin" : @(kVerticalMargin),
};
NSArray* constraints = @[
// Horizontal constraints.
@"H:|-(HAvatarMargin)-[avatar]-(HAvatarMargin)-[title]|",
// Vertical constraints.
@"V:|-(>=VMargin)-[avatar]-(>=VMargin)-|",
@"V:|-(>=VMargin)-[title]",
@"V:[subtitle]-(>=VMargin)-|",
// Size constraints.
@"H:[avatar(AvatarSize)]",
@"V:[avatar(AvatarSize)]",
];
AddSameCenterYConstraint(self, _avatarView);
ApplyVisualConstraintsWithMetrics(constraints, views, metrics);
AddSameConstraintsToSides(_title, _subtitle,
LayoutSides::kLeading | LayoutSides::kTrailing);
_titleConstraintForNameAndEmail =
[self.centerYAnchor constraintEqualToAnchor:_title.bottomAnchor
constant:kTitleOffset];
_titleConstraintForEmailOnly =
[self.centerYAnchor constraintEqualToAnchor:_title.centerYAnchor];
[self.centerYAnchor constraintEqualToAnchor:_subtitle.topAnchor
constant:-kTitleOffset]
.active = YES;
}
return self;
}
#pragma mark - Setter
- (void)setAvatar:(UIImage*)avatarImage {
if (avatarImage) {
self.avatarView.image = CircularImageFromImage(avatarImage, kAvatarSize);
} else {
self.avatarView.image = nil;
}
}
- (void)setName:(NSString*)name email:(NSString*)email {
DCHECK(email);
if (!name || name.length == 0) {
self.titleConstraintForNameAndEmail.active = NO;
self.titleConstraintForEmailOnly.active = YES;
self.subtitle.hidden = YES;
self.title.text = email;
} else {
self.titleConstraintForEmailOnly.active = NO;
self.titleConstraintForNameAndEmail.active = YES;
self.subtitle.hidden = NO;
self.title.text = name;
self.subtitle.text = email;
}
}
@end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment