Skip to content

Commit bf516df

Browse files
committed
Add UI changes for selecting back camera in HostApp
1 parent b746324 commit bf516df

File tree

4 files changed

+70
-27
lines changed

4 files changed

+70
-27
lines changed

HostApp/HostApp/Views/ExampleLivenessView.swift

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,28 @@ import SwiftUI
99
import FaceLiveness
1010

1111
struct ExampleLivenessView: View {
12-
@Binding var isPresented: Bool
12+
@Binding var containerViewState: ContainerViewState
1313
@ObservedObject var viewModel: ExampleLivenessViewModel
1414

15-
init(sessionID: String, isPresented: Binding<Bool>) {
16-
self.viewModel = .init(sessionID: sessionID)
17-
self._isPresented = isPresented
15+
init(sessionID: String, containerViewState: Binding<ContainerViewState>) {
16+
self._containerViewState = containerViewState
17+
if case let .liveness(selectedCamera) = _containerViewState.wrappedValue {
18+
self.viewModel = .init(sessionID: sessionID, presentationState: .liveness(selectedCamera))
19+
} else {
20+
self.viewModel = .init(sessionID: sessionID)
21+
}
1822
}
1923

2024
var body: some View {
2125
switch viewModel.presentationState {
22-
case .liveness:
26+
case .liveness(let camera):
2327
FaceLivenessDetectorView(
2428
sessionID: viewModel.sessionID,
2529
region: "us-east-1",
26-
challengeOptions: .init(faceMovementChallengeOption: FaceMovementChallengeOption(camera: .front),
30+
challengeOptions: .init(faceMovementChallengeOption: FaceMovementChallengeOption(camera: camera),
2731
faceMovementAndLightChallengeOption: FaceMovementAndLightChallengeOption()),
2832
isPresented: Binding(
29-
get: { viewModel.presentationState == .liveness },
33+
get: { viewModel.presentationState == .liveness(camera) },
3034
set: { _ in }
3135
),
3236
onCompletion: { result in
@@ -35,11 +39,11 @@ struct ExampleLivenessView: View {
3539
case .success:
3640
withAnimation { viewModel.presentationState = .result }
3741
case .failure(.sessionNotFound), .failure(.cameraPermissionDenied), .failure(.accessDenied):
38-
viewModel.presentationState = .liveness
39-
isPresented = false
42+
viewModel.presentationState = .liveness(camera)
43+
containerViewState = .startSession
4044
case .failure(.userCancelled):
41-
viewModel.presentationState = .liveness
42-
isPresented = false
45+
viewModel.presentationState = .liveness(camera)
46+
containerViewState = .startSession
4347
case .failure(.sessionTimedOut):
4448
viewModel.presentationState = .error(.sessionTimedOut)
4549
case .failure(.socketClosed):
@@ -55,16 +59,16 @@ struct ExampleLivenessView: View {
5559
case .failure(.cameraNotAvailable):
5660
viewModel.presentationState = .error(.cameraNotAvailable)
5761
default:
58-
viewModel.presentationState = .liveness
62+
viewModel.presentationState = .liveness(camera)
5963
}
6064
}
6165
}
6266
)
63-
.id(isPresented)
67+
.id(containerViewState)
6468
case .result:
6569
LivenessResultView(
6670
sessionID: viewModel.sessionID,
67-
onTryAgain: { isPresented = false },
71+
onTryAgain: { containerViewState = .startSession },
6872
content: {
6973
LivenessResultContentView(fetchResults: viewModel.fetchLivenessResult)
7074
}
@@ -73,7 +77,7 @@ struct ExampleLivenessView: View {
7377
case .error(let detectionError):
7478
LivenessResultView(
7579
sessionID: viewModel.sessionID,
76-
onTryAgain: { isPresented = false },
80+
onTryAgain: { containerViewState = .startSession },
7781
content: {
7882
switch detectionError {
7983
case .socketClosed:

HostApp/HostApp/Views/ExampleLivenessViewModel.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ import FaceLiveness
1010
import Amplify
1111

1212
class ExampleLivenessViewModel: ObservableObject {
13-
@Published var presentationState = PresentationState.liveness
13+
@Published var presentationState: PresentationState = .liveness(.front)
1414
let sessionID: String
1515

16-
init(sessionID: String) {
16+
init(sessionID: String, presentationState: PresentationState = .liveness(.front)) {
1717
self.sessionID = sessionID
18+
self.presentationState = presentationState
1819
}
1920

2021
func fetchLivenessResult() async throws -> LivenessResultContentView.Result {
@@ -30,6 +31,6 @@ class ExampleLivenessViewModel: ObservableObject {
3031
}
3132

3233
enum PresentationState: Equatable {
33-
case liveness, result, error(FaceLivenessDetectionError)
34+
case liveness(LivenessCamera), result, error(FaceLivenessDetectionError)
3435
}
3536
}

HostApp/HostApp/Views/RootView.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,32 @@
66
//
77

88
import SwiftUI
9+
import FaceLiveness
910

1011
struct RootView: View {
1112
@EnvironmentObject var sceneDelegate: SceneDelegate
1213
@State var sessionID = ""
13-
@State var isPresentingContainerView = false
14+
@State var containerViewState = ContainerViewState.startSession
1415

1516
var body: some View {
16-
if isPresentingContainerView {
17+
switch containerViewState {
18+
case .liveness:
1719
ExampleLivenessView(
1820
sessionID: sessionID,
19-
isPresented: $isPresentingContainerView
21+
containerViewState: $containerViewState
2022
)
21-
} else {
23+
case .startSession:
2224
StartSessionView(
2325
sessionID: $sessionID,
24-
isPresentingContainerView: $isPresentingContainerView
26+
containerViewState: $containerViewState
2527
)
2628
.background(Color.dynamicColors(light: .white, dark: .secondarySystemBackground))
2729
.edgesIgnoringSafeArea(.all)
2830
}
2931
}
3032
}
33+
34+
enum ContainerViewState: Hashable {
35+
case liveness(LivenessCamera)
36+
case startSession
37+
}

HostApp/HostApp/Views/StartSessionView.swift

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct StartSessionView: View {
1212
@EnvironmentObject var sceneDelegate: SceneDelegate
1313
@ObservedObject var viewModel = StartSessionViewModel()
1414
@Binding var sessionID: String
15-
@Binding var isPresentingContainerView: Bool
15+
@Binding var containerViewState: ContainerViewState
1616
@State private var showAlert = false
1717

1818
var body: some View {
@@ -26,7 +26,7 @@ struct StartSessionView: View {
2626
)
2727

2828
button(
29-
text: "Create Liveness Session",
29+
text: "Create Liveness Session (front camera)",
3030
backgroundColor: .dynamicColors(
3131
light: .hex("#047D95"),
3232
dark: .hex("#7dd6e8")
@@ -35,7 +35,7 @@ struct StartSessionView: View {
3535
viewModel.createSession { sessionId, err in
3636
if let sessionId = sessionId {
3737
sessionID = sessionId
38-
isPresentingContainerView = true
38+
containerViewState = .liveness(.front)
3939
}
4040

4141
showAlert = err != nil
@@ -50,7 +50,38 @@ struct StartSessionView: View {
5050
dismissButton: .default(
5151
Text("OK"),
5252
action: {
53-
isPresentingContainerView = false
53+
containerViewState = .startSession
54+
}
55+
)
56+
)
57+
}
58+
59+
button(
60+
text: "Create Liveness Session (back camera)",
61+
backgroundColor: .dynamicColors(
62+
light: .hex("#047D95"),
63+
dark: .hex("#7dd6e8")
64+
),
65+
action: {
66+
viewModel.createSession { sessionId, err in
67+
if let sessionId = sessionId {
68+
sessionID = sessionId
69+
containerViewState = .liveness(.back)
70+
}
71+
72+
showAlert = err != nil
73+
}
74+
},
75+
enabled: viewModel.isSignedIn
76+
)
77+
.alert(isPresented: $showAlert) {
78+
Alert(
79+
title: Text("Error Creating Liveness Session"),
80+
message: Text("Unable to create a liveness session id. Please try again."),
81+
dismissButton: .default(
82+
Text("OK"),
83+
action: {
84+
containerViewState = .startSession
5485
}
5586
)
5687
)

0 commit comments

Comments
 (0)