diff --git a/Documentation/source/Customization guide.md b/Documentation/source/Customization guide.md index 45b752a..020d5d8 100644 --- a/Documentation/source/Customization guide.md +++ b/Documentation/source/Customization guide.md @@ -95,15 +95,15 @@ To enable this feature simply pass `true` to `GiniConfiguration.shared.multipage ### Camera -* Enable the flash toggle button: - To allow users toggle the camera flash pass `true` to `GiniConfiguration.shared.flashToggleEnabled`. +- Enable the flash toggle button: +To allow users toggle the camera flash pass `true` to `GiniConfiguration.shared.flashToggleEnabled`. -* Turn off flash by default: - Flash is on by default, and you can turn it off by passing `false` to `GiniConfiguration.shared.flashOnByDefault`. +- Turn off flash by default: +Flash is on by default, and you can turn it off by passing `false` to `GiniConfiguration.shared.flashOnByDefault`. ### Camera access TODO - ### QR Code Scanning +### QR Code Scanning When a supported QR code is detected with valid payment data, the QR Code will be processed automatically without any further user interaction. The QR Code scanning may be triggered directly without the need to analyze the document. @@ -138,7 +138,7 @@ Please find more information in the [Import PDFs and images guide](https://devel You can show a custom loading indicator with custom animation support on the process button. Your custom loading indicator should implement `OnButtonLoadingIndicatorAdapter` interface and be passed to `GiniConfiguration.shared.onButtonLoadingIndicator`. -The example implementation is available [here](https://github.com/gini/gini-mobile-ios/blob/GiniCaptureSDK%3B3.0.0-beta02/BankSDK/GiniBankSDKExample/GiniBankSDKExample/CustomLoadingIndicator.swift#L36). +The example implementation is available [here](https://github.com/gini/gini-mobile-ios/blob/GiniCaptureSDK%3B3.0.0-beta03/BankSDK/GiniBankSDKExample/GiniBankSDKExample/CustomLoadingIndicator.swift#L36). ## Analysis screen @@ -147,7 +147,7 @@ The example implementation is available [here](https://github.com/gini/gini-mobi You can show a custom loading indicator with custom animation support. Your custom loading indicator should implement `CustomLoadingIndicatorAdapter` interface and be passed to `GiniConfiguration.shared.customLoadingIndicator`. -The example implementation is available [here](https://github.com/gini/gini-mobile-ios/blob/GiniCaptureSDK%3B3.0.0-beta02/BankSDK/GiniBankSDKExample/GiniBankSDKExample/CustomLoadingIndicator.swift). +The example implementation is available [here](https://github.com/gini/gini-mobile-ios/blob/GiniCaptureSDK%3B3.0.0-beta03/BankSDK/GiniBankSDKExample/GiniBankSDKExample/CustomLoadingIndicator.swift). ## Help screens @@ -173,10 +173,20 @@ You can also disable the supported formats help screen by passing `false` to -## No result screen TODO +## No result screen -# Error screen TODO +You can show your own UI for data input if an error occurred and the user clicks the "Enter manually" button on the error screen. +For this you must to implement `GiniCaptureResultsDelegate.giniCaptureDidEnterManually() `. + +You can show a bottom navigation bar by passing true to `GiniConfiguration.shared.bottomNavigationBarEnabled`. There is a default implementation, but you can also use +your own by implementing the `NoResultBottomNavigationBarAdapter` interface and passing it to `GiniConfiguration.shared.noResultNavigationBarBottomAdapter`. + +You can find more details [here](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/features.html#no-result-screen-customization). + +## Error screen + +You can find more details [here](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/features.html#error-screen-customization). diff --git a/Documentation/source/Features.md b/Documentation/source/Features.md index 0c11c4d..3b2e4b1 100644 --- a/Documentation/source/Features.md +++ b/Documentation/source/Features.md @@ -41,23 +41,23 @@ The onboarding feature presents essential information to the user on how to best You can customize the onboarding in the following ways: -* Disable showing the onboarding at first run: - By default the onboarding is shown at first run. To disable this pass `false` to - `GiniConfiguration.shared.onboardingShowAtFirstLaunch`. +- Disable showing the onboarding at first run: +By default the onboarding is shown at first run. To disable this pass `false` to +`GiniConfiguration.shared.onboardingShowAtFirstLaunch`. -* Customize the onboarding pages: - If you wish to show different onboarding pages then pass a list of `OnboardingPage` structs to `GiniConfiguration.shared.customOnboardingPages`. +- Customize the onboarding pages: +If you wish to show different onboarding pages then pass a list of `OnboardingPage` structs to `GiniConfiguration.shared.customOnboardingPages`. -* Force show the onboarding: - If you wish to show the onboarding after the first run then pass `true` to - `GiniConfiguration.shared.onboardingShowAtLaunch`. +- Force show the onboarding: +If you wish to show the onboarding after the first run then pass `true` to +`GiniConfiguration.shared.onboardingShowAtLaunch`. -* Animate illustrations by injecting custom views: - If you need to animate the illustrations on the onboarding pages implement the `OnboardingIllustrationAdapter` interface to inject a view that can animate images (e.g., `Lottie`) and pass it to the relevant onboarding illustration adapter setters (e.g., `onboardingAlignCornersIllustrationAdapter`, - `onboardingLightingIllustrationAdapter`, - `onboardingMultiPageIllustrationAdapter`, - `onboardingQRCodeIllustrationAdapter`) - when configuring the `GiniConfiguration.shared` instance. +- Animate illustrations by injecting custom views: +If you need to animate the illustrations on the onboarding pages implement the `OnboardingIllustrationAdapter` interface to inject a view that can animate images (e.g., `Lottie`) and pass it to the relevant onboarding illustration adapter setters (e.g., `onboardingAlignCornersIllustrationAdapter`, +`onboardingLightingIllustrationAdapter`, +`onboardingMultiPageIllustrationAdapter`, +`onboardingQRCodeIllustrationAdapter`) + when configuring the `GiniConfiguration.shared` instance. ## Single Page @@ -74,11 +74,11 @@ To enable this simply pass `true` to `GiniConfiguration.shared.multipageEnabled` ## Camera -* Enable the flash toggle button: - To allow users toggle the camera flash pass `true` to `GiniConfiguration.shared.flashToggleEnabled`. +- Enable the flash toggle button: +To allow users toggle the camera flash pass `true` to `GiniConfiguration.shared.flashToggleEnabled`. -* Turn off flash by default: - Flash is on by default, and you can turn it off by passing `false` to `GiniConfiguration.shared.flashOnByDefault`. +- Turn off flash by default: +Flash is on by default, and you can turn it off by passing `false` to `GiniConfiguration.shared.flashOnByDefault`. # QR Code Scanning @@ -107,7 +107,7 @@ The `Open with` feature allows importing of files from other apps via iOS `share Please find more information in the [Open with guide](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/open-with-guide.html). -# Help Screen Customization +# Help screen Customization You can show your own help screens in the Gini Capture SDK. You can pass the title and view controller for each screen to the @@ -124,6 +124,36 @@ The example implementation is availible [here](https://github.com/gini/gini-mobi You can also disable the supported formats help screen by passing `false` to `GiniConfiguration.shared.shouldShowSupportedFormatsScreen`. +# No result screen customization + +You can show custom back navigation button on bottom navigation bar. You can pass your custom `NoResultBottomNavigationBarAdapter` implementation to + `GiniConfiguration.shared.errorNavigationBarBottomAdapter`: + +``` swift + let customNoResultNavigationBarBottomAdapter = CustomNoResultBottomNavigationBarAdapter() + + GiniConfiguration.shared.noResultNavigationBarBottomAdapter = customNoResultNavigationBarBottomAdapter +``` + +You can show your own UI if an error occured and the user chooses to enter details manually. For this you must to implement `GiniCaptureResultsDelegate.giniCaptureDidEnterManually() `. + +The buttom "Retake images" will be shown only if you took or imported images. + +# Error screen customization + + You can show custom back navigation button on bottom navigation bar. You can pass your custom `ErrorBottomNavigationBarAdapter` implementation to + `GiniConfiguration.shared.errorNavigationBarBottomAdapter`: + +``` swift + let customErrorNavigationBarBottomAdapter = CustomErrorNavigationBarBottomAdapter() + + GiniConfiguration.shared.errorNavigationBarBottomAdapter = customErrorNavigationBarBottomAdapter +``` + +You can show your own UI if an error occured and the user chooses to enter details manually. For this you must to implement `GiniCaptureResultsDelegate.giniCaptureDidEnterManually() `. + +The buttom "Retake images" will be shown only if you took or imported images. + # Event Tracking You have the possibility to track various events which occur during the usage of the Gini Capture SDK. @@ -133,4 +163,3 @@ Please find more information in the [Event tracking guide](https://developer.gin # Error Logging The SDK logs errors to the Gini Bank API when the default networking implementation is used (see the `Default networking` implementation in the [Integration](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/integration.html). - diff --git a/Documentation/source/Getting started.md b/Documentation/source/Getting started.md index ac99c38..3e813de 100644 --- a/Documentation/source/Getting started.md +++ b/Documentation/source/Getting started.md @@ -22,14 +22,14 @@ Once you have your Swift package set up, adding `GiniCaptureSDK` as a dependency ```swift dependencies: [ - .package(url: "https://github.com/gini/capture-sdk-ios.git", .exact("3.0.0-beta02")) + .package(url: "https://github.com/gini/capture-sdk-ios.git", .exact("3.0.0-beta03")) ] ``` In case that you want to use the certificate pinning in the library, add `GiniCaptureSDKPinning`: ```swift dependencies: [ - .package(url: "https://github.com/gini/capture-sdk-pinning-ios.git", .exact("3.0.0-beta02")) + .package(url: "https://github.com/gini/capture-sdk-pinning-ios.git", .exact("3.0.0-beta03")) ] ``` diff --git a/Documentation/source/Migration to version 3.x.x.md b/Documentation/source/Migration to version 3.x.x.md index 0577a38..6168a44 100644 --- a/Documentation/source/Migration to version 3.x.x.md +++ b/Documentation/source/Migration to version 3.x.x.md @@ -52,11 +52,11 @@ The following steps will help you migrate to the new public API: * Handling the analysis results and receiving the extracted information (error or cancellation) can be handled though `GiniCaptureResultsDelegate` protocol implementation. * You can also provide your own networking by implementing the `GiniCaptureNetworkService` and `GiniCaptureResultsDelegate` protocols. Pass your instances to the `UIViewController` initialiser of GiniCapture as shown below. * Remove all code related to interacting with the SDK's specific view controllers. From now on the entry point is the `UIViewController` and customization happens through `GiniConfiguration` and via overriding of images and color resources. -* Use the new UI customization options and follow the [Customization guide](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta02/customization-guide.html) to adapt the look of the new UI. +* Use the new UI customization options and follow the [Customization guide](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/customization-guide.html) to adapt the look of the new UI. # Migrate from Screen API -The new public API is based on the Screen API, so you only need to use the new UI customization options and follow the [Customization guide](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta02/customization-guide.html) to adapt the look of the new UI. +The new public API is based on the Screen API, so you only need to use the new UI customization options and follow the [Customization guide](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/customization-guide.html) to adapt the look of the new UI. # Overview of New UI Customization Options @@ -130,7 +130,7 @@ customizations. Images and text are onboarding page specific and need to be customized for each page. -[here][https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta02/features.html#onboarding] and [here](https://www.figma.com/file/1985HMF83siAXmysSn3dC6/iOS-Gini-Capture-SDK-3.0.0-UI-Customisation?node-id=243%3A3305&t=6sAk7LGf1mi3zV9L-1). +[here][https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/features.html#onboarding] and [here](https://www.figma.com/file/1985HMF83siAXmysSn3dC6/iOS-Gini-Capture-SDK-3.0.0-UI-Customisation?node-id=243%3A3305&t=6sAk7LGf1mi3zV9L-1). ### Breaking Changes @@ -175,8 +175,7 @@ For enabling QR code only mode the both flags `GiniConfiguration.shared.qrCodeSc ## Help screens -The new help screens use the global UI customization options. You can discard the old screen specific -customizations. +The new help screens use the global UI customization options. You can discard the old screen specific customizations. ### Breaking Changes @@ -192,14 +191,13 @@ String keys changed: You can show a bottom navigation bar by passing true to `GiniConfiguration.shared.bottomNavigationBarEnabled`. There is a default implementation, but you can also use your own by implementing the `HelpBottomNavigationBarAdapter` interface and passing it to `GiniConfiguration.shared.helpNavigationBarBottomAdapter`. -You can find more details [here][https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta02/features.html#help-screen-customization] and [here](https://www.figma.com/file/1985HMF83siAXmysSn3dC6/iOS-Gini-Capture-SDK-3.0.0-UI-Customisation?node-id=141%3A2328&t=6sAk7LGf1mi3zV9L-1). +You can find more details [here][https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/features.html#help-screen-customization] and [here](https://www.figma.com/file/1985HMF83siAXmysSn3dC6/iOS-Gini-Capture-SDK-3.0.0-UI-Customisation?node-id=141%3A2328&t=6sAk7LGf1mi3zV9L-1). ## Analysis screen -The new analysis screen uses the global UI customization options. You can discard the old screen specific -customizations. +The new analysis screen uses the global UI customization options. You can discard the old screen specific customizations. -### Breaking Changes section +### Breaking Changes String keys removed: `ginicapture.analysis.suggestion.header` @@ -213,8 +211,95 @@ The following string keys now represent suggestion titles with new keys added fo ### New Features +#### Custom loading indicator + You can show a custom loading indicator with custom animation support on the center of the screen. Your custom loading indicator should implement `CustomLoadingIndicatorAdapter` interface and be passed to `GiniConfiguration.shared.customLoadingIndicator`. This loading indicator is also used on the `Camera screen` when loading data for a valid QR code. You can find more details [here](https://www.figma.com/file/1985HMF83siAXmysSn3dC6/iOS-Gini-Capture-SDK-3.0.0-UI-Customisation?node-id=501%3A7494&t=6sAk7LGf1mi3zV9L-1). + +## Review screen + +The new review screen uses the global UI customization options. You can discard the old screen specific customizations. + +### Breaking Changes + +We unified UI for the single page and multi pages options. +We removed rotation and reorder functionalities. +Tips view was removed as well. + +### New Features + +#### Custom loading indicator + +You can show a custom loading indicator with custom animation support on the process button of the screen. +Your custom loading indicator should implement `OnButtonLoadingIndicatorAdapter` interface and be passed to `GiniConfiguration.shared.onButtonLoadingIndicator`. + +#### Bottom navigation bar + +You can show a bottom navigation bar by passing true to `GiniConfiguration.shared.bottomNavigationBarEnabled`. There is a default implementation, but you can also use +your own by implementing the `ReviewScreenBottomNavigationBarAdapter` interface and passing it to `GiniConfiguration.shared.reviewNavigationBarBottomAdapter`. + +You can find more details [here](https://www.figma.com/file/1985HMF83siAXmysSn3dC6/iOS-Gini-Capture-SDK-3.0.0-UI-Customisation?node-id=261%3A8256&t=6sAk7LGf1mi3zV9L-1). + +## No results screen + +The new no results screen uses the global UI customization options. You can discard the old screen specific +customizations. + +### Breaking Changes + +#### Removed localization keys: + +`ginicapture.noresults.warning` +`ginicapture.noresults.collection.header` +`ginicapture.noresults.gotocamera` +`ginicapture.noresults.warningHelpMenu` + +### New features + +#### New localization keys: + +`ginicapture.noresult.enterManually` +`ginicapture.noresult.retakeImages` + +#### Option to enter details manually + +You can show your own UI for data input if an error occurred and the user clicks the "Enter manually" button on the error screen. +For this you must to implement `GiniCaptureResultsDelegate.giniCaptureDidEnterManually() `. + +#### Bottom navigation bar + +You can show a bottom navigation bar by passing true to `GiniConfiguration.shared.bottomNavigationBarEnabled`. There is a default implementation, but you can also use +your own by implementing the `NoResultBottomNavigationBarAdapter` interface and passing it to `GiniConfiguration.shared.noResultNavigationBarBottomAdapter`. + +You can find more details [here](https://www.figma.com/file/1985HMF83siAXmysSn3dC6/iOS-Gini-Capture-SDK-3.0.0-UI-Customisation?node-id=263%3A6989&t=7wXW9XyhTUcmp5sk-1) and [here](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/customization-guide.html#no-result-screen). + +## Error screen + +The new error screen uses the global UI customization options. + +### Breaking Changes + +Showing errors during usage of the SDK was changed from snackbar to a whole new screen. + +### New Features + +#### New UI + +The new error screen gives options to retake photos or enter details manually and displays errors with more detailed description. + +#### Bottom navigation bar + +You can show a bottom navigation bar by passing true to `GiniConfiguration.shared.bottomNavigationBarEnabled`. There is a default implementation, but you can also use +your own by implementing the `ErrorBottomNavigationBarAdapter` interface and passing it to `GiniConfiguration.shared.errorNavigationBarBottomAdapter`. + +You can find more details [here](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/customization-guide.html#error-screen). + +#### Option to enter details manually + +You can show your own UI for data input if an error occured and the user clicks the "Enter manually" button on the error screen. +For this you must to implement `GiniCaptureResultsDelegate.giniCaptureDidEnterManually() `. + +You can find more details [here](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/features.html#error-screen-customization) and [here]((https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/3.0.0-beta03/customization-guide.html#error-screen). diff --git a/Package.swift b/Package.swift index 18e4bee..77b7fcc 100644 --- a/Package.swift +++ b/Package.swift @@ -16,7 +16,7 @@ let package = Package( dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), - .package(name: "GiniBankAPILibrary", url: "https://github.com/gini/bank-api-library-ios.git", .exact("3.0.0-beta02")), + .package(name: "GiniBankAPILibrary", url: "https://github.com/gini/bank-api-library-ios.git", .exact("3.0.0-beta03")), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/Sources/GiniCaptureSDK/Core/Custom views/MultilineTitleButton.swift b/Sources/GiniCaptureSDK/Core/Custom views/MultilineTitleButton.swift index 7984aaf..0248d68 100644 --- a/Sources/GiniCaptureSDK/Core/Custom views/MultilineTitleButton.swift +++ b/Sources/GiniCaptureSDK/Core/Custom views/MultilineTitleButton.swift @@ -7,19 +7,34 @@ import UIKit -class MultilineTitleButton: UIButton { - required init?(coder aDecoder: NSCoder) { +/** +- internal only + + `MultilineTitleButton` is a subclass of `UIButton`and it allows for multiple lines of text + to be displayed in the button's title, and the button's size is adjusted to fit the text. The content hugging priority is set s + o that the button's width and height can be adjusted by the Auto Layout system. + **/ + +public class MultilineTitleButton: UIButton { + + /** + `init?(coder:)` is used for creating an instance of the class from a nib file + **/ + public required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) commonInit() } - override init(frame: CGRect) { + /** + `init(frame:)` is used for creating an instance of the class programmatically + */ + public override init(frame: CGRect) { super.init(frame: frame) commonInit() } - func commonInit() { + private func commonInit() { titleLabel?.adjustsFontForContentSizeCategory = true titleLabel?.numberOfLines = 0 titleLabel?.textAlignment = .center @@ -27,14 +42,23 @@ class MultilineTitleButton: UIButton { setContentHuggingPriority(UILayoutPriority.defaultLow + 1, for: .horizontal) } - override var intrinsicContentSize: CGSize { + /** + The class overrides the `intrinsicContentSize` property to adjust the size of the button + based on the intrinsic size of the title label and the content edge insets. + */ + public override var intrinsicContentSize: CGSize { let size = titleLabel!.intrinsicContentSize return CGSize( width: size.width + contentEdgeInsets.left + contentEdgeInsets.right, height: size.height + contentEdgeInsets.top + contentEdgeInsets.bottom) } - override func layoutSubviews() { + + /** + It also overrides the `layoutSubviews()` function to set the preferred maximum + layout width of the title label to the width of the button. + */ + public override func layoutSubviews() { super.layoutSubviews() titleLabel?.preferredMaxLayoutWidth = self.titleLabel!.frame.size.width } diff --git a/Sources/GiniCaptureSDK/Core/Extensions/UIFont.swift b/Sources/GiniCaptureSDK/Core/Extensions/UIFont.swift index 3539916..99a4e3f 100644 --- a/Sources/GiniCaptureSDK/Core/Extensions/UIFont.swift +++ b/Sources/GiniCaptureSDK/Core/Extensions/UIFont.swift @@ -24,5 +24,5 @@ extension UIFont.TextStyle { public static let bodyBold: UIFont.TextStyle = .init(rawValue: "kBodyBold") public static let calloutBold: UIFont.TextStyle = .init(rawValue: "kCalloutBold") public static let footnoteBold: UIFont.TextStyle = .init(rawValue: "kFootnoteBold") - + public static let title2Bold: UIFont.TextStyle = .init(rawValue: "kTitle2Bold") } diff --git a/Sources/GiniCaptureSDK/Core/GiniConfiguration.swift b/Sources/GiniCaptureSDK/Core/GiniConfiguration.swift index 7286b00..9f5cff1 100644 --- a/Sources/GiniCaptureSDK/Core/GiniConfiguration.swift +++ b/Sources/GiniCaptureSDK/Core/GiniConfiguration.swift @@ -108,7 +108,8 @@ import GiniBankAPILibrary ButtonConfiguration(backgroundColor: .GiniCapture.dark4, borderColor: GiniColor(light: UIColor.GiniCapture.light6, dark: UIColor.clear).uiColor(), - titleColor: .GiniCapture.accent1, + titleColor: GiniColor(light: UIColor.GiniCapture.dark6, + dark: UIColor.GiniCapture.light1).uiColor(), shadowColor: .clear, cornerRadius: 16, borderWidth: 2, @@ -326,6 +327,11 @@ import GiniBankAPILibrary * Set an adapter implementation to show a custom bottom navigation bar on the review screen. */ public var reviewNavigationBarBottomAdapter: ReviewScreenBottomNavigationBarAdapter? + + /** + * Set an adapter implementation to show a custom bottom navigation bar on the image picker screen. + */ + public var imagePickerNavigationBarBottomAdapter: ImagePickerBottomNavigationBarAdapter? /** * Set an adapter implementation to show a custom bottom navigation bar on the onboarding screen. diff --git a/Sources/GiniCaptureSDK/Core/Helpers/ButtonConfiguration.swift b/Sources/GiniCaptureSDK/Core/Helpers/ButtonConfiguration.swift index de0ad67..fe70166 100644 --- a/Sources/GiniCaptureSDK/Core/Helpers/ButtonConfiguration.swift +++ b/Sources/GiniCaptureSDK/Core/Helpers/ButtonConfiguration.swift @@ -54,7 +54,7 @@ extension BottomLabelButton { } } -extension UIButton { +public extension UIButton { func configure(with configuration: ButtonConfiguration) { self.backgroundColor = configuration.backgroundColor self.layer.borderColor = configuration.borderColor.cgColor diff --git a/Sources/GiniCaptureSDK/Core/Models/GiniError.swift b/Sources/GiniCaptureSDK/Core/Models/GiniError.swift index afc7e5b..b696d52 100644 --- a/Sources/GiniCaptureSDK/Core/Models/GiniError.swift +++ b/Sources/GiniCaptureSDK/Core/Models/GiniError.swift @@ -178,7 +178,7 @@ public protocol GiniCaptureError: Error { } public static func == (lhs: DocumentValidationError, rhs: DocumentValidationError) -> Bool { - return lhs.message == rhs.message + return lhs.rawValue == rhs.rawValue } } diff --git a/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift b/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift index 0b09ef5..7b3725b 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift @@ -106,8 +106,8 @@ final class CaptureSuggestionsView: UIView { // Center on align to margins depending on device if UIDevice.current.isIpad { - Constraints.active(item: suggestionContainer, attr: .width, relatedBy: .lessThanOrEqual, to: self, - attr: .width, multiplier: 0.9) + Constraints.active(item: suggestionContainer, attr: .width, relatedBy: .equal, to: self, + attr: .width, multiplier: 0.7) Constraints.active(item: suggestionContainer, attr: .centerX, relatedBy: .equal, to: self, attr: .centerX) } else { Constraints.active(item: suggestionContainer, attr: .leading, relatedBy: .equal, to: self, attr: .leading, diff --git a/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera2/Camera2ViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera2/Camera2ViewController.swift index 295a481..eb71bba 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera2/Camera2ViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera2/Camera2ViewController.swift @@ -44,6 +44,7 @@ public final class Camera2ViewController: UIViewController, CameraScreen { private var navigationBarBottomAdapter: CameraBottomNavigationBarAdapter? private var bottomNavigationBar: UIView? + @IBOutlet weak var iPadBottomPaneConstraint: NSLayoutConstraint! @IBOutlet weak var bottomButtonsConstraints: NSLayoutConstraint! @IBOutlet weak var bottomPaneConstraint: NSLayoutConstraint! /** @@ -183,7 +184,7 @@ public final class Camera2ViewController: UIViewController, CameraScreen { private func layoutBottomNavigationBar(_ navigationBar: UIView) { if UIDevice.current.isIpad { - view.removeConstraints([cameraPreviewBottomContraint]) + view.removeConstraints([cameraPreviewBottomContraint, iPadBottomPaneConstraint]) navigationBar.translatesAutoresizingMaskIntoConstraints = false view.addSubview(navigationBar) NSLayoutConstraint.activate([ @@ -191,6 +192,7 @@ public final class Camera2ViewController: UIViewController, CameraScreen { navigationBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), navigationBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), navigationBar.heightAnchor.constraint(equalToConstant: navigationBar.frame.height), + cameraPane.bottomAnchor.constraint(equalTo: navigationBar.topAnchor), cameraPreviewViewController.view.bottomAnchor.constraint(equalTo: navigationBar.topAnchor) ]) } else { diff --git a/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraPreviewViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraPreviewViewController.swift index 13bad95..aadc3e5 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraPreviewViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraPreviewViewController.swift @@ -78,8 +78,14 @@ final class CameraPreviewViewController: UIViewController { return UIImageNamedPreferred(named: "cameraFocusSmall") } + // A flag to determine the default image when testing on simulator. + private var isReturnAssistantTesting = true fileprivate var defaultImage: UIImage? { - return UIImageNamedPreferred(named: "cameraDefaultDocumentImage") + if isReturnAssistantTesting { + return UIImageNamedPreferred(named: "CameraDefaultReturnAssistantDocument") + } else { + return UIImageNamedPreferred(named: "cameraDefaultDocumentImage") + } } var isAuthorized = false diff --git a/Sources/GiniCaptureSDK/Core/Screens/Camera/Views/CameraPane.swift b/Sources/GiniCaptureSDK/Core/Screens/Camera/Views/CameraPane.swift index 7fd233b..f9ff88f 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Camera/Views/CameraPane.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Camera/Views/CameraPane.swift @@ -16,6 +16,8 @@ final class CameraPane: UIView { @IBOutlet weak var leftButtonsStack: UIView! @IBOutlet weak var thumbnailConstraint: NSLayoutConstraint! @IBOutlet weak var leftStackViewMargin: NSLayoutConstraint! + + private var shouldShowFlashButton: Bool = false override func awakeFromNib() { super.awakeFromNib() setupView() @@ -83,6 +85,7 @@ final class CameraPane: UIView { } func toggleFlashButtonActivation(state: Bool) { + shouldShowFlashButton = state flashButton.isHidden = !state } @@ -94,8 +97,11 @@ final class CameraPane: UIView { func setupAuthorization(isHidden: Bool) { let giniConfiguration = GiniConfiguration.shared self.isHidden = isHidden + captureButton.isHidden = isHidden - flashButton.isHidden = isHidden + if shouldShowFlashButton { + flashButton.isHidden = isHidden + } if cameraTitleLabel != nil { cameraTitleLabel.isHidden = isHidden } diff --git a/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/DefaultImagePickerBottomNavigationBarAdapter.swift b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/DefaultImagePickerBottomNavigationBarAdapter.swift new file mode 100644 index 0000000..0baa960 --- /dev/null +++ b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/DefaultImagePickerBottomNavigationBarAdapter.swift @@ -0,0 +1,38 @@ +// +// DefaultImagePickerBottomNavigationBarAdapter.swift +// +// +// Created by David Vizaknai on 13.01.2023. +// + +import UIKit + +final class DefaultImagePickerBottomNavigationBarAdapter: ImagePickerBottomNavigationBarAdapter { + private var backButtonCallback: (() -> Void)? + + // Add the callback whenever the back button is clicked + func setBackButtonClickedActionCallback(_ callback: @escaping () -> Void) { + backButtonCallback = callback + } + + func injectedView() -> UIView { + if let navigationBarView = BackButtonBottomNavigationBar().loadNib() as? BackButtonBottomNavigationBar { + navigationBarView.backButton.addTarget( + self, + action: #selector(backButtonClicked), + for: .touchUpInside) + return navigationBarView + } else { + return UIView() + } + } + + @objc func backButtonClicked() { + backButtonCallback?() + } + + func onDeinit() { + backButtonCallback = nil + } +} + diff --git a/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/GalleryCoordinator.swift b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/GalleryCoordinator.swift index b90eb6e..28d0e1e 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/GalleryCoordinator.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/GalleryCoordinator.swift @@ -56,7 +56,11 @@ final class GalleryCoordinator: NSObject, Coordinator { lazy fileprivate(set) var albumsController: AlbumsPickerViewController = { let albumsPickerVC = AlbumsPickerViewController(galleryManager: self.galleryManager) albumsPickerVC.delegate = self - albumsPickerVC.navigationItem.leftBarButtonItem = self.cancelButton + if giniConfiguration.bottomNavigationBarEnabled { + albumsPickerVC.navigationItem.rightBarButtonItem = self.cancelButton + } else { + albumsPickerVC.navigationItem.leftBarButtonItem = self.cancelButton + } return albumsPickerVC }() @@ -146,6 +150,9 @@ final class GalleryCoordinator: NSObject, Coordinator { giniConfiguration: giniConfiguration) imagePickerViewController.delegate = self imagePickerViewController.navigationItem.rightBarButtonItem = cancelButton + if giniConfiguration.bottomNavigationBarEnabled { + imagePickerViewController.navigationItem.setHidesBackButton(true, animated: false) + } return imagePickerViewController } @@ -225,8 +232,8 @@ extension GalleryCoordinator: UINavigationControllerDelegate { to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { if let imagePicker = fromVC as? ImagePickerViewController { galleryManager.stopCachingImages(for: imagePicker.currentAlbum) - selectedImageDocuments.removeAll() currentImagePickerViewController = nil + selectedImageDocuments.removeAll() } return nil } diff --git a/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/ImagePickerBottomNavigationBarAdapter.swift b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/ImagePickerBottomNavigationBarAdapter.swift new file mode 100644 index 0000000..667fd37 --- /dev/null +++ b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/ImagePickerBottomNavigationBarAdapter.swift @@ -0,0 +1,24 @@ +// +// ImagePickerBottomNavigationBarAdapter.swift.swift +// +// +// Created by David Vizaknai on 13.01.2023. +// + +import UIKit + +/** +Protocol for injecting a custom bottom navigation bar on the image picker screen. + +- note: Bottom navigation only. +*/ +public protocol ImagePickerBottomNavigationBarAdapter: InjectedViewAdapter { + + /** + * Set the callback for the back button action. + * + * - Parameter callback: An action callback, which should be retained and called in back button action method + */ + func setBackButtonClickedActionCallback(_ callback: @escaping () -> Void) +} + diff --git a/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/ImagePickerViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/ImagePickerViewController.swift index 70c3490..d373f9b 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/ImagePickerViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Document picker/Gallery/ImagePickerViewController.swift @@ -26,6 +26,8 @@ final class ImagePickerViewController: UIViewController { fileprivate let galleryManager: GalleryManagerProtocol fileprivate let giniConfiguration: GiniConfiguration private var isInitialized: Bool = false + private var isLayoutDone: Bool = false + private var navigationBarBottomAdapter: ImagePickerBottomNavigationBarAdapter? // MARK: - Views @@ -44,6 +46,12 @@ final class ImagePickerViewController: UIViewController { forCellWithReuseIdentifier: ImagePickerCollectionViewCell.identifier) return collectionView }() + + private lazy var contentView: UIView = { + let contentView = UIView() + contentView.translatesAutoresizingMaskIntoConstraints = false + return contentView + }() // MARK: - Initializers @@ -62,23 +70,47 @@ final class ImagePickerViewController: UIViewController { // MARK: - UIViewController - override func loadView() { - super.loadView() - - title = currentAlbum.title - - view.backgroundColor = GiniColor(light: .GiniCapture.light2, dark: .GiniCapture.dark2).uiColor() - - view.addSubview(collectionView) - - Constraints.pin(view: collectionView, toSuperView: view) + override func viewDidLoad() { + super.viewDidLoad() + + setupView() + configureBottomNavigationBar() + setupConstraints() } - + override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() + scrollToBottomOnStartup() + isLayoutDone = true } - + + private func setupView() { + title = currentAlbum.title + + view.backgroundColor = GiniColor(light: .GiniCapture.light2, dark: .GiniCapture.dark2).uiColor() + view.addSubview(contentView) + contentView.addSubview(collectionView) + } + + private func setupConstraints() { + let contentViewBottomConstraint = contentView.bottomAnchor.constraint( + greaterThanOrEqualTo: view.bottomAnchor) + contentViewBottomConstraint.priority = .defaultLow + + NSLayoutConstraint.activate([ + collectionView.topAnchor.constraint(equalTo: contentView.topAnchor), + collectionView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), + collectionView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), + collectionView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), + + contentView.topAnchor.constraint(equalTo: view.topAnchor), + contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor), + contentView.trailingAnchor.constraint(equalTo: view.trailingAnchor), + contentViewBottomConstraint + ]) + } + // MARK: - Others func addToDownloadingItems(index: IndexPath, needsReloading: Bool = true) { @@ -118,6 +150,7 @@ final class ImagePickerViewController: UIViewController { } fileprivate func scrollToBottomOnStartup() { + guard isLayoutDone else { return } // This tweak is needed to fix an issue with the UICollectionView. UICollectionView doesn't // scroll to the bottom on `viewWillAppear`, which is right after `viewDidLayoutSubviews`. // Since this method can be called several times during the lifecycle, there should be @@ -130,6 +163,42 @@ final class ImagePickerViewController: UIViewController { animated: false) } } + + private func configureBottomNavigationBar() { + if giniConfiguration.bottomNavigationBarEnabled { + if let bottomBar = giniConfiguration.imagePickerNavigationBarBottomAdapter { + navigationBarBottomAdapter = bottomBar + } else { + navigationBarBottomAdapter = DefaultImagePickerBottomNavigationBarAdapter() + } + + navigationBarBottomAdapter?.setBackButtonClickedActionCallback { [weak self] in + self?.navigationController?.popViewController(animated: true) + } + + if let navigationBar = + navigationBarBottomAdapter?.injectedView() { + navigationBar.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(navigationBar) + + layoutBottomNavigationBar(navigationBar) + } + } + } + + private func layoutBottomNavigationBar(_ navigationBar: UIView) { + navigationBar.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(navigationBar) + NSLayoutConstraint.activate([ + contentView.bottomAnchor.constraint(equalTo: navigationBar.topAnchor), + navigationBar.bottomAnchor.constraint(equalTo: view.bottomAnchor), + navigationBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), + navigationBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), + navigationBar.heightAnchor.constraint(equalToConstant: 114) + ]) + view.bringSubviewToFront(navigationBar) + view.layoutSubviews() + } } // MARK: UICollectionViewDataSource diff --git a/Sources/GiniCaptureSDK/Core/Screens/Help/ViewControllers/HelpImportViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Help/ViewControllers/HelpImportViewController.swift index a8e8de9..393168f 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Help/ViewControllers/HelpImportViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Help/ViewControllers/HelpImportViewController.swift @@ -129,6 +129,8 @@ extension HelpImportViewController: UITableViewDataSource { itemType: HelpImportCellType, rowNumber: Int) { let headerTitle: String + let accessibilityDescription: String + switch itemType { case .selectInvoice: headerTitle = "\(rowNumber). " + NSLocalizedStringPreferredFormat( @@ -139,6 +141,10 @@ extension HelpImportViewController: UITableViewDataSource { "ginicapture.help.import.selectInvoice.desc", comment: "Select an invoice description") cell.importImageView.image = UIImageNamedPreferred(named: "helpImport1") + + accessibilityDescription = NSLocalizedStringPreferredFormat( + "ginicapture.help.import.selectInvoice.accessibility", + comment: "Select an invoice accessibility description") case .importToApp: headerTitle = "\(rowNumber). " + NSLocalizedStringPreferredFormat( "ginicapture.help.import.importtoapp.title", comment: "Import to app header") @@ -147,6 +153,10 @@ extension HelpImportViewController: UITableViewDataSource { "ginicapture.help.import.importtoapp.desc", comment: "Import to app description") cell.importImageView.image = UIImageNamedPreferred(named: "helpImport2") + + accessibilityDescription = NSLocalizedStringPreferredFormat( + "ginicapture.help.import.importtoapp.accessibility", + comment: "Import to app accessibility description") case .dragAndDrop: headerTitle = "\(rowNumber). " + NSLocalizedStringPreferredFormat( "ginicapture.help.import.draganddrop.title", comment: "Drag and Drop header") @@ -155,8 +165,12 @@ extension HelpImportViewController: UITableViewDataSource { "ginicapture.help.import.draganddrop.desc", comment: "Drag and Drop description") cell.importImageView.image = UIImageNamedPreferred(named: "helpImport3") + + accessibilityDescription = NSLocalizedStringPreferredFormat( + "ginicapture.help.import.draganddrop.accessibility", + comment: "Drag and Drop accessibility description") } - configureCellAccessibility(cell: cell, item: headerTitle) + configureCellAccessibility(cell: cell, item: accessibilityDescription) } private func configureCell(cell: HelpImportCell, indexPath: IndexPath) { diff --git a/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift index 5ab9d3f..06295d9 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift @@ -326,9 +326,10 @@ extension ReviewViewController { } else { if resetToEnd { resetToEnd = false - setCellStatus(for: currentPage, isActive: true) } + setCellStatus(for: currentPage, isActive: true) } + collectionView.reloadData() } public override func viewWillLayoutSubviews() { @@ -469,6 +470,8 @@ extension ReviewViewController { extension ReviewViewController { private func addConstraints() { + collectionViewHeightConstraint.priority = .defaultLow + NSLayoutConstraint.activate(tipLabelConstraints) NSLayoutConstraint.activate(collectionViewConstraints) NSLayoutConstraint.activate(pageControlConstraints) diff --git a/Sources/GiniCaptureSDK/GiniCaptureSDKVersion.swift b/Sources/GiniCaptureSDK/GiniCaptureSDKVersion.swift index 3f4f1c3..fd9d98f 100644 --- a/Sources/GiniCaptureSDK/GiniCaptureSDKVersion.swift +++ b/Sources/GiniCaptureSDK/GiniCaptureSDKVersion.swift @@ -5,4 +5,4 @@ // Created by Nadya Karaban on 29.10.21. // -public let GiniCaptureSDKVersion = "3.0.0-beta02" +public let GiniCaptureSDKVersion = "3.0.0-beta03" diff --git a/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift b/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift index 55a8300..2414d2b 100644 --- a/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift +++ b/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift @@ -33,7 +33,7 @@ import GiniBankAPILibrary func giniCaptureDidCancelAnalysis() /** - Called when the 'Enter Manually' was pressed within No Result screen + Called when the 'Enter Manually' was pressed within No Result/ Error screen */ func giniCaptureDidEnterManually() } diff --git a/Sources/GiniCaptureSDK/Resources/Camera/CameraiPad.xib b/Sources/GiniCaptureSDK/Resources/Camera/CameraiPad.xib index cd2dbed..6c69727 100644 --- a/Sources/GiniCaptureSDK/Resources/Camera/CameraiPad.xib +++ b/Sources/GiniCaptureSDK/Resources/Camera/CameraiPad.xib @@ -12,6 +12,7 @@ + @@ -61,6 +62,7 @@ + diff --git a/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/CameraDefaultReturnAssistantDocument.imageset/CameraDefaultReturnAssistantDocument.jpg b/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/CameraDefaultReturnAssistantDocument.imageset/CameraDefaultReturnAssistantDocument.jpg new file mode 100644 index 0000000..ce0b224 Binary files /dev/null and b/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/CameraDefaultReturnAssistantDocument.imageset/CameraDefaultReturnAssistantDocument.jpg differ diff --git a/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/CameraDefaultReturnAssistantDocument.imageset/Contents.json b/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/CameraDefaultReturnAssistantDocument.imageset/Contents.json new file mode 100644 index 0000000..ada148c --- /dev/null +++ b/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/CameraDefaultReturnAssistantDocument.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "CameraDefaultReturnAssistantDocument.jpg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/delete_icon.imageset/delete_icon.pdf b/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/delete_icon.imageset/delete_icon.pdf index 71b42a6..f2ae2c2 100644 Binary files a/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/delete_icon.imageset/delete_icon.pdf and b/Sources/GiniCaptureSDK/Resources/GiniImages.xcassets/delete_icon.imageset/delete_icon.pdf differ diff --git a/Sources/GiniCaptureSDK/Resources/de.lproj/Localizable.strings b/Sources/GiniCaptureSDK/Resources/de.lproj/Localizable.strings index 3365aae..380fbdd 100644 --- a/Sources/GiniCaptureSDK/Resources/de.lproj/Localizable.strings +++ b/Sources/GiniCaptureSDK/Resources/de.lproj/Localizable.strings @@ -144,10 +144,13 @@ "ginicapture.help.import.title" = "Importieren"; "ginicapture.help.import.selectInvoice.title" = "Rechnung auswählen"; "ginicapture.help.import.selectInvoice.desc" = "Bitte die PDF-Rechnung in der Email-App, PDF-Ordner oder einer anderen App aus dem Handy auswählen. Um das Dokument nun an die Banking App zu senden, sollte die “Teilen mit” Funktion benutzt werden, welche mit einem Rechteck und Pfeil nach oben zeigend dargestellt ist."; +"ginicapture.help.import.selectInvoice.accessibility" = "Aktivieren Sie die Teilen-Funktion. Dazu wählen Sie eine Datei aus und verwenden anschließend die Teilen-Funktion, dargestellt als Viereck mit hoch-zeigendem Pfeil"; "ginicapture.help.import.importtoapp.title" = "Aus der App importieren"; "ginicapture.help.import.importtoapp.desc" = "Nun die Banking App aus der Liste auswählen, um das Dokument zum Analysieren weiterzuleiten."; +"ginicapture.help.import.importtoapp.accessibility" = "Banking App auswählen. Wählen Sie nun die gewünschte App aus mit der das Dokument geteilt werden soll"; "ginicapture.help.import.draganddrop.title" = "Drag & drop auf dem iPad"; "ginicapture.help.import.draganddrop.desc" = "Auf dem iPad können Sie ab iOS 12 oder neuer PDFs oder Fotos bequem aus der Datei-Browser-App per “Drag and Drop” in die Banking App gezogen werden, um den Überweisungsprozess zu starten. Hierzu öffnen Sie zunächst Ihre Banking App und die Datei-Browser-App parallel auf Ihrem Bildschirm. Ziehen Sie dann die gewünschte Datei rüber in die Banking App."; +"ginicapture.help.import.draganddrop.accessibility" = "Auf dem Tablet können Sie auch die zu teilende Datei mit Drag and Drop in die Banking App ziehen"; "ginicapture.help.supportedFormats.title" = "Formate"; "ginicapture.help.supportedFormats.section.1.title" = "Unterstützte Formate"; diff --git a/Sources/GiniCaptureSDK/Resources/en.lproj/Localizable.strings b/Sources/GiniCaptureSDK/Resources/en.lproj/Localizable.strings index 06f329b..42450a0 100644 --- a/Sources/GiniCaptureSDK/Resources/en.lproj/Localizable.strings +++ b/Sources/GiniCaptureSDK/Resources/en.lproj/Localizable.strings @@ -123,11 +123,14 @@ are also supported"; "ginicapture.help.import.title" = "How to import"; "ginicapture.help.import.selectInvoice.title" = "Select an invoice"; "ginicapture.help.import.selectInvoice.desc" = "To do so, please select a PDF invoice from within your email app, PDF viewer or other app on your smartphone. To redirect the file to Your Bank, use the “Share” function, represented as a square with the arrow pointing up."; +"ginicapture.help.import.selectInvoice.accessibility" = "Activate share function. Therefore select file and press share button, represented as a square with the arrow pointing up"; "ginicapture.help.import.importtoapp.title" = "Import to app"; "ginicapture.help.import.importtoapp.desc" = "Please select your Banking App from the list to start the analysis and transfer process."; +"ginicapture.help.import.importtoapp.accessibility" = "Select Banking App from the list to start the analysis process"; "ginicapture.help.import.draganddrop.title" = "Drag and drop on iPad"; "ginicapture.help.import.draganddrop.desc" = "If your iPad is running iOS 12 or newer, you can conveniently drag-and-drop PDFs from the iOS Files app to your Banking App to start a payment. To do this, open your Banking App and open the Files app as a second app on the screen. Select the desired invoice file in the Files app and drag this over to your Banking App."; +"ginicapture.help.import.draganddrop.accessibility" = "On tablet you can use the drag and drop function to move the file into the banking app"; "ginicapture.help.supportedFormats.title" = "Formats"; "ginicapture.help.supportedFormats.section.1.title" = "SUPPORTED FORMATS";