diff --git a/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModel.swift b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModel.swift index 93591409064..ede4b56fa5c 100644 --- a/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModel.swift +++ b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModel.swift @@ -3,8 +3,7 @@ import SwiftUI struct PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModel: Identifiable { let title: String = Localization.title - private let progress: Float - let image: Image + let progress: Float let progressTitle: String let progressSubtitle: String = Localization.messageOptional let cancelButtonTitle: String @@ -13,8 +12,11 @@ struct PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModel // This relies on the closures being immutable let id = UUID() + var isComplete: Bool { + progress >= 1.0 + } + init(progress: Float, cancel: (() -> Void)?) { - self.image = Image(uiImage: .posSoftwareUpdateProgress(progress: CGFloat(progress))) self.progress = progress self.progressTitle = String(format: Localization.percentCompleteFormat, 100 * progress) diff --git a/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel.swift b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel.swift index e2f08db2911..43d749dced0 100644 --- a/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel.swift +++ b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel.swift @@ -3,7 +3,6 @@ import SwiftUI struct PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel { let title: String = Localization.title - let image: Image = .init(uiImage: .posSoftwareUpdateProgress(progress: CGFloat(1.0))) let progressTitle: String = .init(format: Localization.percentCompleteFormat, 100.0) } diff --git a/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift new file mode 100644 index 00000000000..159392cf533 --- /dev/null +++ b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift @@ -0,0 +1,44 @@ +import SwiftUI + +struct PointOfSaleCardPresentPaymentReaderUpdateProgressView: View { + let progress: CGFloat + let isComplete: Bool + + var body: some View { + ZStack { + Circle() + .fill(Color(.posSecondary)) + .frame(width: Constants.size, height: Constants.size) + + Circle() + .fill(Color(.posPrimary)) + .frame(width: Constants.size - Constants.borderInset, height: Constants.size - Constants.borderInset) + .clipShape( + Rectangle() + .offset(y: (1 - progress) * Constants.size) + ) + .animation(.easeOut(duration: 0.2), value: progress) + + Image(uiImage: isComplete ? .cardReaderUpdateProgressCheckmark : .cardReaderUpdateProgressArrow) + .renderingMode(.template) + .foregroundColor(Color(.posOnPrimary)) + } + .frame(width: Constants.size, height: Constants.size) + } +} + +private enum Constants { + static let size: CGFloat = 100 + static let borderInset: CGFloat = POSSpacing.xSmall +} + +@available(iOS 17.0, *) +#Preview { + @Previewable @State var progress: CGFloat = 0.5 + + VStack(spacing: 20) { + PointOfSaleCardPresentPaymentReaderUpdateProgressView(progress: progress, isComplete: progress >= 1.0) + Slider(value: $progress, in: 0...1) + } + .padding() +} diff --git a/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModel.swift b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModel.swift index 7a033cc6fe4..9e0c3856904 100644 --- a/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModel.swift +++ b/WooCommerce/Classes/POS/Presentation/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModel.swift @@ -3,8 +3,7 @@ import SwiftUI struct PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModel: Identifiable { let title: String = Localization.title - private let progress: Float - let image: Image + let progress: Float let progressTitle: String let progressSubtitle: String = Localization.messageRequired let cancelButtonTitle: String @@ -13,8 +12,11 @@ struct PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModel // This relies on the closures being immutable let id = UUID() + var isComplete: Bool { + progress >= 1.0 + } + init(progress: Float, cancel: (() -> Void)?) { - self.image = Image(uiImage: .posSoftwareUpdateProgress(progress: CGFloat(progress))) self.progress = progress self.progressTitle = String(format: Localization.percentCompleteFormat, 100 * progress) diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressView.swift index 68280570542..1a44c965f39 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressView.swift @@ -14,9 +14,12 @@ struct PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressView: View { VStack(spacing: PointOfSaleReaderConnectionModalLayout.contentButtonSpacing) { Spacer() VStack(spacing: PointOfSaleReaderConnectionModalLayout.imageTextSpacing) { - viewModel.image - .accessibilityHidden(true) - .matchedGeometryEffect(id: animation.iconTransitionId, in: animation.namespace, properties: .position) + PointOfSaleCardPresentPaymentReaderUpdateProgressView( + progress: CGFloat(viewModel.progress), + isComplete: viewModel.isComplete + ) + .accessibilityHidden(true) + .matchedGeometryEffect(id: animation.iconTransitionId, in: animation.namespace, properties: .position) VStack(spacing: PointOfSaleReaderConnectionModalLayout.textSpacing) { Text(viewModel.title) @@ -29,6 +32,7 @@ struct PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressView: View { Text(viewModel.progressTitle) .font(POSFontStyle.posBodyLargeRegular()) .fixedSize(horizontal: false, vertical: true) + .animation(nil, value: viewModel.progressTitle) Text(viewModel.progressSubtitle) .font(POSFontStyle.posBodyLargeRegular()) .fixedSize(horizontal: false, vertical: true) diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionView.swift index 3d4f19f2770..08ff986880d 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionView.swift @@ -12,9 +12,12 @@ struct PointOfSaleCardPresentPaymentReaderUpdateCompletionView: View { var body: some View { VStack(spacing: PointOfSaleReaderConnectionModalLayout.imageTextSpacing) { - viewModel.image - .accessibilityHidden(true) - .matchedGeometryEffect(id: animation.iconTransitionId, in: animation.namespace, properties: .position) + PointOfSaleCardPresentPaymentReaderUpdateProgressView( + progress: 1, + isComplete: true + ) + .accessibilityHidden(true) + .matchedGeometryEffect(id: animation.iconTransitionId, in: animation.namespace, properties: .position) VStack(spacing: PointOfSaleReaderConnectionModalLayout.textSpacing) { Text(viewModel.title) diff --git a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressView.swift b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressView.swift index 893e0abd880..135bc25adcd 100644 --- a/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressView.swift +++ b/WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressView.swift @@ -14,9 +14,12 @@ struct PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressView: View { VStack(spacing: PointOfSaleReaderConnectionModalLayout.contentButtonSpacing) { Spacer() VStack(spacing: PointOfSaleReaderConnectionModalLayout.imageTextSpacing) { - viewModel.image - .accessibilityHidden(true) - .matchedGeometryEffect(id: animation.iconTransitionId, in: animation.namespace, properties: .position) + PointOfSaleCardPresentPaymentReaderUpdateProgressView( + progress: CGFloat(viewModel.progress), + isComplete: viewModel.isComplete + ) + .accessibilityHidden(true) + .matchedGeometryEffect(id: animation.iconTransitionId, in: animation.namespace, properties: .position) VStack(spacing: PointOfSaleReaderConnectionModalLayout.textSpacing) { Text(viewModel.title) diff --git a/WooCommerce/Classes/ViewRelated/ReusableViews/UpdateProgressImage.swift b/WooCommerce/Classes/ViewRelated/ReusableViews/UpdateProgressImage.swift index 5e6f02530de..021a94a07a8 100644 --- a/WooCommerce/Classes/ViewRelated/ReusableViews/UpdateProgressImage.swift +++ b/WooCommerce/Classes/ViewRelated/ReusableViews/UpdateProgressImage.swift @@ -8,7 +8,7 @@ extension UIImage { } let size = firstImage.size let rect = CGRect(origin: .zero, size: size) - UIGraphicsBeginImageContext(size) + UIGraphicsBeginImageContextWithOptions(size, false, 0.0) for image in images { image.draw(in: rect) @@ -28,7 +28,7 @@ extension UIImage { let rect = CGRect(x: 0, y: 0, width: Constants.size, height: Constants.size) let clippingRect = CGRect(x: 0, y: (1 - progress) * Constants.size, width: Constants.size, height: Constants.size) - UIGraphicsBeginImageContext(rect.size) + UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) defer { UIGraphicsEndImageContext() } guard let context = UIGraphicsGetCurrentContext() else { @@ -43,26 +43,16 @@ extension UIImage { } static func softwareUpdateProgress(progress: CGFloat) -> UIImage { - let symbol: UIImage = progress == 1 ? .cardReaderUpdateProgressCheckmark : .cardReaderUpdateProgressArrow - - return .composite(images: [ - .cardReaderUpdateProgressBackground, - .softwareUpdateProgressFill(progress: progress), - symbol - ].compactMap { $0 }) ?? .init() - } - - static func posSoftwareUpdateProgress(progress: CGFloat) -> UIImage { let symbol: UIImage = progress == 1 ? .cardReaderUpdateProgressCheckmark : .cardReaderUpdateProgressArrow let backgroundImage = UIImage.cardReaderUpdateProgressBackground .withRenderingMode(.alwaysTemplate) - .withTintColor(UIColor(.posSecondary)) + .withTintColor(.accent.withAlphaComponent(0.5)) return .composite( images: [ backgroundImage, - .softwareUpdateProgressFill(progress: progress, fillColor: UIColor(.posPrimary)), - symbol.withTintColor(UIColor(.posOnPrimary)), + .softwareUpdateProgressFill(progress: progress, fillColor: .accent), + symbol ].compactMap { $0 }) ?? .init() } } @@ -85,12 +75,6 @@ struct UpdateProgressImage_Previews: PreviewProvider { Image(uiImage: UIImage.softwareUpdateProgress(progress: complete)) } - VStack { - Text("POS Style") - .font(.headline) - Image(uiImage: UIImage.posSoftwareUpdateProgress(progress: complete)) - } - Slider(value: $complete, in: 0...1) } .padding() diff --git a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj index 87330e18c54..6b41cb7e1a6 100644 --- a/WooCommerce/WooCommerce.xcodeproj/project.pbxproj +++ b/WooCommerce/WooCommerce.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ 013D2FB62CFF54BB00845D75 /* TapToPayEducationStepsFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 013D2FB52CFF54B600845D75 /* TapToPayEducationStepsFactory.swift */; }; 01435CF82DFC2CE800C0279B /* PointOfSaleInformationModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 01435CF72DFC2CE800C0279B /* PointOfSaleInformationModal.swift */; }; 014371272DFC8E2800C0279B /* PointOfSaleBarcodeScannerInformationModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014371262DFC8E2100C0279B /* PointOfSaleBarcodeScannerInformationModal.swift */; }; + 014997222E1432AB002C50E1 /* PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014997212E1432AB002C50E1 /* PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift */; }; 014BD4B82C64E2BA0011A66E /* PointOfSaleOrderSyncErrorMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 014BD4B72C64E2BA0011A66E /* PointOfSaleOrderSyncErrorMessageView.swift */; }; 015456CE2DB0341D0071C3C4 /* POSPageHeaderActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 015456CD2DB033FF0071C3C4 /* POSPageHeaderActionButton.swift */; }; 0157A9962C4FEA7200866FFD /* PointOfSaleLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0157A9952C4FEA7200866FFD /* PointOfSaleLoadingView.swift */; }; @@ -3184,6 +3185,7 @@ 013D2FB52CFF54B600845D75 /* TapToPayEducationStepsFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TapToPayEducationStepsFactory.swift; sourceTree = ""; }; 01435CF72DFC2CE800C0279B /* PointOfSaleInformationModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleInformationModal.swift; sourceTree = ""; }; 014371262DFC8E2100C0279B /* PointOfSaleBarcodeScannerInformationModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleBarcodeScannerInformationModal.swift; sourceTree = ""; }; + 014997212E1432AB002C50E1 /* PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift; sourceTree = ""; }; 014BD4B72C64E2BA0011A66E /* PointOfSaleOrderSyncErrorMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleOrderSyncErrorMessageView.swift; sourceTree = ""; }; 015456CD2DB033FF0071C3C4 /* POSPageHeaderActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSPageHeaderActionButton.swift; sourceTree = ""; }; 0157A9952C4FEA7200866FFD /* PointOfSaleLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleLoadingView.swift; sourceTree = ""; }; @@ -8126,6 +8128,7 @@ 205B7EB52C19F89B00D14A36 /* Connection Alerts */ = { isa = PBXGroup; children = ( + 014997212E1432AB002C50E1 /* PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift */, 203163BC2C1C9602001C96DA /* PointOfSaleCardPresentPaymentAlertType.swift */, 205B7EB82C19FAF700D14A36 /* PointOfSaleCardPresentPaymentScanningForReadersAlertViewModel.swift */, 205B7EBA2C19FB1200D14A36 /* PointOfSaleCardPresentPaymentScanningFailedAlertViewModel.swift */, @@ -15756,6 +15759,7 @@ B99B30CD2A85200D0066743D /* AddressFormViewModel.swift in Sources */, 205E79462C204387001BA266 /* PointOfSaleCardPresentPaymentCancelledOnReaderMessageViewModel.swift in Sources */, 029D025C2C231A1F00CB1E75 /* PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel.swift in Sources */, + 014997222E1432AB002C50E1 /* PointOfSaleCardPresentPaymentReaderUpdateProgressView.swift in Sources */, 01620C4E2C5394B200D3EA2F /* POSProgressViewStyle.swift in Sources */, 0196FF942DA8067A0063CEF1 /* CouponCardView.swift in Sources */, 021125A52578E5730075AD2A /* BoldableTextView.swift in Sources */, diff --git a/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModelTests.swift b/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModelTests.swift index e14c155a132..294d9db641e 100644 --- a/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertViewModelTests.swift @@ -9,7 +9,7 @@ final class PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertView cancel: {}) XCTAssertPropertyCount(sut, - expectedCount: 8, + expectedCount: 7, messageHint: "Please check that the manual equatable conformance includes new properties.") } @@ -19,7 +19,7 @@ final class PointOfSaleCardPresentPaymentOptionalReaderUpdateInProgressAlertView cancel: {}) XCTAssertPropertyCount(sut, - expectedCount: 8, + expectedCount: 7, messageHint: "Please check that the manual hashable conformance includes new properties.") } diff --git a/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModelTests.swift b/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModelTests.swift index 21d794febb8..b77f1566683 100644 --- a/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModelTests.swift @@ -7,7 +7,7 @@ final class PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModelTes let sut = PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel() XCTAssertPropertyCount(sut, - expectedCount: 3, + expectedCount: 2, messageHint: "Please check that the manual hashable conformance includes new properties.") } @@ -15,7 +15,7 @@ final class PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModelTes let sut = PointOfSaleCardPresentPaymentReaderUpdateCompletionAlertViewModel() XCTAssertPropertyCount(sut, - expectedCount: 3, + expectedCount: 2, messageHint: "Please check that the manual equatable conformance includes new properties.") } diff --git a/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModelTests.swift b/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModelTests.swift index c806dcd6d10..2d5ad782db4 100644 --- a/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModelTests.swift +++ b/WooCommerce/WooCommerceTests/POS/Card Present Payments/Connection Alerts/PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertViewModelTests.swift @@ -9,7 +9,7 @@ final class PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertView cancel: {}) XCTAssertPropertyCount(sut, - expectedCount: 8, + expectedCount: 7, messageHint: "Please check that the manual equatable conformance includes new properties.") } @@ -19,7 +19,7 @@ final class PointOfSaleCardPresentPaymentRequiredReaderUpdateInProgressAlertView cancel: {}) XCTAssertPropertyCount(sut, - expectedCount: 8, + expectedCount: 7, messageHint: "Please check that the manual hashable conformance includes new properties.") }