From 0045174d2ce22f06de13aa80a7b7b9f261f29e6c Mon Sep 17 00:00:00 2001 From: Team Mobile Schorsch Date: Wed, 17 Nov 2021 17:16:35 +0000 Subject: [PATCH] Release version 1.1.0 --- .jazzy.yaml | 1 + Documentation/source/Customization guide.md | 4 +- Documentation/source/Error logging guide.md | 2 +- Documentation/source/Installation.md | 8 +- Documentation/source/Integration.md | 8 +- Documentation/source/License.md | 48 ++++- Documentation/source/Migration guide.md | 4 + Documentation/source/Open with guide.md | 2 +- .../source/QR Code scanning guide.md | 6 +- LICENSE | 56 +++++- Package.swift | 2 +- README.md | 1 + Sources/GiniCaptureSDK/Core/GiniCapture.swift | 2 +- .../Core/Helpers/GiniCaptureUtils.swift | 2 +- .../Helpers/PreferredButtonResource.swift | 2 +- .../Analysis/AnalysisViewController.swift | 6 +- .../Analysis/CaptureSuggestionsView.swift | 13 +- .../Core/Screens/Camera/Camera.swift | 1 - .../CameraViewController+Constraints.swift | 4 +- .../Screens/Camera/CameraViewController.swift | 6 +- .../DocumentPickerCoordinator.swift | 177 ++++++++---------- .../Screens/Help/HelpMenuViewController.swift | 14 +- ...ImageAnalysisNoResultsViewController.swift | 12 +- .../OpenWithTutorialViewController.swift | 4 +- .../SupportedFormatsViewController.swift | 21 ++- .../MultipageReviewMainCollectionCell.swift | 2 +- .../MultipageReviewPagesCollectionCell.swift | 2 +- .../MultipageReviewViewController.swift | 12 +- .../Multipage Review/PageStateView.swift | 4 +- .../OnboardingContainerViewController.swift | 4 +- .../Screens/Review/ReviewViewController.swift | 6 +- .../GiniScreenAPICoordinator+Camera.swift | 1 - .../GiniNetworkingScreenAPICoordinator.swift | 2 +- Sources/GiniCaptureSDKVersion.swift | 2 +- .../HelpMenuViewControllerTests.swift | 6 +- .../PageStateViewTests.swift | 6 +- .../SupportedFormatsViewControllerTests.swift | 4 +- 37 files changed, 262 insertions(+), 195 deletions(-) create mode 100644 Documentation/source/Migration guide.md diff --git a/.jazzy.yaml b/.jazzy.yaml index ae149e9..f62d5d8 100644 --- a/.jazzy.yaml +++ b/.jazzy.yaml @@ -32,6 +32,7 @@ custom_categories: - QR Code scanning guide - Event tracking guide - Error logging guide + - Migration guide - name: Classes children: diff --git a/Documentation/source/Customization guide.md b/Documentation/source/Customization guide.md index 9af8101..64a7ff0 100644 --- a/Documentation/source/Customization guide.md +++ b/Documentation/source/Customization guide.md @@ -18,11 +18,9 @@ The Gini Capture SDK components can be customized either through the `GiniConfig ## Supporting dark mode -Some background and text colors use the `GiniColor` type with which you can set colors for dark and light modes. Please make sure to set contrasting images to the background colors in your `.xcassets` for the Gini Vision Library images you override (e.g. `onboardingPage1`). The text colors should also be set in contrast to the background colors. +Some background and text colors use the `GiniColor` type with which you can set colors for dark and light modes. Please make sure to set contrasting images to the background colors in your `.xcassets` for the Gini Capture SDK images you override (e.g. `onboardingPage1`). The text colors should also be set in contrast to the background colors. ## Generic components - -`GiniConfiguration.backgroundColor` is deprecated in version 5.5.0. Use the screen specific background color instead e.g. `GiniConfiguration.onboardingScreenBackgroundColor`. ##### 1. Navigation bar
diff --git a/Documentation/source/Error logging guide.md b/Documentation/source/Error logging guide.md index b0bef79..1ef0a11 100644 --- a/Documentation/source/Error logging guide.md +++ b/Documentation/source/Error logging guide.md @@ -1,7 +1,7 @@ Error Logging ============================= -The Gini Capture SDK logs errors to the Gini Pay API when the default networking implementation is used (see the UI with Networking (Recommended) section in Integration guide). We log only non-sensitive information like response status codes, headers and error messsages. +The Gini Capture SDK logs errors to the Gini Bank API when the default networking implementation is used (see the UI with Networking (Recommended) section in Integration guide). We log only non-sensitive information like response status codes, headers and error messsages. You can disable the default error logging by passing false to `GiniConfiguration().giniErrorLoggerIsOn`. diff --git a/Documentation/source/Installation.md b/Documentation/source/Installation.md index ee7feea..64dad7e 100644 --- a/Documentation/source/Installation.md +++ b/Documentation/source/Installation.md @@ -8,16 +8,16 @@ Gini Capture SDK can either be installed by using Swift Package Manager or by ma The [Swift Package Manager](https://swift.org/package-manager/) is a tool for managing the distribution of Swift code. Once you have your Swift package set up, adding `GiniCaptureSDK` as a dependency is as easy as adding it to the dependencies value of your `Package.swift` -```swif +```swift dependencies: [ - .package(url: "https://github.com/gini/capture-sdk-ios.git", .exact("1.0.0")) + .package(url: "https://github.com/gini/capture-sdk-ios.git", .exact("1.1.0")) ] ``` In case that you want to use the certificate pinning in the library, add `GiniCaptureSDKPinning`: -```swif +```swift dependencies: [ - .package(url: "https://github.com/gini/capture-sdk-pinning-ios.git", .exact("1.0.0")) + .package(url: "https://github.com/gini/capture-sdk-pinning-ios.git", .exact("1.1.0")) ] ``` diff --git a/Documentation/source/Integration.md b/Documentation/source/Integration.md index fd58100..69a7e09 100644 --- a/Documentation/source/Integration.md +++ b/Documentation/source/Integration.md @@ -53,7 +53,7 @@ let viewController = GiniCapture.viewController(withClient: client, present(viewController, animated: true, completion:nil) ``` -**Note**: Starting from Gini Capture SDK version 1.0.6 the pinning certification we suppo**iOS 12** +**Note**: Starting from Gini Capture SDK version 1.0.6 certificate pinning requires **iOS 12**. > ⚠️ **Important** > - The document metadata for the upload process is intended to be used for reporting. @@ -95,9 +95,9 @@ The components that can be found in the SDK are: ## Sending Feedback -Your app should send feedback for the extractions the Gini Pay API delivered. Feedback should be sent only for the extractions the user has seen and accepted (or corrected). +Your app should send feedback for the extractions the Gini Bank API delivered. Feedback should be sent only for the extractions the user has seen and accepted (or corrected). -For additional information about feedback see the [Gini Pay API documentation](https://pay-api.gini.net/documentation/#send-feedback-and-get-even-better-extractions-next-time). +For additional information about feedback see the [Gini Bank API documentation](https://pay-api.gini.net/documentation/#send-feedback-and-get-even-better-extractions-next-time). ### Default Implementation @@ -127,6 +127,6 @@ sendFeedbackBlock(updatedExtractions) ``` ### Custom Implementation -If you use your own networking implementation and directly communicate with the Gini Pay API then see [this section](https://pay-api.gini.net/documentation/#submitting-feedback-on-extractions) in its documentation on how to send feedback. +If you use your own networking implementation and directly communicate with the Gini Bank API then see [this section](https://pay-api.gini.net/documentation/#submitting-feedback-on-extractions) in its documentation on how to send feedback. In case you use the [Gini Bank API Library](https://developer.gini.net/gini-mobile-ios/GiniBankAPILibrary/) then see [this section](https://developer.gini.net/gini-mobile-ios/GiniBankAPILibrary/getting-started.html) in its documentation for details. \ No newline at end of file diff --git a/Documentation/source/License.md b/Documentation/source/License.md index 8185583..85c2839 100644 --- a/Documentation/source/License.md +++ b/Documentation/source/License.md @@ -1,7 +1,7 @@ License ======= -The Gini Capture SDK for iOS is licensed under a Private License. +The [Gini Capture SDK for iOS](https://github.com/gini/capture-sdk-ios) is licensed under a Private License. Always make sure to ship all license notices and permissions with your application. @@ -21,7 +21,7 @@ Always make sure to ship all license notices and permissions with your applicati The Gini Capture SDK uses code from the following libraries: -## [Gini Pay Api Library](https://github.com/gini/gini-pay-api-lib-ios) +## [Gini Bank API Library for iOS](https://github.com/gini/bank-api-library-ios) The MIT License (MIT) @@ -45,6 +45,50 @@ The Gini Capture SDK uses code from the following libraries: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +The [Gini Capture SDK Pinning for iOS](https://github.com/gini/capture-sdk-pinning-ios) is licensed under a Private License. + +Always make sure to ship all license notices and permissions with your application. + + Copyright (c) 2014-2021, Gini GmbH + All rights reserved. + + The Gini Capture SDK is licensed through Gini GmbH ("Gini") and may not be + used, altered or copied in any way without explicit permission by Gini. The + terms of usage are defined in a separate usage agreement between Gini and the + licensee, where the licensee can gain access to a non-exclusive, + non-transferable usage right which is restricted for the time of a contractual + relationship between Gini and the licensee. + + For license related inquiries contact Gini via the email address + technical-support@gini.net. + + +The Gini Capture SDK Pinning uses code from the following libraries: + +## [Gini Bank API Library Pinning for iOS](https://github.com/gini/bank-api-library-pinning-ios) + + The MIT License (MIT) + + Copyright (c) 2014 - 2021 Gini GmbH + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ## [TrustKit](https://github.com/datatheorem/TrustKit) The MIT License (MIT) diff --git a/Documentation/source/Migration guide.md b/Documentation/source/Migration guide.md new file mode 100644 index 0000000..cb65c99 --- /dev/null +++ b/Documentation/source/Migration guide.md @@ -0,0 +1,4 @@ +Migrate from the old Gini Capture SDK +===================================== + +We've migrated from CocoaPods to Swift Package Manager. Please, find more details in [Installation](https://developer.gini.net/gini-mobile-ios/GiniCaptureSDK/installation.html). diff --git a/Documentation/source/Open with guide.md b/Documentation/source/Open with guide.md index 9be6450..f8f513a 100644 --- a/Documentation/source/Open with guide.md +++ b/Documentation/source/Open with guide.md @@ -108,4 +108,4 @@ func application(_ app: UIApplication, ### Documentation - [AppDelegate resource handling](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623112-application) from _Apple Documentation_ -- [Supported file formats](http://developer.gini.net/gini-api/html/documents.html#supported-file-formats) from _Gini API_ +- [Supported file formats](https://pay-api.gini.net/documentation/#supported-file-formats) from _Gini Bank API_ diff --git a/Documentation/source/QR Code scanning guide.md b/Documentation/source/QR Code scanning guide.md index 125f56c..7c3a1ce 100644 --- a/Documentation/source/QR Code scanning guide.md +++ b/Documentation/source/QR Code scanning guide.md @@ -22,10 +22,6 @@ Handle and process the Payment Data Once the QR code has been detected and the user has tapped the button to use it, the payment data is returned and ready to be analyzed in the API. In order to handle the Payment Data from the QR code, on one hand if you are using the _Screen API_ the `GiniQRCodeDocument` is received in the delegate method `GiniCaptureDelegate.didCapture(document:)`, where it must be sent to the API as though it was an image or a pdf. On the other hand if you are using the _Component API_, you will get the `GiniQRCodeDocument` in the `CameraScreenSuccessBlock`, where it also must be sent to the API as if it was an image or a pdf. -#### Note: ---- -If you are using the [Gini API SDK](https://github.com/gini/gini-sdk-ios) to send the documents to the Gini API, you have to update to `0.5.2` in order to analyze the QR Codes. - Customization ---------------------- It is possible to customize the text label, button and background colors with these parameters: @@ -42,7 +38,7 @@ Supported QR codes ---------------------- The supported QR codes are: -- [BezahlCode](http://www.bezahlcode.de) +- BezahlCode - [EPC069-12](https://www.europeanpaymentscouncil.eu/document-library/guidance-documents/quick-response-code-guidelines-enable-data-capture-initiation) - [Stuzza (AT)](https://www.stuzza.at/de/zahlungsverkehr/qr-code.html) - [GiroCode (DE)](https://www.girocode.de/rechnungsempfaenger/) diff --git a/LICENSE b/LICENSE index 1c9c517..c6749ab 100644 --- a/LICENSE +++ b/LICENSE @@ -1,12 +1,50 @@ Copyright (c) 2014-2021, Gini GmbH All rights reserved. -The Gini Capture SDK is licensed through Gini GmbH ("Gini") and may not be -used, altered or copied in any way without explicit permission by Gini. The -terms of usage are defined in a separate usage agreement between Gini and the -licensee, where the licensee can gain access to a non-exclusive, -non-transferable usage right which is restricted for the time of a contractual -relationship between Gini and the licensee. - -For license related inquiries contact Gini via the email address -technical-support@gini.net. +License +======= + +The [Gini Capture SDK for iOS](https://github.com/gini/capture-sdk-ios) is licensed under a Private License. + +Always make sure to ship all license notices and permissions with your application. + + Copyright (c) 2014-2021, Gini GmbH + All rights reserved. + + The Gini Capture SDK is licensed through Gini GmbH ("Gini") and may not be + used, altered or copied in any way without explicit permission by Gini. The + terms of usage are defined in a separate usage agreement between Gini and the + licensee, where the licensee can gain access to a non-exclusive, + non-transferable usage right which is restricted for the time of a contractual + relationship between Gini and the licensee. + + For license related inquiries contact Gini via the email address + technical-support@gini.net. + + +The Gini Capture SDK uses code from the following libraries: + +## [Gini Bank API Library for iOS](https://github.com/gini/bank-api-library-ios) + + The MIT License (MIT) + + Copyright (c) 2014 - 2021 Gini GmbH + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + diff --git a/Package.swift b/Package.swift index ae07d03..3497fa3 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("0.0.1")), + .package(name: "GiniBankAPILibrary", url: "https://github.com/gini/bank-api-library-ios.git", .exact("1.0.0")), ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. diff --git a/README.md b/README.md index b062528..31c071d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ [![Platform](https://img.shields.io/badge/platform-iOS-lightgrey.svg)]() [![Devices](https://img.shields.io/badge/devices-iPhone%20%7C%20iPad-blue.svg)]() [![Swift version](https://img.shields.io/badge/swift-5.0-orange.svg)]() +[![Swift package manager](https://img.shields.io/badge/Swift_Package_Manager-compatible-orange?style=flat-square)]() The Gini Capture SDK provides components for capturing, reviewing and analyzing photos of invoices and remittance slips. diff --git a/Sources/GiniCaptureSDK/Core/GiniCapture.swift b/Sources/GiniCaptureSDK/Core/GiniCapture.swift index 935d6e3..1605201 100644 --- a/Sources/GiniCaptureSDK/Core/GiniCapture.swift +++ b/Sources/GiniCaptureSDK/Core/GiniCapture.swift @@ -125,7 +125,7 @@ public typealias GiniCaptureNetworkDelegate = AnalysisDelegate & UploadDelegate The Gini Capture SDK provides views for capturing, reviewing and analysing documents. By integrating this library in your application you can allow your users to easily take a picture of - a document, review it and - by implementing the necessary callbacks - upload the document for analysis to the Gini API. + a document, review it and - by implementing the necessary callbacks - upload the document for analysis to the Gini Bank API. The Gini Capture SDK can be integrated in two ways, either by using the **Screen API** or the **Component API**. The Screen API provides a fully pre-configured navigation controller for diff --git a/Sources/GiniCaptureSDK/Core/Helpers/GiniCaptureUtils.swift b/Sources/GiniCaptureSDK/Core/Helpers/GiniCaptureUtils.swift index 572ba82..5676bdf 100644 --- a/Sources/GiniCaptureSDK/Core/Helpers/GiniCaptureUtils.swift +++ b/Sources/GiniCaptureSDK/Core/Helpers/GiniCaptureUtils.swift @@ -34,7 +34,7 @@ public func UIImageNamedPreferred(named name: String) -> UIImage? { - returns: String resource for the given key. */ -func NSLocalizedStringPreferredFormat(_ key: String, +public func NSLocalizedStringPreferredFormat(_ key: String, fallbackKey: String = "", comment: String, isCustomizable: Bool = true) -> String { diff --git a/Sources/GiniCaptureSDK/Core/Helpers/PreferredButtonResource.swift b/Sources/GiniCaptureSDK/Core/Helpers/PreferredButtonResource.swift index d195127..ffa6e54 100644 --- a/Sources/GiniCaptureSDK/Core/Helpers/PreferredButtonResource.swift +++ b/Sources/GiniCaptureSDK/Core/Helpers/PreferredButtonResource.swift @@ -36,7 +36,7 @@ class GiniPreferredButtonResource: PreferredButtonResource { private let localizedTextComment: String? private let localizedConfigEntry: String? private let appBundle = Bundle.main - private let libBundle = Bundle(for: GiniCapture.self) + private let libBundle = Bundle.module private var imageSource: ResourceOrigin { if let name = imageName { if UIImage(named: name, in: appBundle, compatibleWith: nil) != nil { diff --git a/Sources/GiniCaptureSDK/Core/Screens/Analysis/AnalysisViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Analysis/AnalysisViewController.swift index 84b2052..84d109b 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Analysis/AnalysisViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Analysis/AnalysisViewController.swift @@ -206,9 +206,9 @@ import UIKit self.view.addSubview(imageView) imageView.translatesAutoresizingMaskIntoConstraints = false - Constraints.active(item: imageView, attr: .top, relatedBy: .equal, to: self.topLayoutGuide, attr: .bottom, + Constraints.active(item: imageView, attr: .top, relatedBy: .equal, to: view.safeAreaLayoutGuide, attr: .top, priority: 999) - Constraints.active(item: imageView, attr: .bottom, relatedBy: .equal, to: self.bottomLayoutGuide, attr: .top, + Constraints.active(item: imageView, attr: .bottom, relatedBy: .equal, to: view.safeAreaLayoutGuide, attr: .bottom, priority: 999) Constraints.active(item: imageView, attr: .trailing, relatedBy: .equal, to: self.view, attr: .trailing) Constraints.active(item: imageView, attr: .leading, relatedBy: .equal, to: self.view, attr: .leading) @@ -288,7 +288,7 @@ import UIKit fileprivate func showCaptureSuggestions(giniConfiguration: GiniConfiguration) { let captureSuggestions = CaptureSuggestionsView(superView: self.view, - bottomLayout: bottomLayoutGuide, + bottomAnchor: view.safeAreaLayoutGuide.bottomAnchor, font: giniConfiguration.customFont.with(weight: .regular, size: 16, style: .body)) diff --git a/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift b/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift index e3be88b..79f1a82 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Analysis/CaptureSuggestionsView.swift @@ -24,10 +24,9 @@ final class CaptureSuggestionsView: UIView { fileprivate var itemSeparationConstraint: NSLayoutConstraint = NSLayoutConstraint() fileprivate var bottomConstraint: NSLayoutConstraint = NSLayoutConstraint() fileprivate let repeatInterval: TimeInterval = 5 - fileprivate let superViewBottomLayout: UILayoutSupport + fileprivate let superViewBottomAnchor: NSLayoutYAxisAnchor fileprivate let suggestionIconImage = UIImage(named: "analysisSuggestionsIcon", - in: Bundle(for: GiniCapture.self), - compatibleWith: nil) + in: Bundle.module, compatibleWith: nil) fileprivate var suggestionTexts: [String] = [ .localized(resource: AnalysisStrings.suggestion1Text), .localized(resource: AnalysisStrings.suggestion2Text), @@ -35,11 +34,11 @@ final class CaptureSuggestionsView: UIView { .localized(resource: AnalysisStrings.suggestion4Text) ] - init(superView: UIView, bottomLayout: UILayoutSupport, font: UIFont) { + init(superView: UIView, bottomAnchor: NSLayoutYAxisAnchor, font: UIFont) { suggestionContainer = UIView() suggestionTitle = UILabel() suggestionText = UILabel() - superViewBottomLayout = bottomLayout + superViewBottomAnchor = bottomAnchor suggestionIcon = UIImageView(image: suggestionIconImage) suggestionIcon.contentMode = .scaleAspectFit @@ -85,9 +84,7 @@ final class CaptureSuggestionsView: UIView { guard let superview = superview else { return } // self - bottomConstraint = NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, - toItem: superViewBottomLayout, attribute: .top, multiplier: 1, - constant: containerHeight) + bottomConstraint = self.bottomAnchor.constraint(equalTo: superViewBottomAnchor, constant: containerHeight) Constraints.active(item: self, attr: .leading, relatedBy: .equal, to: superview, attr: .leading) Constraints.active(item: self, attr: .trailing, relatedBy: .equal, to: superview, attr: .trailing) Constraints.active(item: self, attr: .height, relatedBy: .equal, to: nil, attr: .notAnAttribute, diff --git a/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera.swift b/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera.swift index 0e41415..08cd272 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Camera/Camera.swift @@ -322,7 +322,6 @@ extension Camera: AVCapturePhotoCaptureDelegate { didCaptureImageHandler?(imageData, nil) } - @available(iOS 11.0, *) func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?){ if error != nil { didCaptureImageHandler?(nil, .captureFailed) diff --git a/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController+Constraints.swift b/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController+Constraints.swift index 9cf49da..eba5098 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController+Constraints.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController+Constraints.swift @@ -60,8 +60,8 @@ extension CameraViewController { to: cameraPreviewViewController.view, attr: .bottom) Constraints.active(item: cameraButtonsViewController.view, attr: .bottom, relatedBy: .equal, - to: self.bottomLayoutGuide, - attr: .top) + to: view.safeAreaLayoutGuide, + attr: .bottom) Constraints.active(item: cameraButtonsViewController.view, attr: .trailing, relatedBy: .equal, to: self.view, attr: .trailing) Constraints.active(item: cameraButtonsViewController.view, attr: .leading, relatedBy: .equal, diff --git a/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController.swift index ee81bad..a9ed689 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Camera/CameraViewController.swift @@ -475,10 +475,10 @@ extension CameraViewController: CameraButtonsViewControllerDelegate { if let tooltip = fileImportToolTipView, tooltip.isHidden == false { showImportFileSheet() } else { - if ToolTipView.shouldShowFileImportToolTip { + if let fileImportToolTipView = self.fileImportToolTipView, ToolTipView.shouldShowFileImportToolTip { shouldShowQRCodeNext = true - fileImportToolTipView?.dismiss(withCompletion: nil) - fileImportToolTipView = nil + fileImportToolTipView.dismiss(withCompletion: nil) + self.fileImportToolTipView = nil } else { showImportFileSheet() } diff --git a/Sources/GiniCaptureSDK/Core/Screens/Document picker/DocumentPickerCoordinator.swift b/Sources/GiniCaptureSDK/Core/Screens/Document picker/DocumentPickerCoordinator.swift index cda2937..f71d067 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Document picker/DocumentPickerCoordinator.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Document picker/DocumentPickerCoordinator.swift @@ -6,28 +6,28 @@ // Copyright © 2017 Gini GmbH. All rights reserved. // -import UIKit import MobileCoreServices +import UIKit /** The CameraViewControllerDelegate protocol defines methods that allow you to handle picked documents from both Gallery and Files Explorer. - + - note: Component API only. */ public protocol DocumentPickerCoordinatorDelegate: AnyObject { /** Called when a user picks one or several files from either the gallery or the files explorer. - + - parameter coordinator: `DocumentPickerCoordinator` where the documents were imported. - parameter documents: One or several documents imported. */ func documentPicker(_ coordinator: DocumentPickerCoordinator, didPick documents: [GiniCaptureDocument]) - + /** Called when the picked documents could not be opened. - + - parameter coordinator: `DocumentPickerCoordinator` where the documents were imported. - parameter urls: URLs of the picked documents. */ @@ -46,7 +46,7 @@ public protocol DocumentPickerCoordinatorDelegate: AnyObject { @objc public enum DocumentPickerType: Int { /// Gallery picker case gallery - + /// File explorer picker case explorer } @@ -57,38 +57,37 @@ public protocol DocumentPickerCoordinatorDelegate: AnyObject { the `delegate` property. When using multipage and having imported/captured images, you have to update the `isPDFSelectionAllowed` property before showing the File explorer in order to filter out PDFs. - + - note: Component API only. */ -//swiftlint:disable file_length +// swiftlint:disable file_length public final class DocumentPickerCoordinator: NSObject { - /** The object that acts as the delegate of the document picker coordinator. */ public weak var delegate: DocumentPickerCoordinatorDelegate? - + /** Used to filter out PDFs when there are already imported images. */ public var isPDFSelectionAllowed: Bool = true - + /** Once the user has selected one or several documents from a picker, this has to be dismissed. Files explorer dismissal is handled by the OS and drag and drop does not need to be dismissed. However, the Gallery picker should be dismissed once the images has been imported. - + It is also used to check if the `currentPickerViewController` is still present so an error dialog can be shown fro there */ - private(set) public var currentPickerDismissesAutomatically: Bool = false - + public private(set) var currentPickerDismissesAutomatically: Bool = false + /** The current picker `UIViewController`. Used to show an error after validating picked documents. */ - private(set) public var currentPickerViewController: UIViewController? - + public private(set) var currentPickerViewController: UIViewController? + /** Indicates if the user granted access to the gallery before. Used to start caching images before showing the Gallery picker. @@ -96,15 +95,15 @@ public final class DocumentPickerCoordinator: NSObject { public var isGalleryPermissionGranted: Bool { return galleryCoordinator.isGalleryPermissionGranted } - + let galleryCoordinator: GalleryCoordinator let giniConfiguration: GiniConfiguration - + fileprivate lazy var navigationBarAppearance: UINavigationBar = .init() fileprivate lazy var searchBarAppearance: UISearchBar = .init() fileprivate lazy var barButtonItemAppearance: UIBarButtonItem = .init() fileprivate lazy var barButtonItemAppearanceInSearchBar: UIBarButtonItem = .init() - + fileprivate var acceptedDocumentTypes: [String] { switch giniConfiguration.fileImportSupportedTypes { case .pdf_and_images: @@ -117,41 +116,40 @@ public final class DocumentPickerCoordinator: NSObject { return [] } } - + /** Designated initializer for the `DocumentPickerCoordinator`. - + - parameter giniConfiguration: `GiniConfiguration` use to configure the pickers. */ public init(giniConfiguration: GiniConfiguration) { self.giniConfiguration = giniConfiguration - self.galleryCoordinator = GalleryCoordinator(giniConfiguration: giniConfiguration) + galleryCoordinator = GalleryCoordinator(giniConfiguration: giniConfiguration) } - + /** Starts caching gallery images. Gallery permissions should have been granted before using it. */ public func startCaching() { galleryCoordinator.start() } - + /** Set up the drag and drop feature in a view. - + - parameter view: View that will handle the drop interaction. - note: Only available in iOS >= 11 */ - @available(iOS 11.0, *) public func setupDragAndDrop(in view: UIView) { let dropInteraction = UIDropInteraction(delegate: self) view.addInteraction(dropInteraction) } - + // MARK: Picker presentation - + /** Shows the Gallery picker from a given viewController - + - parameter viewController: View controller which presentes the gallery picker */ public func showGalleryPicker(from viewController: UIViewController) { @@ -170,61 +168,58 @@ public final class DocumentPickerCoordinator: NSObject { } }) } - + /** Shows the File explorer picker from a given viewController - + - parameter viewController: View controller which presentes the gallery picker */ public func showDocumentPicker(from viewController: UIViewController, device: UIDevice = UIDevice.current) { let documentPicker = UIDocumentPickerViewController(documentTypes: acceptedDocumentTypes, in: .import) - + documentPicker.delegate = self - - if #available(iOS 11.0, *) { - documentPicker.allowsMultipleSelection = giniConfiguration.multipageEnabled - - if let tintColor = giniConfiguration.documentPickerNavigationBarTintColor { - // Starting with iOS 11.0, the UIDocumentPickerViewController navigation bar almost can't be customized, - // only being possible to customize the tint color. To avoid issues with custom UIAppearance styles, - // this is reset to default, saving the current state in order to restore it during dismissal. - saveCurrentNavBarAppearance() - applyDefaultNavBarAppearance() - - UINavigationBar.appearance().tintColor = tintColor - UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]) - .setTitleTextAttributes([.foregroundColor: tintColor], - for: .normal) - } + documentPicker.allowsMultipleSelection = giniConfiguration.multipageEnabled + + if let tintColor = giniConfiguration.documentPickerNavigationBarTintColor { + // Starting with iOS 11.0, the UIDocumentPickerViewController navigation bar almost can't be customized, + // only being possible to customize the tint color. To avoid issues with custom UIAppearance styles, + // this is reset to default, saving the current state in order to restore it during dismissal. + saveCurrentNavBarAppearance() + applyDefaultNavBarAppearance() + + UINavigationBar.appearance().tintColor = tintColor + UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]) + .setTitleTextAttributes([.foregroundColor: tintColor], + for: .normal) } - + // This is needed since the UIDocumentPickerViewController on iPad is presented over the current view controller // without covering the previous screen. This causes that the `viewWillAppear` method is not being called // in the current view controller. if !device.isIpad { setStatusBarStyle(to: .default) } - - self.currentPickerDismissesAutomatically = true - self.currentPickerViewController = documentPicker - + + currentPickerDismissesAutomatically = true + currentPickerViewController = documentPicker + viewController.present(documentPicker, animated: true, completion: nil) } - + /** Dimisses the `currentPickerViewController` - + - parameter completion: Completion block executed once the picker is dismissed */ public func dismissCurrentPicker(completion: @escaping () -> Void) { if currentPickerDismissesAutomatically { completion() } else { - self.galleryCoordinator.dismissGallery(completion: completion) + galleryCoordinator.dismissGallery(completion: completion) } - + currentPickerViewController = nil } } @@ -235,10 +230,10 @@ fileprivate extension DocumentPickerCoordinator { func createDocument(fromData data: Data) -> GiniCaptureDocument? { let documentBuilder = GiniCaptureDocumentBuilder(documentSource: .external) documentBuilder.importMethod = .picker - + return documentBuilder.build(with: data) } - + func data(fromUrl url: URL) -> Data? { do { _ = url.startAccessingSecurityScopedResource() @@ -248,11 +243,10 @@ fileprivate extension DocumentPickerCoordinator { } catch { url.stopAccessingSecurityScopedResource() } - + return nil } - - @available(iOS 11.0, *) + func saveCurrentNavBarAppearance() { update(navigationBarAppearance, with: UINavigationBar.appearance()) update(searchBarAppearance, with: UISearchBar.appearance()) @@ -260,8 +254,7 @@ fileprivate extension DocumentPickerCoordinator { update(barButtonItemAppearanceInSearchBar, with: UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self])) } - - @available(iOS 11.0, *) + func applyDefaultNavBarAppearance() { update(UINavigationBar.appearance(), with: nil) update(UISearchBar.appearance(), with: nil) @@ -269,18 +262,15 @@ fileprivate extension DocumentPickerCoordinator { update(UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]), with: nil) } - - @available(iOS 11.0, *) + func restoreSavedNavBarAppearance() { update(UINavigationBar.appearance(), with: navigationBarAppearance) update(UISearchBar.appearance(), with: searchBarAppearance) update(UIBarButtonItem.appearance(), with: barButtonItemAppearance) update(UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]), with: barButtonItemAppearance) - } - - @available(iOS 11.0, *) + func update(_ currentNavigationBar: UINavigationBar, with navigationBar: UINavigationBar?) { currentNavigationBar.barTintColor = navigationBar?.barTintColor currentNavigationBar.tintColor = navigationBar?.tintColor @@ -290,8 +280,7 @@ fileprivate extension DocumentPickerCoordinator { currentNavigationBar.shadowImage = navigationBar?.shadowImage currentNavigationBar.setBackgroundImage(navigationBar?.backIndicatorImage, for: .default) } - - @available(iOS 11.0, *) + func update(_ currentSearchBar: UISearchBar, with searchBar: UISearchBar?) { currentSearchBar.backgroundColor = searchBar?.backgroundColor currentSearchBar.barTintColor = searchBar?.barTintColor @@ -299,8 +288,7 @@ fileprivate extension DocumentPickerCoordinator { currentSearchBar.searchBarStyle = searchBar?.searchBarStyle ?? .default currentSearchBar.setImage(searchBar?.image(for: .search, state: .normal), for: .search, state: .normal) } - - @available(iOS 11.0, *) + func update(_ currentBarButtonItem: UIBarButtonItem, with barButtonItem: UIBarButtonItem?) { currentBarButtonItem.setTitleTextAttributes(barButtonItem?.titleTextAttributes(for: .normal), for: .normal) @@ -318,7 +306,7 @@ extension DocumentPickerCoordinator: GalleryCoordinatorDelegate { didSelectImageDocuments imageDocuments: [GiniImageDocument]) { delegate?.documentPicker(self, didPick: imageDocuments) } - + func gallery(_ coordinator: GalleryCoordinator, didCancel: Void) { coordinator.dismissGallery() } @@ -329,43 +317,42 @@ extension DocumentPickerCoordinator: GalleryCoordinatorDelegate { extension DocumentPickerCoordinator: UIDocumentPickerDelegate { public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { let documents: [GiniCaptureDocument] = urls - .compactMap(self.data) - .compactMap(self.createDocument) - + .compactMap(data) + .compactMap(createDocument) + guard documents.isNotEmpty else { delegate?.documentPicker(self, failedToPickDocumentsAt: urls) return } - + if #available(iOS 11.0, *), giniConfiguration.documentPickerNavigationBarTintColor != nil { restoreSavedNavBarAppearance() } - + delegate?.documentPicker(self, didPick: documents) - } - + } + public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { - self.documentPicker(controller, didPickDocumentsAt: [url]) + documentPicker(controller, didPickDocumentsAt: [url]) } - + public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { if #available(iOS 11.0, *), giniConfiguration.documentPickerNavigationBarTintColor != nil { restoreSavedNavBarAppearance() } - + controller.dismiss(animated: false, completion: nil) } } // MARK: UIDropInteractionDelegate -@available(iOS 11.0, *) extension DocumentPickerCoordinator: UIDropInteractionDelegate { public func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool { guard isPDFDropSelectionAllowed(forSession: session) else { return false } - + let isMultipleItemsSelectionAllowed = session.items.count > 1 ? giniConfiguration.multipageEnabled : true switch giniConfiguration.fileImportSupportedTypes { case .pdf_and_images: @@ -377,34 +364,34 @@ extension DocumentPickerCoordinator: UIDropInteractionDelegate { return false } } - + public func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal { return UIDropProposal(operation: .copy) } - + public func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession) { let dispatchGroup = DispatchGroup() var documents: [GiniCaptureDocument] = [] - + loadDocuments(ofClass: GiniPDFDocument.self, from: session, in: dispatchGroup) { pdfItems in if let pdfs = pdfItems { documents.append(contentsOf: pdfs as [GiniCaptureDocument]) } } - + loadDocuments(ofClass: GiniImageDocument.self, from: session, in: dispatchGroup) { imageItems in if let images = imageItems { documents.append(contentsOf: images as [GiniCaptureDocument]) } } - + dispatchGroup.notify(queue: DispatchQueue.main) { self.currentPickerDismissesAutomatically = true self.delegate?.documentPicker(self, didPick: documents) } } - + private func loadDocuments(ofClass classs: T.Type, from session: UIDropSession, in group: DispatchGroup, @@ -419,17 +406,17 @@ extension DocumentPickerCoordinator: UIDropInteractionDelegate { group.leave() } } - + private func isPDFDropSelectionAllowed(forSession session: UIDropSession) -> Bool { if session.hasItemsConforming(toTypeIdentifiers: GiniPDFDocument.acceptedPDFTypes) { let pdfIdentifier = GiniPDFDocument.acceptedPDFTypes[0] let pdfItems = session.items.filter { $0.itemProvider.hasItemConformingToTypeIdentifier(pdfIdentifier) } - + if pdfItems.count > 1 || !isPDFSelectionAllowed { return false } } - + return true } } diff --git a/Sources/GiniCaptureSDK/Core/Screens/Help/HelpMenuViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Help/HelpMenuViewController.swift index 7a47b14..44b6764 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Help/HelpMenuViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Help/HelpMenuViewController.swift @@ -108,21 +108,23 @@ final public class HelpMenuViewController: UITableViewController { tableView.backgroundColor = UIColor.from(giniColor: giniConfiguration.helpScreenBackgroundColor) // In iOS it is .automatic by default, having an initial animation when the view is loaded. - if #available(iOS 11.0, *) { - tableView.contentInsetAdjustmentBehavior = .never - } + tableView.contentInsetAdjustmentBehavior = .never } fileprivate func configureMainView() { title = .localized(resource: HelpStrings.menuTitle) } - override public func viewDidLoad() { - super.viewDidLoad() - + fileprivate func configureLayout() { configureMainView() configureTableView() configureMenuItems() + edgesForExtendedLayout = [] + } + + override public func viewDidLoad() { + super.viewDidLoad() + configureLayout() } @objc func back() { diff --git a/Sources/GiniCaptureSDK/Core/Screens/Help/No results/ImageAnalysisNoResultsViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Help/No results/ImageAnalysisNoResultsViewController.swift index 7f5d6cb..3e8a7ec 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Help/No results/ImageAnalysisNoResultsViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Help/No results/ImageAnalysisNoResultsViewController.swift @@ -65,22 +65,22 @@ public final class ImageAnalysisNoResultsViewController: UIViewController { public convenience init(title: String? = nil, subHeaderText: String? = NSLocalizedString("ginicapture.noresults.collection.header", - bundle: Bundle(for: GiniCapture.self), + bundle: giniCaptureBundle(), comment: "no results suggestions collection " + "header title"), topViewText: String = NSLocalizedString("ginicapture.noresults.warning", - bundle: Bundle(for: GiniCapture.self), + bundle: giniCaptureBundle(), comment: "Warning text that indicates that there " + "was any result for this photo analysis"), topViewIcon: UIImage? = UIImage(named: "warningNoResults", - in: Bundle(for: GiniCapture.self), + in: giniCaptureBundle(), compatibleWith: nil)?.withRenderingMode(.alwaysTemplate), bottomButtonText: String? = NSLocalizedString("ginicapture.noresults.gotocamera", - bundle: Bundle(for: GiniCapture.self), + bundle: giniCaptureBundle(), comment: "bottom button title (go to camera" + " button)"), bottomButtonIcon: UIImage? = UIImage(named: "cameraIcon", - in: Bundle(for: GiniCapture.self), + in: giniCaptureBundle(), compatibleWith: nil)) { self.init(title: title, subHeaderText: subHeaderText, @@ -151,7 +151,7 @@ public final class ImageAnalysisNoResultsViewController: UIViewController { // Button if bottomButtonText != nil { - Constraints.active(item: self.bottomLayoutGuide, attr: .top, relatedBy: .equal, to: bottomButton, + Constraints.active(item: view.safeAreaLayoutGuide, attr: .bottom, relatedBy: .equal, to: bottomButton, attr: .bottom, constant: 20) Constraints.active(item: self.view, attr: .leading, relatedBy: .equal, to: bottomButton, attr: .leading, constant: -20, priority: 999) diff --git a/Sources/GiniCaptureSDK/Core/Screens/Help/Open with tutorial/OpenWithTutorialViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Help/Open with tutorial/OpenWithTutorialViewController.swift index a492c79..ef4b770 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Help/Open with tutorial/OpenWithTutorialViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Help/Open with tutorial/OpenWithTutorialViewController.swift @@ -71,8 +71,7 @@ final class OpenWithTutorialViewController: UICollectionViewController { } self.collectionView!.backgroundColor = nil - self.edgesForExtendedLayout = [] - self.automaticallyAdjustsScrollViewInsets = false + self.collectionView.contentInsetAdjustmentBehavior = .never self.collectionView!.register(OpenWithTutorialCollectionCell.self, forCellWithReuseIdentifier: openWithTutorialCollectionCellIdentifier) @@ -83,6 +82,7 @@ final class OpenWithTutorialViewController: UICollectionViewController { stepsCollectionLayout.minimumLineSpacing = 1 stepsCollectionLayout.minimumInteritemSpacing = 1 stepsCollectionLayout.estimatedItemSize = estimatedCellSize(widthParentSize: view.frame.size) + self.edgesForExtendedLayout = [] } override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { diff --git a/Sources/GiniCaptureSDK/Core/Screens/Help/Supported formats/SupportedFormatsViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Help/Supported formats/SupportedFormatsViewController.swift index 55edb7b..9824d8e 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Help/Supported formats/SupportedFormatsViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Help/Supported formats/SupportedFormatsViewController.swift @@ -24,13 +24,13 @@ final class SupportedFormatsViewController: UITableViewController { (.localized(resource: HelpStrings.supportedFormatsSection1Title), [.localized(resource: HelpStrings.supportedFormatsSection1Item1Text)], UIImage(named: "supportedFormatsIcon", - in: Bundle(for: GiniCapture.self), + in: Bundle.module, compatibleWith: nil), GiniConfiguration.shared.supportedFormatsIconColor), (.localized(resource: HelpStrings.supportedFormatsSection2Title), [.localized(resource: HelpStrings.supportedFormatsSection2Item1Text), .localized(resource: HelpStrings.supportedFormatsSection2Item2Text)], - UIImage(named: "nonSupportedFormatsIcon", in: Bundle(for: GiniCapture.self), compatibleWith: nil), + UIImage(named: "nonSupportedFormatsIcon", in: Bundle.module, compatibleWith: nil), GiniConfiguration.shared.nonSupportedFormatsIconColor) ] @@ -55,9 +55,7 @@ final class SupportedFormatsViewController: UITableViewController { fatalError("init(coder:) has not been implemented") } - override func viewDidLoad() { - super.viewDidLoad() - title = .localized(resource: HelpStrings.supportedFormatsTitle) + fileprivate func configureTableView() { tableView.register(SupportedFormatsTableViewCell.self, forCellReuseIdentifier: supportedFormatsCellIdentifier) tableView.rowHeight = rowHeight tableView.tableFooterView = UIView() @@ -71,11 +69,14 @@ final class SupportedFormatsViewController: UITableViewController { } tableView.alwaysBounceVertical = false - - // On iOS is .automatic by default and it the transition to this view controller looks weird. - if #available(iOS 11.0, *) { - tableView.contentInsetAdjustmentBehavior = .never - } + tableView.contentInsetAdjustmentBehavior = .never + } + + override func viewDidLoad() { + super.viewDidLoad() + title = .localized(resource: HelpStrings.supportedFormatsTitle) + configureTableView() + edgesForExtendedLayout = [] } // MARK: - Table view data source diff --git a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewMainCollectionCell.swift b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewMainCollectionCell.swift index c8db7af..169e096 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewMainCollectionCell.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewMainCollectionCell.swift @@ -18,7 +18,7 @@ final class MultipageReviewMainCollectionCell: UICollectionViewCell { imageView.clipsToBounds = true imageView.accessibilityLabel = NSLocalizedString("ginicapture.review.documentImageTitle", - bundle: Bundle(for: GiniCapture.self), + bundle: Bundle.module, comment: "Document") return imageView diff --git a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewPagesCollectionCell.swift b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewPagesCollectionCell.swift index e5b379a..e7bb2b5 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewPagesCollectionCell.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewPagesCollectionCell.swift @@ -68,7 +68,7 @@ final class MultipageReviewPagesCollectionCell: UICollectionViewCell { }() lazy var draggableIcon: UIImageView = { - let image = UIImage(named: "draggablePageIcon", in: Bundle(for: GiniCapture.self), compatibleWith: nil) + let image = UIImage(named: "draggablePageIcon", in: Bundle.module, compatibleWith: nil) let imageView = UIImageView(image: image?.withRenderingMode(.alwaysTemplate)) imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleAspectFit diff --git a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewViewController.swift index 8bce180..8d01ee6 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/MultipageReviewViewController.swift @@ -188,7 +188,7 @@ public final class MultipageReviewViewController: UIViewController { action: #selector(rotateImageButtonAction)) button.accessibilityLabel = NSLocalizedString("ginicapture.review.rotateButton", - bundle: Bundle(for: GiniCapture.self), + bundle: Bundle.module, comment: "Rotate button") return button }() @@ -244,7 +244,7 @@ extension MultipageReviewViewController { override public func viewDidLoad() { super.viewDidLoad() view.backgroundColor = mainCollection.backgroundColor - automaticallyAdjustsScrollViewInsets = false + mainCollection.contentInsetAdjustmentBehavior = .never edgesForExtendedLayout = [] longPressGesture.delaysTouchesBegan = true @@ -458,14 +458,14 @@ extension MultipageReviewViewController { // mainCollection Constraints.active(item: mainCollection, attr: .bottom, relatedBy: .equal, to: pagesCollectionContainer, attr: .top) - Constraints.active(item: mainCollection, attr: .top, relatedBy: .equal, to: topLayoutGuide, - attr: .bottom) + Constraints.active(item: mainCollection, attr: .top, relatedBy: .equal, to: view.safeAreaLayoutGuide, + attr: .top) Constraints.active(item: mainCollection, attr: .trailing, relatedBy: .equal, to: view, attr: .trailing) Constraints.active(item: mainCollection, attr: .leading, relatedBy: .equal, to: view, attr: .leading) // toolBar - Constraints.active(item: toolBar, attr: .bottom, relatedBy: .equal, to: bottomLayoutGuide, - attr: .top) + Constraints.active(item: toolBar, attr: .bottom, relatedBy: .equal, to: view.safeAreaLayoutGuide, + attr: .bottom) Constraints.active(item: toolBar, attr: .trailing, relatedBy: .equal, to: view, attr: .trailing) Constraints.active(item: toolBar, attr: .leading, relatedBy: .equal, to: view, attr: .leading) diff --git a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/PageStateView.swift b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/PageStateView.swift index 2093bd7..3570fc8 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/PageStateView.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Multipage Review/PageStateView.swift @@ -56,14 +56,14 @@ final class PageStateView: UIView { case .succeeded: backgroundColor = Colors.Gini.springGreen icon.image = UIImage.init(named: "successfullUploadIcon", - in: Bundle(for: GiniCapture.self), + in: Bundle.module, compatibleWith: nil) loadingIndicator.stopAnimating() case .failed: backgroundColor = Colors.Gini.crimson icon.image = UIImage.init(named: "failureUploadIcon", - in: Bundle(for: GiniCapture.self), + in: Bundle.module, compatibleWith: nil) loadingIndicator.stopAnimating() case .loading: diff --git a/Sources/GiniCaptureSDK/Core/Screens/Onboarding/OnboardingContainerViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Onboarding/OnboardingContainerViewController.swift index a452256..db7c87a 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Onboarding/OnboardingContainerViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Onboarding/OnboardingContainerViewController.swift @@ -155,8 +155,8 @@ final class OnboardingContainerViewController: UIViewController, ContainerViewCo attr: .bottom, priority: 750) Constraints.active(item: pageControlContainerView, attr: .trailing, relatedBy: .equal, to: superview, attr: .trailing) - Constraints.active(item: pageControlContainerView, attr: .bottom, relatedBy: .equal, to: bottomLayoutGuide, - attr: .top) + Constraints.active(item: pageControlContainerView, attr: .bottom, relatedBy: .equal, to: view.safeAreaLayoutGuide, + attr: .bottom) Constraints.active(item: pageControlContainerView, attr: .leading, relatedBy: .equal, to: superview, attr: .leading) Constraints.active(item: pageControlContainerView, attr: .height, relatedBy: .greaterThanOrEqual, diff --git a/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift b/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift index 1d542a2..41c89ed 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Review/ReviewViewController.swift @@ -223,9 +223,9 @@ import UIKit // MARK: Constraints fileprivate func addConstraints() { // Scroll view - Constraints.active(item: scrollView, attr: .top, relatedBy: .equal, to: topLayoutGuide, attr: .bottom) + Constraints.active(item: scrollView, attr: .top, relatedBy: .equal, to: view.safeAreaLayoutGuide, attr: .top) Constraints.active(item: scrollView, attr: .trailing, relatedBy: .equal, to: view, attr: .trailing) - Constraints.active(item: scrollView, attr: .bottom, relatedBy: .equal, to: bottomLayoutGuide, attr: .top) + Constraints.active(item: scrollView, attr: .bottom, relatedBy: .equal, to: view.safeAreaLayoutGuide, attr: .bottom) Constraints.active(item: scrollView, attr: .leading, relatedBy: .equal, to: view, attr: .leading) // Image view @@ -252,7 +252,7 @@ import UIKit Constraints.active(item: bottomView, attr: .top, relatedBy: .equal, to: scrollView, attr: .bottom, priority: 750) Constraints.active(item: bottomView, attr: .trailing, relatedBy: .equal, to: view, attr: .trailing) - Constraints.active(item: bottomView, attr: .bottom, relatedBy: .equal, to: self.bottomLayoutGuide, attr: .top) + Constraints.active(item: bottomView, attr: .bottom, relatedBy: .equal, to: view.safeAreaLayoutGuide, attr: .bottom) Constraints.active(item: bottomView, attr: .leading, relatedBy: .equal, to: view, attr: .leading) // Rotate button diff --git a/Sources/GiniCaptureSDK/Core/Screens/Screen API Coordinator/GiniScreenAPICoordinator+Camera.swift b/Sources/GiniCaptureSDK/Core/Screens/Screen API Coordinator/GiniScreenAPICoordinator+Camera.swift index 76a3fb8..63da043 100644 --- a/Sources/GiniCaptureSDK/Core/Screens/Screen API Coordinator/GiniScreenAPICoordinator+Camera.swift +++ b/Sources/GiniCaptureSDK/Core/Screens/Screen API Coordinator/GiniScreenAPICoordinator+Camera.swift @@ -247,7 +247,6 @@ extension GiniScreenAPICoordinator: DocumentPickerCoordinatorDelegate { } } - @available(iOS 11.0, *) fileprivate func addDropInteraction(forView view: UIView, with delegate: UIDropInteractionDelegate) { let dropInteraction = UIDropInteraction(delegate: delegate) view.addInteraction(dropInteraction) diff --git a/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift b/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift index d1696bd..3dd0356 100644 --- a/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift +++ b/Sources/GiniCaptureSDK/Networking/GiniNetworkingScreenAPICoordinator.swift @@ -186,7 +186,7 @@ extension GiniNetworkingScreenAPICoordinator: GiniCaptureDelegate { } public func didCapture(document: GiniCaptureDocument, networkDelegate: GiniCaptureNetworkDelegate) { - // The EPS QR codes are a special case, since they don0t have to be analyzed by the Gini API and therefore, + // The EPS QR codes are a special case, since they don0t have to be analyzed by the Gini Bank API and therefore, // they are ready to be delivered after capturing them. if let qrCodeDocument = document as? GiniQRCodeDocument, let format = qrCodeDocument.qrCodeFormat, diff --git a/Sources/GiniCaptureSDKVersion.swift b/Sources/GiniCaptureSDKVersion.swift index c40bc2e..55e543f 100644 --- a/Sources/GiniCaptureSDKVersion.swift +++ b/Sources/GiniCaptureSDKVersion.swift @@ -5,4 +5,4 @@ // Created by Nadya Karaban on 29.10.21. // -public let GiniCaptureSDKVersion = "0.0.2" +public let GiniCaptureSDKVersion = "1.1.0" diff --git a/Tests/GiniCaptureSDKTests/HelpMenuViewControllerTests.swift b/Tests/GiniCaptureSDKTests/HelpMenuViewControllerTests.swift index 54af340..047677a 100644 --- a/Tests/GiniCaptureSDKTests/HelpMenuViewControllerTests.swift +++ b/Tests/GiniCaptureSDKTests/HelpMenuViewControllerTests.swift @@ -15,21 +15,21 @@ final class HelpMenuViewControllerTests: XCTestCase { var items: [(text: String, id: Int)] { var items = [ (NSLocalizedString("ginicapture.helpmenu.firstItem", - bundle: Bundle(for: GiniCapture.self), + bundle: Bundle.module, comment: "help menu first item text"), 1) ] if GiniConfiguration.shared.shouldShowSupportedFormatsScreen { items.append((NSLocalizedString("ginicapture.helpmenu.thirdItem", - bundle: Bundle(for: GiniCapture.self), + bundle: Bundle.module, comment: "help menu third item text"), 3)) } if GiniConfiguration.shared.openWithEnabled { items.append((NSLocalizedString("ginicapture.helpmenu.secondItem", - bundle: Bundle(for: GiniCapture.self), + bundle: Bundle.module, comment: "help menu second item text"), 2)) } diff --git a/Tests/GiniCaptureSDKTests/PageStateViewTests.swift b/Tests/GiniCaptureSDKTests/PageStateViewTests.swift index 5d023e9..eef76ee 100644 --- a/Tests/GiniCaptureSDKTests/PageStateViewTests.swift +++ b/Tests/GiniCaptureSDKTests/PageStateViewTests.swift @@ -28,7 +28,7 @@ final class PageStateViewTests: XCTestCase { XCTAssertEqual(statusView.backgroundColor, Colors.Gini.springGreen, "background color should be green") XCTAssertEqual(statusView.icon.image, UIImage(named: "successfullUploadIcon", - in: Bundle(for: GiniCapture.self), + in: giniCaptureBundle(), compatibleWith: nil), "icon image should match successfullUploadIcon asset") XCTAssertFalse(statusView.loadingIndicator.isAnimating, @@ -40,9 +40,9 @@ final class PageStateViewTests: XCTestCase { XCTAssertEqual(statusView.backgroundColor, Colors.Gini.crimson, "background color should be red") XCTAssertEqual(statusView.icon.image, UIImage(named: "failureUploadIcon", - in: Bundle(for: GiniCapture.self), + in: giniCaptureBundle(), compatibleWith: nil), - "icon image should match failureUploadIcon asset") + "icon image should match failureUploadIcon asset") XCTAssertFalse(statusView.loadingIndicator.isAnimating, "loading indicator should not be animating when loading") } diff --git a/Tests/GiniCaptureSDKTests/SupportedFormatsViewControllerTests.swift b/Tests/GiniCaptureSDKTests/SupportedFormatsViewControllerTests.swift index a0213a4..4759419 100644 --- a/Tests/GiniCaptureSDKTests/SupportedFormatsViewControllerTests.swift +++ b/Tests/GiniCaptureSDKTests/SupportedFormatsViewControllerTests.swift @@ -19,14 +19,14 @@ final class SupportedFormatsViewControllerTests: XCTestCase { .localized(resource: HelpStrings.supportedFormatsSection1Item2Text), .localized(resource: HelpStrings.supportedFormatsSection1Item3Text)], UIImage(named: "supportedFormatsIcon", - in: Bundle(for: GiniCapture.self), + in: giniCaptureBundle(), compatibleWith: nil), GiniConfiguration.shared.supportedFormatsIconColor), (.localized(resource: HelpStrings.supportedFormatsSection2Title), [.localized(resource: HelpStrings.supportedFormatsSection2Item1Text), .localized(resource: HelpStrings.supportedFormatsSection2Item2Text)], UIImage(named: "nonSupportedFormatsIcon", - in: Bundle(for: GiniCapture.self), + in: giniCaptureBundle(), compatibleWith: nil), GiniConfiguration.shared.nonSupportedFormatsIconColor) ]