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

Side by Side 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, 8 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/payments/payment_request_picker_view_controller.h"
6
7 #import "base/logging.h"
8 #import "ios/chrome/browser/payments/payment_request_picker_row.h"
9 #import "ios/third_party/material_components_ios/src/components/CollectionCells/ src/MaterialCollectionCells.h"
10
11 #if !defined(__has_feature) || !__has_feature(objc_arc)
12 #error "This file requires ARC support."
13 #endif
14
15 NSString* const kPaymentRequestPickerRowAccessibilityID =
16 @"kPaymentRequestPickerRowAccessibilityID";
17 NSString* const kPaymentRequestPickerSelectedRowAccessibilityID =
18 @"kPaymentRequestPickerSelectedRowAccessibilityID";
19 NSString* const kPaymentRequestPickerSearchBarAccessibilityID =
20 @"kPaymentRequestPickerSearchBarAccessibilityID";
21
22 namespace {
23 NSString* const kPaymentRequestPickerViewControllerAccessibilityID =
24 @"kPaymentRequestPickerViewControllerAccessibilityID";
25
lpromero 2017/03/29 11:38:15 Remove empty line.
Moe 2017/03/29 17:04:09 Done.
26 } // namespace
27
28 @interface PaymentRequestPickerViewController ()<UITableViewDataSource,
29 UITableViewDelegate,
lpromero 2017/03/29 11:38:15 This is already done by the base class.
Moe 2017/03/29 17:04:09 Done.
30 UISearchResultsUpdating>
31
32 // Search controller that contains search bar.
33 @property(nonatomic, strong) UISearchController* searchController;
34
35 // Full data set displayed when tableView is not filtered.
36 @property(nonatomic, strong) NSArray<PickerRow*>* allRows;
37
38 // Displayed rows in the tableView.
39 @property(nonatomic, strong) NSArray<PickerRow*>* displayedRows;
40
41 // Selected row.
42 @property(nonatomic, strong) PickerRow* selectedRow;
43
44 @end
45
46 @implementation PaymentRequestPickerViewController
47 @synthesize searchController = _searchController;
48 @synthesize allRows = _allRows;
49 @synthesize displayedRows = _displayedRows;
50 @synthesize selectedRow = _selectedRow;
51 @synthesize delegate = _delegate;
52
53 - (instancetype)initWithRows:(NSArray<PickerRow*>*)rows
54 selected:(PickerRow*)selectedRow {
55 self = [super initWithStyle:UITableViewStylePlain];
56 if (self) {
57 self.allRows = [rows sortedArrayUsingComparator:^NSComparisonResult(
58 PickerRow* row1, PickerRow* row2) {
59 return [row1.label localizedCaseInsensitiveCompare:row2.label];
60 }];
61 self.selectedRow = selectedRow;
62 // Default to displaying all the rows.
63 self.displayedRows = self.allRows;
64 }
65 return self;
66 }
67
68 #pragma mark - UIViewController
69
70 - (void)viewDidLoad {
71 [super viewDidLoad];
72
73 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.
74 self.tableView.accessibilityIdentifier =
75 kPaymentRequestPickerViewControllerAccessibilityID;
76
77 self.searchController =
78 [[UISearchController alloc] initWithSearchResultsController:nil];
79 self.searchController.searchResultsUpdater = self;
80 self.searchController.dimsBackgroundDuringPresentation = NO;
81 self.searchController.searchBar.accessibilityIdentifier =
82 kPaymentRequestPickerSearchBarAccessibilityID;
83 self.tableView.tableHeaderView = self.searchController.searchBar;
84
85 // Presentation of searchController will walk up the view controller hierarchy
86 // until it finds the root view controller or one that defines a presentation
87 // context. Make this class the presentation context so that the search
88 // controller does not present on top of the navigation controller.
89 self.definesPresentationContext = YES;
90 }
91
92 #pragma mark - UITableViewDataSource
93
94 - (NSArray<NSString*>*)sectionIndexTitlesForTableView:(UITableView*)tableView {
95 return [self sectionTitles];
96 }
97
98 - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
99 return [[self sectionTitles] count];
100 }
101
102 - (NSString*)tableView:(UITableView*)tableView
103 titleForHeaderInSection:(NSInteger)section {
104 return [[self sectionTitles] objectAtIndex:section];
105 }
106
107 - (NSInteger)tableView:(UITableView*)tableView
108 numberOfRowsInSection:(NSInteger)section {
109 return [[self rowsInSection:section] count];
110 }
111
112 - (UITableViewCell*)tableView:(UITableView*)tableView
113 cellForRowAtIndexPath:(NSIndexPath*)indexPath {
114 UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
115 if (!cell) {
116 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
117 reuseIdentifier:@"cell"];
118 }
119 PickerRow* row =
120 [[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row];
121 cell.textLabel.text = row.label;
122 cell.accessoryType = (row == self.selectedRow)
123 ? UITableViewCellAccessoryCheckmark
124 : UITableViewCellAccessoryNone;
125 cell.accessibilityLabel = row.label;
126 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.
127 (row == self.selectedRow)
128 ? kPaymentRequestPickerSelectedRowAccessibilityID
129 : kPaymentRequestPickerRowAccessibilityID;
130 return cell;
131 }
132
133 #pragma mark - UITableViewDelegate
134
135 - (void)tableView:(UITableView*)tableView
136 didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
137 if (self.selectedRow) {
138 NSIndexPath* oldSelectedIndexPath = [self indexPathForRow:self.selectedRow];
139 self.selectedRow = nil;
140 // Reload the previously selected row.
141 [self.tableView reloadRowsAtIndexPaths:@[ oldSelectedIndexPath ]
142 withRowAnimation:UITableViewRowAnimationFade];
143 }
144
145 self.selectedRow =
146 [[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row];
147 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.
148 // Reload the newly selected row.
149 [self.tableView reloadRowsAtIndexPaths:@[ newSelectedIndexPath ]
150 withRowAnimation:UITableViewRowAnimationFade];
151
152 [_delegate paymentRequestPickerViewController:self
153 didSelectRow:self.selectedRow];
154 }
155
156 #pragma mark - UISearchResultsUpdating
157
158 - (void)updateSearchResultsForSearchController:
159 (UISearchController*)searchController {
160 [self filterContentForSearchText:searchController.searchBar.text];
161 }
162
163 #pragma mark - Private
164
165 // Returns the indexPath for |row| by calculating its section and its index
166 // within the section.
167 - (NSIndexPath*)indexPathForRow:(PickerRow*)row {
168 NSString* sectionTitle = [self sectionTitleForRow:row];
169 NSInteger section = [[self sectionTitles] indexOfObject:sectionTitle];
170 DCHECK(section != NSNotFound);
171
172 NSInteger indexInSection = [[self rowsInSection:section] indexOfObject:row];
173 DCHECK(indexInSection != NSNotFound);
174
175 return [NSIndexPath indexPathForRow:indexInSection inSection:section];
176 }
177
178 // Returns the titles for the displayed sections in the tableView.
179 - (NSArray<NSString*>*)sectionTitles {
180 NSMutableOrderedSet<NSString*>* sectionTitles =
181 [[NSMutableOrderedSet alloc] init];
182 [self.displayedRows
183 enumerateObjectsUsingBlock:^(PickerRow* row, NSUInteger idx, BOOL* stop) {
184 [sectionTitles addObject:[self sectionTitleForRow:row]];
185 }];
186 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
187 }
188
189 // Returns the displayed rows in the given section.
190 - (NSArray<PickerRow*>*)rowsInSection:(NSInteger)section {
191 NSArray<NSString*>* sectionTitles = [self sectionTitles];
192 DCHECK(section >= 0 && section < static_cast<NSInteger>(sectionTitles.count));
193
194 NSString* sectionTitle = [sectionTitles objectAtIndex:section];
195
196 // Find the rows in the section with the title |sectionTitle| based on the
197 // labels of the rows. The search is case-insensitive and ignores diacritics.
198 NSPredicate* prediacate = [NSPredicate
lpromero 2017/03/29 11:38:15 *predicate
Moe 2017/03/29 17:04:09 Done.
199 predicateWithFormat:@"label BEGINSWITH[cd] %@", sectionTitle];
200 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
201 }
202
203 // Returns the title for the section the given row gets added to. The section
204 // title for a row is the capitalized first letter of the label for that row.
205 - (NSString*)sectionTitleForRow:(PickerRow*)row {
206 return [[row.label substringToIndex:1] uppercaseString];
207 }
208
209 // Filters |allRows| for |searchText| and reloads the tableView. If |searchText|
210 // is empty, tableView will be loaded with |allRows|.
211 - (void)filterContentForSearchText:(NSString*)searchText {
212 self.displayedRows = self.allRows;
213
214 if (searchText.length != 0) {
215 // The search is case-insensitive and ignores diacritics.
216 NSPredicate* prediacate =
217 [NSPredicate predicateWithFormat:@"label CONTAINS[cd] %@", searchText];
218 self.displayedRows = [self.allRows filteredArrayUsingPredicate:prediacate];
219 }
220
221 [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
222 }
223
224 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698