Skip to content

Commit

Permalink
recover code camera view clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
SabrinaTardio committed Nov 27, 2023
1 parent 56cc912 commit 4760be6
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 29 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"images" : [
{
"filename" : "Arrow-Circle-Right-12.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}
6 changes: 3 additions & 3 deletions DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ extension SyncSettingsViewController: SyncManagementViewModelDelegate {
model.delegate = self

var controller: UIHostingController<AnyView>
if showEnterTextCode {
controller = UIHostingController(rootView: AnyView(PasteCodeView(model: model, isfirstScreen: true)))
} else {
if showConnectMode {
controller = UIHostingController(rootView: AnyView(ScanOrPasteCodeView(model: model)))
} else {
controller = UIHostingController(rootView: AnyView(ScanOrEnterCodeToRecoverSyncedData(model: model)))
}

let navController = UIDevice.current.userInterfaceIdiom == .phone
Expand Down
152 changes: 152 additions & 0 deletions LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/CameraView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
//
// CameraView.swift
// DuckDuckGo
//
// Copyright © 2023 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI

public struct CameraView: View {

@ObservedObject var model: ScanOrPasteCodeViewModel

public var body: some View {
GeometryReader { g in
ZStack(alignment: .top) {
fullscreenCameraBackground()

VStack(spacing: 0) {
Rectangle() // Also acts as the blur for the camera
.fill(.black)
.frame(height: g.safeAreaInsets.top)

ZStack {
// Background in case fullscreen camera view doesn't work
if !model.showCamera {
Rectangle().fill(Color.black)
}

Group {
cameraPermissionDenied()
cameraUnavailable()
}
.padding(.horizontal, 0)

VStack {
Spacer()
Text(UserText.cameraPointCameraIndication)
.padding(.vertical, 8)
.padding(.horizontal, 20)
.background(
RoundedRectangle(cornerRadius: 56)
.fill(.clear)
.background(BlurView(style: .light))
.cornerRadius(20)
)
.daxCaption()
}
.padding(.bottom, 20)
}
}
.ignoresSafeArea()
}
}
}

@ViewBuilder
func fullscreenCameraBackground() -> some View {
Group {
if model.showCamera {
QRCodeScannerView {
return await model.codeScanned($0)
} onCameraUnavailable: {
model.cameraUnavailable()
}
} else {
Rectangle()
.fill(.black)
}
}
.ignoresSafeArea()
}

@ViewBuilder
func cameraPermissionDenied() -> some View {
if model.videoPermission == .denied {
VStack(spacing: 0) {

Image("SyncCameraPermission")
.padding(.top, 40)
.padding(.bottom, 20)

Text(UserText.cameraPermissionRequired)
.daxTitle3()
.lineSpacing(1.05)
.padding(.bottom, 8)

Text(UserText.cameraPermissionInstructions)
.lineLimit(nil)
.multilineTextAlignment(.center)
.daxBodyRegular()
.lineSpacing(1.1)

Spacer()

Button {
model.gotoSettings()
} label: {
HStack {
Image("SyncGotoButton")
Text(UserText.cameraGoToSettingsButton)
}
}
.buttonStyle(SyncLabelButtonStyle())
.padding(.bottom, 40)
}
.padding(.horizontal, 40)
}
}

@ViewBuilder
func cameraUnavailable() -> some View {
if model.videoPermission == .authorised && !model.showCamera {
VStack(spacing: 0) {

Image("SyncCameraUnavailable")
.padding(.top, 40)
.padding(.bottom, 20)

Text(UserText.cameraIsUnavailableTitle)
.daxTitle3()
.lineSpacing(1.05)

}
.padding(.horizontal, 40)
}
}

struct BlurView: UIViewRepresentable {
var style: UIBlurEffect.Style

func makeUIView(context: Context) -> UIVisualEffectView {
return UIVisualEffectView(effect: UIBlurEffect(style: style))
}

func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
uiView.effect = UIBlurEffect(style: style)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@ struct QRCodeScannerView: UIViewRepresentable {
let scanningQueue: ScanningQueue

let onCameraUnavailable: () -> Void
let onInvalidCodeScanned: () -> Void

init(onQRCodeScanned: @escaping (String) async -> Bool, onCameraUnavailable: @escaping () -> Void, onInvalidCodeScanned: @escaping () -> Void) {
init(onQRCodeScanned: @escaping (String) async -> Bool, onCameraUnavailable: @escaping () -> Void) {
scanningQueue = ScanningQueue(onQRCodeScanned)
self.onCameraUnavailable = onCameraUnavailable
self.onInvalidCodeScanned = onInvalidCodeScanned
}

func makeCoordinator() -> Coordinator {
Expand Down Expand Up @@ -112,7 +110,6 @@ struct QRCodeScannerView: UIViewRepresentable {
Task { @MainActor in
let codeAccepted = await cameraView.scanningQueue.codeScanned(code)
if !codeAccepted {
cameraView.onInvalidCodeScanned()
captureCodes = true
}
}
Expand Down
26 changes: 17 additions & 9 deletions LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,23 @@ struct UserText {
static let deviceSyncedSheetTitle = NSLocalizedString("device.synced.sheet.title", value: "Your Data is Synced!", comment: "Device SyncedSheet - Title")

// Recover Synced Data Sheet
static let recoverSyncedDataTitle = "Recover Synced Data"
static let recoverSyncedDataDescription = "To restore your synced data, you'll need the Recovery Code you saved when you first set up Sync. This code may have been saved as a PDF on the device you originally used to set up Sync."
static let recoverSyncedDataButton = "Get Started"
static let recoverSyncedDataTitle = NSLocalizedString("recover.synced.data.sheet.title", value: "Recover Synced Data", comment: "Recover Synced Data Sheet - Title")
static let recoverSyncedDataDescription = NSLocalizedString("recover.synced.data.sheet.description", value: "To restore your synced data, you'll need the Recovery Code you saved when you first set up Sync. This code may have been saved as a PDF on the device you originally used to set up Sync.", comment: "Recover Synced Data Sheet - Description")
static let recoverSyncedDataButton = NSLocalizedString("recover.synced.data.sheet.button", value: "Get Started", comment: "Recover Synced Data Sheet - Button")

// Scan Or Enter Code To Recover Synced Data View
static let scanCodeToRecoverSyncedDataTitle = NSLocalizedString("scan.code.to.recover.synced.data.title", value: "Recover Synced Data", comment: "Scan Or Enter Code To Recover Synced Data View - Title")
static let scanCodeToRecoverSyncedDataExplanation = NSLocalizedString("scan.code.to.recover.synced.data.explanation", value: "Scan the QR code on your Recovery PDF, or another synced device, to recover your data.", comment: "Scan Or Enter Code To Recover Synced Data View - Explanation")
static let scanCodeToRecoverSyncedDataFooter = NSLocalizedString("scan.code.to.recover.synced.data.footer", value: "Can’t Scan?", comment: "Scan Or Enter Code To Recover Synced Data View - Footer")
static let scanCodeToRecoverSyncedDataEnterCodeLink = NSLocalizedString("scan.code.to.recover.synced.data.enter.code.link", value: "Enter Text Code Manually", comment: "Scan Or Enter Code To Recover Synced Data View - Enter Code Link")

// Camera View
static let cameraPointCameraIndication = NSLocalizedString("camera.point.camera.indication", value: "Point camera at QR code to sync", comment: "Camera View - Point Camera Indication")
static let cameraPermissionRequired = NSLocalizedString("camera.permission.required", value: "Camera Permission is Required", comment: "Camera View - Permission Required")
static let cameraPermissionInstructions = NSLocalizedString("camera.permission.instructions", value: "Please go to your device's settings and grant permission for this app to access your camera.", comment: "Camera View - Permission Instructions")
static let cameraIsUnavailableTitle = NSLocalizedString("camera.is.unavailable.title", value: "Camera is Unavailable", comment: "Camera View - Unavailable Title")
static let cameraGoToSettingsButton = NSLocalizedString("camera.go.to.settings.button", value: "Go to Settings", comment: "Camera View - Go to Settings Button")


static let scanQRCode = "Scan QR Code"
static let enterTextCode = "Enter Text Code"
Expand Down Expand Up @@ -116,12 +130,6 @@ struct UserText {
static let multipleDevicesSyncedMessage = "Your bookmarks and Logins are now syncing on "
static let wordDevices = "devices"

static let cameraPermissionRequired = "Camera Permission is Required"
static let cameraPermissionInstructions = "Please go to your device's settings and grant permission for this app to access your camera."
static let cameraIsUnavailableTitle = "Camera is Unavailable"

static let goToSettingsButton = "Go to Settings"

static let syncTitle = "Sync & Backup"

static let thisDevice = "This Device"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public struct RecoverSyncedData: View {
VStack(spacing: 0) {
HStack {
Button(action: onCancel, label: {
Text("Cancel")
Text(UserText.cancelButton)
.foregroundColor(.primary)
})
Spacer()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// ScanOrEnterCodeToRecoverSyncedData.swift
// DuckDuckGo
//
// Copyright © 2023 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import SwiftUI
import DuckUI

public struct ScanOrEnterCodeToRecoverSyncedData: View {

@ObservedObject var model: ScanOrPasteCodeViewModel

public init(model: ScanOrPasteCodeViewModel) {
self.model = model
}

public var body: some View {
VStack(spacing: 10) {
VStack(spacing: 10) {
Text(UserText.scanCodeToRecoverSyncedDataExplanation)
.daxFootnoteRegular()
.multilineTextAlignment(.center)
.padding(.horizontal, 20)
.padding(.top, 10)
.padding(.bottom, 20)
CameraView(model: model)
.aspectRatio(1.0, contentMode: .fill)
}
.navigationTitle(UserText.scanCodeToRecoverSyncedDataTitle)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(UserText.cancelButton, action: model.cancel)
.foregroundColor(Color.white)
}
}
ZStack {
Rectangle().fill(Color.black)
VStack(alignment: .center) {
HStack(spacing: 4) {
Text(UserText.scanCodeToRecoverSyncedDataFooter)
.daxBodyRegular()
.foregroundColor(Color(designSystemColor: .textSecondary))
HStack(alignment: .center) {
NavigationLink(UserText.scanCodeToRecoverSyncedDataEnterCodeLink, destination: {
PasteCodeView(model: model)
})
.foregroundColor(Color(designSystemColor: .accent))
Image("Arrow-Circle-Right-12")
}
}
.padding(20)
Spacer()
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,6 @@ public struct ScanOrPasteCodeView: View {
return await model.codeScanned($0)
} onCameraUnavailable: {
model.cameraUnavailable()
} onInvalidCodeScanned: {
withAnimation(.linear.delay(0.0)) {
isInvalidCode = true
}

withAnimation(.linear.delay(0.2)) {
isInvalidCode = false
}
}
} else {
Rectangle()
Expand Down Expand Up @@ -223,10 +215,6 @@ public struct ScanOrPasteCodeView: View {
Rectangle().fill(Color.black)
}

// cameraViewPort()
// .frame(width: g.size.width, height: g.size.width)
// .frame(maxHeight: g.size.height)

Group {
cameraPermissionDenied()
cameraUnavailable()
Expand Down

0 comments on commit 4760be6

Please sign in to comment.