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

Pp 749 gini demo app tl show attachments #784

Open
wants to merge 92 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
88b6749
refactor(GiniBankSDKExample): Refactor and cleanup `TransactionSummar…
ValentinaIancu-Gini Jan 10, 2025
ac031f9
feat(GiniBankSDKExample): Add FileManagerHelper class to writes new d…
ValentinaIancu-Gini Jan 10, 2025
114f730
feat(GiniBankSDKExample): Save transaction documents after extraction…
ValentinaIancu-Gini Jan 10, 2025
bbcdf38
feat(GiniBankSDKExample): Add `transactionListButton` into DemoViewCo…
ValentinaIancu-Gini Jan 10, 2025
4b0d25f
feat(GiniBankSDKExample): Add utility method to extract acronym from …
ValentinaIancu-Gini Jan 23, 2025
5256b8c
feat(GiniBankSDK): Expose `transactionDocs` to be able to get all the…
ValentinaIancu-Gini Jan 23, 2025
ce643e9
fix(GiniBankSDK): Fix swiftlint warnings
ValentinaIancu-Gini Jan 23, 2025
233aefc
feat(GiniBankSDKExample): Add fast way to get the image from assetcat…
ValentinaIancu-Gini Jan 23, 2025
e8c0361
feat(GiniBankSDKExample): Display a list of transactions with attache…
ValentinaIancu-Gini Jan 23, 2025
ee3b6d6
feat(GiniBankSDKExample): Add utility method to transform date into s…
ValentinaIancu-Gini Jan 27, 2025
1803b53
feat(GiniBankSDKExample): Add localizable strings for TDs
ValentinaIancu-Gini Jan 27, 2025
e36eaf1
feat(GiniBankAPILibrary): Add new methods for `pages for documentId` …
ValentinaIancu-Gini Jan 29, 2025
aa69a13
feat(GiniBankSDK): Modify TransactionDocs logic to support a list of …
ValentinaIancu-Gini Jan 29, 2025
b45c4ca
feat(GiniBankSDK): Make some properties in TransactionDocsViewModel t…
ValentinaIancu-Gini Jan 29, 2025
bc56a75
feat(GiniBankSDK): Remove unnecessary guard check
ValentinaIancu-Gini Jan 29, 2025
81190bd
feat(GiniBankSDK): Add UIApplication extension for safe area insets
ValentinaIancu-Gini Jan 31, 2025
f7fec5c
fix(GiniBankSDK): Fix extractions stackview positioning near bottom o…
ValentinaIancu-Gini Jan 31, 2025
ab5a333
feat(GiniBankSDK): Expose `documentPagesRequest` to load TDs details …
ValentinaIancu-Gini Jan 31, 2025
7b623aa
feat(GiniBankSDKExample): Show transaction details when tapping on a …
ValentinaIancu-Gini Jan 31, 2025
03deac3
feat(GiniCaptureSDK): Add a public variable for the original name of …
ValentinaIancu-Gini Jan 31, 2025
20f5a7c
feat(GiniBankSDK): Set the original name of the document if exists
ValentinaIancu-Gini Jan 31, 2025
fab2eda
fix(GiniBankSDKExample): Return only two characters as the acronym
ValentinaIancu-Gini Jan 31, 2025
62b76a1
fix(GiniBankSDKExample): Add localized strings for transaction extrac…
ValentinaIancu-Gini Jan 31, 2025
86ded0c
fix(GiniBankSDKExample): Filter the transactions by date and show the…
ValentinaIancu-Gini Jan 31, 2025
9c3a5fb
fix(GiniBankSDKExample): Show the original name of the pdf or a hardc…
ValentinaIancu-Gini Jan 31, 2025
9d0413c
fix(GiniBankSDK): Fix swiftlint warnings for indentation
ValentinaIancu-Gini Feb 3, 2025
c8bd318
feat(GiniBankAPILibrray): Add new method to fetch extractions for a g…
ValentinaIancu-Gini Feb 4, 2025
f1e7770
feat(GiniBankSDK): Add method to get document extractions
ValentinaIancu-Gini Feb 4, 2025
39e6909
feat(GiniBankSDKExample): Show for each transaction the corresponding…
ValentinaIancu-Gini Feb 4, 2025
ccd6633
fix(GiniBankSDK): Fix swiftlint warnings for indentation
ValentinaIancu-Gini Feb 4, 2025
37fc412
feat(GiniBankSDK): Make "amount to pay" localization configurable in …
ValentinaIancu-Gini Feb 4, 2025
00413a0
feat(GiniBankSDKExample): Make "amount to pay" localization configura…
ValentinaIancu-Gini Feb 4, 2025
6a92ae4
feat(GiniBankSDKExample): Add settings button to trigger the display …
ValentinaIancu-Gini Feb 4, 2025
dff7893
fix(GiniBankSDK): Cleanup
ValentinaIancu-Gini Feb 4, 2025
39b30c6
fix(GiniBankSDK): Use gini logger from `GiniBankConfiguration` to log…
ValentinaIancu-Gini Feb 4, 2025
4f02f21
fix(GiniBankSDKExample): Remove unnecessary print
ValentinaIancu-Gini Feb 5, 2025
2ab24cb
feat(GiniBankSDK): Move logic to load document data inside the GinBan…
ValentinaIancu-Gini Feb 5, 2025
f779921
refactor(GiniBankSDKExample): Cleanup unnecessary code
ValentinaIancu-Gini Feb 5, 2025
8786db4
fix(GiniBankSDK): Fix crash when calling UI updates in background thread
ValentinaIancu-Gini Feb 17, 2025
51d3d13
feat(GiniBankSDKExample): Add code comment
ValentinaIancu-Gini Feb 17, 2025
e874c52
refactor(GiniBankSDK): Refactor TransactionDocs to support multiple t…
ValentinaIancu-Gini Feb 18, 2025
aa9bac3
refactor(GiniBankSDKExample): Use `transactionDocsDataCoordinator.set…
ValentinaIancu-Gini Feb 18, 2025
c76bd0f
fix(GiniBankSDK): Improve documentation for transaction management me…
ValentinaIancu-Gini Feb 18, 2025
76789e7
fix(GiniBankSDK): Make TransactionDocsDataCoordinator class final
ValentinaIancu-Gini Feb 18, 2025
fbdc470
fix(GiniBankSDK): Remove extra new line
ValentinaIancu-Gini Feb 18, 2025
70f046a
fix(GiniBankSDKExample): Remove unnecessary line of code
ValentinaIancu-Gini Feb 18, 2025
e90d102
feat(GiniBankSDK): Adjust tests for TransactionDocs
ValentinaIancu-Gini Feb 18, 2025
d5a0d03
fix(GiniBankSDK): Fix deletion of an attached document
ValentinaIancu-Gini Feb 18, 2025
16c1882
fix(GiniBankSDK): Add missing new line
ValentinaIancu-Gini Feb 18, 2025
432d331
fix(GiniBankSDKExample): Fix deletion of an attached document from Tr…
ValentinaIancu-Gini Feb 18, 2025
b743c51
fix(GiniBankSDKExample): Remove todo
ValentinaIancu-Gini Feb 18, 2025
e994b45
feat(GiniBankSDK): Add image resource for transactionDocs attached im…
ValentinaIancu-Gini Feb 19, 2025
bad7f20
refactor(GiniBankSDK): Restrict visibility of `TransactionDocsDocumen…
ValentinaIancu-Gini Feb 19, 2025
6f0c9a0
refactor(GiniBankSDK): Mark public class as final to prevent subclassing
ValentinaIancu-Gini Feb 19, 2025
1945bf6
refactor(GiniBankSDK): Move attached document filename processing log…
ValentinaIancu-Gini Feb 19, 2025
c6c4bff
feat(GiniBankSDK): Use image resource for transactionDocs attached im…
ValentinaIancu-Gini Feb 19, 2025
1f052d5
feat(GiniBankSDKExample): Use the right property to map the type of t…
ValentinaIancu-Gini Feb 19, 2025
0347499
feat(GiniBankSDKExample): Add image resource for transactionDocs atta…
ValentinaIancu-Gini Feb 19, 2025
bb2d655
feat(GiniBankSDKExample): Use image resource for transactionDocs atta…
ValentinaIancu-Gini Feb 19, 2025
d9f1dc6
fix(GiniBankSDKExample): Cleanup logic for showing the attached docum…
ValentinaIancu-Gini Feb 19, 2025
6d33836
fix(GiniBankSDKExample): Fix `AttachmentView` to handle long file names
ValentinaIancu-Gini Feb 19, 2025
43489f6
feat(GiniBankSDKExample): Improve cell corner rounding logic in trans…
ValentinaIancu-Gini Feb 19, 2025
aa3ebe6
feat(GiniBankSDK): Introduce GiniTransaction model for structured tra…
ValentinaIancu-Gini Feb 19, 2025
2b84410
fix(GiniBankSDK): Modified related test to align with the new `GiniTr…
ValentinaIancu-Gini Feb 19, 2025
347dfd8
feat(GiniBankSDKExample): Use `GiniTransaction` struct
ValentinaIancu-Gini Feb 19, 2025
9cc4037
feat(GiniBankSDKExample): Add settings image asset for the settings b…
ValentinaIancu-Gini Feb 19, 2025
03ca556
feat(GiniBankSDKExample): Adjust buttons background colors as in Figm…
ValentinaIancu-Gini Feb 19, 2025
8db10d6
refactor(GiniBankSDK): Refactor `TransactionDocDataProtocol` to remov…
ValentinaIancu-Gini Feb 20, 2025
018befd
refactor(GiniBankSDKExample): Removed `transactionDocIDs` property an…
ValentinaIancu-Gini Feb 20, 2025
24c8204
feat(GiniBankSDKExample): Add inline comment
ValentinaIancu-Gini Feb 20, 2025
8329e0e
fix(GiniBankSDK): Fix test
ValentinaIancu-Gini Feb 20, 2025
c338d21
fix(GiniBankSDKExample): Fix transaction list button background color…
ValentinaIancu-Gini Feb 20, 2025
5ee50dc
Merge branch 'main' into PP-749-Gini-Demo-app-TL-show-attachments
ValentinaIancu-Gini Feb 20, 2025
4355d85
fix(GiniBankSDKExample): Remove unnecessary print
ValentinaIancu-Gini Feb 20, 2025
18cd4cc
Merge branch 'PP-749-Gini-Demo-app-TL-show-attachments' of github.com…
ValentinaIancu-Gini Feb 20, 2025
82789c2
refactor(GiniBankSDK): Refactor `TransactionDocDataInternalProtocol` …
ValentinaIancu-Gini Feb 20, 2025
19c4a28
refactor(GiniBankSDK): Refactor `TransactionDocsItemView` to handle t…
ValentinaIancu-Gini Feb 20, 2025
38a1e1d
Merge branch 'main' into PP-749-Gini-Demo-app-TL-show-attachments
ValentinaIancu-Gini Feb 26, 2025
f59858e
Merge branch 'main' into PP-749-Gini-Demo-app-TL-show-attachments
ValentinaIancu-Gini Feb 26, 2025
78fe47a
fix(GiniCaptureSDK): Fix typo
ValentinaIancu-Gini Mar 6, 2025
cbf908f
fix(GiniBankSDK): Fix typos
ValentinaIancu-Gini Mar 6, 2025
c59c7a4
fix(GiniBankSDK): Fix after merge conflicts to use `Self.makeMetadata…
ValentinaIancu-Gini Mar 6, 2025
01fcae2
refactor(GiniBankAPILibrary): Refactor extraction handling to reduce …
ValentinaIancu-Gini Mar 6, 2025
22b108f
refactor(GiniBankAPILibrary): Refactor page fetching to eliminate dup…
ValentinaIancu-Gini Mar 6, 2025
72fc4cd
refactor(GiniBankAPILibrary): Refactor page preview fetching to remov…
ValentinaIancu-Gini Mar 6, 2025
2bdc5e8
refactor(GiniBankAPILibrary): Refactor document page fetching to elim…
ValentinaIancu-Gini Mar 6, 2025
53025d2
refactor(GiniBankAPILibrary): Refactor feedback submission to reduce …
ValentinaIancu-Gini Mar 6, 2025
aa04478
refactor(GiniBankSDK): Introduce DocumentServiceProviding protocol an…
ValentinaIancu-Gini Mar 6, 2025
278b92f
refactor(GiniBankSDK): Update GiniBank to use DocumentServiceProvidin…
ValentinaIancu-Gini Mar 6, 2025
2bf34b3
refactor(GiniBankSDK): Update GiniBankNetworkingScreenApiCoordinator …
ValentinaIancu-Gini Mar 6, 2025
cc1b264
refactor(GiniBankSDK): Update method documentation
ValentinaIancu-Gini Mar 6, 2025
77f8b55
fix(GiniBankSDKExample): Extract hard coded values in Constants
ValentinaIancu-Gini Mar 6, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,19 @@ public final class DefaultDocumentService: DefaultDocumentServiceProtocol {
cancellationToken: cancellationToken,
completion: completion)
}

/**
* Retrieves the extractions for a given documentId.
*
* - Parameter documentId: Document id from which to get the extractions for
* - Parameter completion: A completion callback, returning the extraction list on success
*/
public func extractions(for documentId: String,
completion: @escaping CompletionResult<ExtractionResult>) {
fetchDocumentExtractions(resourceHandler: sessionManager.data,
for: documentId,
completion: completion)
}

/**
* Retrieves the layout of a given document
*
Expand All @@ -171,7 +183,17 @@ public final class DefaultDocumentService: DefaultDocumentServiceProtocol {
public func pages(in document: Document, completion: @escaping CompletionResult<[Document.Page]>) {
pages(resourceHandler: sessionManager.data, in: document, completion: completion)
}


/**
* Retrieves the pages of a given document
*
* - Parameter documentId: Document id from which to retrieve the pages
* - Parameter completion: A completion callback, returning the requested document layout on success
*/
public func pages(for documentId: String, completion: @escaping CompletionResult<[Document.Page]>) {
pages(resourceHandler: sessionManager.data, for: documentId, completion: completion)
}

/**
* Retrieves the page preview of a document for a given page and size
*
Expand Down Expand Up @@ -208,6 +230,25 @@ public final class DefaultDocumentService: DefaultDocumentServiceProtocol {
completion: completion)
}

/**
* Retrieves the page data of a document for a given page number and size
*
* - Parameter documentId: Document id to get the preview for
* - Parameter pageNumber: The document's page number
* - Parameter size: The size of the page to retrieve (e.g., large, medium)
* - Parameter completion: A completion callback, returning the requested page preview on success, or an error on failure
*/
public func documentPage(for documentId: String,
pageNumber: Int,
size: Document.Page.Size,
completion: @escaping CompletionResult<Data>) {
documentPage(resourceHandler: sessionManager.download,
in: documentId,
pageNumber: pageNumber,
size: size,
completion: completion)
}

/**
* Retrieves the page data of a document for a given page number and size
*
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ final class DocumentPagesFooterView: UIView {
}

private func setupConstraints() {
let bottomSafeAreaHeight = safeAreaInsets.bottom
let bottomSafeAreaHeight = UIApplication.shared.safeAreaInsets.bottom
let stackViewBottomConstraint = bottomSafeAreaHeight + Constants.stackViewBottomPadding
NSLayoutConstraint.activate([
footerStackView.leadingAnchor.constraint(equalTo: leadingAnchor,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// DocumentServiceHelper.swift
//
// Copyright © 2025 Gini GmbH. All rights reserved.
//

import GiniCaptureSDK
import GiniBankAPILibrary
import UIKit

class DocumentServiceHelper {
static func loadAllPages(from service: DocumentServiceProviding,
pages: [Document.Page],
completion: @escaping (Result<[UIImage], GiniError>) -> Void) {
var images: [UIImage] = []
var loadError: GiniError?
let dispatchGroup = DispatchGroup()

for page in pages {
dispatchGroup.enter()
service.getDocumentPage(for: page.number, size: page.images[0].size) { result in
switch result {
case .success(let data):
if let image = UIImage(data: data) {
images.append(image)
}
case .failure(let error):
loadError = error
}
dispatchGroup.leave()
}
}

dispatchGroup.notify(queue: .main) {
if let error = loadError {
completion(.failure(error))
} else {
completion(.success(images))
}
}
}

static func fetchDocumentPages(from service: DocumentServiceProviding,
completion: @escaping (Result<[UIImage], GiniError>) -> Void) {
service.getDocumentPages { result in
switch result {
case .success(let pages):
loadAllPages(from: service, pages: pages, completion: completion)
case .failure(let error):
completion(.failure(error))
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// DocumentServiceProviding.swift
//
// Copyright © 2025 Gini GmbH. All rights reserved.
//

import GiniCaptureSDK
import GiniBankAPILibrary
import UIKit

protocol DocumentServiceProviding {
func getDocumentPages(completion: @escaping (Result<[Document.Page], GiniError>) -> Void)
func getDocumentPage(for pageNumber: Int,
size: Document.Page.Size,
completion: @escaping (Result<Data, GiniError>) -> Void)
}
130 changes: 127 additions & 3 deletions BankSDK/GiniBankSDK/Sources/GiniBankSDK/Core/GiniBank.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,26 @@ import GiniBankAPILibrary
import GiniCaptureSDK

/**
Core class for Gini Bank SDK.
Core class for the Gini Bank SDK, providing functionalities for document handling and payment processing.
*/
@objc public final class GiniBank: NSObject {
/// reponsible for interaction with Gini Bank backend.

/// Handles interaction with the Gini Bank backend.
public var giniApiLib: GiniBankAPI
/// reponsible for the payment processing.

/// Provides services for payment processing.
public var paymentService: PaymentService

private var documentService: DefaultDocumentService {
return giniApiLib.documentService()
}

private var documentId: String?

// Cast the coordinator to the internal protocol to access internal properties and methods
private var internalTransactionDocsDataCoordinator: TransactionDocsDataInternalProtocol? {
return GiniBankConfiguration.shared.transactionDocsDataCoordinator as? TransactionDocsDataInternalProtocol
}
/**
Returns a GiniBank instance

Expand Down Expand Up @@ -111,6 +123,20 @@ import GiniCaptureSDK
}
}

// MARK: - Transaction Docs

/**
Initiates the process of loading transaction document data.

- Parameter documentId: The identifier of the document to process.
*/
public func handleTransactionDocsDataLoading(for documentId: String) {
self.documentId = documentId
internalTransactionDocsDataCoordinator?.loadDocumentData = { [weak self] in
self?.processTransactionDocs(for: documentId)
}
}

// MARK: - Screen API without Networking - Initializers for 'UIViewController'

/**
Expand Down Expand Up @@ -245,3 +271,101 @@ import GiniCaptureSDK
GiniCapture.setConfiguration(captureConfiguration)
}
}

extension GiniBank: DocumentServiceProviding {
func getDocumentPages(completion: @escaping (Result<[Document.Page], GiniError>) -> Void) {
guard let documentId else { return }
documentService.pages(for: documentId, completion: completion)
}

func getDocumentPage(for pageNumber: Int,
size: Document.Page.Size,
completion: @escaping (Result<Data, GiniError>) -> Void) {
guard let documentId else { return }
documentService.documentPage(for: documentId,
pageNumber: pageNumber,
size: size,
completion: completion)
}
}
//
// MARK: - Private Methods
fileprivate extension GiniBank {

private func processTransactionDocs(for documentId: String) {
guard let viewModel = internalTransactionDocsDataCoordinator?.getTransactionDocsViewModel(),
let images = viewModel.cachedImages[documentId], !images.isEmpty else {
loadDocumentData(for: documentId)
return
}

loadDocumentExtractions(for: documentId) { extractions in
DispatchQueue.main.async { [weak self] in
self?.internalTransactionDocsDataCoordinator?.updateTransactionDocsViewModel(with: images,
extractions: extractions,
for: documentId)
}
}
}

private func loadDocumentData(for documentId: String) {
let dispatchGroup = DispatchGroup()
var extractedData: [Extraction] = []
var documentImages: [UIImage] = []
var documentPagesError: GiniError?

dispatchGroup.enter()
DocumentServiceHelper.fetchDocumentPages(from: self) { result in
switch result {
case .success(let images):
documentImages = images
case .failure(let error):
documentPagesError = error
}
dispatchGroup.leave()
}

dispatchGroup.enter()
loadDocumentExtractions(for: documentId) { extractions in
extractedData = extractions
dispatchGroup.leave()
}

dispatchGroup.notify(queue: .main) {
if let error = documentPagesError {
self.handlePreviewDocumentError(error: error)
} else {
self.internalTransactionDocsDataCoordinator?.updateTransactionDocsViewModel(
with: documentImages,
extractions: extractedData,
for: documentId
)
}
}
}

private func loadDocumentExtractions(for documentId: String,
completion: @escaping ([Extraction]) -> Void) {
fetchDocumentExtractions(for: documentId) { result in
switch result {
case.success(let extractionResult):
completion(extractionResult.extractions)
case.failure:
completion([])
}
}
}

private func handlePreviewDocumentError(error: GiniError) {
internalTransactionDocsDataCoordinator?
.getTransactionDocsViewModel()?
.setPreviewDocumentError(error: error) {
self.internalTransactionDocsDataCoordinator?.loadDocumentData?()
}
}

private func fetchDocumentExtractions(for documentId: String,
completion: @escaping (Result<ExtractionResult, GiniError>) -> Void) {
documentService.extractions(for: documentId, completion: completion)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -322,12 +322,12 @@ public final class GiniBankConfiguration: NSObject {
*/
public var skontoNavigationBarBottomAdapter: SkontoNavigationBarBottomAdapter?

// MAKR: - Transaction Docs feature
/**
Set an adapter implementation to show a custom bottom navigation bar on the Skonto help screen
*/
public var skontoHelpNavigationBarBottomAdapter: SkontoHelpNavigationBarBottomAdapter?

// MARK: - Transaction Docs feature
/**
Indicates whether the Return reasons feature is enabled or not. In the case of `true`,
the users will be asked to select from a predefined list of reasons why they decided to return an item.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import UIKit

extension GiniBankNetworkingScreenApiCoordinator {
func handleTransactionDocsAlertIfNeeded(on controller: UIViewController,

defaultAction: @escaping () -> Void,
attachAction: @escaping () -> Void) {
let savedConfiguration = GiniBankUserDefaultsStorage.clientConfiguration
Expand Down
Loading