Skip to content

Commit

Permalink
Set config via QR code (#93)
Browse files Browse the repository at this point in the history
* Rename to RootView to match Android

* Add OnboardingScreen

* iOS 14

* ignoresSafeArea

* remove redundant comment

* Add QR code scanning

* Add viewfinder

* Restore smile_config for sample app
  • Loading branch information
vanshg authored Nov 2, 2023
1 parent b7c9503 commit dc7408e
Show file tree
Hide file tree
Showing 16 changed files with 900 additions and 51 deletions.
32 changes: 26 additions & 6 deletions Example/SmileID.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
1ECAE3872A2F69CD00653FCA /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ECAE3862A2F69BC00653FCA /* ToastView.swift */; };
1ED53F6A2A2F28590020BEFB /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED53F602A2F28590020BEFB /* HomeViewModel.swift */; };
1ED53F6B2A2F28590020BEFB /* ProductCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED53F612A2F28590020BEFB /* ProductCell.swift */; };
1ED53F6C2A2F28590020BEFB /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED53F622A2F28590020BEFB /* MainView.swift */; };
1ED53F6C2A2F28590020BEFB /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED53F622A2F28590020BEFB /* RootView.swift */; };
1ED53F6D2A2F28590020BEFB /* SmileTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED53F632A2F28590020BEFB /* SmileTextField.swift */; };
1ED53F6E2A2F28590020BEFB /* ResourcesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED53F642A2F28590020BEFB /* ResourcesView.swift */; };
1ED53F712A2F28590020BEFB /* EnterUserIDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ED53F672A2F28590020BEFB /* EnterUserIDView.swift */; };
Expand All @@ -26,8 +26,11 @@
58C7118C2A69DE920062BBFB /* EnhancedKycTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58C7118B2A69DE920062BBFB /* EnhancedKycTest.swift */; };
607FACDB1AFB9204008FA782 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 607FACD91AFB9204008FA782 /* Main.storyboard */; };
607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; };
6AC9802B9D1A630961B5454B /* CodeScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC98436935FFEA40E632182 /* CodeScanner.swift */; };
6AC983F056A8F9088D6CF3F7 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC982147640002B81F72DEC /* SettingsView.swift */; };
6AC984526F49F4E8F52C7494 /* ScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC98BA00298258573CBCBD4 /* ScannerViewController.swift */; };
6AC9870BB28E40FCACC75947 /* DocumentVerificationIdTypeSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC9868BCF06ECE5F65DF248 /* DocumentVerificationIdTypeSelector.swift */; };
6AC98856053013D0E8ABB188 /* OnboardingScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC982F34F80CAE1AA5569AB /* OnboardingScreen.swift */; };
6AC98990097662789B0107EB /* SettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC98BC49871655D87C7DEE3 /* SettingsViewModel.swift */; };
6AC98B6FFA753C5463F7216F /* SmileConfigEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC984E484EEF69069C705C7 /* SmileConfigEntryView.swift */; };
6AC98C0E9305B4B3EB66ED35 /* Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC980584C522B17A099E098 /* Util.swift */; };
Expand Down Expand Up @@ -66,7 +69,7 @@
1ECAE3862A2F69BC00653FCA /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = "<group>"; };
1ED53F602A2F28590020BEFB /* HomeViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeViewModel.swift; sourceTree = "<group>"; };
1ED53F612A2F28590020BEFB /* ProductCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProductCell.swift; sourceTree = "<group>"; };
1ED53F622A2F28590020BEFB /* MainView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
1ED53F622A2F28590020BEFB /* RootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = "<group>"; };
1ED53F632A2F28590020BEFB /* SmileTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmileTextField.swift; sourceTree = "<group>"; };
1ED53F642A2F28590020BEFB /* ResourcesView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResourcesView.swift; sourceTree = "<group>"; };
1ED53F672A2F28590020BEFB /* EnterUserIDView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnterUserIDView.swift; sourceTree = "<group>"; };
Expand All @@ -87,9 +90,12 @@
67420F8D15457A4FC46AFB84 /* Pods-SmileID_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SmileID_Example.debug.xcconfig"; path = "Target Support Files/Pods-SmileID_Example/Pods-SmileID_Example.debug.xcconfig"; sourceTree = "<group>"; };
6AC980584C522B17A099E098 /* Util.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Util.swift; sourceTree = "<group>"; };
6AC982147640002B81F72DEC /* SettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
6AC982F34F80CAE1AA5569AB /* OnboardingScreen.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnboardingScreen.swift; sourceTree = "<group>"; };
6AC98436935FFEA40E632182 /* CodeScanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeScanner.swift; sourceTree = "<group>"; };
6AC984E484EEF69069C705C7 /* SmileConfigEntryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmileConfigEntryView.swift; sourceTree = "<group>"; };
6AC9868BCF06ECE5F65DF248 /* DocumentVerificationIdTypeSelector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentVerificationIdTypeSelector.swift; sourceTree = "<group>"; };
6AC9893915EBA33F6984A6D9 /* DocumentSelectorViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DocumentSelectorViewModel.swift; sourceTree = "<group>"; };
6AC98BA00298258573CBCBD4 /* ScannerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScannerViewController.swift; sourceTree = "<group>"; };
6AC98BC49871655D87C7DEE3 /* SettingsViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsViewModel.swift; sourceTree = "<group>"; };
915748522AA09A1F004A9F23 /* RouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterTests.swift; sourceTree = "<group>"; };
916E487A2A4057B400C589FE /* smile_config.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = smile_config.json; sourceTree = "<group>"; };
Expand Down Expand Up @@ -159,7 +165,7 @@
1ED53F672A2F28590020BEFB /* EnterUserIDView.swift */,
1ED53F692A2F28590020BEFB /* HomeView.swift */,
1ED53F602A2F28590020BEFB /* HomeViewModel.swift */,
1ED53F622A2F28590020BEFB /* MainView.swift */,
1ED53F622A2F28590020BEFB /* RootView.swift */,
1ED53F612A2F28590020BEFB /* ProductCell.swift */,
1ED53F642A2F28590020BEFB /* ResourcesView.swift */,
1ED53F632A2F28590020BEFB /* SmileTextField.swift */,
Expand All @@ -180,6 +186,8 @@
6AC982147640002B81F72DEC /* SettingsView.swift */,
6AC98BC49871655D87C7DEE3 /* SettingsViewModel.swift */,
6AC984E484EEF69069C705C7 /* SmileConfigEntryView.swift */,
6AC982F34F80CAE1AA5569AB /* OnboardingScreen.swift */,
6AC98DDBE27D169AF8DB4B98 /* CodeScanner */,
);
name = Example;
path = SmileID;
Expand Down Expand Up @@ -235,6 +243,15 @@
name = Frameworks;
sourceTree = "<group>";
};
6AC98DDBE27D169AF8DB4B98 /* CodeScanner */ = {
isa = PBXGroup;
children = (
6AC98436935FFEA40E632182 /* CodeScanner.swift */,
6AC98BA00298258573CBCBD4 /* ScannerViewController.swift */,
);
path = CodeScanner;
sourceTree = "<group>";
};
828BF541E068101B2E6ED55F /* Pods */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -505,7 +522,7 @@
files = (
1ECAE3872A2F69CD00653FCA /* ToastView.swift in Sources */,
1ED53F722A2F28590020BEFB /* SmileEnvironmentToggleButton.swift in Sources */,
1ED53F6C2A2F28590020BEFB /* MainView.swift in Sources */,
1ED53F6C2A2F28590020BEFB /* RootView.swift in Sources */,
1ED53F6E2A2F28590020BEFB /* ResourcesView.swift in Sources */,
1ED53F6A2A2F28590020BEFB /* HomeViewModel.swift in Sources */,
1E60ED372A29C306002695FF /* HomeViewController.swift in Sources */,
Expand All @@ -523,6 +540,9 @@
6AC983F056A8F9088D6CF3F7 /* SettingsView.swift in Sources */,
6AC98990097662789B0107EB /* SettingsViewModel.swift in Sources */,
6AC98B6FFA753C5463F7216F /* SmileConfigEntryView.swift in Sources */,
6AC98856053013D0E8ABB188 /* OnboardingScreen.swift in Sources */,
6AC9802B9D1A630961B5454B /* CodeScanner.swift in Sources */,
6AC984526F49F4E8F52C7494 /* ScannerViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -688,7 +708,7 @@
INFOPLIST_FILE = SmileID/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Smile ID";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.2;
MODULE_NAME = ExampleApp;
Expand All @@ -715,7 +735,7 @@
INFOPLIST_FILE = SmileID/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "Smile ID";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.2;
MODULE_NAME = ExampleApp;
Expand Down
3 changes: 1 addition & 2 deletions Example/SmileID/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import SwiftUI
import netfox

@UIApplicationMain
@available(iOS 14.0, *)
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
Expand All @@ -21,7 +20,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

// NOTE TO PARTNERS: Normally, you would call SmileID.initialize() here

window?.rootViewController = UIHostingController(rootView: MainView())
window?.rootViewController = UIHostingController(rootView: RootView())
window?.makeKeyAndVisible()
return true
}
Expand Down
128 changes: 128 additions & 0 deletions Example/SmileID/CodeScanner/CodeScanner.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// swiftlint:disable all
// MIT License: https://github.com/twostraws/CodeScanner/blob/main/LICENSE
// CodeScanner.swift
// https://github.com/twostraws/CodeScanner
//
// Created by Paul Hudson on 14/12/2021.
// Copyright © 2021 Paul Hudson. All rights reserved.
//

import AVFoundation
import SwiftUI

/// An enum describing the ways CodeScannerView can hit scanning problems.
public enum ScanError: Error {
/// The camera could not be accessed.
case badInput

/// The camera was not capable of scanning the requested codes.
case badOutput

/// Initialization failed.
case initError(_ error: Error)

/// The camera permission is denied
case permissionDenied
}

/// The result from a successful scan: the string that was scanned, and also the type of data that was found.
/// The type is useful for times when you've asked to scan several different code types at the same time, because
/// it will report the exact code type that was found.
@available(macCatalyst 14.0, *)
public struct ScanResult {
/// The contents of the code.
public let string: String

/// The type of code that was matched.
public let type: AVMetadataObject.ObjectType

/// The image of the code that was matched
public let image: UIImage?

/// The corner coordinates of the scanned code.
public let corners: [CGPoint]
}

/// The operating mode for CodeScannerView.
public enum ScanMode {
/// Scan exactly one code, then stop.
case once

/// Scan each code no more than once.
case oncePerCode

/// Keep scanning all codes until dismissed.
case continuous

/// Scan only when capture button is tapped.
case manual
}

/// A SwiftUI view that is able to scan barcodes, QR codes, and more, and send back what was found.
/// To use, set `codeTypes` to be an array of things to scan for, e.g. `[.qr]`, and set `completion` to
/// a closure that will be called when scanning has finished. This will be sent the string that was detected or a `ScanError`.
/// For testing inside the simulator, set the `simulatedData` property to some test data you want to send back.
@available(macCatalyst 14.0, *)
public struct CodeScannerView: UIViewControllerRepresentable {

public let codeTypes: [AVMetadataObject.ObjectType]
public let scanMode: ScanMode
public let manualSelect: Bool
public let scanInterval: Double
public let showViewfinder: Bool
public var simulatedData = ""
public var shouldVibrateOnSuccess: Bool
public var isTorchOn: Bool
public var isGalleryPresented: Binding<Bool>
public var videoCaptureDevice: AVCaptureDevice?
public var completion: (Result<ScanResult, ScanError>) -> Void

public init(
codeTypes: [AVMetadataObject.ObjectType],
scanMode: ScanMode = .once,
manualSelect: Bool = false,
scanInterval: Double = 2.0,
showViewfinder: Bool = false,
simulatedData: String = "",
shouldVibrateOnSuccess: Bool = true,
isTorchOn: Bool = false,
isGalleryPresented: Binding<Bool> = .constant(false),
videoCaptureDevice: AVCaptureDevice? = AVCaptureDevice.bestForVideo,
completion: @escaping (Result<ScanResult, ScanError>) -> Void
) {
self.codeTypes = codeTypes
self.scanMode = scanMode
self.manualSelect = manualSelect
self.showViewfinder = showViewfinder
self.scanInterval = scanInterval
self.simulatedData = simulatedData
self.shouldVibrateOnSuccess = shouldVibrateOnSuccess
self.isTorchOn = isTorchOn
self.isGalleryPresented = isGalleryPresented
self.videoCaptureDevice = videoCaptureDevice
self.completion = completion
}

public func makeUIViewController(context: Context) -> ScannerViewController {
return ScannerViewController(showViewfinder: showViewfinder, parentView: self)
}

public func updateUIViewController(_ uiViewController: ScannerViewController, context: Context) {
uiViewController.parentView = self
uiViewController.updateViewController(
isTorchOn: isTorchOn,
isGalleryPresented: isGalleryPresented.wrappedValue,
isManualCapture: scanMode == .manual,
isManualSelect: manualSelect
)
}
}

@available(macCatalyst 14.0, *)
struct CodeScannerView_Previews: PreviewProvider {
static var previews: some View {
CodeScannerView(codeTypes: [.qr]) { result in
// do nothing
}
}
}
Loading

0 comments on commit dc7408e

Please sign in to comment.