From ff587e1984bdb3f9b5c86d4535c54cefe2c7e04c Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 10 Jul 2025 09:35:35 +0100 Subject: [PATCH 1/7] Move welcome view to new file --- .../PointOfSaleBarcodeScannerSetupFlow.swift | 22 ---------- ...ntOfSaleBarcodeScannerSetupStepViews.swift | 42 +++++++++++++++++++ .../PointOfSaleBarcodeScannerSetupViews.swift | 19 --------- .../WooCommerce.xcodeproj/project.pbxproj | 4 ++ 4 files changed, 46 insertions(+), 41 deletions(-) create mode 100644 WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift index 9feb543c75d..e07dd45e4bd 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift @@ -112,28 +112,6 @@ class PointOfSaleBarcodeScannerSetupFlow { } } -// MARK: - Button Customizations -@available(iOS 17.0, *) -struct PointOfSaleBarcodeScannerWelcomeButtonCustomization: PointOfSaleBarcodeScannerButtonCustomization { - func customizeButtons(for flow: PointOfSaleBarcodeScannerSetupFlow) -> PointOfSaleFlowButtonConfiguration { - return PointOfSaleFlowButtonConfiguration( - primaryButton: PointOfSaleFlowButtonConfiguration.ButtonConfig( - title: Localization.doneButtonTitle, - action: { flow.nextStep() } - ), - secondaryButton: nil - ) - } - - private enum Localization { - static let doneButtonTitle = NSLocalizedString( - "pos.barcodeScannerSetup.done.button.title", - value: "Done", - comment: "Title for the done button in barcode scanner setup navigation" - ) - } -} - // MARK: - Private Localization Extension @available(iOS 17.0, *) private extension PointOfSaleBarcodeScannerSetupFlow { diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift new file mode 100644 index 00000000000..4f8f913bc82 --- /dev/null +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift @@ -0,0 +1,42 @@ +import SwiftUI + +// TODO: Remove this view when all flows are complete +struct PointOfSaleBarcodeScannerWelcomeView: View { + let title: String + + var body: some View { + VStack(spacing: POSSpacing.medium) { + Text(title) + .font(.posBodyLargeBold) + .foregroundColor(.posOnSurface) + + Text("TODO: Implement \(title) setup flow") + .font(.posBodyMediumRegular()) + .foregroundColor(.posOnSurfaceVariantHighest) + .multilineTextAlignment(.center) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } +} + +// MARK: - Button Customizations +@available(iOS 17.0, *) +struct PointOfSaleBarcodeScannerWelcomeButtonCustomization: PointOfSaleBarcodeScannerButtonCustomization { + func customizeButtons(for flow: PointOfSaleBarcodeScannerSetupFlow) -> PointOfSaleFlowButtonConfiguration { + return PointOfSaleFlowButtonConfiguration( + primaryButton: PointOfSaleFlowButtonConfiguration.ButtonConfig( + title: Localization.doneButtonTitle, + action: { flow.nextStep() } + ), + secondaryButton: nil + ) + } + + private enum Localization { + static let doneButtonTitle = NSLocalizedString( + "pos.barcodeScannerSetup.done.button.title", + value: "Done", + comment: "Title for the done button in barcode scanner setup navigation" + ) + } +} diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupViews.swift index df479b348d1..d6163c10929 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupViews.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupViews.swift @@ -56,25 +56,6 @@ struct PointOfSaleBarcodeScannerOptionView: View { } } -// MARK: - Step Views -struct PointOfSaleBarcodeScannerWelcomeView: View { - let title: String - - var body: some View { - VStack(spacing: POSSpacing.medium) { - Text(title) - .font(.posBodyLargeBold) - .foregroundColor(.posOnSurface) - - Text("TODO: Implement \(title) setup flow") - .font(.posBodyMediumRegular()) - .foregroundColor(.posOnSurfaceVariantHighest) - .multilineTextAlignment(.center) - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - } -} - // MARK: - Private Localization Extensions private extension PointOfSaleBarcodeScannerSetupSelectionView { enum Localization { diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index 4a85e1a4037..cf9338e2008 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -886,6 +886,7 @@ 2088784B2D96E98000F7AE03 /* PointOfSaleCardPresentPaymentConnectingLocationPreAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2088784A2D96E98000F7AE03 /* PointOfSaleCardPresentPaymentConnectingLocationPreAlertView.swift */; }; 2088784D2D96EA3900F7AE03 /* PointOfSaleCardPresentPaymentConnectingLocationPreAlertViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2088784C2D96EA3900F7AE03 /* PointOfSaleCardPresentPaymentConnectingLocationPreAlertViewModel.swift */; }; 20897C9E2D4A68C5008AD16C /* PointOfSaleUnsupportedWidthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20897C9D2D4A68C5008AD16C /* PointOfSaleUnsupportedWidthView.swift */; }; + 208C0F0A2E1FAC1900FE619E /* PointOfSaleBarcodeScannerSetupStepViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 208C0F092E1FAC1900FE619E /* PointOfSaleBarcodeScannerSetupStepViews.swift */; }; 209566252D4CF00100977124 /* PointOfSalePaymentMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 209566242D4CF00100977124 /* PointOfSalePaymentMethod.swift */; }; 209AD3D02AC1EDDA00825D76 /* WooPaymentsPayoutsCurrencyOverviewViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 209AD3CF2AC1EDDA00825D76 /* WooPaymentsPayoutsCurrencyOverviewViewModel.swift */; }; 209AD3D22AC1EDF600825D76 /* WooPaymentsPayoutsCurrencyOverviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 209AD3D12AC1EDF600825D76 /* WooPaymentsPayoutsCurrencyOverviewView.swift */; }; @@ -4057,6 +4058,7 @@ 2088784A2D96E98000F7AE03 /* PointOfSaleCardPresentPaymentConnectingLocationPreAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentConnectingLocationPreAlertView.swift; sourceTree = ""; }; 2088784C2D96EA3900F7AE03 /* PointOfSaleCardPresentPaymentConnectingLocationPreAlertViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentConnectingLocationPreAlertViewModel.swift; sourceTree = ""; }; 20897C9D2D4A68C5008AD16C /* PointOfSaleUnsupportedWidthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleUnsupportedWidthView.swift; sourceTree = ""; }; + 208C0F092E1FAC1900FE619E /* PointOfSaleBarcodeScannerSetupStepViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleBarcodeScannerSetupStepViews.swift; sourceTree = ""; }; 209566242D4CF00100977124 /* PointOfSalePaymentMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSalePaymentMethod.swift; sourceTree = ""; }; 209AD3CF2AC1EDDA00825D76 /* WooPaymentsPayoutsCurrencyOverviewViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooPaymentsPayoutsCurrencyOverviewViewModel.swift; sourceTree = ""; }; 209AD3D12AC1EDF600825D76 /* WooPaymentsPayoutsCurrencyOverviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooPaymentsPayoutsCurrencyOverviewView.swift; sourceTree = ""; }; @@ -8310,6 +8312,7 @@ 20C3DB1F2E1E69CF00CF7D3B /* PointOfSaleBarcodeScannerSetupFlowManager.swift */, 20C3DB202E1E69CF00CF7D3B /* PointOfSaleBarcodeScannerSetupModels.swift */, 20C3DB212E1E69CF00CF7D3B /* PointOfSaleBarcodeScannerSetupViews.swift */, + 208C0F092E1FAC1900FE619E /* PointOfSaleBarcodeScannerSetupStepViews.swift */, 20C3DB282E1E6FBA00CF7D3B /* PointOfSaleFlowButtonsView.swift */, ); path = "Barcode Scanner Setup"; @@ -15239,6 +15242,7 @@ 03E471CA293E0A30001A58AD /* CardPresentModalTapToPayConfigurationProgress.swift in Sources */, 31AD0B1126E9575F000B6391 /* CardPresentModalConnectingFailed.swift in Sources */, 576EA39425264C9B00AFC0B3 /* RefundConfirmationViewModel.swift in Sources */, + 208C0F0A2E1FAC1900FE619E /* PointOfSaleBarcodeScannerSetupStepViews.swift in Sources */, 02ED3D272C23315400ED6F3E /* PointOfSaleCardPresentPaymentReaderUpdateFailedView.swift in Sources */, 01BD77482C58D19C00147191 /* PointOfSaleCardPresentPaymentCancelledOnReaderMessageView.swift in Sources */, DEC51B00276AEE91009F3DF4 /* SystemStatusReportViewModel.swift in Sources */, From b9003595bb3dfd4c42d5ce8cba10593d2498ac8e Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 10 Jul 2025 10:15:24 +0100 Subject: [PATCH 2/7] Add Star set up code view in set up flow --- .../PointOfSaleBarcodeScannerSetupFlow.swift | 10 ++++++- ...PointOfSaleBarcodeScannerSetupModels.swift | 25 ++++++++++++++++- ...ntOfSaleBarcodeScannerSetupStepViews.swift | 26 ++++++++++++++++++ .../POS/Presentation/PointOfSaleAssets.swift | 3 ++ .../Contents.json | 12 ++++++++ .../star-bsh20-setup-barcode.pdf | Bin 0 -> 12140 bytes 6 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 WooCommerce/Resources/Images.xcassets/POS/star-bsh20-setup-barcode.imageset/Contents.json create mode 100644 WooCommerce/Resources/Images.xcassets/POS/star-bsh20-setup-barcode.imageset/star-bsh20-setup-barcode.pdf diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift index e07dd45e4bd..36dc5988dec 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift @@ -85,7 +85,12 @@ class PointOfSaleBarcodeScannerSetupFlow { ] case .starBSH20B: return [ - createWelcomeStep(title: "Star BSH-20B Setup") + PointOfSaleBarcodeScannerSetupStep(content: { + PointOfSaleBarcodeScannerBarcodeView( + title: String(format: Localization.starSetUpBarcodeStepTitleFormat, scannerType.name), + instruction: Localization.setUpBarcodeStepInstruction, + barcode: .starBsh20SetupBarcode) + }) // TODO: Add more steps for Star BSH-20B WOOMOB-696 ] case .tbcScanner: @@ -131,5 +136,8 @@ private extension PointOfSaleBarcodeScannerSetupFlow { value: "Back", comment: "Title for the back button in barcode scanner setup navigation" ) + //TODO: WOOMOB-792 + static let starSetUpBarcodeStepTitleFormat = "%1$@ Setup" + static let setUpBarcodeStepInstruction = "Scan the barcode to set up your scanner." } } diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift index 12a1ce4554d..5fdaa3a9dc5 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift @@ -13,6 +13,29 @@ enum PointOfSaleBarcodeScannerType { case starBSH20B case tbcScanner case other + + var name: String { + switch self { + case .socketS720: + return Localization.socketS720Name + case .starBSH20B: + return Localization.starBsh20BName + case .tbcScanner: + return Localization.tbcScannerName + case .other: + return Localization.otherName + } + } +} + +private extension PointOfSaleBarcodeScannerType { + //TODO: WOOMOB-792 + enum Localization { + static let socketS720Name = "Socket S720" + static let starBsh20BName = "Star BSH-20B" + static let tbcScannerName = "TBC scanner" + static let otherName = "Other scanner" + } } // MARK: - Flow State @@ -35,7 +58,7 @@ struct PointOfSaleBarcodeScannerSetupStep { let buttonCustomization: PointOfSaleBarcodeScannerButtonCustomization? init( - title: String, + title: String = "", @ViewBuilder content: () -> any View, buttonCustomization: PointOfSaleBarcodeScannerButtonCustomization? = nil ) { diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift index 4f8f913bc82..f4d682ba857 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift @@ -19,6 +19,32 @@ struct PointOfSaleBarcodeScannerWelcomeView: View { } } +struct PointOfSaleBarcodeScannerBarcodeView: View { + let title: String + let instruction: String + let barcode: PointOfSaleAssets + + var body: some View { + VStack(spacing: POSSpacing.xLarge) { + VStack(alignment: .center, spacing: POSSpacing.small) { + Text(title) + .font(.posHeadingBold) + .foregroundColor(.posOnSurface) + .accessibilityAddTraits(.isHeader) + + Text(instruction) + .font(.posBodyMediumRegular()) + .foregroundColor(.posOnSurfaceVariantHighest) + .multilineTextAlignment(.center) + } + + Image(barcode.imageName) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } +} + + // MARK: - Button Customizations @available(iOS 17.0, *) struct PointOfSaleBarcodeScannerWelcomeButtonCustomization: PointOfSaleBarcodeScannerButtonCustomization { diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift index 3bd6597d82c..fe28390fe39 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift @@ -14,6 +14,7 @@ enum PointOfSaleAssets: CaseIterable { case shoppingBags case successCheck case coupons + case starBsh20SetupBarcode var imageName: String { switch self { @@ -43,6 +44,8 @@ enum PointOfSaleAssets: CaseIterable { "pos-success-check" case .coupons: "coupons" + case .starBsh20SetupBarcode: + "star-bsh20-setup-barcode" } } } diff --git a/WooCommerce/Resources/Images.xcassets/POS/star-bsh20-setup-barcode.imageset/Contents.json b/WooCommerce/Resources/Images.xcassets/POS/star-bsh20-setup-barcode.imageset/Contents.json new file mode 100644 index 00000000000..6397e2d72f5 --- /dev/null +++ b/WooCommerce/Resources/Images.xcassets/POS/star-bsh20-setup-barcode.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "star-bsh20-setup-barcode.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/WooCommerce/Resources/Images.xcassets/POS/star-bsh20-setup-barcode.imageset/star-bsh20-setup-barcode.pdf b/WooCommerce/Resources/Images.xcassets/POS/star-bsh20-setup-barcode.imageset/star-bsh20-setup-barcode.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8b367953fd37cc6a8f2ae94766b91dec580446b3 GIT binary patch literal 12140 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 Z&`7BL3~VGB8cB%%1B)Oykoz|*{y(LI?B)Of literal 0 HcmV?d00001 From 8553d97c603c6e7e28cc9c7ef53dae7712ceed6e Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 10 Jul 2025 10:57:21 +0100 Subject: [PATCH 3/7] Add pairing barcode scanner set up step --- .../PointOfSaleBarcodeScannerSetupFlow.swift | 5 +- ...ntOfSaleBarcodeScannerSetupStepViews.swift | 49 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift index 36dc5988dec..5ec56a28065 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift @@ -90,7 +90,10 @@ class PointOfSaleBarcodeScannerSetupFlow { title: String(format: Localization.starSetUpBarcodeStepTitleFormat, scannerType.name), instruction: Localization.setUpBarcodeStepInstruction, barcode: .starBsh20SetupBarcode) - }) + }), + PointOfSaleBarcodeScannerSetupStep(content: { + PointOfSaleBarcodeScannerPairingView(scanner: scannerType) + }), // TODO: Add more steps for Star BSH-20B WOOMOB-696 ] case .tbcScanner: diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift index f4d682ba857..fae5c3c42dd 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift @@ -44,6 +44,55 @@ struct PointOfSaleBarcodeScannerBarcodeView: View { } } +struct PointOfSaleBarcodeScannerPairingView: View { + let scanner: PointOfSaleBarcodeScannerType + + var body: some View { + VStack(spacing: POSSpacing.xLarge) { + // Temporary image until finalised assets are available + Image(systemName: "gearshape") + .font(.system(size: 78)) + .accessibilityHidden(true) + + VStack(alignment: .center, spacing: POSSpacing.small) { + Text(Localization.title) + .font(.posHeadingBold) + .foregroundColor(.posOnSurface) + .accessibilityAddTraits(.isHeader) + + Text(instruction) + .font(.posBodyMediumRegular()) + .foregroundColor(.posOnSurfaceVariantHighest) + .multilineTextAlignment(.center) + } + + Button { + guard let targetURL = URL(string: UIApplication.openSettingsURLString) else { + return + } + UIApplication.shared.open(targetURL) + } label: { + Text(Localization.settingsButtonTitle) + } + .buttonStyle(POSOutlinedButtonStyle(size: .extraSmall)) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + } + + private var instruction: String { + String(format: Localization.instructionFormat, scanner.name) + } +} + +private extension PointOfSaleBarcodeScannerPairingView { + //TODO: WOOMOB-792 + enum Localization { + static let settingsButtonTitle = "Go to settings" + static let title = "Pair your device" + static let instructionFormat = "Enable Bluetooth and select your %1$@ scanner in iOS Settings." + } +} + // MARK: - Button Customizations @available(iOS 17.0, *) From b180138edecf1e81badaad25e54e92df893334a9 Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 10 Jul 2025 11:40:00 +0100 Subject: [PATCH 4/7] Avoid setting the frame on every step view --- .../Barcode Scanner Setup/PointOfSaleBarcodeScannerSetup.swift | 1 + .../PointOfSaleBarcodeScannerSetupStepViews.swift | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetup.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetup.swift index 39f3e9da729..5f6af304c92 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetup.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetup.swift @@ -18,6 +18,7 @@ struct PointOfSaleBarcodeScannerSetup: View { VStack { currentContent + .frame(maxWidth: .infinity, maxHeight: .infinity) Spacer() } .scrollVerticallyIfNeeded() diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift index fae5c3c42dd..50348bdfbb2 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift @@ -15,7 +15,6 @@ struct PointOfSaleBarcodeScannerWelcomeView: View { .foregroundColor(.posOnSurfaceVariantHighest) .multilineTextAlignment(.center) } - .frame(maxWidth: .infinity, maxHeight: .infinity) } } @@ -40,7 +39,6 @@ struct PointOfSaleBarcodeScannerBarcodeView: View { Image(barcode.imageName) } - .frame(maxWidth: .infinity, maxHeight: .infinity) } } @@ -76,7 +74,6 @@ struct PointOfSaleBarcodeScannerPairingView: View { } .buttonStyle(POSOutlinedButtonStyle(size: .extraSmall)) } - .frame(maxWidth: .infinity, maxHeight: .infinity) } private var instruction: String { From 6f9cd77fbca3b9042ab5a97e6b382914e5f21674 Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 10 Jul 2025 11:40:20 +0100 Subject: [PATCH 5/7] Add test barcode scanner setup step --- .../PointOfSaleBarcodeScannerSetupFlow.swift | 34 ++++++++ ...PointOfSaleBarcodeScannerSetupModels.swift | 19 +++++ ...tOfSaleBarcodeScannerSetupScanTester.swift | 26 ++++++ ...ntOfSaleBarcodeScannerSetupStepViews.swift | 21 +++++ .../POS/Presentation/PointOfSaleAssets.swift | 4 + .../test-ean13-barcode.imageset/Contents.json | 12 +++ .../barcode-1-2.png | Bin 0 -> 3660 bytes .../WooCommerce.xcodeproj/project.pbxproj | 16 ++++ ...leBarcodeScannerSetupScanTesterTests.swift | 80 ++++++++++++++++++ 9 files changed, 212 insertions(+) create mode 100644 WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTester.swift create mode 100644 WooCommerce/Resources/Images.xcassets/POS/test-ean13-barcode.imageset/Contents.json create mode 100644 WooCommerce/Resources/Images.xcassets/POS/test-ean13-barcode.imageset/barcode-1-2.png create mode 100644 WooCommerce/WooCommerceTests/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTesterTests.swift diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift index 5ec56a28065..15833b5a908 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift @@ -94,6 +94,19 @@ class PointOfSaleBarcodeScannerSetupFlow { PointOfSaleBarcodeScannerSetupStep(content: { PointOfSaleBarcodeScannerPairingView(scanner: scannerType) }), + PointOfSaleBarcodeScannerSetupStep( + content: { + PointOfSaleBarcodeScannerTestBarcodeView( + scanTester: PointOfSaleBarcodeScannerSetupScanTester( + onTestPass: { [weak self] in + self?.nextStep() + }, + onTestFailure: {}, + barcodeDefinition: .ean13) + ) + }, + buttonCustomization: PointOfSaleBarcodeScannerBackOnlyButtonCustomization() + ) // TODO: Add more steps for Star BSH-20B WOOMOB-696 ] case .tbcScanner: @@ -120,6 +133,27 @@ class PointOfSaleBarcodeScannerSetupFlow { } } +@available(iOS 17.0, *) +struct PointOfSaleBarcodeScannerBackOnlyButtonCustomization: PointOfSaleBarcodeScannerButtonCustomization { + func customizeButtons(for flow: PointOfSaleBarcodeScannerSetupFlow) -> PointOfSaleFlowButtonConfiguration { + return PointOfSaleFlowButtonConfiguration( + primaryButton: nil, + secondaryButton: PointOfSaleFlowButtonConfiguration.ButtonConfig( + title: Localization.backButtonTitle, + action: { flow.previousStep() } + ) + ) + } + + private enum Localization { + static let backButtonTitle = NSLocalizedString( + "pos.barcodeScannerSetup.back.button.title", + value: "Back", + comment: "Title for the back button in barcode scanner setup navigation" + ) + } +} + // MARK: - Private Localization Extension @available(iOS 17.0, *) private extension PointOfSaleBarcodeScannerSetupFlow { diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift index 5fdaa3a9dc5..c0732ce9e9a 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupModels.swift @@ -67,3 +67,22 @@ struct PointOfSaleBarcodeScannerSetupStep { self.buttonCustomization = buttonCustomization } } + +// MARK: - Test Barcodes +enum PointOfSaleBarcodeScannerTestBarcode { + case ean13 + + var barcodeAsset: PointOfSaleAssets { + switch self { + case .ean13: + return .testEan13Barcode + } + } + + var expectedValue: String { + switch self { + case .ean13: + return "1234567890128" + } + } +} diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTester.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTester.swift new file mode 100644 index 00000000000..bc530c92ecf --- /dev/null +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTester.swift @@ -0,0 +1,26 @@ +import Foundation + +struct PointOfSaleBarcodeScannerSetupScanTester { + private let onTestPass: () -> Void + private let onTestFailure: () -> Void + private let barcodeDefinition: PointOfSaleBarcodeScannerTestBarcode + + init(onTestPass: @escaping () -> Void, onTestFailure: @escaping () -> Void, barcodeDefinition: PointOfSaleBarcodeScannerTestBarcode) { + self.onTestPass = onTestPass + self.onTestFailure = onTestFailure + self.barcodeDefinition = barcodeDefinition + } + + var barcode: PointOfSaleAssets { + barcodeDefinition.barcodeAsset + } + + func handleScan(_ scanResult: Result) { + switch scanResult { + case .success(barcodeDefinition.expectedValue): + onTestPass() + case .success, .failure: + onTestFailure() + } + } +} diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift index 50348bdfbb2..e6f0e625c4f 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift @@ -90,6 +90,27 @@ private extension PointOfSaleBarcodeScannerPairingView { } } +@available(iOS 17.0, *) +struct PointOfSaleBarcodeScannerTestBarcodeView: View { + let scanTester: PointOfSaleBarcodeScannerSetupScanTester + + var body: some View { + PointOfSaleBarcodeScannerBarcodeView(title: Localization.title, + instruction: Localization.instruction, + barcode: scanTester.barcode) + .barcodeScanning { result in + scanTester.handleScan(result) + } + } +} + +@available(iOS 17.0, *) +private extension PointOfSaleBarcodeScannerTestBarcodeView { + enum Localization { + static let title = "Test your scanner" + static let instruction = "Scan the barcode to test your scanner" + } +} // MARK: - Button Customizations @available(iOS 17.0, *) diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift index fe28390fe39..855e8d175f0 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift @@ -14,7 +14,9 @@ enum PointOfSaleAssets: CaseIterable { case shoppingBags case successCheck case coupons + //TODO: WOOMOB-793 Update the imagesets for these barcodes to vector/dark mode friendly images case starBsh20SetupBarcode + case testEan13Barcode var imageName: String { switch self { @@ -46,6 +48,8 @@ enum PointOfSaleAssets: CaseIterable { "coupons" case .starBsh20SetupBarcode: "star-bsh20-setup-barcode" + case .testEan13Barcode: + "test-ean13-barcode" } } } diff --git a/WooCommerce/Resources/Images.xcassets/POS/test-ean13-barcode.imageset/Contents.json b/WooCommerce/Resources/Images.xcassets/POS/test-ean13-barcode.imageset/Contents.json new file mode 100644 index 00000000000..06f78194e6b --- /dev/null +++ b/WooCommerce/Resources/Images.xcassets/POS/test-ean13-barcode.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "barcode-1-2.png", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/WooCommerce/Resources/Images.xcassets/POS/test-ean13-barcode.imageset/barcode-1-2.png b/WooCommerce/Resources/Images.xcassets/POS/test-ean13-barcode.imageset/barcode-1-2.png new file mode 100644 index 0000000000000000000000000000000000000000..eaf93522dcc640f967d1a8d14864e10d9778e821 GIT binary patch literal 3660 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 Ba*O}~ literal 0 HcmV?d00001 diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index cf9338e2008..016248bc084 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -871,6 +871,8 @@ 207823E32C5D18CE00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207823E22C5D18CE00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift */; }; 207823E52C5D1B2F00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207823E42C5D1B2F00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift */; }; 207823E92C5D3A1700025A59 /* POSErrorExclamationMark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207823E82C5D3A1700025A59 /* POSErrorExclamationMark.swift */; }; + 207CEA852E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207CEA842E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift */; }; + 207CEA882E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207CEA872E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift */; }; 207D2D232CFDCCBF00F79204 /* MockPOSOrderableItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207D2D222CFDCCBF00F79204 /* MockPOSOrderableItem.swift */; }; 207E71CB2C60F765008540FC /* MockPOSOrderService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207E71CA2C60F765008540FC /* MockPOSOrderService.swift */; }; 2084B7A22C77693600EFBD2E /* CardPresentPaymentsModalButtonViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2084B7A12C77693600EFBD2E /* CardPresentPaymentsModalButtonViewModelTests.swift */; }; @@ -4043,6 +4045,8 @@ 207823E22C5D18CE00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentConnectionSuccessAlertViewModel.swift; sourceTree = ""; }; 207823E42C5D1B2F00025A59 /* PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentConnectionSuccessAlertView.swift; sourceTree = ""; }; 207823E82C5D3A1700025A59 /* POSErrorExclamationMark.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSErrorExclamationMark.swift; sourceTree = ""; }; + 207CEA842E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleBarcodeScannerSetupScanTester.swift; sourceTree = ""; }; + 207CEA872E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleBarcodeScannerSetupScanTesterTests.swift; sourceTree = ""; }; 207D2D222CFDCCBF00F79204 /* MockPOSOrderableItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = MockPOSOrderableItem.swift; path = ../Modules/Tests/YosemiteTests/Mocks/MockPOSOrderableItem.swift; sourceTree = SOURCE_ROOT; }; 207E71CA2C60F765008540FC /* MockPOSOrderService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockPOSOrderService.swift; sourceTree = ""; }; 2084B7A12C77693600EFBD2E /* CardPresentPaymentsModalButtonViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentPaymentsModalButtonViewModelTests.swift; sourceTree = ""; }; @@ -7229,6 +7233,7 @@ 026A502D2D2F8087002C42C2 /* Presentation */ = { isa = PBXGroup; children = ( + 207CEA862E1FD6D80023EC35 /* Barcode Scanner Setup */, 20D5575E2DFAE3D500D9EC8B /* Barcode Scanning */, 01AB2D132DDC7CD000AA67FD /* POSItemActionHandlerFactoryTests.swift */, 01AB2D112DDC7AD100AA67FD /* PointOfSaleItemListAnalyticsTrackerTests.swift */, @@ -8234,6 +8239,14 @@ path = "Reader Messages"; sourceTree = ""; }; + 207CEA862E1FD6D80023EC35 /* Barcode Scanner Setup */ = { + isa = PBXGroup; + children = ( + 207CEA872E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift */, + ); + path = "Barcode Scanner Setup"; + sourceTree = ""; + }; 2084B7A02C7768E200EFBD2E /* Connection Alerts */ = { isa = PBXGroup; children = ( @@ -8313,6 +8326,7 @@ 20C3DB202E1E69CF00CF7D3B /* PointOfSaleBarcodeScannerSetupModels.swift */, 20C3DB212E1E69CF00CF7D3B /* PointOfSaleBarcodeScannerSetupViews.swift */, 208C0F092E1FAC1900FE619E /* PointOfSaleBarcodeScannerSetupStepViews.swift */, + 207CEA842E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift */, 20C3DB282E1E6FBA00CF7D3B /* PointOfSaleFlowButtonsView.swift */, ); path = "Barcode Scanner Setup"; @@ -15457,6 +15471,7 @@ CE22E3F72170E23C005A6BEF /* PrivacySettingsViewController.swift in Sources */, 02222BD02D5AFE4F00FB97D2 /* POSButtonProgressViewStyle.swift in Sources */, 021125482577CC650075AD2A /* ShippingLabelDetailsViewModel.swift in Sources */, + 207CEA852E1FD59B0023EC35 /* PointOfSaleBarcodeScannerSetupScanTester.swift in Sources */, 2004E2D82C08E56300D62521 /* CardPresentPaymentOnboardingPresentationEvent.swift in Sources */, 68D1BEDD2900E4180074A29E /* CustomerSearchUICommand.swift in Sources */, 316837DA25CCA90C00E36B2F /* OrderStatusListDataSource.swift in Sources */, @@ -17598,6 +17613,7 @@ B9CB14E02A42E246005912C2 /* BarcodeScannerErrorNoticeFactoryTests.swift in Sources */, 6856D49DB7DCF4D87745C0B1 /* MockPushNotificationsManager.swift in Sources */, 4569D3C925DC065B00CDC3E2 /* SiteAddressTests.swift in Sources */, + 207CEA882E1FD6F80023EC35 /* PointOfSaleBarcodeScannerSetupScanTesterTests.swift in Sources */, EE289AFE2C9D9CF0004AB1A6 /* ProductCreationAIEligibilityCheckerTests.swift in Sources */, CC4D1E7925EE415D00B6E4E7 /* RenameAttributesViewModelTests.swift in Sources */, 458BAC702C57E38F009440EA /* ProductPasswordEligibilityUseCaseTests.swift in Sources */, diff --git a/WooCommerce/WooCommerceTests/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTesterTests.swift b/WooCommerce/WooCommerceTests/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTesterTests.swift new file mode 100644 index 00000000000..9e42ed01628 --- /dev/null +++ b/WooCommerce/WooCommerceTests/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupScanTesterTests.swift @@ -0,0 +1,80 @@ +import Testing +@testable import WooCommerce + +struct PointOfSaleBarcodeScannerSetupScanTesterTests { + + @Test func test_scanTester_calls_onTestPass_when_scan_received_for_expected_barcode() { + // Given a test EAN13 barcode + let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13 + var onTestPassCalled = false + var onTestFailureCalled = false + + let sut = PointOfSaleBarcodeScannerSetupScanTester( + onTestPass: { onTestPassCalled = true }, + onTestFailure: { onTestFailureCalled = true }, + barcodeDefinition: expectedBarcode) + + // When the barcode is scanned + sut.handleScan(.success(expectedBarcode.expectedValue)) + + // Then it calls the pass closure + #expect(onTestPassCalled == true) + #expect(onTestFailureCalled == false) + } + + @Test func test_scanTester_calls_onTestFailure_when_scan_received_for_unexpected_barcode() { + // Given a test EAN13 barcode + let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13 + var onTestPassCalled = false + var onTestFailureCalled = false + + let sut = PointOfSaleBarcodeScannerSetupScanTester( + onTestPass: { onTestPassCalled = true }, + onTestFailure: { onTestFailureCalled = true }, + barcodeDefinition: expectedBarcode) + + // When an unexpected barcode is scanned + sut.handleScan(.success("9999999999999")) + + // Then it calls the failure closure + #expect(onTestPassCalled == false) + #expect(onTestFailureCalled == true) + } + + @Test func test_scanTester_calls_onTestFailure_when_scan_fails() { + // Given a test EAN13 barcode + let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13 + var onTestPassCalled = false + var onTestFailureCalled = false + + let sut = PointOfSaleBarcodeScannerSetupScanTester( + onTestPass: { onTestPassCalled = true }, + onTestFailure: { onTestFailureCalled = true }, + barcodeDefinition: expectedBarcode) + + // When the scan fails + sut.handleScan(.failure(TestError.scanFailed)) + + // Then it calls the failure closure + #expect(onTestPassCalled == false) + #expect(onTestFailureCalled == true) + } + + private enum TestError: Error { + case scanFailed + } + + @Test func test_scanTester_provides_correct_barcode_asset() { + // Given a test EAN13 barcode + let expectedBarcode = PointOfSaleBarcodeScannerTestBarcode.ean13 + + let sut = PointOfSaleBarcodeScannerSetupScanTester( + onTestPass: {}, + onTestFailure: {}, + barcodeDefinition: expectedBarcode) + + // Then it provides the correct barcode asset + #expect(sut.barcode == .testEan13Barcode) + } + +} From 74eec0b9ea1b08bdc845461c9fb58bc062e9aeca Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 10 Jul 2025 13:03:12 +0100 Subject: [PATCH 6/7] Add basic success view --- .../PointOfSaleBarcodeScannerSetupFlow.swift | 8 +++- ...ntOfSaleBarcodeScannerSetupStepViews.swift | 44 +++++++++++++++++++ .../PointOfSalePaymentSuccessView.swift | 4 +- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift index 15833b5a908..9258559eac0 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupFlow.swift @@ -106,8 +106,12 @@ class PointOfSaleBarcodeScannerSetupFlow { ) }, buttonCustomization: PointOfSaleBarcodeScannerBackOnlyButtonCustomization() - ) - // TODO: Add more steps for Star BSH-20B WOOMOB-696 + ), + PointOfSaleBarcodeScannerSetupStep( + content: { + PointOfSaleBarcodeScannerSetupCompleteView() + }) + // TODO: Add optional error step and documentation step for Star BSH-20B WOOMOB-696 ] case .tbcScanner: return [ diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift index e6f0e625c4f..44620ceefbe 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift @@ -112,6 +112,50 @@ private extension PointOfSaleBarcodeScannerTestBarcodeView { } } +struct PointOfSaleBarcodeScannerSetupCompleteView: View { + var body: some View { + VStack(spacing: POSSpacing.xLarge) { + // Temporary image until finalised assets are available + successIcon + .accessibilityHidden(true) + + VStack(alignment: .center, spacing: POSSpacing.small) { + Text(Localization.title) + .font(.posHeadingBold) + .foregroundColor(.posOnSurface) + .accessibilityAddTraits(.isHeader) + + Text(Localization.instruction) + .font(.posBodyMediumRegular()) + .foregroundColor(.posOnSurfaceVariantHighest) + .multilineTextAlignment(.center) + } + } + } + + @ViewBuilder private var successIcon: some View { + ZStack { + Circle() + .frame(width: 104, height: 104) + .foregroundColor(.posSuccess) + Image(PointOfSaleAssets.successCheck.imageName) + .renderingMode(.template) + .resizable() + .frame(width: 48, height: 48) + .foregroundColor(.posOnSuccess) + } + } +} + +private extension PointOfSaleBarcodeScannerSetupCompleteView { + enum Localization { + //TODO: WOOMOB-792 + static let title = "Scanner set up!" + static let instruction = "You are ready to start scanning products. \n" + + "Read more about barcode and QR code scanner support." + } +} + // MARK: - Button Customizations @available(iOS 17.0, *) struct PointOfSaleBarcodeScannerWelcomeButtonCustomization: PointOfSaleBarcodeScannerButtonCustomization { diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSalePaymentSuccessView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSalePaymentSuccessView.swift index c297644add8..bd52bfcb9f9 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSalePaymentSuccessView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Reader Messages/PointOfSalePaymentSuccessView.swift @@ -101,7 +101,7 @@ struct PointOfSalePaymentSuccessView: View { Image(PointOfSaleAssets.successCheck.imageName) .renderingMode(.template) .foregroundColor(checkmarkColor) - .frame(width: 52) + .frame(width: Constants.checkmarkSize) .accessibilityHidden(true) } } @@ -116,7 +116,7 @@ private extension PointOfSalePaymentSuccessView { enum Constants { static let imageName: String = "checkmark" static let imageSize: CGSize = .init(width: 165, height: 165) - static let checkmarkSize: CGFloat = 56 + static let checkmarkSize: CGFloat = 52 static let shadowOpacity: CGFloat = 0.16 static let shadowRadius: CGFloat = 16 static let shadowSize: CGSize = .init(width: 0, height: 8) From f29c5799bad65a242e2fe83436c8464a3de9ef66 Mon Sep 17 00:00:00 2001 From: Josh Heald Date: Thu, 10 Jul 2025 13:13:44 +0100 Subject: [PATCH 7/7] =?UTF-8?q?Show=20hint=20when=20we=20don=E2=80=99t=20g?= =?UTF-8?q?et=20a=20test=20scan=20within=2010s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ntOfSaleBarcodeScannerSetupStepViews.swift | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift index 44620ceefbe..458eb01dcea 100644 --- a/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift +++ b/WooCommerce/Classes/POS/Presentation/Barcode Scanner Setup/PointOfSaleBarcodeScannerSetupStepViews.swift @@ -93,14 +93,29 @@ private extension PointOfSaleBarcodeScannerPairingView { @available(iOS 17.0, *) struct PointOfSaleBarcodeScannerTestBarcodeView: View { let scanTester: PointOfSaleBarcodeScannerSetupScanTester + @State private var timerCompleted = false + @State private var timer: Timer? var body: some View { - PointOfSaleBarcodeScannerBarcodeView(title: Localization.title, - instruction: Localization.instruction, + PointOfSaleBarcodeScannerBarcodeView(title: timerCompleted ? Localization.timeoutTitle : Localization.title, + instruction: timerCompleted ? Localization.timeoutInstruction : Localization.instruction, barcode: scanTester.barcode) .barcodeScanning { result in scanTester.handleScan(result) } + .onAppear { + startTimer() + } + .onDisappear { + timer?.invalidate() + timer = nil + } + } + + private func startTimer() { + timer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: false) { _ in + timerCompleted = true + } } } @@ -109,6 +124,8 @@ private extension PointOfSaleBarcodeScannerTestBarcodeView { enum Localization { static let title = "Test your scanner" static let instruction = "Scan the barcode to test your scanner" + static let timeoutTitle = "No scan data found yet" + static let timeoutInstruction = "Scan the barcode to test your scanner. If the issue continues, please check Bluetooth settings and try again." } }