Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Unified Diff: ios/chrome/browser/payments/payment_request_picker_view_controller.mm

Issue 2778343002: [Payment Request] Picker view + showcase integration + egtests (Closed)
Patch Set: Initial Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/payments/payment_request_picker_view_controller.mm
diff --git a/ios/chrome/browser/payments/payment_request_picker_view_controller.mm b/ios/chrome/browser/payments/payment_request_picker_view_controller.mm
new file mode 100644
index 0000000000000000000000000000000000000000..7131852bc0d4f89a9adf467ce20c7440ff7b8e70
--- /dev/null
+++ b/ios/chrome/browser/payments/payment_request_picker_view_controller.mm
@@ -0,0 +1,224 @@
+// 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 "ios/chrome/browser/payments/payment_request_picker_row.h"
+#import "ios/third_party/material_components_ios/src/components/CollectionCells/src/MaterialCollectionCells.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+NSString* const kPaymentRequestPickerRowAccessibilityID =
+ @"kPaymentRequestPickerRowAccessibilityID";
+NSString* const kPaymentRequestPickerSelectedRowAccessibilityID =
+ @"kPaymentRequestPickerSelectedRowAccessibilityID";
+NSString* const kPaymentRequestPickerSearchBarAccessibilityID =
+ @"kPaymentRequestPickerSearchBarAccessibilityID";
+
+namespace {
+NSString* const kPaymentRequestPickerViewControllerAccessibilityID =
+ @"kPaymentRequestPickerViewControllerAccessibilityID";
+
lpromero 2017/03/29 11:38:15 Remove empty line.
Moe 2017/03/29 17:04:09 Done.
+} // namespace
+
+@interface PaymentRequestPickerViewController ()<UITableViewDataSource,
+ UITableViewDelegate,
lpromero 2017/03/29 11:38:15 This is already done by the base class.
Moe 2017/03/29 17:04:09 Done.
+ 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;
+
+@end
+
+@implementation PaymentRequestPickerViewController
+@synthesize searchController = _searchController;
+@synthesize allRows = _allRows;
+@synthesize displayedRows = _displayedRows;
+@synthesize selectedRow = _selectedRow;
+@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;
+}
+
+#pragma mark - UIViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+
+ self.tableView.rowHeight = MDCCellDefaultOneLineHeight;
lpromero 2017/03/29 11:38:15 I'd suggest just setting your own value here, not
Moe 2017/03/29 17:04:09 Done.
+ 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"];
+ }
+ PickerRow* row =
+ [[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row];
+ cell.textLabel.text = row.label;
+ cell.accessoryType = (row == self.selectedRow)
+ ? UITableViewCellAccessoryCheckmark
+ : UITableViewCellAccessoryNone;
+ cell.accessibilityLabel = row.label;
+ cell.accessibilityIdentifier =
lpromero 2017/03/29 11:38:15 If you remove the need for the 2 different IDs, yo
Moe 2017/03/29 17:04:09 Done.
+ (row == self.selectedRow)
+ ? kPaymentRequestPickerSelectedRowAccessibilityID
+ : kPaymentRequestPickerRowAccessibilityID;
+ 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.
+ [self.tableView reloadRowsAtIndexPaths:@[ oldSelectedIndexPath ]
+ withRowAnimation:UITableViewRowAnimationFade];
+ }
+
+ self.selectedRow =
+ [[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row];
+ NSIndexPath* newSelectedIndexPath = [self indexPathForRow:self.selectedRow];
lpromero 2017/03/29 11:38:15 Isn't this equal to indexPath?
Moe 2017/03/29 17:04:09 Oops. Done.
+ // Reload the newly selected row.
+ [self.tableView reloadRowsAtIndexPaths:@[ newSelectedIndexPath ]
+ withRowAnimation:UITableViewRowAnimationFade];
+
+ [_delegate paymentRequestPickerViewController:self
+ didSelectRow:self.selectedRow];
+}
+
+#pragma mark - UISearchResultsUpdating
+
+- (void)updateSearchResultsForSearchController:
+ (UISearchController*)searchController {
+ [self filterContentForSearchText:searchController.searchBar.text];
+}
+
+#pragma mark - Private
+
+// Returns the indexPath for |row| by calculating its section and its index
+// within the section.
+- (NSIndexPath*)indexPathForRow:(PickerRow*)row {
+ NSString* sectionTitle = [self sectionTitleForRow:row];
+ NSInteger section = [[self sectionTitles] indexOfObject:sectionTitle];
+ DCHECK(section != NSNotFound);
+
+ NSInteger indexInSection = [[self rowsInSection:section] indexOfObject:row];
+ DCHECK(indexInSection != NSNotFound);
+
+ return [NSIndexPath indexPathForRow:indexInSection inSection:section];
+}
+
+// Returns the titles for the displayed sections in the tableView.
+- (NSArray<NSString*>*)sectionTitles {
+ NSMutableOrderedSet<NSString*>* sectionTitles =
+ [[NSMutableOrderedSet alloc] init];
+ [self.displayedRows
+ enumerateObjectsUsingBlock:^(PickerRow* row, NSUInteger idx, BOOL* stop) {
+ [sectionTitles addObject:[self sectionTitleForRow:row]];
+ }];
+ return [sectionTitles array];
lpromero 2017/03/29 11:38:15 Should you cache this array? (You'll need to inval
Moe 2017/03/29 17:04:09 I'm now keeping a map of section titles to the sec
+}
+
+// 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];
+
+ // Find the rows in the section with the title |sectionTitle| based on the
+ // labels of the rows. The search is case-insensitive and ignores diacritics.
+ NSPredicate* prediacate = [NSPredicate
lpromero 2017/03/29 11:38:15 *predicate
Moe 2017/03/29 17:04:09 Done.
+ predicateWithFormat:@"label BEGINSWITH[cd] %@", sectionTitle];
+ return [self.displayedRows filteredArrayUsingPredicate:prediacate];
lpromero 2017/03/29 11:38:15 idem, should this be cached? It is called several
Moe 2017/03/29 17:04:09 with the map of section titles to the section rows
+}
+
+// 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];
+}
+
+// Filters |allRows| for |searchText| and reloads the tableView. If |searchText|
+// is empty, tableView will be loaded with |allRows|.
+- (void)filterContentForSearchText:(NSString*)searchText {
+ self.displayedRows = self.allRows;
+
+ if (searchText.length != 0) {
+ // The search is case-insensitive and ignores diacritics.
+ NSPredicate* prediacate =
+ [NSPredicate predicateWithFormat:@"label CONTAINS[cd] %@", searchText];
+ self.displayedRows = [self.allRows filteredArrayUsingPredicate:prediacate];
+ }
+
+ [self.tableView reloadData];
lpromero 2017/03/29 11:38:15 Showcase handles that more nicely, as it animates
Moe 2017/03/29 17:04:09 Since we have sections here and they would have to
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698