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

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: Addressed comments 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 "base/mac/foundation_util.h"
9 #import "ios/chrome/browser/payments/payment_request_picker_row.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 kPaymentRequestPickerSearchBarAccessibilityID =
18 @"kPaymentRequestPickerSearchBarAccessibilityID";
19
20 namespace {
21 NSString* const kPaymentRequestPickerViewControllerAccessibilityID =
22 @"kPaymentRequestPickerViewControllerAccessibilityID";
23 } // namespace
24
25 @interface PaymentRequestPickerViewController ()<UISearchResultsUpdating>
26
27 // Search controller that contains search bar.
28 @property(nonatomic, strong) UISearchController* searchController;
29
30 // Full data set displayed when tableView is not filtered.
31 @property(nonatomic, strong) NSArray<PickerRow*>* allRows;
32
33 // Displayed rows in the tableView.
34 @property(nonatomic, strong) NSArray<PickerRow*>* displayedRows;
35
36 // Selected row.
37 @property(nonatomic, strong) PickerRow* selectedRow;
38
39 @property(nonatomic, strong)
40 NSDictionary<NSString*, NSArray<PickerRow*>*>* sectionTitleToSectionRowsMap;
41
42 @end
43
44 @implementation PaymentRequestPickerViewController
45 @synthesize searchController = _searchController;
46 @synthesize allRows = _allRows;
47 @synthesize displayedRows = _displayedRows;
48 @synthesize selectedRow = _selectedRow;
49 @synthesize sectionTitleToSectionRowsMap = _sectionTitleToSectionRowsMap;
50 @synthesize delegate = _delegate;
51
52 - (instancetype)initWithRows:(NSArray<PickerRow*>*)rows
53 selected:(PickerRow*)selectedRow {
54 self = [super initWithStyle:UITableViewStylePlain];
55 if (self) {
56 self.allRows = [rows sortedArrayUsingComparator:^NSComparisonResult(
57 PickerRow* row1, PickerRow* row2) {
58 return [row1.label localizedCaseInsensitiveCompare:row2.label];
59 }];
60 self.selectedRow = selectedRow;
61 // Default to displaying all the rows.
62 self.displayedRows = self.allRows;
63 }
64 return self;
65 }
66
67 - (void)setDisplayedRows:(NSArray<PickerRow*>*)displayedRows {
68 _displayedRows = displayedRows;
69
70 // Update the mapping from section titles to rows in that section, for
71 // currently displayed rows.
72 [self updateSectionTitleToSectionRowsMap];
73 }
74
75 #pragma mark - UIViewController
76
77 - (void)viewDidLoad {
78 [super viewDidLoad];
79
80 self.tableView.rowHeight = 48.0f; // The same as MDCCellDefaultOneLineHeight.
81 self.tableView.accessibilityIdentifier =
82 kPaymentRequestPickerViewControllerAccessibilityID;
83
84 self.searchController =
85 [[UISearchController alloc] initWithSearchResultsController:nil];
86 self.searchController.searchResultsUpdater = self;
87 self.searchController.dimsBackgroundDuringPresentation = NO;
88 self.searchController.searchBar.accessibilityIdentifier =
89 kPaymentRequestPickerSearchBarAccessibilityID;
90 self.tableView.tableHeaderView = self.searchController.searchBar;
91
92 // Presentation of searchController will walk up the view controller hierarchy
93 // until it finds the root view controller or one that defines a presentation
94 // context. Make this class the presentation context so that the search
95 // controller does not present on top of the navigation controller.
96 self.definesPresentationContext = YES;
97 }
98
99 #pragma mark - UITableViewDataSource
100
101 - (NSArray<NSString*>*)sectionIndexTitlesForTableView:(UITableView*)tableView {
102 return [self sectionTitles];
103 }
104
105 - (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView {
106 return [[self sectionTitles] count];
107 }
108
109 - (NSString*)tableView:(UITableView*)tableView
110 titleForHeaderInSection:(NSInteger)section {
111 return [[self sectionTitles] objectAtIndex:section];
112 }
113
114 - (NSInteger)tableView:(UITableView*)tableView
115 numberOfRowsInSection:(NSInteger)section {
116 return [[self rowsInSection:section] count];
117 }
118
119 - (UITableViewCell*)tableView:(UITableView*)tableView
120 cellForRowAtIndexPath:(NSIndexPath*)indexPath {
121 UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
122 if (!cell) {
123 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
124 reuseIdentifier:@"cell"];
125 cell.isAccessibilityElement = YES;
126 cell.accessibilityIdentifier = kPaymentRequestPickerRowAccessibilityID;
127 }
128 PickerRow* row =
129 [[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row];
130 cell.textLabel.text = row.label;
131 cell.accessoryType = (row == self.selectedRow)
132 ? UITableViewCellAccessoryCheckmark
133 : UITableViewCellAccessoryNone;
134 if (row == self.selectedRow)
135 cell.accessibilityTraits |= UIAccessibilityTraitSelected;
136 else
137 cell.accessibilityTraits &= ~UIAccessibilityTraitSelected;
138
139 return cell;
140 }
141
142 #pragma mark - UITableViewDelegate
143
144 - (void)tableView:(UITableView*)tableView
145 didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
146 if (self.selectedRow) {
147 NSIndexPath* oldSelectedIndexPath = [self indexPathForRow:self.selectedRow];
148 self.selectedRow = nil;
149 // Reload the previously selected row if it is displaying.
150 if (oldSelectedIndexPath) {
151 [self.tableView reloadRowsAtIndexPaths:@[ oldSelectedIndexPath ]
152 withRowAnimation:UITableViewRowAnimationFade];
153 }
154 }
155
156 self.selectedRow =
157 [[self rowsInSection:indexPath.section] objectAtIndex:indexPath.row];
158 // Reload the newly selected row.
159 [self.tableView reloadRowsAtIndexPaths:@[ indexPath ]
160 withRowAnimation:UITableViewRowAnimationFade];
161
162 [_delegate paymentRequestPickerViewController:self
163 didSelectRow:self.selectedRow];
164 }
165
166 #pragma mark - UISearchResultsUpdating
167
168 - (void)updateSearchResultsForSearchController:
169 (UISearchController*)searchController {
170 NSString* searchText = searchController.searchBar.text;
171
172 // Filter |allRows| for |searchText| and reload the tableView. If |searchText|
173 // is empty, tableView will be loaded with |allRows|.
174 if (searchText.length != 0) {
175 // The search is case-insensitive and ignores diacritics.
176 NSPredicate* predicate =
177 [NSPredicate predicateWithFormat:@"label CONTAINS[cd] %@", searchText];
178 self.displayedRows = [self.allRows filteredArrayUsingPredicate:predicate];
179 } else {
180 self.displayedRows = self.allRows;
181 }
182
183 [self.tableView reloadData];
184 }
185
186 #pragma mark - Private
187
188 // Creates a mapping from section titles to rows in that section, for currently
189 // displaying rows, and updates |sectionTitleToSectionRowsMap|.
190 - (void)updateSectionTitleToSectionRowsMap {
191 NSMutableDictionary<NSString*, NSArray<PickerRow*>*>*
192 sectionTitleToSectionRowsMap = [[NSMutableDictionary alloc] init];
193
194 for (PickerRow* row in self.displayedRows) {
195 NSString* sectionTitle = [self sectionTitleForRow:row];
196 NSMutableArray<PickerRow*>* sectionRows =
197 base::mac::ObjCCastStrict<NSMutableArray<PickerRow*>>(
198 sectionTitleToSectionRowsMap[sectionTitle]);
199 if (!sectionRows)
200 sectionRows = [[NSMutableArray alloc] init];
201 [sectionRows addObject:row];
202 [sectionTitleToSectionRowsMap setObject:sectionRows forKey:sectionTitle];
203 }
204
205 self.sectionTitleToSectionRowsMap = sectionTitleToSectionRowsMap;
206 }
207
208 // Returns the indexPath for |row| by calculating its section and its index
209 // within the section. Returns nil if the row is not currently displaying.
210 - (NSIndexPath*)indexPathForRow:(PickerRow*)row {
211 NSString* sectionTitle = [self sectionTitleForRow:row];
212
213 NSInteger section = [[self sectionTitles] indexOfObject:sectionTitle];
214 if (section == NSNotFound)
215 return nil;
216
217 NSInteger indexInSection =
218 [self.sectionTitleToSectionRowsMap[sectionTitle] indexOfObject:row];
219 if (indexInSection == NSNotFound)
220 return nil;
221
222 return [NSIndexPath indexPathForRow:indexInSection inSection:section];
223 }
224
225 // Returns the titles for the displayed sections in the tableView.
226 - (NSArray<NSString*>*)sectionTitles {
227 return [[self.sectionTitleToSectionRowsMap allKeys]
228 sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
229 }
230
231 // Returns the displayed rows in the given section.
232 - (NSArray<PickerRow*>*)rowsInSection:(NSInteger)section {
233 NSArray<NSString*>* sectionTitles = [self sectionTitles];
234 DCHECK(section >= 0 && section < static_cast<NSInteger>(sectionTitles.count));
235
236 NSString* sectionTitle = [sectionTitles objectAtIndex:section];
237
238 return self.sectionTitleToSectionRowsMap[sectionTitle];
239 }
240
241 // Returns the title for the section the given row gets added to. The section
242 // title for a row is the capitalized first letter of the label for that row.
243 - (NSString*)sectionTitleForRow:(PickerRow*)row {
244 return [[row.label substringToIndex:1] uppercaseString];
245 }
246
247 - (NSString*)description {
248 return kPaymentRequestPickerViewControllerAccessibilityID;
249 }
250
251 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/payments/payment_request_picker_view_controller.h ('k') | ios/showcase/common/protocol_alerter.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698