Skip to content

Commit

Permalink
Merge pull request #476 from gini/IPC-231-Show-all-payment-providers
Browse files Browse the repository at this point in the history
feat(GiniHealthSDK): Present all payment providers IPC-231
  • Loading branch information
razvancapra authored Apr 26, 2024
2 parents ebb57dc + 0a0f39d commit 187e4a9
Show file tree
Hide file tree
Showing 22 changed files with 437 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,6 @@ extension String {
func toColor() -> UIColor? {
return UIColor(hex: String.rgbaHexFrom(rgbHex: self))
}

func canOpenURLString() -> Bool {
if let url = URL(string: self) {
if UIApplication.shared.canOpenURL(url) {
return true
}
}
return false
}
}

public extension String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,15 @@ class BankSelectionTableViewCell: UITableViewCell {
selectedBorderColor: cellViewModel.selectedBankBorderColor,
notSelectedBorderColor: cellViewModel.notSelectedBankBorderColor)

appStoreImageView.isHidden = !cellViewModel.shouldShowAppStoreIcon
selectionIndicatorImageView.image = cellViewModel.selectionIndicatorImage
selectionIndicatorImageView.isHidden = !cellViewModel.shouldShowSelectionIcon

appStoreBankNameSpacingConstraint.priority = !cellViewModel.shouldShowAppStoreIcon ? .required - 1 : .required
selectionIndicatorBankNameSpacingConstraint.priority = !cellViewModel.shouldShowSelectionIcon ? .required - 1 : .required
}
}

@IBOutlet private weak var cellView: UIView!
@IBOutlet private weak var bankImageView: UIImageView!
@IBOutlet private weak var bankNameLabel: UILabel!
@IBOutlet private weak var appStoreImageView: UIImageView!
@IBOutlet private weak var selectionIndicatorImageView: UIImageView!
@IBOutlet private weak var appStoreBankNameSpacingConstraint: NSLayoutConstraint!
@IBOutlet private weak var selectionIndicatorBankNameSpacingConstraint: NSLayoutConstraint!

override func awakeFromNib() {
super.awakeFromNib()
Expand All @@ -58,12 +51,6 @@ class BankSelectionTableViewCell: UITableViewCell {
cellView.layer.borderWidth = Constants.notSelectedBorderWidth
}
}

override func prepareForReuse() {
super.prepareForReuse()
appStoreBankNameSpacingConstraint.priority = .required - 1
selectionIndicatorBankNameSpacingConstraint.priority = .required - 1
}
}

extension BankSelectionTableViewCell {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,9 @@ import GiniHealthAPILibrary
final class BankSelectionTableViewCellModel {

private var isSelected: Bool = false
private var isPaymentProviderInstalled = false

var shouldShowAppStoreIcon: Bool {
!isPaymentProviderInstalled
}
var shouldShowSelectionIcon: Bool {
isPaymentProviderInstalled && isSelected
isSelected
}

let backgroundColor: UIColor = GiniColor(lightModeColor: UIColor.GiniHealthColors.dark7,
Expand Down Expand Up @@ -47,7 +43,6 @@ final class BankSelectionTableViewCellModel {

init(paymentProvider: PaymentProviderAdditionalInfo) {
self.isSelected = paymentProvider.isSelected
self.isPaymentProviderInstalled = paymentProvider.isInstalled
self.bankImageIconData = paymentProvider.paymentProvider.iconData
self.bankName = paymentProvider.paymentProvider.name

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ class BanksBottomView: UIView {
setupViewHierarchy()
setupViewAttributes()
setupLayout()
setupListeners()
}

private func setupViewHierarchy() {
Expand Down Expand Up @@ -126,18 +125,6 @@ class BanksBottomView: UIView {
setupTableViewConstraints()
setupPoweredByGiniConstraints()
}

private func setupListeners() {
NotificationCenter.default.addObserver(self,
selector: #selector(willEnterForeground),
name: UIApplication.willEnterForegroundNotification,
object: nil)
}

@objc private func willEnterForeground() {
viewModel.updatePaymentProvidersInstalledState()
paymentProvidersTableView.reloadData()
}

private func setupTopRectangleConstraints() {
NSLayoutConstraint.activate([
Expand Down Expand Up @@ -245,10 +232,6 @@ extension BanksBottomView: UITableViewDataSource, UITableViewDelegate {
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if viewModel.paymentProviders[indexPath.row].isInstalled {
viewModel.viewDelegate?.didSelectPaymentProvider(paymentProvider: viewModel.paymentProviders[indexPath.row].paymentProvider)
} else {
openPaymentProvidersAppStoreLink(urlString: viewModel.paymentProviders[indexPath.row].paymentProvider.appStoreUrlIOS)
}
viewModel.viewDelegate?.didSelectPaymentProvider(paymentProvider: viewModel.paymentProviders[indexPath.row].paymentProvider)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,12 @@ final class BanksBottomViewModel {
let descriptionLabelAccentColor: UIColor = GiniColor(lightModeColor: UIColor.GiniHealthColors.dark3,
darkModeColor: UIColor.GiniHealthColors.light3).uiColor()
var descriptionLabelFont: UIFont

private var urlOpener: URLOpener

init(paymentProviders: PaymentProviders, selectedPaymentProvider: PaymentProvider?) {
init(paymentProviders: PaymentProviders, selectedPaymentProvider: PaymentProvider?, urlOpener: URLOpener = URLOpener(UIApplication.shared)) {
self.selectedPaymentProvider = selectedPaymentProvider
self.urlOpener = urlOpener

let defaultRegularFont: UIFont = UIFont.systemFont(ofSize: 14, weight: .regular)
let defaultBoldFont: UIFont = UIFont.systemFont(ofSize: 14, weight: .bold)
Expand All @@ -64,26 +67,13 @@ final class BanksBottomViewModel {
self.descriptionLabelFont = GiniHealthConfiguration.shared.textStyleFonts[.caption1] ?? defaultRegularFont

self.paymentProviders = paymentProviders
.filter({ $0.appStoreUrlIOS != nil || isPaymentProviderInstalled(paymentProvider: $0) })
.map({ PaymentProviderAdditionalInfo(isSelected: $0.id == selectedPaymentProvider?.id,
isInstalled: isPaymentProviderInstalled(paymentProvider: $0),
paymentProvider: $0)})

.sorted(by: { $0.isInstalled && !$1.isInstalled })
self.calculateHeights()
}

func updatePaymentProvidersInstalledState() {
for index in 0 ..< paymentProviders.count {
paymentProviders[index].isInstalled = isPaymentProviderInstalled(paymentProvider: paymentProviders[index].paymentProvider)
}
if selectedPaymentProvider == nil {
selectedPaymentProvider = paymentProviders.first(where: { $0.isInstalled == true })?.paymentProvider
if let indexSelected = paymentProviders.firstIndex(where: { $0.paymentProvider.id == selectedPaymentProvider?.id }) {
paymentProviders[indexSelected].isSelected = true
}
}
}

private func calculateHeights() {
let totalTableViewHeight = CGFloat(paymentProviders.count) * Constants.cellSizeHeight
let totalBottomViewHeight = Constants.blankBottomViewHeight + totalTableViewHeight
Expand All @@ -105,7 +95,10 @@ final class BanksBottomViewModel {
}

private func isPaymentProviderInstalled(paymentProvider: PaymentProvider) -> Bool {
paymentProvider.appSchemeIOS.canOpenURLString()
if let urlAppScheme = URL(string: paymentProvider.appSchemeIOS) {
return urlOpener.canOpenLink(url: urlAppScheme)
}
return false
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,7 @@ final class PaymentComponentView: UIView {
button.customConfigure(labelText: viewModel.bankNameLabelText,
leftImageIcon: viewModel.bankImageIcon,
rightImageIcon: viewModel.chevronDownIconName,
rightImageTintColor: viewModel.chevronDownIconColor,
isPaymentProviderInstalled: viewModel.isPaymentProviderInstalled,
notInstalledTextColor: viewModel.notInstalledBankTextColor)
rightImageTintColor: viewModel.chevronDownIconColor)
return button
}()

Expand All @@ -113,8 +111,7 @@ final class PaymentComponentView: UIView {
button.translatesAutoresizingMaskIntoConstraints = false
button.frame = CGRect(x: 0, y: 0, width: .greatestFiniteMagnitude, height: Constants.buttonViewHeight)
button.configure(with: viewModel.giniHealthConfiguration.primaryButtonConfiguration)
button.customConfigure(paymentProviderColors: viewModel.paymentProviderColors,
isPaymentProviderInstalled: viewModel.isPaymentProviderInstalled,
button.customConfigure(paymentProviderColors: viewModel.paymentProviderColors,
text: viewModel.payInvoiceLabelText)
return button
}()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ final class PaymentComponentViewModel {
private var bankName: String?
var bankNameLabelText: String {
if let bankName, !bankName.isEmpty {
return isPaymentProviderInstalled ? bankName : placeholderBankNameText
return bankName
}
return placeholderBankNameText
}
Expand All @@ -110,13 +110,6 @@ final class PaymentComponentViewModel {
let payInvoiceLabelText: String = NSLocalizedStringPreferredFormat("ginihealth.paymentcomponent.payInvoice.label",
comment: "Title label used for the pay invoice button")

// Payment provider installation status
var isPaymentProviderInstalled: Bool {
if let paymentProviderScheme, let url = URL(string: paymentProviderScheme), UIApplication.shared.canOpenURL(url) {
return true
}
return false
}
private var paymentProviderScheme: String?

weak var delegate: PaymentComponentViewProtocol?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public final class PaymentComponentsController: PaymentComponentsProtocol {

private var giniHealth: GiniHealth
private var paymentProviders: PaymentProviders = []
private var installedPaymentProviders: PaymentProviders = []

/// storing the current selected payment provider
public var selectedPaymentProvider: PaymentProvider?
Expand Down Expand Up @@ -83,7 +82,7 @@ public final class PaymentComponentsController: PaymentComponentsProtocol {
- Returns: a Payment Provider object.
*/
private func defaultInstalledPaymentProvider() -> PaymentProvider? {
savedPaymentProvider() ?? installedPaymentProviders.first
savedPaymentProvider() ?? paymentProviders.first
}

/**
Expand All @@ -97,7 +96,6 @@ public final class PaymentComponentsController: PaymentComponentsProtocol {
switch result {
case let .success(paymentProviders):
self?.paymentProviders = paymentProviders
self?.checkInstalledPaymentProviders()
self?.selectedPaymentProvider = self?.defaultInstalledPaymentProvider()
self?.delegate?.didFetchedPaymentProviders()
case let .failure(error):
Expand All @@ -115,15 +113,6 @@ public final class PaymentComponentsController: PaymentComponentsProtocol {
}
}

private func checkInstalledPaymentProviders() {
installedPaymentProviders = []
for paymentProvider in paymentProviders {
if checkPaymentProviderIsInstalled(paymentProvider: paymentProvider) {
self.installedPaymentProviders.append(paymentProvider)
}
}
}

private func storeDefaultPaymentProvider(paymentProvider: PaymentProvider) {
do {
let encoder = JSONEncoder()
Expand All @@ -139,7 +128,7 @@ public final class PaymentComponentsController: PaymentComponentsProtocol {
do {
let decoder = JSONDecoder()
let paymentProvider = try decoder.decode(PaymentProvider.self, from: data)
if self.installedPaymentProviders.contains(where: { $0.id == paymentProvider.id }) {
if self.paymentProviders.contains(where: { $0.id == paymentProvider.id }) {
return paymentProvider
}
} catch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ final class PaymentInfoViewModel {

init(paymentProviders: PaymentProviders) {
self.paymentProviders = paymentProviders
.filter({ $0.appStoreUrlIOS != nil || $0.appStoreUrlIOS?.canOpenURLString() ?? false })

let giniHealthConfiguration = GiniHealthConfiguration.shared

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ extension PaymentPrimaryButton {
}
}

func customConfigure(paymentProviderColors: ProviderColors?, isPaymentProviderInstalled: Bool, text: String, leftImageData: Data? = nil) {
if let backgroundHexColor = paymentProviderColors?.background.toColor(), isPaymentProviderInstalled {
func customConfigure(paymentProviderColors: ProviderColors?, text: String, leftImageData: Data? = nil) {
if let backgroundHexColor = paymentProviderColors?.background.toColor() {
contentView.backgroundColor = backgroundHexColor
}
contentView.isUserInteractionEnabled = isPaymentProviderInstalled
contentView.isUserInteractionEnabled = true

titleLabel.text = text
if let textHexColor = paymentProviderColors?.text.toColor() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,22 +69,15 @@ final class PaymentSecondaryButton: UIView {
])
}

private func activateBankImageViewConstraints(isPaymentProviderInstalled: Bool) {
if isPaymentProviderInstalled {
leftImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: Constants.contentLeadingPadding).isActive = true
leftImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
leftImageView.widthAnchor.constraint(equalToConstant: leftImageView.frame.width).isActive = true
leftImageView.heightAnchor.constraint(equalToConstant: leftImageView.frame.height).isActive = true
let bankNameBankViewConstraint = titleLabel.leadingAnchor.constraint(equalTo: leftImageView.trailingAnchor, constant: Constants.contentLeadingPadding)
bankNameBankViewConstraint.priority = .required - 1 // fix needed because of embeded views in cells issue. We need this to silent the "Unable to simultaneously satisfy constraints" warning
bankNameBankViewConstraint.isActive = true
leftImageView.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor).isActive = true
} else {
let bankNameLeadingSuperviewConstraint = titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: Constants.contentLeadingPadding)
bankNameLeadingSuperviewConstraint.priority = .required - 1
bankNameLeadingSuperviewConstraint.isActive = true
contentView.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor).isActive = true
}
private func activateBankImageViewConstraints() {
leftImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: Constants.contentLeadingPadding).isActive = true
leftImageView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
leftImageView.widthAnchor.constraint(equalToConstant: leftImageView.frame.width).isActive = true
leftImageView.heightAnchor.constraint(equalToConstant: leftImageView.frame.height).isActive = true
let bankNameBankViewConstraint = titleLabel.leadingAnchor.constraint(equalTo: leftImageView.trailingAnchor, constant: Constants.contentLeadingPadding)
bankNameBankViewConstraint.priority = .required - 1 // fix needed because of embeded views in cells issue. We need this to silent the "Unable to simultaneously satisfy constraints" warning
bankNameBankViewConstraint.isActive = true
leftImageView.centerYAnchor.constraint(equalTo: titleLabel.centerYAnchor).isActive = true
}

@objc
Expand All @@ -110,8 +103,8 @@ extension PaymentSecondaryButton {
}
}

func customConfigure(labelText: String, leftImageIcon: UIImage?, rightImageIcon: String?, rightImageTintColor: UIColor, isPaymentProviderInstalled: Bool, notInstalledTextColor: UIColor) {
if let leftImageIcon, isPaymentProviderInstalled {
func customConfigure(labelText: String, leftImageIcon: UIImage?, rightImageIcon: String?, rightImageTintColor: UIColor) {
if let leftImageIcon {
leftImageView.image = leftImageIcon
leftImageView.isHidden = false
} else {
Expand All @@ -125,10 +118,7 @@ extension PaymentSecondaryButton {
rightImageView.isHidden = true
}
titleLabel.text = labelText
if !isPaymentProviderInstalled {
titleLabel.textColor = notInstalledTextColor
}
activateBankImageViewConstraints(isPaymentProviderInstalled: isPaymentProviderInstalled)
activateBankImageViewConstraints()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ public final class PaymentReviewViewController: UIViewController, UIGestureRecog
guard let model else { return }
payInvoiceButton.configure(with: giniHealthConfiguration.primaryButtonConfiguration)
payInvoiceButton.customConfigure(paymentProviderColors: selectedPaymentProvider?.colors,
isPaymentProviderInstalled: true,
text: model.payInvoiceLabelText,
leftImageData: selectedPaymentProvider?.iconData)
disablePayButtonIfNeeded()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public struct URLOpener {
completion?(false)
}
}

func canOpenLink(url: URL) -> Bool {
application.canOpenURL(url)
}
}

public protocol URLOpenerProtocol {
Expand Down
Loading

0 comments on commit 187e4a9

Please sign in to comment.