From c041451fbaf25fe27e70d5538648d43e1833da32 Mon Sep 17 00:00:00 2001 From: Sabrina Tardio Date: Mon, 27 Nov 2023 13:30:09 +0100 Subject: [PATCH] clean up scan or view code --- ...cSettingsViewController+SyncDelegate.swift | 2 +- .../Views/Internal/ConnectModeView.swift | 38 +- .../Views/Internal/EditDeviceView.swift | 4 +- .../Views/Internal/QRCodeCopierView.swift | 156 ++++---- .../SyncUI/Views/Internal/UserText.swift | 130 +++---- .../SyncUI/Views/ScanOrPasteCodeView.swift | 368 ++++-------------- 6 files changed, 219 insertions(+), 479 deletions(-) diff --git a/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift b/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift index e005d2c22e..aa7420875c 100644 --- a/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift +++ b/DuckDuckGo/SyncSettingsViewController+SyncDelegate.swift @@ -116,7 +116,7 @@ extension SyncSettingsViewController: SyncManagementViewModelDelegate { var controller: UIHostingController if showConnectMode { - controller = UIHostingController(rootView: AnyView(ScanOrPasteCodeView(model: model))) + controller = UIHostingController(rootView: AnyView(ScanOrSeeCode(model: model))) } else { controller = UIHostingController(rootView: AnyView(ScanOrEnterCodeToRecoverSyncedData(model: model))) } diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ConnectModeView.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ConnectModeView.swift index 7ccb491200..9e74a5c74e 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ConnectModeView.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ConnectModeView.swift @@ -17,22 +17,22 @@ // limitations under the License. // -import SwiftUI - -/// We have to defer starting connect mode untl we're visible because otherwise SwiftUI might start it prematurely as a result of the NavigationLink. -/// In iOS 16 we use a value binding on the NavigationLink, but this better anyway as we can show progress. -struct ConnectModeView: View { - - @ObservedObject var model: ScanOrPasteCodeViewModel - @State var qrCodeModel = ShowQRCodeViewModel() - - var body: some View { - QRCodeCopierView(model: qrCodeModel) - .padding(.vertical, 20) - .frame(maxWidth: Constants.maxFullScreenWidth) - .onAppear { - self.qrCodeModel = model.startConnectMode() - } - } - -} +//import SwiftUI +// +///// We have to defer starting connect mode untl we're visible because otherwise SwiftUI might start it prematurely as a result of the NavigationLink. +///// In iOS 16 we use a value binding on the NavigationLink, but this better anyway as we can show progress. +//struct ConnectModeView: View { +// +// @ObservedObject var model: ScanOrPasteCodeViewModel +// @State var qrCodeModel = ShowQRCodeViewModel() +// +// var body: some View { +// QRCodeCopierView(model: qrCodeModel) +// .padding(.vertical, 20) +// .frame(maxWidth: Constants.maxFullScreenWidth) +// .onAppear { +// self.qrCodeModel = model.startConnectMode() +// } +// } +// +//} diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/EditDeviceView.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/EditDeviceView.swift index 02d3ac5202..e2e9e0fa8b 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/EditDeviceView.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/EditDeviceView.swift @@ -31,11 +31,11 @@ struct EditDeviceView: View { Section { TextField("", text: $model.name) } header: { - Text(UserText.editDeviceLabel) + Text(UserText.editDeviceHeader) } } .applyListStyle() - .navigationTitle(UserText.editDevice(model.name)) + .navigationTitle(UserText.editDeviceTitle(model.name)) .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/QRCodeCopierView.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/QRCodeCopierView.swift index 292ae5dd18..b45b0ba340 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/QRCodeCopierView.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/QRCodeCopierView.swift @@ -20,81 +20,81 @@ import SwiftUI import DesignResourcesKit -struct QRCodeCopierView: View { - - @ObservedObject var model: ShowQRCodeViewModel - - @ViewBuilder - func progressView() -> some View { - if model.code == nil { - ZStack { - SwiftUI.ProgressView() - }.frame(width: 200, height: 200) - } - } - - @ViewBuilder - func qrCodeView() -> some View { - if let code = model.code { - VStack(spacing: 20) { - Spacer() - - QRCodeView(string: code, size: 220) - .padding() - - Spacer() - - Button { - model.copy() - } label: { - Label(UserText.copyCodeLabel, image: "SyncCopy") - } - .buttonStyle(SyncLabelButtonStyle()) - .padding(.bottom, 20) - } - } - } - - @ViewBuilder - func instructions() -> some View { - - if model.code != nil { - Text(UserText.viewQRCodeInstructions) - .daxCaption() - .foregroundColor(.secondary) - .lineLimit(nil) - .multilineTextAlignment(.center) - } - - } - - @ViewBuilder - func qrCodeSection() -> some View { - ZStack { - VStack { - HStack { Spacer() } - Spacer() - } - RoundedRectangle(cornerRadius: 8).foregroundColor(.white.opacity(0.12)) - progressView() - qrCodeView() - } - .frame(maxWidth: 350, maxHeight: 350) - .padding() - } - - var body: some View { - ZStack(alignment: .top) { - VStack(spacing: 20) { - qrCodeSection() - instructions() - Spacer() - } - .padding(.horizontal, 20) - .frame(maxWidth: Constants.maxFullScreenWidth, alignment: .center) - } - .navigationTitle(UserText.viewQRCodeTitle) - .modifier(BackButtonModifier()) - } - -} +//struct QRCodeCopierView: View { +// +// @ObservedObject var model: ShowQRCodeViewModel +// +// @ViewBuilder +// func progressView() -> some View { +// if model.code == nil { +// ZStack { +// SwiftUI.ProgressView() +// }.frame(width: 200, height: 200) +// } +// } +// +// @ViewBuilder +// func qrCodeView() -> some View { +// if let code = model.code { +// VStack(spacing: 20) { +// Spacer() +// +// QRCodeView(string: code, size: 220) +// .padding() +// +// Spacer() +// +// Button { +// model.copy() +// } label: { +// Label(UserText.copyCodeLabel, image: "SyncCopy") +// } +// .buttonStyle(SyncLabelButtonStyle()) +// .padding(.bottom, 20) +// } +// } +// } +// +// @ViewBuilder +// func instructions() -> some View { +// +// if model.code != nil { +// Text(UserText.viewQRCodeInstructions) +// .daxCaption() +// .foregroundColor(.secondary) +// .lineLimit(nil) +// .multilineTextAlignment(.center) +// } +// +// } +// +// @ViewBuilder +// func qrCodeSection() -> some View { +// ZStack { +// VStack { +// HStack { Spacer() } +// Spacer() +// } +// RoundedRectangle(cornerRadius: 8).foregroundColor(.white.opacity(0.12)) +// progressView() +// qrCodeView() +// } +// .frame(maxWidth: 350, maxHeight: 350) +// .padding() +// } +// +// var body: some View { +// ZStack(alignment: .top) { +// VStack(spacing: 20) { +// qrCodeSection() +// instructions() +// Spacer() +// } +// .padding(.horizontal, 20) +// .frame(maxWidth: Constants.maxFullScreenWidth, alignment: .center) +// } +// .navigationTitle(UserText.viewQRCodeTitle) +// .modifier(BackButtonModifier()) +// } +// +//} diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift index e570f2e5d2..eea20a3005 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/UserText.swift @@ -23,7 +23,10 @@ import Foundation // Localise these later, when feature is closer to exernal release struct UserText { -// Sync Set Up + //Sync Title + static let syncTitle = NSLocalizedString("sync.title", value: "Sync & Backup", comment: "Sync & Backup Title") + + // Sync Set Up // Sync With Another Device Card static let syncWithAnotherDeviceTitle = NSLocalizedString("sync.with.another.device.title", value: "Begin Syncing", comment: "Title for syncing with another device") static let syncWithAnotherDeviceMessage = NSLocalizedString("sync.with.another.device.message", value: "Securely sync bookmarks and passwords between your devices.", comment: "Message for syncing with another device") @@ -34,7 +37,7 @@ struct UserText { static let recoverSyncedDataLink = NSLocalizedString("recover.synced.data.link", value: "Recover Synced Data", comment: "Link label for recovering synced data") static let otherOptionsSectionHeader = NSLocalizedString("other.options.section.header", value: "Other Options", comment: "Section header for other syncing options") -// Sync Enabled View + // Sync Enabled View // Turn Sync Off static let turnSyncOff = NSLocalizedString("turn.sync.off", value: "Turn Off Sync & Backup...", comment: "Turn Sync Off - Button") static let turnSyncOffSectionHeader = NSLocalizedString("turn.sync.off.section.header", value: "Sync Enabled", comment: "Turn Sync Off - Section Header") @@ -59,19 +62,19 @@ struct UserText { // Delete Server Data static let deleteServerData = NSLocalizedString("delete.server.data", value: "Turn Off and Delete Server Data...", comment: "Delete Server Data - Button") -// Connect With Server Sheet + // Connect With Server Sheet static let connectWithServerSheetTitle = NSLocalizedString("connect.with.server.sheet.title", value: "Sync and Back Up This Device", comment: "Connect With Server Sheet - Title") static let connectWithServerSheetDescriptionPart1 = NSLocalizedString("connect.with.server.sheet.description.part1", value: "This creates an encrypted backup of your bookmarks and passwords on DuckDuckGo’s secure server, which can be synced with your other devices.", comment: "Connect With Server Sheet - Description Part 1") static let connectWithServerSheetDescriptionPart2 = NSLocalizedString("connect.with.server.sheet.description.part2", value: "The encryption key is only stored on your device, DuckDuckGo cannot access it.", comment: "Connect With Server Sheet - Description Part 2") static let connectWithServerSheetButton = NSLocalizedString("connect.with.server.sheet.button", value: "Turn on Sync & Backup", comment: "Connect With Server Sheet - Button") static let connectWithServerSheetFooter = NSLocalizedString("connect.with.server.sheet.footer", value: "You can sync with your other devices later.", comment: "Connect With Server Sheet - Footer") -// Preparing To Sync Sheet + // Preparing To Sync Sheet static let preparingToSyncSheetTitle = NSLocalizedString("preparing.to.sync.sheet.title", value: "Setting Up Sync and Backup", comment: "Preparing To Sync Sheet - Title") static let preparingToSyncSheetDescription = NSLocalizedString("preparing.to.sync.sheet.description", value: "Your bookmarks and passwords are being prepared to sync. This should only take a moment.", comment: "Preparing To Sync Sheet - Description") static let preparingToSyncSheetFooter = NSLocalizedString("preparing.to.sync.sheet.footer", value: "Connecting…", comment: "Preparing To Sync Sheet - Footer") -// Save Recovery Code Sheet + // Save Recovery Code Sheet static let saveRecoveryCodeSheetTitle = NSLocalizedString("save.recovery.code.sheet.title", value: "Save Recovery Code", comment: "Save Recovery Code Sheet - Title") static let saveRecoveryCodeSheetDescription = NSLocalizedString("save.recovery.code.sheet.description", value: "If you lose access to your devices, you will need this code to recover your synced data.", comment: "Save Recovery Code Sheet - Description") static let saveRecoveryCodeSheetFooter = NSLocalizedString("save.recovery.code.sheet.footer", value: "Anyone with access to this code can access your synced data, so please keep it in a safe place.", comment: "Save Recovery Code Sheet - Footer") @@ -79,100 +82,67 @@ struct UserText { static let saveRecoveryCodeSaveAsPdfButton = NSLocalizedString("save.recovery.code.save.as.pdf.button", value: "Save as PDF", comment: "Save Recovery Code Sheet - Save as PDF Button") static let saveRecoveryCodeSaveCodeCopiedToast = NSLocalizedString("save.recovery.code.code.copied.button", value: "Recovery code copied to clipboard", comment: "Save Recovery Code Sheet - Copy Code Toast") -// Device Synced Sheet + // Device Synced Sheet static let deviceSyncedSheetTitle = NSLocalizedString("device.synced.sheet.title", value: "Your Data is Synced!", comment: "Device SyncedSheet - Title") -// Recover Synced Data Sheet + // Recover Synced Data Sheet 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 + // 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 + // 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") -// Manually Enter Code View - static let manuallyEnterCodeTitle = "Enter Text Code" - static let manuallyEnterCodeValidatingCodeAction = "Validating code" - static let manuallyEnterCodeValidatingCodeFailedAction = "Invalid code." - static let manuallyEnterCodeInstructionPart1 = "Go to " - static let manuallyEnterCodeInstructionPart2 = "Settings > Sync & Backup > Sync With Another Device " - static let manuallyEnterCodeInstructionPart3 = "and select " - static let manuallyEnterCodeInstructionPart4 = "View Text Code " - static let manuallyEnterCodeInstructionPart5 = "in the DuckDuckGo App on another synced device and paste the code here to sync this device." - - static let scanQRCode = "Scan QR Code" - static let enterTextCode = "Enter Text Code" - - static let singleDeviceSetUpTitle = "Single-Device Setup" - static let singleDeviceSetUpInstruction = "Set up this device now, sync with other devices later." - static let turnSyncOn = "Start Sync & Backup" - static let recoverYourData = "Recover Your Data" - - static let syncSettingsFooter = "Your data is end-to-end encrypted, and DuckDuckGo does not have access to the decryption key." - - static let connectDeviceInstructions = "Go to Settings › Sync & Backup in the DuckDuckGo Browser on a another device and select \n”Sync with Another Device.”" - - static let recoveryModeInstructions = "Scan the QR code on your Recovery PDF, or another synced device, to recover your data." - - static let pasteCodeInstructions = "Copy the code from the\n Settings > Sync & Back Up page in the DuckDuckGo App on another synced device and paste it here to sync this device." - - static let viewQRCodeInstructions = "Open the DuckDuckGo app on another device. Navigate to Settings > Sync & Back Up and scan this QR code." - static let viewQRCodeTitle = "Your Sync Code" - - static let syngleDeviceConnectedTitle = "All Set!" - static let deviceSyncedTitle = "Device Synced!" - static let firstDeviceSyncedMessage = "You can sync this device’s bookmarks and Logins with additional devices at any time from the Sync & Back Up menu in Settings." - static let deviceSyncedMessage = "Your bookmarks and Logins are now syncing with " - static let multipleDevicesSyncedMessage = "Your bookmarks and Logins are now syncing on " - static let wordDevices = "devices" - - static let syncTitle = "Sync & Backup" - - static let thisDevice = "This Device" - - static let copyCodeLabel = "Copy Code" - - - static let showQRCodeLabel = "Show QR Code" - static let showQRCodeSubLabel = "Display code to scan with another device" - - static let settingsNewDeviceInstructions1 = "Go to Settings > Sync in the" - static let settingsNewDeviceInstructions2 = "DuckDuckGo App" - static let settingsNewDeviceInstructions3 = "on a different device and scan to connect instantly" - static let settingsScanQRCodeButton = "Scan QR Code" - static let settingsShowCodeButton = "Show Text Code" - static let settingsSaveRecoveryPDFButton = "Save Recovery PDF" - static let settingsRecoveryPDFWarning = "If you lose your device, you will need this recovery code to restore your synced data." - -// Standard Buttons - static let cancelButton = "Cancel" - static let doneButton = "Done" - static let nextButton = "Next" - static let backButton = "Back" - static let pasteButton = "Paste" - - static let removeButton = "Remove" - static let notNowButton = "Not Now" - - static let editDeviceLabel = "Device Name" - static func editDevice(_ name: String) -> String { - return "Edit \(name)" + // Manually Enter Code View + static let manuallyEnterCodeTitle = NSLocalizedString("manually.enter.code.title", value: "Manually Enter Code", comment: "Manually Enter Code View - Title") + static let manuallyEnterCodeValidatingCodeAction = NSLocalizedString("manually.enter.code.validating.code.action", value: "Validating code", comment: "Manually Enter Code View - Validating Code Action") + static let manuallyEnterCodeValidatingCodeFailedAction = NSLocalizedString("manually.enter.code.validating.code.failed.action", value: "Invalid code.", comment: "Manually Enter Code View - Validating Code Failed Action") + static let manuallyEnterCodeInstructionPart1 = NSLocalizedString("manually.enter.code.instruction.part1", value: "Go to ", comment: "Manually Enter Code View - Instruction Part 1") + static let manuallyEnterCodeInstructionPart2 = NSLocalizedString("manually.enter.code.instruction.part2", value: "Settings > Sync & Backup > Sync With Another Device ", comment: "Manually Enter Code View - Instruction Part 2") + static let manuallyEnterCodeInstructionPart3 = NSLocalizedString("manually.enter.code.instruction.part3", value: "and select ", comment: "Manually Enter Code View - Instruction Part 3") + static let manuallyEnterCodeInstructionPart4 = NSLocalizedString("manually.enter.code.instruction.part4", value: "View Text Code ", comment: "Manually Enter Code View - Instruction Part 4") + static let manuallyEnterCodeInstructionPart5 = NSLocalizedString("manually.enter.code.instruction.part5", value: "in the DuckDuckGo App on another synced device and paste the code here to sync this device.", comment: "Manually Enter Code View - Instruction Part 5") + + // Scan or See Code View + static let scanOrSeeCodeTitle = NSLocalizedString("scan.or.see.code.title", value: "Scan QR Code", comment: "Scan or See Code View - Title") + static let scanOrSeeCodeInstructionPart1 = NSLocalizedString("scan.or.see.code.instruction.part1", value: "Go to ", comment: "Scan or See Code View - Instruction Part 1") + static let scanOrSeeCodeInstructionPart2 = NSLocalizedString("scan.or.see.code.instruction.part2", value: "Settings › Sync & Backup ", comment: "Scan or See Code View - Instruction Part 2") + static let scanOrSeeCodeInstructionPart3 = NSLocalizedString("scan.or.see.code.instruction.part3", value: "in the DuckDuckGo Browser on another device and select ”Sync with Another Device.”", comment: "Scan or See Code View - Instruction Part 3") + static let scanOrSeeCodeManuallyEnterCodeLink = NSLocalizedString("scan.or.see.code.manually.enter.code.link", value: "Manually Enter Code", comment: "Scan or See Code View - Manually Enter Code Link") + static let scanOrSeeCodeScanCodeInstructionsTitle = NSLocalizedString("scan.or.see.code.scan.code.instructions.title", value: "Mobile-to-Mobile?", comment: "Scan or See Code View - Scan Code Instructions Title") + static let scanOrSeeCodeScanCodeInstructionsBody = NSLocalizedString("scan.or.see.code.scan.code.instructions.body", value: "Scan this code with another device to sync.", comment: "Scan or See Code View - Scan Code Instructions Body") + static let scanOrSeeCodeFooter = NSLocalizedString("scan.or.see.code.footer", value: "Can’t Scan?", comment: "Scan or See Code View - Footer") + static let scanOrSeeCodeShareCodeLink = NSLocalizedString("scan.or.see.code.share.code.link", value: "Share Text Code?", comment: "Scan or See Code View - Share Code Link") + + // Edit Device View + static let editDeviceHeader = NSLocalizedString("edit.device.header", value: "Device Name", comment: "Edit Device View - Header") + static func editDeviceTitle(_ name: String) -> String { + return NSLocalizedString("edit.device.title", value: "Edit \(name)", comment: "Edit Device View - Title") } - static let removeDeviceTitle = "Remove Device?" - static let removeDeviceButton = "Remove Device" + // Remove Device View + static let removeDeviceTitle = NSLocalizedString("remove.device.title", value: "Remove Device?", comment: "Remove Device View - Title") + static let removeDeviceButton = NSLocalizedString("remove.device.button", value: "Remove Device", comment: "Remove Device View - Button") static func removeDeviceMessage(_ name: String) -> String { - return "\"\(name)\" will no longer be able to access your synced data." + return NSLocalizedString("remove.device.message", value: "\"\(name)\" will no longer be able to access your synced data.", comment: "Remove Device View - Message") } + + // Standard Buttons + static let cancelButton = NSLocalizedString("cancel.button", value: "Cancel", comment: "Standard Buttons - Cancel Button") + static let doneButton = NSLocalizedString("done.button", value: "Done", comment: "Standard Buttons - Done Button") + static let nextButton = NSLocalizedString("next.button", value: "Next", comment: "Standard Buttons - Next Button") + static let backButton = NSLocalizedString("back.button", value: "Back", comment: "Standard Buttons - Back Button") + static let pasteButton = NSLocalizedString("paste.button", value: "Paste", comment: "Standard Buttons - Paste Button") + + // swiftlint:enable line_length } -// swiftlint:enable line_length diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift index bbbc82a350..8bd0b6f61c 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift @@ -20,9 +20,7 @@ import SwiftUI import DesignResourcesKit -/// Handles scanning or pasting a code. -public struct ScanOrPasteCodeView: View { - +public struct ScanOrSeeCode: View { @ObservedObject var model: ScanOrPasteCodeViewModel @State var qrCodeModel = ShowQRCodeViewModel() @@ -32,326 +30,98 @@ public struct ScanOrPasteCodeView: View { self.model = model } - @State var isInvalidCode = false - - @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 waitingForCameraPermission() -> some View { - if model.videoPermission == .unknown { - SwiftUI.ProgressView() - } - } - - @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) - + public var body: some View { + VStack(spacing: 10) { + VStack(spacing: 10) { + titleView() + CameraView(model: model) } - .padding(.horizontal, 40) - } - } - - @ViewBuilder - func instructions() -> some View { - - Text(model.showConnectMode ? UserText.connectDeviceInstructions : UserText.recoveryModeInstructions) - .daxFootnoteRegular() - .multilineTextAlignment(.center) - .padding(.horizontal, 16) - } - - @ViewBuilder - func buttons() -> some View { - - Group { - Section { - NavigationLink { - PasteCodeView(model: model) - } label: { - HStack(spacing: 16) { - Image("SyncKeyboardIcon") - Text(UserText.manuallyEnterCodeTitle) - .daxButton() - .foregroundColor(.white.opacity(0.84)) - } + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(UserText.cancelButton, action: model.cancel) + .foregroundColor(Color.white) } - } - Section { - if model.showConnectMode { - NavigationLink { - ConnectModeView(model: model) - } label: { - HStack(spacing: 16) { - Image("SyncQRCodeIcon") - - VStack(alignment: .leading, spacing: 4) { - Text(UserText.showQRCodeLabel) - .daxButton() - .foregroundColor(.white.opacity(0.84)) - Text(UserText.showQRCodeSubLabel) - .daxCaption() - .foregroundColor(.white.opacity(0.6)) - } - .frame(maxWidth: .infinity, alignment: .leading) - } - } + ToolbarItem(placement: .navigationBarTrailing) { + NavigationLink(UserText.scanOrSeeCodeManuallyEnterCodeLink, destination: { + PasteCodeView(model: model) + }) + .foregroundColor(Color(designSystemColor: .accent)) } } - } - .frame(height: 40) - .foregroundColor(.primary) - .onAppear { - model.endConnectMode() + qrCodeView() } } @ViewBuilder - func cameraViewPort() -> some View { - ZStack(alignment: .center) { - waitingForCameraPermission() - cameraTarget() + func titleView() -> some View { + VStack(spacing: 10) { + Text(UserText.scanOrSeeCodeTitle) + .daxTitle2() + instructionsText() + .daxFootnoteRegular() + .multilineTextAlignment(.center) + .padding(.horizontal, 16) } + .padding(.top, 10) } @ViewBuilder - func cameraTarget() -> some View { - if model.showCamera { - ZStack { - ForEach([0.0, 90.0, 180.0, 270.0], id: \.self) { degrees in - RoundedCorner() - .stroke(lineWidth: 8) - .foregroundColor(isInvalidCode ? .red.opacity(0.6) : .white.opacity(0.8)) - .rotationEffect(.degrees(degrees), anchor: .center) - .frame(width: 250, height: 250) - } - } - } + func instructionsText() -> some View { + (Text(UserText.scanOrSeeCodeInstructionPart1) + + Text(UserText.scanOrSeeCodeInstructionPart2).bold() + + Text(UserText.scanOrSeeCodeInstructionPart3) + ) } - public var body: some View { - VStack(spacing: 10) { - VStack(spacing: 10) { - if model.showConnectMode { - Text("Scan QR Code") - .daxTitle2() - } - instructions() - } - .padding(.top, 10) - 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("Point camera at QR code to sync") - .padding(.vertical, 8) - .padding(.horizontal, 20) - .background( - RoundedRectangle(cornerRadius: 56) - .fill(.clear) - .background(BlurView(style: .light)) - .cornerRadius(20) - ) - .daxCaption() - } - .padding(.bottom, 12) - } - } - .ignoresSafeArea() - } - .toolbar { - ToolbarItem(placement: .navigationBarLeading) { - Button("Cancel", action: model.cancel) - .foregroundColor(Color.white) - } - ToolbarItem(placement: .navigationBarTrailing) { - NavigationLink("Manually Enter Code", destination: { - PasteCodeView(model: model) - }) - .foregroundColor(Color(designSystemColor: .accent)) + @ViewBuilder + func qrCodeView() -> some View { + VStack(spacing: 8) { + HStack(alignment: .top, spacing: 20) { + QRCodeView(string: qrCodeModel.code ?? "", size: 120) + VStack(alignment: .leading, spacing: 10) { + HStack { + Text(UserText.scanOrSeeCodeScanCodeInstructionsTitle) + .daxBodyBold() + .fixedSize() + Spacer() + Image("SyncDeviceType_phone") + .padding(2) + .background( + RoundedRectangle(cornerRadius: 2) + .fill(Color(designSystemColor: .lines)) + ) } + Text(UserText.scanOrSeeCodeScanCodeInstructionsBody) + .foregroundColor(.secondary) + .fixedSize(horizontal: false, vertical: true) + .multilineTextAlignment(.leading) } } - } - if model.showConnectMode { - VStack(spacing: 8) { - HStack(alignment: .top, spacing: 20) { - QRCodeView(string: qrCodeModel.code ?? "", size: 120) - VStack(alignment: .leading, spacing: 10) { - HStack { - Text("Mobile-to-Mobile?") - .daxBodyBold() - .fixedSize() - Spacer() - Image("SyncDeviceType_phone") - .padding(2) - .background( - RoundedRectangle(cornerRadius: 2) - .fill(Color(designSystemColor: .lines)) - ) - } - Text("Scan this code with another device to sync.") - .foregroundColor(.secondary) - .fixedSize(horizontal: false, vertical: true) - .multilineTextAlignment(.leading) - } - } - .padding(20) - .background( - RoundedRectangle(cornerRadius: 8) - .fill(Color(designSystemColor: .panel)) - ) - .padding(20) - HStack { - Text("can't scan?") - Text("Share Text Code") + .padding(20) + .background( + RoundedRectangle(cornerRadius: 8) + .fill(Color(designSystemColor: .panel)) + ) + .padding(20) + HStack { + Text(UserText.scanOrSeeCodeFooter) + HStack(alignment: .center) { + Text(UserText.scanOrSeeCodeShareCodeLink) .foregroundColor(Color(designSystemColor: .accent)) .onTapGesture { model.showShareCodeSheet() } - // .sheet(isPresented: $isShareSheetPresented, content: { - // ShareSheet(activityItems: [qrCodeModel.code ?? ""]) - // .frame(height: UIScreen.main.bounds.height / 2) - // }) - } - } - .padding(.bottom, 40) - .onAppear { - if let recoveryCode = model.recoveryCode { - self.qrCodeModel.code = recoveryCode - } else { - self.qrCodeModel = model.startConnectMode() + Image("Arrow-Circle-Right-12") } } - } else { - Rectangle().fill(Color.black) - .frame(maxHeight: 274) - } - } - - struct ShareSheet: UIViewControllerRepresentable { - let activityItems: [Any] - - func makeUIViewController(context: Context) -> UIViewController { - let controller = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) - return controller - } - - func updateUIViewController(_ uiViewController: UIViewController, context: Context) { - } - } - - - 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) + .padding(.bottom, 40) + .onAppear { + if let recoveryCode = model.recoveryCode { + self.qrCodeModel.code = recoveryCode + } else { + self.qrCodeModel = model.startConnectMode() + } } } - -} - -private struct RoundedCorner: Shape { - - func path(in rect: CGRect) -> Path { - var path = Path() - let c = 50.0 - let r = 30.0 - let e = c - r - - path.move(to: CGPoint(x: 0, y: c)) - path.addLine(to: CGPoint(x: 0, y: e)) - path.addCurve(to: CGPoint(x: e, y: 0), - control1: CGPoint(x: 0, y: 0), - control2: CGPoint(x: e, y: 0)) - path.addLine(to: CGPoint(x: c, y: 0)) - - return path - } - }