Skip to content

Commit

Permalink
feat(GiniBankSDKExample): Implemented Demo screen in SwiftUI <3
Browse files Browse the repository at this point in the history
  • Loading branch information
ValentinaIancu-Gini committed Feb 6, 2025
1 parent a0e889e commit 5051d1a
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
289570932A30CD7600CC2C56 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289570912A30CD7600CC2C56 /* SettingsViewController.swift */; };
289570942A30CE2800CC2C56 /* SettingsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 289570922A30CD7600CC2C56 /* SettingsViewController.xib */; };
289918002BAB0B1900F5D214 /* DigitalInvoiceIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289917FF2BAB0B1900F5D214 /* DigitalInvoiceIntegrationTests.swift */; };
289A754B2D553E9B0079E44A /* DemoScreenSwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289A754A2D553E9B0079E44A /* DemoScreenSwiftUIView.swift */; };
289A75502D55451C0079E44A /* GiniSwiftUIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289A754F2D5545190079E44A /* GiniSwiftUIButton.swift */; };
289A75522D5545460079E44A /* IBANTextFieldSwiftUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289A75512D55453E0079E44A /* IBANTextFieldSwiftUIView.swift */; };
289D3DB32A4EC857002A6681 /* InfoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 289D3DB12A4EC857002A6681 /* InfoTableViewCell.swift */; };
289D3DB42A4EC857002A6681 /* InfoTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 289D3DB22A4EC857002A6681 /* InfoTableViewCell.xib */; };
28A4112F2A6EB9E500421033 /* SettingsViewController+SettingsButtonStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28A4112D2A6EB9E500421033 /* SettingsViewController+SettingsButtonStates.swift */; };
Expand Down Expand Up @@ -112,7 +115,7 @@
28F62F9E2AB21B1700D47866 /* DemoScreenStrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F62F9D2AB21B1700D47866 /* DemoScreenStrings.swift */; };
28F62FA22AB21C2E00D47866 /* DemoScreen.strings in Resources */ = {isa = PBXBuildFile; fileRef = 28F62FA42AB21C2E00D47866 /* DemoScreen.strings */; };
28F62FA72AB2236500D47866 /* Device.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F62FA62AB2236500D47866 /* Device.swift */; };
28F62FA92AB319A000D47866 /* TextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F62FA82AB319A000D47866 /* TextField.swift */; };
28F62FA92AB319A000D47866 /* GiniTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28F62FA82AB319A000D47866 /* GiniTextField.swift */; };
3E7839CE29C9DBB700B42216 /* ExtractionResultTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3E7839CD29C9DBB700B42216 /* ExtractionResultTableViewCell.swift */; };
4C84B5DD264ED55100853F33 /* Credentials.plist in Resources */ = {isa = PBXBuildFile; fileRef = 4C84B5DC264ED55100853F33 /* Credentials.plist */; };
502B63FA2C3FED5D00B5D5EA /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 502B63F92C3FED5D00B5D5EA /* PhotosUI.framework */; };
Expand Down Expand Up @@ -258,6 +261,9 @@
289570912A30CD7600CC2C56 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
289570922A30CD7600CC2C56 /* SettingsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SettingsViewController.xib; sourceTree = "<group>"; };
289917FF2BAB0B1900F5D214 /* DigitalInvoiceIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DigitalInvoiceIntegrationTests.swift; sourceTree = "<group>"; };
289A754A2D553E9B0079E44A /* DemoScreenSwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoScreenSwiftUIView.swift; sourceTree = "<group>"; };
289A754F2D5545190079E44A /* GiniSwiftUIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiniSwiftUIButton.swift; sourceTree = "<group>"; };
289A75512D55453E0079E44A /* IBANTextFieldSwiftUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IBANTextFieldSwiftUIView.swift; sourceTree = "<group>"; };
289D3DB12A4EC857002A6681 /* InfoTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoTableViewCell.swift; sourceTree = "<group>"; };
289D3DB22A4EC857002A6681 /* InfoTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = InfoTableViewCell.xib; sourceTree = "<group>"; };
28A4112D2A6EB9E500421033 /* SettingsViewController+SettingsButtonStates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SettingsViewController+SettingsButtonStates.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -323,7 +329,7 @@
28F62FA32AB21C2E00D47866 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/DemoScreen.strings; sourceTree = "<group>"; };
28F62FA52AB21C3000D47866 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/DemoScreen.strings; sourceTree = "<group>"; };
28F62FA62AB2236500D47866 /* Device.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Device.swift; sourceTree = "<group>"; };
28F62FA82AB319A000D47866 /* TextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextField.swift; sourceTree = "<group>"; };
28F62FA82AB319A000D47866 /* GiniTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GiniTextField.swift; sourceTree = "<group>"; };
3E7839CD29C9DBB700B42216 /* ExtractionResultTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtractionResultTableViewCell.swift; sourceTree = "<group>"; };
4C84B5DC264ED55100853F33 /* Credentials.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Credentials.plist; sourceTree = "<group>"; };
4C84B5DE2653FFF000853F33 /* Example Swift.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Example Swift.entitlements"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -487,6 +493,34 @@
path = DigitalInvoiceWithSkonto;
sourceTree = "<group>";
};
289A754C2D5544C70079E44A /* DemoScreen */ = {
isa = PBXGroup;
children = (
289A754E2D5544DD0079E44A /* UIKit */,
289A754D2D5544D20079E44A /* SwiftUI */,
);
path = DemoScreen;
sourceTree = "<group>";
};
289A754D2D5544D20079E44A /* SwiftUI */ = {
isa = PBXGroup;
children = (
289A75512D55453E0079E44A /* IBANTextFieldSwiftUIView.swift */,
289A754A2D553E9B0079E44A /* DemoScreenSwiftUIView.swift */,
289A754F2D5545190079E44A /* GiniSwiftUIButton.swift */,
);
path = SwiftUI;
sourceTree = "<group>";
};
289A754E2D5544DD0079E44A /* UIKit */ = {
isa = PBXGroup;
children = (
F4AD00C125DED43200C34E15 /* DemoViewController.swift */,
28F62F982AB1C2CA00D47866 /* DemoViewController.xib */,
);
path = UIKit;
sourceTree = "<group>";
};
28B5873A2A37270F008CB210 /* Utils */ = {
isa = PBXGroup;
children = (
Expand All @@ -495,7 +529,7 @@
28B5873D2A3727F8008CB210 /* ReusableView.swift */,
28CDB8222A38A5E40016A81C /* ColorPalette.swift */,
28F62FA62AB2236500D47866 /* Device.swift */,
28F62FA82AB319A000D47866 /* TextField.swift */,
28F62FA82AB319A000D47866 /* GiniTextField.swift */,
2883DE052AB89F4000AE3A9C /* GiniCaptureSDKColors.swift */,
28DB2C812A39AF5000F5B304 /* GiniButton.swift */,
284F52092BD959F300CF70AD /* UIColor.swift */,
Expand Down Expand Up @@ -953,6 +987,7 @@
F490C7E325DE873900D8CA6F /* GiniBankSDKExample */ = {
isa = PBXGroup;
children = (
289A754C2D5544C70079E44A /* DemoScreen */,
28BB82022C91D4D9003C8389 /* TransactionSummary */,
5DCC9FA32C779BC000C1B76A /* Models */,
84CD074B2C7DB501004DF1DE /* DigitalInvoiceSkontoBottomNavigationBar */,
Expand All @@ -973,8 +1008,6 @@
F441DCC525E56BF800AAB09A /* LaunchScreen.xib */,
F459606E2A813CB1004B0112 /* SettingsViewController */,
F4BB7CF126984E5D003FD77E /* CustomMenuItemViewController.swift */,
F4AD00C125DED43200C34E15 /* DemoViewController.swift */,
28F62F982AB1C2CA00D47866 /* DemoViewController.xib */,
F4AD00BB25DED33300C34E15 /* Coordinator.swift */,
F44AD01428D499E6002BAD98 /* CustomOnboardingIllustrationAdapter.swift */,
F414A56225EBB87F00D04A80 /* DocumentAnalysisHelper.swift */,
Expand Down Expand Up @@ -1335,6 +1368,7 @@
files = (
28DAF4B32CD293AD0035A1FF /* GiniCameraAccessScreenUITests.swift in Sources */,
83D02CD3290AC3AD00DA97F7 /* CustomOnboardingBottomNavigationBarAdapter.swift in Sources */,
289A75502D55451C0079E44A /* GiniSwiftUIButton.swift in Sources */,
F4AD00B625DED1A000C34E15 /* AppCoordinator.swift in Sources */,
768B017E28D1E54E009A2124 /* CustomLoadingIndicator.swift in Sources */,
847B68CC2C400A0600544050 /* CustomSkontoBottomNavigationBarAdapter.swift in Sources */,
Expand All @@ -1355,6 +1389,7 @@
28DAF4C42CD3A85A0035A1FF /* HelpScreen.swift in Sources */,
F4AD00EC25DFDE2000C34E15 /* RootNavigationController.swift in Sources */,
F44AD01528D499E6002BAD98 /* CustomOnboardingIllustrationAdapter.swift in Sources */,
289A75522D5545460079E44A /* IBANTextFieldSwiftUIView.swift in Sources */,
28DAF4C02CD3A8520035A1FF /* OnboardingScreen.swift in Sources */,
289447712A3C8ECD00ED012E /* SettingsViewController+SwitchOptionModel.swift in Sources */,
28DAF4BA2CD293C40035A1FF /* GiniMainScreenUITests.swift in Sources */,
Expand All @@ -1369,7 +1404,7 @@
84F2FD142CD0FABC00DAE5B4 /* SettingsHeaderView.swift in Sources */,
28B5873E2A3727F8008CB210 /* ReusableView.swift in Sources */,
F4AD00C225DED43200C34E15 /* DemoViewController.swift in Sources */,
28F62FA92AB319A000D47866 /* TextField.swift in Sources */,
28F62FA92AB319A000D47866 /* GiniTextField.swift in Sources */,
28DAF4BE2CD293CD0035A1FF /* GiniSkontoScreenUITests.swift in Sources */,
28DAF4C92CD3A8660035A1FF /* SettingScreen.swift in Sources */,
28F62FA72AB2236500D47866 /* Device.swift in Sources */,
Expand All @@ -1384,6 +1419,7 @@
8336530128F0334C00B5A1CE /* CustomBottomNavigationBar.swift in Sources */,
28B5873C2A372790008CB210 /* UITableView+CellRegistration.swift in Sources */,
5DCC9FA12C769A0900C1B76A /* APIEnvironment.swift in Sources */,
289A754B2D553E9B0079E44A /* DemoScreenSwiftUIView.swift in Sources */,
28DAF4CA2CD3A8680035A1FF /* TransactionDocsScreen.swift in Sources */,
5D5328882C63F71100DEA203 /* CredentialsTableViewCell.swift in Sources */,
76EFD4D429B0C4EA00C26279 /* CustomDigitalInvoiceOverviewBottomNavigationBar.swift in Sources */,
Expand Down
32 changes: 25 additions & 7 deletions BankSDK/GiniBankSDKExample/GiniBankSDKExample/AppCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import UIKit
import SwiftUI
import GiniCaptureSDK
import GiniBankAPILibrary
import GiniBankSDK
Expand All @@ -19,15 +20,32 @@ final class AppCoordinator: Coordinator {
fileprivate var screenAPIViewController: UIViewController?

var rootViewController: UIViewController {
return demoViewController
return demoView
}
lazy var demoViewController: DemoViewController = {
let viewController = DemoViewController()
viewController.delegate = self
viewController.clientId = self.client.id
return viewController
// lazy var demoViewController: DemoViewController = {
// let viewController = DemoViewController()
// viewController.delegate = self
// viewController.clientId = self.client.id
// return viewController
// }()
lazy var demoView: UIViewController = {
let view = DemoView(
clientId: self.client.id,
onPhotoPayment: { [weak self] in
self?.didSelectEntryPoint(.button)
},
onSettingsTap: { [weak self] in
self?.didSelectSettings()
},
onEntryPointSelected: { [weak self] entryPoint in
self?.didSelectEntryPoint(entryPoint)
}
)

return UIHostingController(rootView: view)
}()


lazy var configuration: GiniBankConfiguration = {
let configuration = GiniBankConfiguration.shared
configuration.debugModeOn = true
Expand Down Expand Up @@ -321,7 +339,7 @@ final class AppCoordinator: Coordinator {

// MARK: - DemoViewControllerDelegate

extension AppCoordinator: DemoViewControllerDelegate {
extension AppCoordinator {
func didSelectEntryPoint(_ entryPoint: GiniCaptureSDK.GiniConfiguration.GiniEntryPoint) {
GiniBankConfiguration.shared.entryPoint = entryPoint
showScreenAPI()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import SwiftUI
import GiniCaptureSDK
import GiniBankSDK

struct DemoView: View {
@State private var ibanText: String = ""
var clientId: String?
var onPhotoPayment: () -> Void
var onSettingsTap: () -> Void
var onEntryPointSelected: (GiniConfiguration.GiniEntryPoint) -> Void

var body: some View {
VStack {
Spacer(minLength: Constants.giniLogoTopConstant)

// Gini Logo
Image("gini_logo")
.resizable()
.scaledToFit()
.frame(width: 114, height: 72)

// Welcome Title
Text(DemoScreenStrings.welcomeTitle.localized)
.font(.system(size: 22, weight: .bold))
.padding(.top, Constants.welcomeTitleTopConstant)

// Description Text
Text(DemoScreenStrings.screenDescription.localized)
.font(.system(size: 17))
.multilineTextAlignment(.center)
.lineLimit(nil)
.fixedSize(horizontal: false, vertical: true)
.padding(.horizontal, 50)
.padding(.top, 12)

VStack(spacing: 24) {
IBANTextFieldSwiftUIView(ibanText: $ibanText, onCameraTap: {
onEntryPointSelected(.field)
})
.padding(.horizontal, Constants.stackViewMarginConstant)

Text(DemoScreenStrings.alternativeText.localized)
.font(.system(size: 15))
.multilineTextAlignment(.center)

GiniSwiftUIButton(title: DemoScreenStrings.photoPaymentButtonTitle.localized,
action: {
onEntryPointSelected(.button)
})
.frame(maxWidth: .infinity, minHeight: 44)
.background(Color(Constants.itemBackgroundColor))
.cornerRadius(7)
.padding(.horizontal, Constants.stackViewMarginConstant)
}
.padding(.top, Constants.stackViewTopConstant)


Spacer()

// Meta Information
Text("Gini Bank SDK: (\(GiniBankSDKVersion)) / Gini Capture SDK: (\(GiniCaptureSDKVersion)) / Client id: \(clientId ?? "")")
.font(.system(size: 11))
.multilineTextAlignment(.center)
.lineLimit(nil) // Ensures unlimited lines (equivalent to numberOfLines = 0)
.fixedSize(horizontal: false, vertical: true) // Allows text to expand vertically
.padding(.horizontal, 50)
.padding(.bottom, 14)
.onTapGesture {
onSettingsTap()
}
}
.background(Color(UIColor.systemBackground))
.onTapGesture {
hideKeyboard()
}
}
}

// MARK: - Constants
private struct Constants {
static let welcomeTitleTopConstant: CGFloat = Device.small ? 24 : UIDevice.current.isIpad ? 85 : 48
static let giniLogoTopConstant: CGFloat = Device.small ? 48 : UIDevice.current.isIpad ? 150 : 112
static let stackViewTopConstant: CGFloat = 72
static let stackViewMarginConstant: CGFloat = UIDevice.current.isIpad ? 64 : 16
static let itemBackgroundColor = GiniColor(
light: giniCaptureColor("Light04"),
dark: giniCaptureColor("Dark04")
).uiColor()
}

// MARK: - Hide Keyboard Helper
extension View {
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}

// MARK: - Preview
#Preview {
DemoView(clientId: "example-client-id",
onPhotoPayment: {},
onSettingsTap: {},
onEntryPointSelected: { _ in })
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// GiniSwiftUIButton.swift
//
// Copyright © 2025 Gini GmbH. All rights reserved.
//

import SwiftUI
import GiniCaptureSDK

struct GiniSwiftUIButton: View {
let title: String
let action: () -> Void

var body: some View {
Button(action: action) {
Text(title)
.font(.system(size: 17, weight: .semibold))
.frame(maxWidth: .infinity)
.foregroundColor(Color(Constants.textColor))
.padding()
}
.background(Color(Constants.itemBackgroundColor))
.cornerRadius(7)
}
}

private struct Constants {
static let textColor = GiniColor(light: .black, dark: .white).uiColor()
static let iconColor = GiniColor(light: .black, dark: .white).uiColor()
static let itemBackgroundColor = GiniColor(
light: giniCaptureColor("Light04"),
dark: giniCaptureColor("Dark04")
).uiColor()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// IBANTextFieldSwiftUIView.swift
//
// Copyright © 2025 Gini GmbH. All rights reserved.
//

import SwiftUI
import GiniCaptureSDK

struct IBANTextFieldSwiftUIView: View {
@Binding var ibanText: String
var onCameraTap: () -> Void

var body: some View {
HStack {
// IBAN TextField
TextField(DemoScreenStrings.ibanTextFieldPlaceholder.localized, text: $ibanText)
.font(.system(size: 17))
.padding(.leading, 16)
.foregroundColor(.black)
.frame(height: 50) // Adjust height to match design
.background(Color.clear)

// Camera Icon Button
Button(action: onCameraTap) {
Image(systemName: "camera")
.resizable()
.scaledToFit()
.frame(width: 24, height: 24)
.foregroundColor(.black)
.padding(.trailing, 16)
}
}
.frame(height: 50) // Match the height
.background(Color(UIColor.systemGray6)) // Use a light background color
.cornerRadius(10) // Rounded corners
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ final class DemoViewController: UIViewController {

@IBOutlet private weak var contentView: UIView!
@IBOutlet private weak var metaInformationLabel: UILabel!
@IBOutlet private weak var ibanTextField: TextField!
@IBOutlet private weak var ibanTextField: GiniTextField!
@IBOutlet private weak var alternativeTitle: UILabel!
@IBOutlet private weak var descriptionTitle: UILabel!
@IBOutlet private weak var welcomeTitlte: UILabel!
Expand Down
Loading

0 comments on commit 5051d1a

Please sign in to comment.