forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Payment Request] Picker view + showcase integration + egtests
http://imgur.com/a/S1tcB BUG=602666 Review-Url: https://codereview.chromium.org/2778343002 Cr-Commit-Position: refs/heads/master@{#461989}
- Loading branch information
mahmadi
authored and
Commit bot
committed
Apr 5, 2017
1 parent
b4ad68a
commit 14a3ede
Showing
11 changed files
with
759 additions
and
1 deletion.
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
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,22 @@ | ||
// Copyright 2017 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_PAYMENTS_PAYMENT_REQUEST_PICKER_ROW_H_ | ||
#define IOS_CHROME_BROWSER_PAYMENTS_PAYMENT_REQUEST_PICKER_ROW_H_ | ||
|
||
#import <Foundation/Foundation.h> | ||
|
||
// The model object for a row in the payment request picker. | ||
@interface PickerRow : NSObject | ||
|
||
// The label for the row. This is displayed in the UI. | ||
@property(nonatomic, copy) NSString* label; | ||
// The value for the row. This is not displayed in the UI and is optional. | ||
@property(nonatomic, copy) NSString* value; | ||
|
||
- (instancetype)initWithLabel:(NSString*)label value:(NSString*)value; | ||
|
||
@end | ||
|
||
#endif // IOS_CHROME_BROWSER_PAYMENTS_PAYMENT_REQUEST_PICKER_ROW_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 2017 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/payments/payment_request_picker_row.h" | ||
|
||
#if !defined(__has_feature) || !__has_feature(objc_arc) | ||
#error "This file requires ARC support." | ||
#endif | ||
|
||
@implementation PickerRow | ||
|
||
@synthesize label = _label; | ||
@synthesize value = _value; | ||
|
||
- (instancetype)initWithLabel:(NSString*)label value:(NSString*)value { | ||
self = [super init]; | ||
if (self) { | ||
_label = label; | ||
_value = value; | ||
} | ||
return self; | ||
} | ||
|
||
- (NSString*)description { | ||
return [NSString stringWithFormat:@"Label: %@, Value: %@", _label, _value]; | ||
} | ||
|
||
@end |
45 changes: 45 additions & 0 deletions
45
ios/chrome/browser/payments/payment_request_picker_view_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,45 @@ | ||
// Copyright 2017 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_PAYMENT_REQUEST_PICKER_VIEW_CONTROLLER_H_ | ||
#define IOS_CHROME_BROWSER_PAYMENT_REQUEST_PICKER_VIEW_CONTROLLER_H_ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
extern NSString* const kPaymentRequestPickerRowAccessibilityID; | ||
extern NSString* const kPaymentRequestPickerSearchBarAccessibilityID; | ||
|
||
@class PaymentRequestPickerViewController; | ||
@class PickerRow; | ||
|
||
// Delegate protocol for PaymentRequestPickerViewController. | ||
@protocol PaymentRequestPickerViewControllerDelegate<NSObject> | ||
|
||
// Notifies the delegate that the user has selected a row. | ||
- (void)paymentRequestPickerViewController: | ||
(PaymentRequestPickerViewController*)controller | ||
didSelectRow:(PickerRow*)row; | ||
|
||
@end | ||
|
||
// TableViewController that displays a searchable list of rows featuring a | ||
// selected row as well as an index list. | ||
@interface PaymentRequestPickerViewController : UITableViewController | ||
|
||
// The delegate to be notified when the user selects a row. | ||
@property(nonatomic, weak) id<PaymentRequestPickerViewControllerDelegate> | ||
delegate; | ||
|
||
// Initializes the tableView with a list of rows and an optional selected row. | ||
- (instancetype)initWithRows:(NSArray<PickerRow*>*)rows | ||
selected:(PickerRow*)row NS_DESIGNATED_INITIALIZER; | ||
|
||
- (instancetype)init NS_UNAVAILABLE; | ||
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; | ||
- (instancetype)initWithNibName:(NSString*)nibNameOrNil | ||
bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; | ||
- (instancetype)initWithStyle:(UITableViewStyle)style NS_UNAVAILABLE; | ||
@end | ||
|
||
#endif // IOS_CHROME_BROWSER_PAYMENT_REQUEST_PICKER_VIEW_CONTROLLER_H_ |
251 changes: 251 additions & 0 deletions
251
ios/chrome/browser/payments/payment_request_picker_view_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,251 @@ | ||
// Copyright 2017 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/payments/payment_request_picker_view_controller.h" | ||
|
||
#import "base/logging.h" | ||
#import "base/mac/foundation_util.h" | ||
#import "ios/chrome/browser/payments/payment_request_picker_row.h" | ||
|
||
#if !defined(__has_feature) || !__has_feature(objc_arc) | ||
#error "This file requires ARC support." | ||
#endif | ||
|
||
NSString* const kPaymentRequestPickerRowAccessibilityID = | ||
@"kPaymentRequestPickerRowAccessibilityID"; | ||
NSString* const kPaymentRequestPickerSearchBarAccessibilityID = | ||
@"kPaymentRequestPickerSearchBarAccessibilityID"; | ||
|
||
namespace { | ||
NSString* const kPaymentRequestPickerViewControllerAccessibilityID = | ||
@"kPaymentRequestPickerViewControllerAccessibilityID"; | ||
} // namespace | ||
|
||
@interface PaymentRequestPickerViewController ()<UISearchResultsUpdating> | ||
|
||
// Search controller that contains search bar. | ||
@property(nonatomic, strong) UISearchController* searchController; | ||
|
||
// Full data set displayed when tableView is not filtered. | ||
@property(nonatomic, strong) NSArray<PickerRow*>* allRows; | ||
|
||
// Displayed rows in the tableView. | ||
@property(nonatomic, strong) NSArray<PickerRow*>* displayedRows; | ||
|
||
// Selected row. | ||
@property(nonatomic, strong) PickerRow* selectedRow; | ||
|
||
@property(nonatomic, strong) | ||
NSDictionary<NSString*, NSArray<PickerRow*>*>* sectionTitleToSectionRowsMap; | ||
|
||
@end | ||
|
||
@implementation PaymentRequestPickerViewController | ||
@synthesize searchController = _searchController; | ||
@synthesize allRows = _allRows; | ||
@synthesize displayedRows = _displayedRows; | ||
@synthesize selectedRow = _selectedRow; | ||
@synthesize sectionTitleToSectionRowsMap = _sectionTitleToSectionRowsMap; | ||
@synthesize delegate = _delegate; | ||
|
||
- (instancetype)initWithRows:(NSArray<PickerRow*>*)rows | ||
selected:(PickerRow*)selectedRow { | ||
self = [super initWithStyle:UITableViewStylePlain]; | ||
if (self) { | ||
self.allRows = [rows sortedArrayUsingComparator:^NSComparisonResult( | ||
PickerRow* row1, PickerRow* row2) { | ||
return [row1.label localizedCaseInsensitiveCompare:row2.label]; | ||
}]; | ||
self.selectedRow = selectedRow; | ||
// Default to displaying all the rows. | ||
self.displayedRows = self.allRows; | ||
} | ||
return self; | ||
} | ||
|
||
- (void)setDisplayedRows:(NSArray<PickerRow*>*)displayedRows { | ||
_displayedRows = displayedRows; | ||
|
||
// Update the mapping from section titles to rows in that section, for | ||
// currently displayed rows. | ||
[self updateSectionTitleToSectionRowsMap]; | ||
} | ||
|
||
#pragma mark - UIViewController | ||
|
||
- (void)viewDidLoad { | ||
[super viewDidLoad]; | ||
|
||
self.tableView.rowHeight = 48.0f; // The same as MDCCellDefaultOneLineHeight. | ||
self.tableView.accessibilityIdentifier = | ||
kPaymentRequestPickerViewControllerAccessibilityID; | ||
|
||
self.searchController = | ||
[[UISearchController alloc] initWithSearchResultsController:nil]; | ||
self.searchController.searchResultsUpdater = self; | ||
self.searchController.dimsBackgroundDuringPresentation = NO; | ||
self.searchController.searchBar.accessibilityIdentifier = | ||
kPaymentRequestPickerSearchBarAccessibilityID; | ||
self.tableView.tableHeaderView = self.searchController.searchBar; | ||
|
||
// Presentation of searchController will walk up the view controller hierarchy | ||
// until it finds the root view controller or one that defines a presentation | ||
// context. Make this class the presentation context so that the search | ||
// controller does not present on top of the navigation controller. | ||
self.definesPresentationContext = YES; | ||
} | ||
|
||
#pragma mark - UITableViewDataSource | ||
|
||
- (NSArray<NSString*>*)sectionIndexTitlesForTableView:(UITableView*)tableView { | ||
return [self sectionTitles]; | ||
} | ||
|
||
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView { | ||
return [[self sectionTitles] count]; | ||
} | ||
|
||
- (NSString*)tableView:(UITableView*)tableView | ||
titleForHeaderInSection:(NSInteger)section { | ||
return [[self sectionTitles] objectAtIndex:section]; | ||
} | ||
|
||
- (NSInteger)tableView:(UITableView*)tableView | ||
numberOfRowsInSection:(NSInteger)section { | ||
return [[self rowsInSection:section] count]; | ||
} | ||
|
||
- (UITableViewCell*)tableView:(UITableView*)tableView | ||
cellForRowAtIndexPath:(NSIndexPath*)indexPath { | ||
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; | ||
if (!cell) { | ||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle | ||
reuseIdentifier:@"cell"]; | ||
cell.isAccessibilityElement = YES; | ||
cell.accessibilityIdentifier = kPaymentRequestPickerRowAccessibilityID; | ||
} | ||
PickerRow* row = | ||
[[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row]; | ||
cell.textLabel.text = row.label; | ||
cell.accessoryType = (row == self.selectedRow) | ||
? UITableViewCellAccessoryCheckmark | ||
: UITableViewCellAccessoryNone; | ||
if (row == self.selectedRow) | ||
cell.accessibilityTraits |= UIAccessibilityTraitSelected; | ||
else | ||
cell.accessibilityTraits &= ~UIAccessibilityTraitSelected; | ||
|
||
return cell; | ||
} | ||
|
||
#pragma mark - UITableViewDelegate | ||
|
||
- (void)tableView:(UITableView*)tableView | ||
didSelectRowAtIndexPath:(NSIndexPath*)indexPath { | ||
if (self.selectedRow) { | ||
NSIndexPath* oldSelectedIndexPath = [self indexPathForRow:self.selectedRow]; | ||
self.selectedRow = nil; | ||
// Reload the previously selected row if it is displaying. | ||
if (oldSelectedIndexPath) { | ||
[self.tableView reloadRowsAtIndexPaths:@[ oldSelectedIndexPath ] | ||
withRowAnimation:UITableViewRowAnimationFade]; | ||
} | ||
} | ||
|
||
self.selectedRow = | ||
[[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row]; | ||
// Reload the newly selected row. | ||
[self.tableView reloadRowsAtIndexPaths:@[ indexPath ] | ||
withRowAnimation:UITableViewRowAnimationFade]; | ||
|
||
[_delegate paymentRequestPickerViewController:self | ||
didSelectRow:self.selectedRow]; | ||
} | ||
|
||
#pragma mark - UISearchResultsUpdating | ||
|
||
- (void)updateSearchResultsForSearchController: | ||
(UISearchController*)searchController { | ||
NSString* searchText = searchController.searchBar.text; | ||
|
||
// Filter |allRows| for |searchText| and reload the tableView. If |searchText| | ||
// is empty, tableView will be loaded with |allRows|. | ||
if (searchText.length != 0) { | ||
// The search is case-insensitive and ignores diacritics. | ||
NSPredicate* predicate = | ||
[NSPredicate predicateWithFormat:@"label CONTAINS[cd] %@", searchText]; | ||
self.displayedRows = [self.allRows filteredArrayUsingPredicate:predicate]; | ||
} else { | ||
self.displayedRows = self.allRows; | ||
} | ||
|
||
[self.tableView reloadData]; | ||
} | ||
|
||
#pragma mark - Private | ||
|
||
// Creates a mapping from section titles to rows in that section, for currently | ||
// displaying rows, and updates |sectionTitleToSectionRowsMap|. | ||
- (void)updateSectionTitleToSectionRowsMap { | ||
NSMutableDictionary<NSString*, NSArray<PickerRow*>*>* | ||
sectionTitleToSectionRowsMap = [[NSMutableDictionary alloc] init]; | ||
|
||
for (PickerRow* row in self.displayedRows) { | ||
NSString* sectionTitle = [self sectionTitleForRow:row]; | ||
NSMutableArray<PickerRow*>* sectionRows = | ||
base::mac::ObjCCastStrict<NSMutableArray<PickerRow*>>( | ||
sectionTitleToSectionRowsMap[sectionTitle]); | ||
if (!sectionRows) | ||
sectionRows = [[NSMutableArray alloc] init]; | ||
[sectionRows addObject:row]; | ||
[sectionTitleToSectionRowsMap setObject:sectionRows forKey:sectionTitle]; | ||
} | ||
|
||
self.sectionTitleToSectionRowsMap = sectionTitleToSectionRowsMap; | ||
} | ||
|
||
// Returns the indexPath for |row| by calculating its section and its index | ||
// within the section. Returns nil if the row is not currently displaying. | ||
- (NSIndexPath*)indexPathForRow:(PickerRow*)row { | ||
NSString* sectionTitle = [self sectionTitleForRow:row]; | ||
|
||
NSInteger section = [[self sectionTitles] indexOfObject:sectionTitle]; | ||
if (section == NSNotFound) | ||
return nil; | ||
|
||
NSInteger indexInSection = | ||
[self.sectionTitleToSectionRowsMap[sectionTitle] indexOfObject:row]; | ||
if (indexInSection == NSNotFound) | ||
return nil; | ||
|
||
return [NSIndexPath indexPathForRow:indexInSection inSection:section]; | ||
} | ||
|
||
// Returns the titles for the displayed sections in the tableView. | ||
- (NSArray<NSString*>*)sectionTitles { | ||
return [[self.sectionTitleToSectionRowsMap allKeys] | ||
sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; | ||
} | ||
|
||
// Returns the displayed rows in the given section. | ||
- (NSArray<PickerRow*>*)rowsInSection:(NSInteger)section { | ||
NSArray<NSString*>* sectionTitles = [self sectionTitles]; | ||
DCHECK(section >= 0 && section < static_cast<NSInteger>(sectionTitles.count)); | ||
|
||
NSString* sectionTitle = [sectionTitles objectAtIndex:section]; | ||
|
||
return self.sectionTitleToSectionRowsMap[sectionTitle]; | ||
} | ||
|
||
// Returns the title for the section the given row gets added to. The section | ||
// title for a row is the capitalized first letter of the label for that row. | ||
- (NSString*)sectionTitleForRow:(PickerRow*)row { | ||
return [[row.label substringToIndex:1] uppercaseString]; | ||
} | ||
|
||
- (NSString*)description { | ||
return kPaymentRequestPickerViewControllerAccessibilityID; | ||
} | ||
|
||
@end |
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
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
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
Oops, something went wrong.