Skip to content

Commit

Permalink
Merge pull request #792 from stripe/bdorfman-custom-footer
Browse files Browse the repository at this point in the history
Add custom footer view support
  • Loading branch information
bdorfman-stripe authored Oct 16, 2017
2 parents c90f6f1 + 3c229f9 commit 59741db
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
C186AC341ECD0DDD00497DE3 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C186AC331ECD0DDD00497DE3 /* Alamofire.framework */; };
C188F2A61CC1A338003A524B /* MyAPIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = C188F2A51CC1A338003A524B /* MyAPIClient.swift */; };
C1B83CBD1CCE6C0700F0790B /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1B83CBC1CCE6C0700F0790B /* Buttons.swift */; };
F1D12FE71F91721600CE68A7 /* PaymentContextFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1D12FE61F91721600CE68A7 /* PaymentContextFooterView.swift */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand Down Expand Up @@ -58,6 +59,7 @@
C188F2A51CC1A338003A524B /* MyAPIClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MyAPIClient.swift; sourceTree = "<group>"; };
C18A6EE11F1EB78B005600CC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = "Standard Integration (Swift)/README.md"; sourceTree = "<group>"; };
C1B83CBC1CCE6C0700F0790B /* Buttons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Buttons.swift; sourceTree = "<group>"; };
F1D12FE61F91721600CE68A7 /* PaymentContextFooterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PaymentContextFooterView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -83,6 +85,7 @@
04BC299F1CD81D3900318357 /* BrowseProductsViewController.swift */,
C124A18C1CCACC92007D42EE /* CheckoutRowView.swift */,
C1B83CBC1CCE6C0700F0790B /* Buttons.swift */,
F1D12FE61F91721600CE68A7 /* PaymentContextFooterView.swift */,
042CA4191A685E8D00D778E7 /* Images.xcassets */,
042CA41A1A685E8D00D778E7 /* Info.plist */,
04D075D91A69B82B00094431 /* Standard Integration (Swift).entitlements */,
Expand Down Expand Up @@ -264,6 +267,7 @@
C1B83CBD1CCE6C0700F0790B /* Buttons.swift in Sources */,
C124A18D1CCACC92007D42EE /* CheckoutRowView.swift in Sources */,
042CA41D1A685E8D00D778E7 /* AppDelegate.swift in Sources */,
F1D12FE71F91721600CE68A7 /* PaymentContextFooterView.swift in Sources */,
C13C24221D14438700F3765E /* SettingsViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,15 @@ class CheckoutViewController: UIViewController, STPPaymentContextDelegate {
paymentContext.prefilledInformation = userInformation
paymentContext.paymentAmount = price
paymentContext.paymentCurrency = self.paymentCurrency

let paymentSelectionFooter = PaymentContextFooterView(text: "You can add custom footer views to the payment selection screen.")
paymentSelectionFooter.theme = settings.theme
paymentContext.paymentMethodsViewControllerFooterView = paymentSelectionFooter

let addCardFooter = PaymentContextFooterView(text: "You can add custom footer views to the add card screen.")
addCardFooter.theme = settings.theme
paymentContext.addCardViewControllerFooterView = addCardFooter

self.paymentContext = paymentContext

self.paymentRow = CheckoutRowView(title: "Payment", detail: "Select Payment",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
//
// PaymentContextFooterView.swift
// Standard Integration (Swift)
//
// Created by Brian Dorfman on 10/13/17.
// Copyright © 2017 Stripe. All rights reserved.
//

import UIKit
import Stripe

class PaymentContextFooterView: UIView {

var insetMargins: UIEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10)

var text: String = "" {
didSet {
textLabel.text = text
}
}

var theme: STPTheme = STPTheme.default() {
didSet {
textLabel.font = theme.smallFont
textLabel.textColor = theme.secondaryForegroundColor
}
}

fileprivate let textLabel = UILabel()

convenience init(text: String) {
self.init()
textLabel.numberOfLines = 0
textLabel.textAlignment = .center
self.addSubview(textLabel)

self.text = text
textLabel.text = text

}

override func layoutSubviews() {
textLabel.frame = UIEdgeInsetsInsetRect(self.bounds, insetMargins)
}

override func sizeThatFits(_ size: CGSize) -> CGSize {
// Add 10 pt border on all sides
var insetSize = size
insetSize.width -= (insetMargins.left + insetMargins.right)
insetSize.height -= (insetMargins.top + insetMargins.bottom)

var newSize = textLabel.sizeThatFits(insetSize)

newSize.width += (insetMargins.left + insetMargins.right)
newSize.height += (insetMargins.top + insetMargins.bottom)

return newSize
}


}
9 changes: 9 additions & 0 deletions Stripe/PublicHeaders/STPAddCardViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, copy, nullable) NSString *managedAccountCurrency;

/**
Provide this view controller with a footer view.
When the footer view needs to be resized, it will be sent a
`sizeThatFits:` call. The view should respond correctly to this method in order
to be sized and positioned properly.
*/
@property (nonatomic, strong, nullable) UIView *customFooterView;

@end

/**
Expand Down
20 changes: 19 additions & 1 deletion Stripe/PublicHeaders/STPPaymentContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,25 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, assign) UIModalPresentationStyle modalPresentationStyle;

/**
A view that will be placed as the footer of the payment methods selection
view controller.
When the footer view needs to be resized, it will be sent a
`sizeThatFits:` call. The view should respond correctly to this method in order
to be sized and positioned properly.
*/
@property (nonatomic, strong) UIView *paymentMethodsViewControllerFooterView;

/**
A view that will be placed as the footer of the add card view controller.
When the footer view needs to be resized, it will be sent a
`sizeThatFits:` call. The view should respond correctly to this method in order
to be sized and positioned properly.
*/
@property (nonatomic, strong) UIView *addCardViewControllerFooterView;

/**
If `paymentContext:didFailToLoadWithError:` is called on your delegate, you
can in turn call this method to try loading again (if that hasn't been called,
Expand Down Expand Up @@ -288,7 +307,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)requestPayment;


@end

/**
Expand Down
21 changes: 20 additions & 1 deletion Stripe/PublicHeaders/STPPaymentMethodsViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface STPPaymentMethodsViewController : STPCoreViewController


/**
The delegate for the view controller.
Expand Down Expand Up @@ -103,6 +102,26 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, strong, nullable) STPUserInformation *prefilledInformation;

/**
A view that will be placed as the footer of the view controller when it is
showing a list of saved payment methods to select from.
When the footer view needs to be resized, it will be sent a
`sizeThatFits:` call. The view should respond correctly to this method in order
to be sized and positioned properly.
*/
@property (nonatomic, strong) UIView *paymentMethodsViewControllerFooterView;

/**
A view that will be placed as the footer of the view controller when it is
showing the add card view.
When the footer view needs to be resized, it will be sent a
`sizeThatFits:` call. The view should respond correctly to this method in order
to be sized and positioned properly.
*/
@property (nonatomic, strong) UIView *addCardViewControllerFooterView;

/**
If you're pushing `STPPaymentMethodsViewController` onto an existing
`UINavigationController`'s stack, you should use this method to dismiss it,
Expand Down
22 changes: 22 additions & 0 deletions Stripe/STPAddCardViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#import "STPPaymentConfiguration+Private.h"
#import "STPPhoneNumberValidator.h"
#import "STPPaymentCardTextFieldCell.h"
#import "STPPromise.h"
#import "STPSectionHeaderView.h"
#import "STPToken.h"
#import "STPWeakStrongMacros.h"
Expand Down Expand Up @@ -162,6 +163,17 @@ - (void)createAndSetupViews {
[[STPAnalyticsClient sharedClient] clearAdditionalInfo];
}

- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];

// Resetting it re-calculates the size based on new view width
// UITableView requires us to call setter again to actually pick up frame
// change on footers
if (self.tableView.tableFooterView) {
self.customFooterView = self.tableView.tableFooterView;
}
}

- (void)setUpCardScanningIfAvailable {
if ([STPCardIOProxy isCardIOAvailable]) {
self.cardIOProxy = [[STPCardIOProxy alloc] initWithDelegate:self];
Expand Down Expand Up @@ -301,6 +313,16 @@ - (void)updateDoneButton {
);
}

- (void)setCustomFooterView:(UIView *)footerView {
_customFooterView = footerView;
[self.stp_willAppearPromise voidOnSuccess:^{
CGSize size = [footerView sizeThatFits:CGSizeMake(self.view.bounds.size.width, CGFLOAT_MAX)];
footerView.frame = CGRectMake(0, 0, size.width, size.height);

self.tableView.tableFooterView = footerView;
}];
}

#pragma mark - STPPaymentCardTextField

- (void)paymentCardTextFieldDidChange:(STPPaymentCardTextField *)textField {
Expand Down
6 changes: 6 additions & 0 deletions Stripe/STPPaymentContext.m
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ - (void)presentPaymentMethodsViewControllerWithNewState:(STPPaymentContextState)
STPPaymentMethodsViewController *paymentMethodsViewController = [[STPPaymentMethodsViewController alloc] initWithPaymentContext:self];
self.paymentMethodsViewController = paymentMethodsViewController;
paymentMethodsViewController.prefilledInformation = self.prefilledInformation;
paymentMethodsViewController.paymentMethodsViewControllerFooterView = self.paymentMethodsViewControllerFooterView;
paymentMethodsViewController.addCardViewControllerFooterView = self.addCardViewControllerFooterView;

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:paymentMethodsViewController];
navigationController.navigationBar.stp_theme = self.theme;
navigationController.modalPresentationStyle = self.modalPresentationStyle;
Expand All @@ -322,6 +325,9 @@ - (void)pushPaymentMethodsViewController {
STPPaymentMethodsViewController *paymentMethodsViewController = [[STPPaymentMethodsViewController alloc] initWithPaymentContext:self];
self.paymentMethodsViewController = paymentMethodsViewController;
paymentMethodsViewController.prefilledInformation = self.prefilledInformation;
paymentMethodsViewController.paymentMethodsViewControllerFooterView = self.paymentMethodsViewControllerFooterView;
paymentMethodsViewController.addCardViewControllerFooterView = self.addCardViewControllerFooterView;

[navigationController pushViewController:paymentMethodsViewController animated:YES];
}
}];
Expand Down
3 changes: 3 additions & 0 deletions Stripe/STPPaymentMethodsInternalViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ NS_ASSUME_NONNULL_BEGIN

- (void)updateWithPaymentMethodTuple:(STPPaymentMethodTuple *)tuple;

@property (nonatomic, strong, nullable) UIView *customFooterView;


@end

NS_ASSUME_NONNULL_END
23 changes: 23 additions & 0 deletions Stripe/STPPaymentMethodsInternalViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
#import "STPLocalizationUtils.h"
#import "STPPaymentMethodTableViewCell.h"
#import "STPPaymentMethodTuple.h"
#import "STPPromise.h"
#import "STPSourceProtocol.h"
#import "UITableViewCell+Stripe_Borders.h"
#import "UIViewController+Stripe_NavigationItemProxy.h"
#import "UIViewController+Stripe_Promises.h"

static NSString * const PaymentMethodCellReuseIdentifier = @"PaymentMethodCellReuseIdentifier";

Expand Down Expand Up @@ -91,6 +93,17 @@ - (void)createAndSetupViews {
[self reloadRightBarButtonItemWithTableViewIsEditing:self.tableView.isEditing animated:NO];
}

- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];

// Resetting it re-calculates the size based on new view width
// UITableView requires us to call setter again to actually pick up frame
// change on footers
if (self.tableView.tableFooterView) {
self.customFooterView = self.tableView.tableFooterView;
}
}

- (void)reloadRightBarButtonItemWithTableViewIsEditing:(BOOL)tableViewIsEditing animated:(BOOL)animated {
UIBarButtonItem *barButtonItem;

Expand Down Expand Up @@ -166,6 +179,16 @@ - (void)updateWithPaymentMethodTuple:(STPPaymentMethodTuple *)tuple {
[self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationAutomatic];
}

- (void)setCustomFooterView:(UIView *)footerView {
_customFooterView = footerView;
[self.stp_willAppearPromise voidOnSuccess:^{
CGSize size = [footerView sizeThatFits:CGSizeMake(self.view.bounds.size.width, CGFLOAT_MAX)];
footerView.frame = CGRectMake(0, 0, size.width, size.height);

self.tableView.tableFooterView = footerView;
}];
}

#pragma mark - Button Handlers

- (void)handleCancelTapped:(__unused id)sender {
Expand Down
28 changes: 19 additions & 9 deletions Stripe/STPPaymentMethodsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,31 @@ - (void)createAndSetupViews {
if (tuple.paymentMethods.count > 0) {
STPCustomerContext *customerContext = ([self.apiAdapter isKindOfClass:[STPCustomerContext class]]) ? (STPCustomerContext *)self.apiAdapter : nil;

internal = [[STPPaymentMethodsInternalViewController alloc] initWithConfiguration:self.configuration
customerContext:customerContext
theme:self.theme
prefilledInformation:self.prefilledInformation
shippingAddress:self.shippingAddress
paymentMethodTuple:tuple
delegate:self];
} else {
STPPaymentMethodsInternalViewController *payMethodsInternal = [[STPPaymentMethodsInternalViewController alloc] initWithConfiguration:self.configuration
customerContext:customerContext
theme:self.theme
prefilledInformation:self.prefilledInformation
shippingAddress:self.shippingAddress
paymentMethodTuple:tuple
delegate:self];
if (self.paymentMethodsViewControllerFooterView) {
payMethodsInternal.customFooterView = self.paymentMethodsViewControllerFooterView;
}
internal = payMethodsInternal;
}
else {
STPAddCardViewController *addCardViewController = [[STPAddCardViewController alloc] initWithConfiguration:self.configuration theme:self.theme];
addCardViewController.delegate = self;
addCardViewController.prefilledInformation = self.prefilledInformation;
addCardViewController.shippingAddress = self.shippingAddress;
internal = addCardViewController;


if (self.addCardViewControllerFooterView) {
addCardViewController.customFooterView = self.addCardViewControllerFooterView;

}
}

internal.stp_navigationItemProxy = self.navigationItem;
[self addChildViewController:internal];
internal.view.alpha = 0;
Expand Down

0 comments on commit 59741db

Please sign in to comment.