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

Side by Side Diff: ios/chrome/browser/payments/payment_request_view_controller.mm

Issue 2585233003: Upstream Chrome on iOS source code [2/11]. (Closed)
Patch Set: Created 4 years 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 2016 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_view_controller.h"
6
7 #import "base/ios/weak_nsobject.h"
8 #include "base/mac/foundation_util.h"
9 #include "base/mac/objc_property_releaser.h"
10 #include "base/mac/scoped_nsobject.h"
11 #include "base/strings/sys_string_conversions.h"
12 #include "components/autofill/core/browser/autofill_data_util.h"
13 #include "components/autofill/core/browser/autofill_profile.h"
14 #include "components/autofill/core/browser/credit_card.h"
15 #include "components/autofill/core/browser/field_types.h"
16 #include "components/autofill/core/browser/personal_data_manager.h"
17 #include "ios/chrome/browser/application_context.h"
18 #import "ios/chrome/browser/payments/cells/page_info_item.h"
19 #import "ios/chrome/browser/payments/cells/payment_method_item.h"
20 #import "ios/chrome/browser/payments/cells/shipping_address_item.h"
21 #import "ios/chrome/browser/payments/payment_request_utils.h"
22 #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrom e.h"
23 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_detail_item .h"
24 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_item.h"
25 #import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h "
26 #import "ios/chrome/browser/ui/collection_view/collection_view_model.h"
27 #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h"
28 #include "ios/chrome/browser/ui/rtl_geometry.h"
29 #include "ios/chrome/grit/ios_strings.h"
30 #import "ios/third_party/material_components_ios/src/components/Buttons/src/Mate rialButtons.h"
31 #import "ios/third_party/material_components_ios/src/components/CollectionCells/ src/MaterialCollectionCells.h"
32 #import "ios/third_party/material_roboto_font_loader_ios/src/src/MaterialRobotoF ontLoader.h"
33 #include "ui/base/l10n/l10n_util.h"
34 #include "ui/base/resource/resource_bundle.h"
35
36 NSString* const kPaymentRequestCollectionViewId =
37 @"kPaymentRequestCollectionViewId";
38
39 namespace {
40
41 const CGFloat kButtonEdgeInset = 9;
42 const CGFloat kSeparatorEdgeInset = 14;
43
44 typedef NS_ENUM(NSInteger, SectionIdentifier) {
45 SectionIdentifierSummary = kSectionIdentifierEnumZero,
46 SectionIdentifierShipping,
47 SectionIdentifierPayment,
48
49 };
50
51 typedef NS_ENUM(NSInteger, ItemType) {
52 ItemTypeSummaryPageInfo = kItemTypeEnumZero,
53 ItemTypeSummaryTotal,
54 ItemTypeShippingTitle,
55 ItemTypeShippingAddress,
56 ItemTypeAddShippingAddress,
57 ItemTypePaymentTitle,
58 ItemTypePaymentMethod,
59 };
60
61 } // namespace
62
63 @interface PaymentRequestViewController () {
64 base::WeakNSProtocol<id<PaymentRequestViewControllerDelegate>> _delegate;
65 base::scoped_nsobject<UIBarButtonItem> _cancelButton;
66 base::scoped_nsobject<MDCFlatButton> _payButton;
67
68 ShippingAddressItem* _selectedShippingAddressItem;
69
70 base::mac::ObjCPropertyReleaser
71 _propertyReleaser_PaymentRequestViewController;
72 }
73
74 // Called when the user presses the cancel button.
75 - (void)onCancel;
76
77 // Called when the user presses the confirm button.
78 - (void)onConfirm;
79
80 @end
81
82 @implementation PaymentRequestViewController
83
84 @synthesize paymentRequest = _paymentRequest;
85 @synthesize pageFavicon = _pageFavicon;
86 @synthesize pageTitle = _pageTitle;
87 @synthesize pageHost = _pageHost;
88 @synthesize selectedPaymentMethod = _selectedPaymentMethod;
89 @synthesize selectedShippingAddress = _selectedShippingAddress;
90
91 - (instancetype)init {
92 if ((self = [super initWithStyle:CollectionViewControllerStyleAppBar])) {
93 _propertyReleaser_PaymentRequestViewController.Init(
94 self, [PaymentRequestViewController class]);
95
96 [self setTitle:l10n_util::GetNSString(IDS_IOS_PAYMENT_REQUEST_TITLE)];
97
98 // Set up left (cancel) button.
99 _cancelButton.reset([[UIBarButtonItem alloc]
100 initWithTitle:l10n_util::GetNSString(
101 IDS_IOS_PAYMENT_REQUEST_CANCEL_BUTTON)
102 style:UIBarButtonItemStylePlain
103 target:nil
104 action:@selector(onCancel)]);
105 [_cancelButton setTitleTextAttributes:@{
106 NSForegroundColorAttributeName : [UIColor lightGrayColor]
107 }
108 forState:UIControlStateDisabled];
109 [self navigationItem].leftBarButtonItem = _cancelButton;
110
111 // Set up right (pay) button.
112 _payButton.reset([[MDCFlatButton alloc] init]);
113 [_payButton
114 setTitle:l10n_util::GetNSString(IDS_IOS_PAYMENT_REQUEST_PAY_BUTTON)
115 forState:UIControlStateNormal];
116 [_payButton setBackgroundColor:[[MDCPalette cr_bluePalette] tint500]
117 forState:UIControlStateNormal];
118 [_payButton setInkColor:[UIColor colorWithWhite:1 alpha:0.2]];
119 [_payButton setBackgroundColor:[UIColor grayColor]
120 forState:UIControlStateDisabled];
121 [_payButton addTarget:nil
122 action:@selector(onConfirm)
123 forControlEvents:UIControlEventTouchUpInside];
124 [_payButton sizeToFit];
125 [_payButton setEnabled:NO];
126 [_payButton setAutoresizingMask:UIViewAutoresizingFlexibleTrailingMargin() |
127 UIViewAutoresizingFlexibleTopMargin |
128 UIViewAutoresizingFlexibleBottomMargin];
129
130 // The navigation bar will set the rightBarButtonItem's height to the full
131 // height of the bar. We don't want that for the button so we use a UIView
132 // here to contain the button instead and the button is vertically centered
133 // inside the full bar height.
134 UIView* buttonView =
135 [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
136 [buttonView addSubview:_payButton];
137 // Navigation bar button items are aligned with the trailing edge of the
138 // screen. Make the enclosing view larger here. The pay button will be
139 // aligned with the leading edge of the enclosing view leaving an inset on
140 // the trailing edge.
141 CGRect buttonViewBounds = buttonView.bounds;
142 buttonViewBounds.size.width =
143 [_payButton frame].size.width + kButtonEdgeInset;
144 buttonView.bounds = buttonViewBounds;
145
146 UIBarButtonItem* payButtonItem =
147 [[[UIBarButtonItem alloc] initWithCustomView:buttonView] autorelease];
148 [self navigationItem].rightBarButtonItem = payButtonItem;
149 }
150 return self;
151 }
152
153 - (id<PaymentRequestViewControllerDelegate>)delegate {
154 return _delegate.get();
155 }
156
157 - (void)setDelegate:(id<PaymentRequestViewControllerDelegate>)delegate {
158 _delegate.reset(delegate);
159 }
160
161 - (void)setSelectedPaymentMethod:(autofill::CreditCard*)method {
162 _selectedPaymentMethod = method;
163 [_payButton setEnabled:(method != nil)];
164 }
165
166 - (void)onCancel {
167 [_cancelButton setEnabled:NO];
168 [_payButton setEnabled:NO];
169
170 [_delegate paymentRequestViewControllerDidCancel];
171 }
172
173 - (void)onConfirm {
174 [_cancelButton setEnabled:NO];
175 [_payButton setEnabled:NO];
176
177 [_delegate paymentRequestViewControllerDidConfirm];
178 }
179
180 #pragma mark - CollectionViewController methods
181
182 - (void)loadModel {
183 [super loadModel];
184 CollectionViewModel* model = self.collectionViewModel;
185
186 // Summary section.
187 [model addSectionWithIdentifier:SectionIdentifierSummary];
188
189 PageInfoItem* pageInfo =
190 [[[PageInfoItem alloc] initWithType:ItemTypeSummaryPageInfo] autorelease];
191 pageInfo.pageFavicon = _pageFavicon;
192 pageInfo.pageTitle = _pageTitle;
193 pageInfo.pageHost = _pageHost;
194 [model setHeader:pageInfo forSectionWithIdentifier:SectionIdentifierSummary];
195
196 CollectionViewDetailItem* total = [[[CollectionViewDetailItem alloc]
197 initWithType:ItemTypeSummaryTotal] autorelease];
198 total.text = l10n_util::GetNSString(IDS_IOS_PAYMENT_REQUEST_TOTAL_HEADER);
199 NSString* currencyCode =
200 base::SysUTF16ToNSString(_paymentRequest.details.total.amount.currency);
201 NSDecimalNumber* value = [NSDecimalNumber
202 decimalNumberWithString:SysUTF16ToNSString(
203 _paymentRequest.details.total.amount.value)];
204 NSNumberFormatter* currencyFormatter =
205 [[[NSNumberFormatter alloc] init] autorelease];
206 [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
207 [currencyFormatter setCurrencyCode:currencyCode];
208 total.detailText = [currencyFormatter stringFromNumber:value];
209 if (!_paymentRequest.details.display_items.empty()) {
210 total.accessoryType = MDCCollectionViewCellAccessoryDisclosureIndicator;
211 total.accessibilityTraits |= UIAccessibilityTraitButton;
212 }
213 [model addItem:total toSectionWithIdentifier:SectionIdentifierSummary];
214
215 // Shipping section.
216 [model addSectionWithIdentifier:SectionIdentifierShipping];
217 CollectionViewTextItem* shippingTitle = [[[CollectionViewTextItem alloc]
218 initWithType:ItemTypeShippingTitle] autorelease];
219 shippingTitle.text =
220 l10n_util::GetNSString(IDS_IOS_PAYMENT_REQUEST_SHIPPING_ADDRESS_HEADER);
221 [model setHeader:shippingTitle
222 forSectionWithIdentifier:SectionIdentifierShipping];
223
224 CollectionViewItem* shippingItem = nil;
225 if (_selectedShippingAddress) {
226 _selectedShippingAddressItem = [[[ShippingAddressItem alloc]
227 initWithType:ItemTypeShippingAddress] autorelease];
228 shippingItem = _selectedShippingAddressItem;
229 [self fillShippingAddressItem:_selectedShippingAddressItem
230 withAddress:_selectedShippingAddress];
231 _selectedShippingAddressItem.accessoryType =
232 MDCCollectionViewCellAccessoryDisclosureIndicator;
233
234 } else {
235 CollectionViewDetailItem* addAddressItem =
236 [[[CollectionViewDetailItem alloc]
237 initWithType:ItemTypeAddShippingAddress] autorelease];
238 shippingItem = addAddressItem;
239 addAddressItem.text = l10n_util::GetNSString(
240 IDS_IOS_PAYMENT_REQUEST_SHIPPING_ADDRESS_SELECTION_TITLE);
241 addAddressItem.detailText = [l10n_util::GetNSString(
242 IDS_IOS_PAYMENT_REQUEST_ADD_SHIPPING_ADDRESS_BUTTON)
243 uppercaseStringWithLocale:[NSLocale currentLocale]];
244 }
245 shippingItem.accessibilityTraits |= UIAccessibilityTraitButton;
246 [model addItem:shippingItem
247 toSectionWithIdentifier:SectionIdentifierShipping];
248
249 // Payment method section.
250 [model addSectionWithIdentifier:SectionIdentifierPayment];
251
252 CollectionViewTextItem* paymentTitle = [[[CollectionViewTextItem alloc]
253 initWithType:ItemTypePaymentTitle] autorelease];
254 paymentTitle.text =
255 l10n_util::GetNSString(IDS_IOS_PAYMENT_REQUEST_PAYMENT_METHOD_HEADER);
256 [model setHeader:paymentTitle
257 forSectionWithIdentifier:SectionIdentifierPayment];
258
259 if (_selectedPaymentMethod) {
260 PaymentMethodItem* paymentMethod = [[[PaymentMethodItem alloc]
261 initWithType:ItemTypePaymentMethod] autorelease];
262
263 paymentMethod.methodID = base::SysUTF16ToNSString(
264 _selectedPaymentMethod->TypeAndLastFourDigits());
265 paymentMethod.methodDetail = base::SysUTF16ToNSString(
266 _selectedPaymentMethod->GetRawInfo(autofill::CREDIT_CARD_NAME_FULL));
267
268 int selectedMethodCardTypeIconID =
269 autofill::data_util::GetPaymentRequestData(
270 _selectedPaymentMethod->type())
271 .icon_resource_id;
272 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
273 paymentMethod.methodTypeIcon =
274 rb.GetNativeImageNamed(selectedMethodCardTypeIconID).ToUIImage();
275
276 paymentMethod.accessoryType =
277 MDCCollectionViewCellAccessoryDisclosureIndicator;
278 paymentMethod.accessibilityTraits |= UIAccessibilityTraitButton;
279 [model addItem:paymentMethod
280 toSectionWithIdentifier:SectionIdentifierPayment];
281 } else {
282 CollectionViewTextItem* paymentMethod = [[[CollectionViewTextItem alloc]
283 initWithType:ItemTypePaymentMethod] autorelease];
284 NSString* selectText =
285 l10n_util::GetNSString(IDS_IOS_PAYMENT_REQUEST_METHOD_SELECTION_BUTTON);
286 paymentMethod.text =
287 [selectText uppercaseStringWithLocale:[NSLocale currentLocale]];
288 paymentMethod.accessibilityTraits |= UIAccessibilityTraitButton;
289 [model addItem:paymentMethod
290 toSectionWithIdentifier:SectionIdentifierPayment];
291 }
292 }
293
294 - (void)viewDidLoad {
295 [super viewDidLoad];
296 self.collectionView.accessibilityIdentifier = kPaymentRequestCollectionViewId;
297
298 // Customize collection view settings.
299 self.styler.cellStyle = MDCCollectionViewCellStyleCard;
300 self.styler.separatorInset =
301 UIEdgeInsetsMake(0, kSeparatorEdgeInset, 0, kSeparatorEdgeInset);
302 }
303
304 - (void)updateSelectedShippingAddress:
305 (autofill::AutofillProfile*)shippingAddress {
306 [self setSelectedShippingAddress:shippingAddress];
307 [self fillShippingAddressItem:_selectedShippingAddressItem
308 withAddress:shippingAddress];
309 NSIndexPath* indexPath =
310 [self.collectionViewModel indexPathForItem:_selectedShippingAddressItem
311 inSectionWithIdentifier:SectionIdentifierShipping];
312 [self.collectionView reloadItemsAtIndexPaths:@[ indexPath ]];
313 }
314
315 #pragma mark - Helper methods
316
317 - (void)fillShippingAddressItem:(ShippingAddressItem*)item
318 withAddress:(autofill::AutofillProfile*)address {
319 item.name =
320 base::SysUTF16ToNSString(address->GetRawInfo(autofill::NAME_FULL));
321 item.address =
322 payment_request_utils::AddressLabelFromAutofillProfile(address);
323 item.phoneNumber = base::SysUTF16ToNSString(
324 address->GetRawInfo(autofill::PHONE_HOME_WHOLE_NUMBER));
325 }
326
327 #pragma mark UICollectionViewDataSource
328 - (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView
329 cellForItemAtIndexPath:(nonnull NSIndexPath*)indexPath {
330 UICollectionViewCell* cell =
331 [super collectionView:collectionView cellForItemAtIndexPath:indexPath];
332
333 NSInteger itemType =
334 [self.collectionViewModel itemTypeForIndexPath:indexPath];
335 switch (itemType) {
336 case ItemTypeAddShippingAddress: {
337 CollectionViewDetailCell* detailCell =
338 base::mac::ObjCCastStrict<CollectionViewDetailCell>(cell);
339 detailCell.detailTextLabel.font =
340 [[MDFRobotoFontLoader sharedInstance] mediumFontOfSize:14];
341 detailCell.detailTextLabel.textColor =
342 [[MDCPalette cr_bluePalette] tint700];
343 break;
344 }
345 default:
346 break;
347 }
348 return cell;
349 }
350
351 #pragma mark UICollectionViewDelegate
352
353 - (void)collectionView:(UICollectionView*)collectionView
354 didSelectItemAtIndexPath:(NSIndexPath*)indexPath {
355 [super collectionView:collectionView didSelectItemAtIndexPath:indexPath];
356
357 NSInteger itemType =
358 [self.collectionViewModel itemTypeForIndexPath:indexPath];
359 switch (itemType) {
360 case ItemTypeSummaryTotal:
361 if (!_paymentRequest.details.display_items.empty())
362 [_delegate paymentRequestViewControllerDisplayPaymentItems];
363 break;
364 case ItemTypeShippingAddress:
365 case ItemTypeAddShippingAddress:
366 [_delegate paymentRequestViewControllerSelectShippingAddress];
367 break;
368 case ItemTypePaymentMethod:
369 [_delegate paymentRequestViewControllerSelectPaymentMethod];
370 break;
371 default:
372 NOTREACHED();
373 break;
374 }
375 }
376
377 #pragma mark MDCCollectionViewStylingDelegate
378
379 - (CGFloat)collectionView:(UICollectionView*)collectionView
380 cellHeightAtIndexPath:(NSIndexPath*)indexPath {
381 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
382 if ((type == ItemTypePaymentMethod && _selectedPaymentMethod) ||
383 (type == ItemTypeShippingAddress)) {
384 CollectionViewItem* item =
385 [self.collectionViewModel itemAtIndexPath:indexPath];
386 return [MDCCollectionViewCell
387 cr_preferredHeightForWidth:CGRectGetWidth(collectionView.bounds)
388 forItem:item];
389 } else {
390 return MDCCellDefaultOneLineHeight;
391 }
392 }
393
394 // If there are no payment items to display, there is no effect from touching
395 // the total so there should not be an ink ripple.
396 - (BOOL)collectionView:(UICollectionView*)collectionView
397 hidesInkViewAtIndexPath:(NSIndexPath*)indexPath {
398 NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath];
399 if (type == ItemTypeSummaryTotal &&
400 _paymentRequest.details.display_items.empty()) {
401 return YES;
402 } else {
403 return NO;
404 }
405 }
406
407 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698