Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply Subito customizations to version 9.12.2 #8

Merged
merged 7 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions BraintreeDropIn.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
425B83982347D3990015D1A4 /* BTUIKAppearanceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 425B83972347D3990015D1A4 /* BTUIKAppearanceTests.swift */; };
42D53E782614DA3600D19615 /* BTUIKCardholderNameFormFieldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42D53E772614DA3600D19615 /* BTUIKCardholderNameFormFieldTests.swift */; };
42EA70662616682800B7E626 /* BTDropInResult_Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 42EA70652616682800B7E626 /* BTDropInResult_Internal.h */; };
4C2901B02743FC0700505D46 /* SBTAddCardButtonFormField.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C2901AF2743FC0700505D46 /* SBTAddCardButtonFormField.h */; settings = {ATTRIBUTES = (Private, ); }; };
4C2901B22743FC1B00505D46 /* SBTAddCardButtonFormField.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C2901B12743FC1B00505D46 /* SBTAddCardButtonFormField.m */; };
8005E86125BB32A6003EC2AC /* MockVenmoDriver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8005E86025BB32A6003EC2AC /* MockVenmoDriver.swift */; };
8005E86625BB34B5003EC2AC /* MockAPIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8005E86525BB34B5003EC2AC /* MockAPIClient.swift */; };
8038FA13269789ED007BE751 /* MockPPDataCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8038FA12269789ED007BE751 /* MockPPDataCollector.swift */; };
Expand Down Expand Up @@ -234,6 +236,8 @@
42A10AD8230EE4D600892302 /* UnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnitTests-Bridging-Header.h"; sourceTree = "<group>"; };
42D53E772614DA3600D19615 /* BTUIKCardholderNameFormFieldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BTUIKCardholderNameFormFieldTests.swift; sourceTree = "<group>"; };
42EA70652616682800B7E626 /* BTDropInResult_Internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BTDropInResult_Internal.h; sourceTree = "<group>"; };
4C2901AF2743FC0700505D46 /* SBTAddCardButtonFormField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBTAddCardButtonFormField.h; sourceTree = "<group>"; };
4C2901B12743FC1B00505D46 /* SBTAddCardButtonFormField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBTAddCardButtonFormField.m; sourceTree = "<group>"; };
53E78BDC22248A29000388D3 /* BTUIKHipercardVectorArtView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTUIKHipercardVectorArtView.h; sourceTree = "<group>"; };
53E78BDF22248A29000388D3 /* BTUIKHipercardVectorArtView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BTUIKHipercardVectorArtView.m; sourceTree = "<group>"; };
53E78BE422248BC3000388D3 /* BTUIKLargeHiperVectorArtView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BTUIKLargeHiperVectorArtView.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -486,6 +490,8 @@
D6C2F3332239917F00DFF7E5 /* BTUIKSwitchFormField.m */,
A52901161D8903A600032220 /* BTUIKTextField.h */,
A52900E11D8903A600032220 /* BTUIKTextField.m */,
4C2901AF2743FC0700505D46 /* SBTAddCardButtonFormField.h */,
4C2901B12743FC1B00505D46 /* SBTAddCardButtonFormField.m */,
);
path = Components;
sourceTree = "<group>";
Expand Down Expand Up @@ -733,6 +739,7 @@
buildActionMask = 2147483647;
files = (
4234907A260BA5800006D38B /* BTUIKInputAccessoryToolbar.h in Headers */,
4C2901B02743FC0700505D46 /* SBTAddCardButtonFormField.h in Headers */,
42349098260BA6000006D38B /* BTDropInLocalization.h in Headers */,
42349062260BA5800006D38B /* BTUIKSecurityCodeFormField.h in Headers */,
8068E589256D9C68002904E6 /* BTUIKBarButtonItem_Internal_Declaration.h in Headers */,
Expand Down Expand Up @@ -1031,6 +1038,7 @@
80BBF006260BC77E005D646D /* BTUIKJCBVectorArtView.m in Sources */,
A56C41901D833568000DFFAB /* BTDropInController.m in Sources */,
80BBEFAF260BC75C005D646D /* BTUIKLargeVisaVectorArtView.m in Sources */,
4C2901B22743FC1B00505D46 /* SBTAddCardButtonFormField.m in Sources */,
A56C41A21D8335BB000DFFAB /* BTEnrollmentVerificationViewController.m in Sources */,
4234905E260BA5800006D38B /* BTUIKPostalCodeFormField.m in Sources */,
42349006260BA3730006D38B /* BTUIKCardExpiryFormat.m in Sources */,
Expand Down
3 changes: 2 additions & 1 deletion Demo/UITests/BraintreeDropIn_UITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ class BraintreeDropIn_CardholderNameRequired_UITests: XCTestCase {
postalCodeField.forceTapElement()
postalCodeField.typeText("12345")

XCTAssertFalse(app.buttons["Add Card"].isEnabled)
app.buttons["Add Card"].forceTapElement()
waitForElementToBeHittable(app.staticTexts["Attenzione"])
}

func testDropIn_cardholderNameRequired_canAddCardWithName() {
Expand Down
62 changes: 38 additions & 24 deletions Sources/BraintreeDropIn/BTCardFormViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#import "BTUIKCardListLabel.h"
#import "BTUIKViewUtil.h"
#import "BTDropInLocalization_Internal.h"
#import "SBTAddCardButtonFormField.h"

#if __has_include(<Braintree/BraintreeCore.h>) // CocoaPods
#import <Braintree/BraintreeCard.h>
Expand All @@ -24,11 +25,12 @@
#import <BraintreeUnionPay/BraintreeUnionPay.h>
#endif

@interface BTCardFormViewController ()
@interface BTCardFormViewController () <SBTAddCardButtonFormFieldDelegate>

@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIView *scrollViewContentWrapper;
@property (nonatomic, strong) UIStackView *stackView;
@property (nonatomic, strong) SBTAddCardButtonFormField *addCardField;
@property (nonatomic, strong, readwrite) BTUIKCardNumberFormField *cardNumberField;
@property (nonatomic, strong, readwrite) BTUIKCardholderNameFormField *cardholderNameField;
@property (nonatomic, strong, readwrite) BTUIKExpiryFormField *expirationDateField;
Expand Down Expand Up @@ -186,6 +188,8 @@ - (void)setupForm {
self.mobileCountryCodeField.delegate = self;
self.mobilePhoneField = [[BTUIKMobileNumberFormField alloc] init];
self.mobilePhoneField.delegate = self;
self.addCardField = [[SBTAddCardButtonFormField alloc] init];
self.addCardField.delegate = self;

self.cardNumberHeader = [BTDropInUIUtilities newStackView];
self.cardNumberHeader.layoutMargins = UIEdgeInsetsMake(0, [BTUIKAppearance verticalFormSpace], 0, [BTUIKAppearance verticalFormSpace]);
Expand All @@ -199,7 +203,7 @@ - (void)setupForm {
[BTDropInUIUtilities addSpacerToStackView:self.cardNumberHeader beforeView:cardNumberHeaderLabel size: [BTUIKAppearance verticalFormSpace]];
[self.stackView addArrangedSubview:self.cardNumberHeader];

self.formFields = @[self.cardNumberField, self.cardholderNameField, self.expirationDateField, self.securityCodeField, self.postalCodeField, self.mobileCountryCodeField, self.mobilePhoneField];
self.formFields = @[self.cardNumberField, self.cardholderNameField, self.expirationDateField, self.securityCodeField, self.postalCodeField, self.mobileCountryCodeField, self.mobilePhoneField, self.addCardField];

for (BTUIKFormField *formField in self.formFields) {
[self.stackView addArrangedSubview:formField];
Expand All @@ -213,6 +217,7 @@ - (void)setupForm {
self.postalCodeField.hidden = YES;
self.mobileCountryCodeField.hidden = YES;
self.mobilePhoneField.hidden = YES;
self.addCardField.hidden = YES;

// Privacy Policy label
UILabel *privacyPolicyLabel = [[UILabel alloc] init];
Expand All @@ -230,6 +235,9 @@ - (void)setupForm {
[BTDropInUIUtilities addSpacerToStackView:self.stackView beforeView:self.cardholderNameField size: [BTUIKAppearance verticalFormSpace]];
[BTDropInUIUtilities addSpacerToStackView:self.stackView beforeView:self.mobileCountryCodeField size: [BTUIKAppearance verticalFormSpace]];

// Spacing between add card field and privacy policy label
[self.stackView setCustomSpacing:[BTUIKAppearance verticalFormSpaceTight] afterView:self.addCardField];

self.cardNumberFooter = [BTDropInUIUtilities newStackView];
self.cardNumberFooter.layoutMargins = UIEdgeInsetsMake(0, [BTUIKAppearance verticalFormSpace], 0, [BTUIKAppearance verticalFormSpace]);
self.cardNumberFooter.layoutMarginsRelativeArrangement = true;
Expand Down Expand Up @@ -348,6 +356,7 @@ - (void)setCollapsed:(BOOL)collapsed {
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.15 delay:0.0 options:UIViewAnimationOptionAllowAnimatedContent|UIViewAnimationOptionBeginFromCurrentState animations:^{
self.cardNumberHeader.hidden = !collapsed;
self.cardNumberFooter.hidden = !collapsed;
self.cardholderNameField.hidden = (self.dropInRequest.cardholderNameSetting == BTFormFieldDisabled) || collapsed;
self.expirationDateField.hidden = collapsed;
self.securityCodeField.hidden = ![self.requiredFields containsObject:self.securityCodeField] || collapsed;
Expand All @@ -356,6 +365,7 @@ - (void)setCollapsed:(BOOL)collapsed {
self.mobilePhoneField.hidden = ![self.requiredFields containsObject:self.mobilePhoneField] || collapsed;
self.enrollmentFooter.hidden = self.mobilePhoneField.hidden;
self.shouldVaultCardSwitchField.hidden = ![self shouldDisplaySaveCardToggle] || collapsed;
self.addCardField.hidden = self.collapsed;
[self updateFormBorders];
} completion:^(__unused BOOL finished) {
self.cardNumberFooter.hidden = !collapsed;
Expand All @@ -368,9 +378,9 @@ - (void)setCollapsed:(BOOL)collapsed {
self.mobilePhoneField.hidden = ![self.requiredFields containsObject:self.mobilePhoneField] || collapsed;
self.enrollmentFooter.hidden = self.mobilePhoneField.hidden;
self.shouldVaultCardSwitchField.hidden = ![self shouldDisplaySaveCardToggle] || collapsed;
self.addCardField.hidden = self.collapsed;

[self updateFormBorders];
[self updateSubmitButton];
}];
});
}
Expand All @@ -383,15 +393,11 @@ - (BOOL)shouldDisplaySaveCardToggle {

- (void)resetForm {
self.navigationItem.leftBarButtonItem = [[BTUIKBarButtonItem alloc] initWithTitle:BTDropInLocalizedString(CANCEL_ACTION) style:UIBarButtonItemStylePlain target:self action:@selector(cancelTapped)];
BTUIKBarButtonItem *addButton = [[BTUIKBarButtonItem alloc] initWithTitle:BTDropInLocalizedString(ADD_CARD_ACTION) style:UIBarButtonItemStylePlain target:self action:@selector(tokenizeCard)];
addButton.bold = YES;
self.navigationItem.rightBarButtonItem = addButton;

self.navigationItem.rightBarButtonItem.enabled = NO;
self.navigationItem.rightBarButtonItem.accessibilityHint = BTDropInLocalizedString(REVIEW_AND_TRY_AGAIN);

for (BTUIKFormField *formField in self.formFields) {
formField.text = @"";
if ([formField respondsToSelector:@selector(setText:)]) {
formField.text = @"";
}
formField.hidden = YES;
}
// Using ivar so that setter is not called
Expand Down Expand Up @@ -478,16 +484,6 @@ - (BOOL)isFormValid {
return isFormValid;
}

- (void)updateSubmitButton {
if (!self.collapsed && [self isFormValid]) {
self.navigationItem.rightBarButtonItem.enabled = YES;
self.navigationItem.rightBarButtonItem.accessibilityHint = nil;
} else {
self.navigationItem.rightBarButtonItem.enabled = NO;
self.navigationItem.rightBarButtonItem.accessibilityHint = BTDropInLocalizedString(REVIEW_AND_TRY_AGAIN);
}
}

- (void)advanceFocusFromField:(BTUIKFormField *)currentField {
NSUInteger currentIdx = [self.requiredFields indexOfObject:currentField];
if (currentIdx != NSNotFound && currentIdx < self.requiredFields.count - 1) {
Expand Down Expand Up @@ -588,9 +584,9 @@ - (void)basicTokenization {
spinner.activityIndicatorViewStyle = [BTUIKAppearance sharedInstance].activityIndicatorViewStyle;
[spinner startAnimating];

UIBarButtonItem *addCardButton = self.navigationItem.rightBarButtonItem;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];
self.view.userInteractionEnabled = NO;
[self.addCardField setEnabled:NO];
__block UINavigationController *navController = self.navigationController;

#pragma clang diagnostic push
Expand All @@ -600,8 +596,9 @@ - (void)basicTokenization {
#pragma clang diagnostic pop
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
[self.addCardField setEnabled:YES];

self.navigationItem.rightBarButtonItem = addCardButton;
self.navigationItem.rightBarButtonItem = nil;

if (error != nil) {
NSString *message = BTDropInLocalizedString(REVIEW_AND_TRY_AGAIN);
Expand Down Expand Up @@ -634,6 +631,7 @@ - (void)enrollCard {

currentViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];
self.view.userInteractionEnabled = NO;
[self.addCardField setEnabled:NO];
});

[cardClient enrollCard:cardRequest completion:^(NSString * _Nullable enrollmentID, BOOL smsCodeRequired, NSError * _Nullable error) {
Expand Down Expand Up @@ -684,6 +682,7 @@ - (void)enrollCard {

enrollmentController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];
self.view.userInteractionEnabled = NO;
[self.addCardField setEnabled:NO];
});

#pragma clang diagnostic push
Expand All @@ -695,6 +694,7 @@ - (void)enrollCard {
#pragma clang diagnostic pop
dispatch_async(dispatch_get_main_queue(), ^{
self.view.userInteractionEnabled = YES;
[self.addCardField setEnabled:YES];
enrollmentController.navigationItem.rightBarButtonItem = originalRightBarButtonItem;
if (error) {
[enrollmentController smsErrorHidden:NO];
Expand Down Expand Up @@ -770,8 +770,6 @@ - (void)formFieldDidBeginEditing:(__unused BTUIKFormField *)formField {
}

- (void)formFieldDidChange:(BTUIKFormField *)formField {
[self updateSubmitButton];

// When focus moves from card number field, display the error state if the value in the field is invalid
if (formField == self.cardNumberField && self.cardNumberField.state == BTUIKCardNumberFormFieldStateDefault) {
[self cardNumberErrorHidden:self.cardNumberField.displayAsValid];
Expand Down Expand Up @@ -823,4 +821,20 @@ - (BOOL)textFieldShouldReturn:(__unused UITextField *)textField {
return YES;
}

#pragma mark SBTAddCardButtonFormFieldDelegate

- (void)addCardFieldTapped:(SBTAddCardButtonFormField __unused *)field {
if ([self isFormValid]) {
[self tokenizeCard];
} else {
NSString *alertTitle = @"Attenzione";
NSString *alertMessage = @"Controlla di aver compilato tutti i campi correttamente";
UIAlertAction *alertAction = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:alertTitle message:alertMessage preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:alertAction];

[self presentViewController:alertController animated:YES completion:nil];
}
}

@end
2 changes: 1 addition & 1 deletion Sources/BraintreeDropIn/BTPaymentMethodNonce+DropIn.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ - (NSString *)paymentDescription {
- (BOOL)shouldDisplayVaultedNonceForRequest:(BTDropInRequest *)request config:(BTConfiguration *)configuration {
if ([self isKindOfClass:BTCardNonce.class] && (request.cardDisabled || configuration.supportedCardTypes.count == 0)) {
return NO;
} else if ([self isKindOfClass:BTPayPalAccountNonce.class] && (request.paypalDisabled || !configuration.isPayPalEnabled)) {
} else if ([self isKindOfClass:BTPayPalAccountNonce.class] && (request.paypalDisabled || request.vaultedPaypalAccountsDisabled || !configuration.isPayPalEnabled)) {
return NO;
} else if ([self isKindOfClass:BTVenmoAccountNonce.class] && (request.venmoDisabled || !configuration.isVenmoEnabled)) {
return NO;
Expand Down
22 changes: 22 additions & 0 deletions Sources/BraintreeDropIn/Components/SBTAddCardButtonFormField.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright © 2019 Subito.it. All rights reserved.

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@class SBTAddCardButtonFormField;

@protocol SBTAddCardButtonFormFieldDelegate <NSObject>

- (void)addCardFieldTapped:(SBTAddCardButtonFormField *)field;

@end

@interface SBTAddCardButtonFormField : UIView

@property (nonatomic, weak) id<SBTAddCardButtonFormFieldDelegate> delegate;
@property (nonatomic, assign, getter=isEnabled) BOOL enabled;

@end

NS_ASSUME_NONNULL_END
82 changes: 82 additions & 0 deletions Sources/BraintreeDropIn/Components/SBTAddCardButtonFormField.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright © 2019 Subito.it. All rights reserved.

#import "SBTAddCardButtonFormField.h"
#import "BTDropInLocalization_Internal.h"
#import "BTUIKAppearance.h"

@interface UIImage (Color)

+ (UIImage *)sbt_resizableImageWithColor:(UIColor *)color cornerRadius:(CGFloat)radius;

@end

@implementation UIImage (Color)

+ (UIImage *)sbt_resizableImageWithColor:(UIColor *)color cornerRadius:(CGFloat)radius {
CGSize size = CGSizeMake((radius * 2.0) + 1.0, (radius * 2.0) + 1.0);
CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height);

UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:size];
UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext *context) {
CGContextRef contextRef = context.CGContext;
CGContextSetFillColorWithColor(contextRef, color.CGColor);
CGContextAddPath(contextRef, [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius].CGPath);
CGContextFillPath(contextRef);
}];

UIEdgeInsets capInsets = UIEdgeInsetsMake(radius, radius, radius, radius);
return [image resizableImageWithCapInsets:capInsets];
}

@end

@interface SBTAddCardButtonFormField ()

@property (nonatomic, strong) UIButton *addButton;

@end

@implementation SBTAddCardButtonFormField

- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
UIImage *normalImage = [UIImage sbt_resizableImageWithColor:BTUIKAppearance.sharedInstance.tintColor cornerRadius:4.0];
UIImage *disabledImage = [UIImage sbt_resizableImageWithColor:BTUIKAppearance.sharedInstance.disabledColor cornerRadius:4.0];
UIImage *highlightedImage = [UIImage sbt_resizableImageWithColor:BTUIKAppearance.sharedInstance.highlightedTintColor cornerRadius:4.0];

_addButton = [UIButton new];
_addButton.translatesAutoresizingMaskIntoConstraints = NO;
_addButton.titleLabel.font = [BTUIKAppearance.sharedInstance.headlineFont fontWithSize:UIFont.labelFontSize];
[_addButton setBackgroundImage:normalImage forState:UIControlStateNormal];
[_addButton setBackgroundImage:disabledImage forState:UIControlStateDisabled];
[_addButton setBackgroundImage:highlightedImage forState:UIControlStateHighlighted];
[_addButton setTitle:BTDropInLocalizedString(ADD_CARD_ACTION) forState:UIControlStateNormal];
[_addButton addTarget:self action:@selector(tapped) forControlEvents:UIControlEventTouchUpInside];

[self addSubview:_addButton];

NSLayoutConstraint *heightConstraint = [_addButton.heightAnchor constraintEqualToConstant:44.0];
heightConstraint.priority = UILayoutPriorityDefaultHigh;

[NSLayoutConstraint activateConstraints:@[
heightConstraint,
[_addButton.topAnchor constraintEqualToAnchor:self.topAnchor],
[_addButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[_addButton.leadingAnchor constraintEqualToAnchor:self.layoutMarginsGuide.leadingAnchor],
[_addButton.trailingAnchor constraintEqualToAnchor:self.layoutMarginsGuide.trailingAnchor]
]];
}
return self;
}

- (void)setEnabled:(BOOL)enabled {
_enabled = enabled;
[self.addButton setEnabled:enabled];
}

- (void)tapped {
[self.delegate addCardFieldTapped:self];
}

@end

Loading
Loading