Commit 1e43dc3b authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

[iOS] Create TableView AutofillEditItem

This CL creates the AutofillEditItem to replace the
LegacyAutofillEditItem in UITableView.
The support for Dynamic Type will be done later to keep this close to
the legacy implementation.

Bug: 894791
Change-Id: I9e0e9ab81498dbafe5357487a7249f23c7620df5
Reviewed-on: https://chromium-review.googlesource.com/c/1344062Reviewed-by: default avatarRohit Rao <rohitrao@chromium.org>
Reviewed-by: default avatarMoe Ahmadi <mahmadi@chromium.org>
Reviewed-by: default avatarChris Lu <thegreenfrog@chromium.org>
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611050}
parent 8303e6fc
......@@ -4,6 +4,8 @@
source_set("cells") {
sources = [
"autofill_edit_item.h",
"autofill_edit_item.mm",
"cvc_item.h",
"cvc_item.mm",
"legacy_autofill_edit_item.h",
......@@ -22,6 +24,7 @@ source_set("cells") {
"//ios/chrome/browser/ui/autofill:autofill_ui",
"//ios/chrome/browser/ui/collection_view/cells",
"//ios/chrome/browser/ui/colors",
"//ios/chrome/browser/ui/table_view/cells",
"//ios/chrome/common/ui_util",
"//ios/public/provider/chrome/browser",
"//ios/public/provider/chrome/browser/ui",
......@@ -36,6 +39,7 @@ source_set("cells") {
source_set("unit_tests") {
testonly = true
sources = [
"autofill_edit_item_unittest.mm",
"cvc_item_unittest.mm",
"legacy_autofill_edit_item_unittest.mm",
"status_item_unittest.mm",
......@@ -46,6 +50,7 @@ source_set("unit_tests") {
"//base",
"//components/resources",
"//ios/chrome/browser/ui/collection_view/cells",
"//ios/chrome/browser/ui/table_view:styler",
"//ios/third_party/material_components_ios",
"//testing/gtest",
]
......
// 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_AUTOFILL_CELLS_AUTOFILL_EDIT_ITEM_H_
#define IOS_CHROME_BROWSER_UI_AUTOFILL_CELLS_AUTOFILL_EDIT_ITEM_H_
#import <UIKit/UIKit.h>
#import "ios/chrome/browser/ui/autofill/autofill_ui_type.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h"
// Item to represent and configure an AutofillEditItem. It features a label and
// a text field.
@interface AutofillEditItem : TableViewItem
// The name of the text field.
@property(nonatomic, copy) NSString* textFieldName;
// The value of the text field.
@property(nonatomic, copy) NSString* textFieldValue;
// An icon identifying the text field or its current value, if any.
@property(nonatomic, copy) UIImage* identifyingIcon;
// The inputView for the text field, if any.
@property(nonatomic, strong) UIPickerView* inputView;
// The field type this item is describing.
@property(nonatomic, assign) AutofillUIType autofillUIType;
// Whether this field is required. If YES, an "*" is appended to the name of the
// text field to indicate that the field is required. It is also used for
// validation purposes.
@property(nonatomic, getter=isRequired) BOOL required;
// Whether the text field is enabled for editing.
@property(nonatomic, getter=isTextFieldEnabled) BOOL textFieldEnabled;
// Controls the display of the return key when the keyboard is displaying.
@property(nonatomic, assign) UIReturnKeyType returnKeyType;
// Keyboard type to be displayed when the text field becomes first responder.
@property(nonatomic, assign) UIKeyboardType keyboardType;
// Controls autocapitalization behavior of the text field.
@property(nonatomic, assign)
UITextAutocapitalizationType autoCapitalizationType;
@end
// AutofillEditCell implements an UITableViewCell subclass containing a label
// and a text field.
@interface AutofillEditCell : UITableViewCell
// Label at the leading edge of the cell. It displays the item's textFieldName.
@property(nonatomic, strong) UILabel* textLabel;
// Text field at the trailing edge of the cell. It displays the item's
// |textFieldValue|.
@property(nonatomic, readonly, strong) UITextField* textField;
- (void)setIdentifyingIcon:(UIImage*)icon;
@end
#endif // IOS_CHROME_BROWSER_UI_AUTOFILL_CELLS_AUTOFILL_EDIT_ITEM_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/autofill/cells/autofill_edit_item.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
#import "ios/chrome/browser/ui/util/rtl_geometry.h"
#import "ios/chrome/browser/ui/util/uikit_ui_util.h"
#import "ios/chrome/common/ui_util/constraints_ui_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Minimum gap between the label and the text field.
const CGFloat kLabelAndFieldGap = 5;
} // namespace
@implementation AutofillEditItem
- (instancetype)initWithType:(NSInteger)type {
self = [super initWithType:type];
if (self) {
self.cellClass = [AutofillEditCell class];
_returnKeyType = UIReturnKeyNext;
_keyboardType = UIKeyboardTypeDefault;
_autoCapitalizationType = UITextAutocapitalizationTypeWords;
}
return self;
}
#pragma mark TableViewItem
- (void)configureCell:(AutofillEditCell*)cell
withStyler:(ChromeTableViewStyler*)styler {
[super configureCell:cell withStyler:styler];
NSString* textLabelFormat = self.required ? @"%@*" : @"%@";
cell.textLabel.text =
[NSString stringWithFormat:textLabelFormat, self.textFieldName];
cell.textField.text = self.textFieldValue;
if (self.textFieldName.length) {
cell.textField.accessibilityIdentifier =
[NSString stringWithFormat:@"%@_textField", self.textFieldName];
}
cell.textField.enabled = self.textFieldEnabled;
cell.textField.textColor =
self.textFieldEnabled
? UIColorFromRGB(kTableViewTextLabelColorBlue)
: UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor);
[cell.textField addTarget:self
action:@selector(textFieldChanged:)
forControlEvents:UIControlEventEditingChanged];
cell.textField.inputView = self.inputView;
cell.textField.returnKeyType = self.returnKeyType;
cell.textField.keyboardType = self.keyboardType;
cell.textField.autocapitalizationType = self.autoCapitalizationType;
[cell setIdentifyingIcon:self.identifyingIcon];
}
#pragma mark Actions
- (void)textFieldChanged:(UITextField*)textField {
self.textFieldValue = textField.text;
}
@end
#pragma mark - AutofillEditCell
@interface AutofillEditCell ()
@property(nonatomic, strong) NSLayoutConstraint* iconHeightConstraint;
@property(nonatomic, strong) NSLayoutConstraint* iconWidthConstraint;
@property(nonatomic, strong) NSLayoutConstraint* textFieldTrailingConstraint;
// UIImageView containing the icon identifying |textField| or its current value.
@property(nonatomic, readonly, strong) UIImageView* identifyingIconView;
@end
@implementation AutofillEditCell
@synthesize textLabel = _textLabel;
- (instancetype)initWithStyle:(UITableViewCellStyle)style
reuseIdentifier:(NSString*)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.isAccessibilityElement = YES;
UIView* contentView = self.contentView;
_textLabel = [[UILabel alloc] init];
_textLabel.translatesAutoresizingMaskIntoConstraints = NO;
[_textLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh
forAxis:UILayoutConstraintAxisHorizontal];
[contentView addSubview:_textLabel];
_textField = [[UITextField alloc] init];
_textField.translatesAutoresizingMaskIntoConstraints = NO;
[contentView addSubview:_textField];
_textField.autocorrectionType = UITextAutocorrectionTypeNo;
_textField.clearButtonMode = UITextFieldViewModeWhileEditing;
_textField.contentVerticalAlignment =
UIControlContentVerticalAlignmentCenter;
_textField.textAlignment =
UseRTLLayout() ? NSTextAlignmentLeft : NSTextAlignmentRight;
// Card type icon.
_identifyingIconView = [[UIImageView alloc] initWithFrame:CGRectZero];
_identifyingIconView.translatesAutoresizingMaskIntoConstraints = NO;
[contentView addSubview:_identifyingIconView];
// Set up the icons size constraints. They are activated here and updated in
// layoutSubviews.
_iconHeightConstraint =
[_identifyingIconView.heightAnchor constraintEqualToConstant:0];
_iconWidthConstraint =
[_identifyingIconView.widthAnchor constraintEqualToConstant:0];
_textFieldTrailingConstraint = [_textField.trailingAnchor
constraintEqualToAnchor:_identifyingIconView.leadingAnchor];
// Set up the constraints.
[NSLayoutConstraint activateConstraints:@[
[_textLabel.leadingAnchor
constraintEqualToAnchor:contentView.leadingAnchor
constant:kTableViewHorizontalSpacing],
_textFieldTrailingConstraint,
[_textField.firstBaselineAnchor
constraintEqualToAnchor:_textLabel.firstBaselineAnchor],
[_textField.leadingAnchor
constraintEqualToAnchor:_textLabel.trailingAnchor
constant:kLabelAndFieldGap],
[_identifyingIconView.trailingAnchor
constraintEqualToAnchor:contentView.trailingAnchor
constant:-kTableViewHorizontalSpacing],
[_identifyingIconView.centerYAnchor
constraintEqualToAnchor:contentView.centerYAnchor],
_iconHeightConstraint,
_iconWidthConstraint,
]];
AddOptionalVerticalPadding(contentView, _textLabel,
kTableViewLargeVerticalSpacing);
}
return self;
}
#pragma mark Public
- (void)setIdentifyingIcon:(UIImage*)icon {
self.identifyingIconView.image = icon;
if (icon) {
self.textFieldTrailingConstraint.constant = -kLabelAndFieldGap;
// Set the size constraints of the icon view to the dimensions of the image.
self.iconHeightConstraint.constant = icon.size.height;
self.iconWidthConstraint.constant = icon.size.width;
} else {
self.textFieldTrailingConstraint.constant = 0;
self.iconHeightConstraint.constant = 0;
self.iconWidthConstraint.constant = 0;
}
}
#pragma mark UITableViewCell
- (void)prepareForReuse {
[super prepareForReuse];
self.textLabel.text = nil;
self.textField.text = nil;
self.textField.returnKeyType = UIReturnKeyNext;
self.textField.keyboardType = UIKeyboardTypeDefault;
self.textField.autocapitalizationType = UITextAutocapitalizationTypeWords;
self.textField.autocorrectionType = UITextAutocorrectionTypeNo;
self.textField.clearButtonMode = UITextFieldViewModeWhileEditing;
self.textField.accessibilityIdentifier = nil;
self.textField.enabled = NO;
self.textField.delegate = nil;
[self.textField removeTarget:nil
action:nil
forControlEvents:UIControlEventAllEvents];
self.identifyingIconView.image = nil;
}
#pragma mark Accessibility
- (NSString*)accessibilityLabel {
return [NSString
stringWithFormat:@"%@, %@", self.textLabel.text, self.textField.text];
}
@end
// 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/autofill/cells/autofill_edit_item.h"
#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "testing/gtest_mac.h"
#include "testing/platform_test.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using AutofillEditItemTest = PlatformTest;
// Tests that the label and text field are set properly after a call to
// |configureCell:|.
TEST_F(AutofillEditItemTest, ConfigureCell) {
AutofillEditItem* item = [[AutofillEditItem alloc] initWithType:0];
NSString* name = @"Name";
NSString* value = @"Value";
BOOL enabled = NO;
item.textFieldName = name;
item.textFieldValue = value;
item.textFieldEnabled = enabled;
id cell = [[[item cellClass] alloc] init];
ASSERT_TRUE([cell isMemberOfClass:[AutofillEditCell class]]);
AutofillEditCell* autofillEditCell = cell;
EXPECT_EQ(0U, autofillEditCell.textLabel.text.length);
EXPECT_EQ(0U, autofillEditCell.textField.text.length);
EXPECT_TRUE(autofillEditCell.textField.enabled);
[item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]];
EXPECT_NSEQ(name, autofillEditCell.textLabel.text);
EXPECT_NSEQ(value, autofillEditCell.textField.text);
EXPECT_FALSE(autofillEditCell.textField.enabled);
}
......@@ -7,6 +7,7 @@
// Defines the style of a collection view cell. Individual cells may choose to
// expose and respect this setting.
// TODO(crbug.com/894800): Remove this.
enum class CollectionViewCellStyle {
// A cell style that conforms to Material Design guidelines.
kMaterial = 0,
......
......@@ -4,6 +4,7 @@
#import "ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.h"
#import "ios/chrome/browser/ui/autofill/cells/autofill_edit_item.h"
#import "ios/chrome/browser/ui/settings/cells/settings_detail_item.h"
#import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h"
#import "ios/chrome/browser/ui/table_view/cells/table_view_accessory_item.h"
......@@ -26,6 +27,7 @@ namespace {
typedef NS_ENUM(NSInteger, SectionIdentifier) {
SectionIdentifierText = kSectionIdentifierEnumZero,
SectionIdentifierSettings,
SectionIdentifierAutofill,
SectionIdentifierURL,
};
......@@ -45,6 +47,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
ItemTypeLinkFooter,
ItemTypeDetailText,
ItemTypeSettingsSwitch,
ItemTypeAutofillEditItem,
};
}
......@@ -75,6 +78,7 @@ typedef NS_ENUM(NSInteger, ItemType) {
TableViewModel* model = self.tableViewModel;
[model addSectionWithIdentifier:SectionIdentifierText];
[model addSectionWithIdentifier:SectionIdentifierSettings];
[model addSectionWithIdentifier:SectionIdentifierAutofill];
[model addSectionWithIdentifier:SectionIdentifierURL];
// SectionIdentifierText.
......@@ -168,6 +172,14 @@ typedef NS_ENUM(NSInteger, ItemType) {
[model setFooter:linkFooter
forSectionWithIdentifier:SectionIdentifierSettings];
// SectionIdentifierAutofill.
AutofillEditItem* autofillEditItem =
[[AutofillEditItem alloc] initWithType:ItemTypeAutofillEditItem];
autofillEditItem.textFieldName = @"Autofill field";
autofillEditItem.textFieldValue = @" with a value";
[model addItem:autofillEditItem
toSectionWithIdentifier:SectionIdentifierAutofill];
// SectionIdentifierURL.
TableViewURLItem* item =
[[TableViewURLItem alloc] initWithType:ItemTypeURLNoMetadata];
......
......@@ -16,6 +16,9 @@ extern const CGFloat kTableViewHorizontalSpacing;
// The vertical spacing between views and the container view of a cell.
extern const CGFloat kTableViewVerticalSpacing;
// The large vertical spacing between views and the container view of a cell.
extern const CGFloat kTableViewLargeVerticalSpacing;
// The horizontal spacing between subviews within the container view.
extern const CGFloat kTableViewSubViewHorizontalSpacing;
......@@ -29,6 +32,9 @@ extern const CGFloat kUseDefaultFontSize;
// Spacing between text label and cell contentView.
extern const CGFloat kTableViewLabelVerticalTopSpacing;
// Hex Value for blue label text color.
extern const int kTableViewTextLabelColorBlue;
// Hex Value for light gray label text color.
extern const int kTableViewTextLabelColorLightGrey;
......
......@@ -11,11 +11,13 @@
const CGFloat kTableViewHeaderFooterViewHeight = 44.0;
const CGFloat kTableViewHorizontalSpacing = 16.0;
const CGFloat kTableViewVerticalSpacing = 8.0;
const CGFloat kTableViewLargeVerticalSpacing = 16.0;
const CGFloat kTableViewSubViewHorizontalSpacing = 12.0;
const CGFloat kTableViewCellSelectionAnimationDuration = 0.15;
const CGFloat kUseDefaultFontSize = 0.0;
const CGFloat kTableViewLabelVerticalTopSpacing = 13.0;
const int kTableViewTextLabelColorBlue = 0x1A73E8;
const int kTableViewTextLabelColorLightGrey = 0x6D6D72;
const int kTableViewSecondaryLabelLightGrayTextColor = 0x8E8E93;
const int kTableViewSwitchTintColor = 0x1A73E8;
......
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