diff --git a/WooCommerce/Classes/POS/Presentation/Item Selector/GhostItemCardView.swift b/WooCommerce/Classes/POS/Presentation/Item Selector/GhostItemCardView.swift index 38605d8c0ff..35f70ad90f1 100644 --- a/WooCommerce/Classes/POS/Presentation/Item Selector/GhostItemCardView.swift +++ b/WooCommerce/Classes/POS/Presentation/Item Selector/GhostItemCardView.swift @@ -2,23 +2,31 @@ import SwiftUI struct GhostItemCardView: View { @ScaledMetric private var scale: CGFloat = 1.0 + @State private var viewWidth: CGFloat = 0.0 private var dimension: CGFloat { min(Constants.productCardSize * scale, Constants.maximumProductCardSize) } var body: some View { - HStack(spacing: Constants.cardSpacing) { - Spacer() - .frame(width: dimension, height: dimension) + HStack(alignment: .center, spacing: Constants.cardSpacing) { Rectangle() - .foregroundColor(.posOnSurfaceVariantLowest) - .frame(height: Layout.placeholderHeight * scale) - .cornerRadius(Layout.cornerRadius) - .padding(.horizontal, Constants.horizontalTextPadding) - Spacer() .frame(width: dimension, height: dimension) + VStack(alignment: .leading) { + Rectangle() + .frame(width: viewWidth * 0.5, height: Layout.placeholderHeight * scale) + .cornerRadius(Layout.cornerRadius) + Rectangle() + .frame(width: viewWidth * 0.1, height: Layout.placeholderHeight * scale) + .cornerRadius(Layout.cornerRadius) + } + .padding(.horizontal, Constants.horizontalTextPadding) + Spacer() + } + .measureWidth { width in + viewWidth = width } + .foregroundColor(.posOnSurfaceVariantLowest) .shimmering() .frame(maxWidth: .infinity, idealHeight: dimension) .background(Color.posSurfaceBright) @@ -30,7 +38,7 @@ private extension GhostItemCardView { typealias Constants = PointOfSaleItemListCardConstants enum Layout { - static let placeholderHeight: CGFloat = 36 + static let placeholderHeight: CGFloat = 32 static let cornerRadius: CGFloat = POSCornerRadiusStyle.medium.value } } diff --git a/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift b/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift index 939018a3a00..3753e88e8c8 100644 --- a/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift +++ b/WooCommerce/Classes/POS/Presentation/PointOfSaleCollectCashView.swift @@ -5,6 +5,7 @@ import WooFoundation @available(iOS 17.0, *) struct PointOfSaleCollectCashView: View { @Environment(\.dynamicTypeSize) var dynamicTypeSize + @Environment(\.floatingControlAreaSize) private var floatingControlAreaSize: CGSize @Environment(PointOfSaleAggregateModel.self) private var posModel @FocusState private var isTextFieldFocused: Bool @@ -31,80 +32,85 @@ struct PointOfSaleCollectCashView: View { allowNegativeNumber: false) var body: some View { - ScrollView { - VStack(alignment: .center, spacing: conditionalPadding(POSSpacing.medium)) { - POSPageHeaderView(title: Localization.backNavigationTitle, - subtitle: formattedOrderTotal, - backButtonConfiguration: .init(state: isLoading ? .disabled: .enabled, - action: { - Task { @MainActor in - await posModel.cancelCashPayment() - isTextFieldFocused = false - } - })) - + GeometryReader { geometry in + ScrollView { VStack(alignment: .center, spacing: conditionalPadding(POSSpacing.medium)) { - Spacer() - - VStack(alignment: .center, spacing: conditionalPadding(POSSpacing.xSmall)) { - FormattableAmountTextField(viewModel: textFieldViewModel, style: .pos) - .focused($isTextFieldFocused) - .dynamicTypeSize(...DynamicTypeSize.accessibility1) - .onSubmit { - Task { @MainActor in - await submitCashAmount() + POSPageHeaderView(title: Localization.backNavigationTitle, + subtitle: formattedOrderTotal, + backButtonConfiguration: .init(state: isLoading ? .disabled: .enabled, + action: { + Task { @MainActor in + await posModel.cancelCashPayment() + isTextFieldFocused = false + } + })) + + VStack(alignment: .center, spacing: conditionalPadding(POSSpacing.medium)) { + Spacer() + + VStack(alignment: .center, spacing: conditionalPadding(POSSpacing.xSmall)) { + FormattableAmountTextField(viewModel: textFieldViewModel, style: .pos) + .focused($isTextFieldFocused) + .dynamicTypeSize(...DynamicTypeSize.accessibility1) + .onSubmit { + Task { @MainActor in + await submitCashAmount() + } + } + .onChange(of: textFieldViewModel.amount) { newValue in + textFieldAmountInput = newValue + updateChangeDueMessage() } - } - .onChange(of: textFieldViewModel.amount) { newValue in - textFieldAmountInput = newValue - updateChangeDueMessage() - } - if let changeDue = changeDueMessage { - Text(changeDue) - .font(.posBodySmallRegular()) - .foregroundColor(.posOnSurfaceVariantLowest) - } + if let changeDue = changeDueMessage { + Text(changeDue) + .font(.posBodySmallRegular()) + .foregroundColor(.posOnSurfaceVariantLowest) + } - if let errorMessage = errorMessage { - Text(errorMessage) - .font(.posBodySmallRegular()) - .foregroundColor(.posError) + if let errorMessage = errorMessage { + Text(errorMessage) + .font(.posBodySmallRegular()) + .foregroundColor(.posError) + } } - } - Spacer() + Spacer() - Button(action: { - Task { @MainActor in - await submitCashAmount() + Button(action: { + Task { @MainActor in + await submitCashAmount() + } + }, label: { + Text(Localization.markPaymentCompletedButtonTitle) + }) + .measureFrame { + buttonFrame = $0 } - }, label: { - Text(Localization.markPaymentCompletedButtonTitle) - }) - .measureFrame { - buttonFrame = $0 + .buttonStyle(POSFilledButtonStyle(size: .normal, isLoading: isLoading)) + .frame(maxWidth: .infinity) + .dynamicTypeSize(...DynamicTypeSize.accessibility1) + .disabled(isLoading) } - .buttonStyle(POSFilledButtonStyle(size: .normal, isLoading: isLoading)) - .frame(maxWidth: .infinity) - .dynamicTypeSize(...DynamicTypeSize.accessibility1) - .disabled(isLoading) + .padding([.horizontal]) + .padding(.bottom, max(keyboardFrame.height - geometry.safeAreaInsets.bottom, + floatingControlAreaSize.height) + Constants.bottomPadding + ) } - .padding([.horizontal]) - .padding(.bottom, keyboardFrame.height) - } - .background(backgroundColor) - .animation(.easeInOut, value: errorMessage) - .animation(.easeInOut, value: changeDueMessage) - .onChange(of: textFieldAmountInput) { _ in - errorMessage = nil - } - .onReceive(Publishers.keyboardFrame) { - keyboardFrame = $0 - shouldMinimizePadding = $0.intersects(buttonFrame) + .frame(minHeight: geometry.size.height) + .animation(.easeInOut, value: errorMessage) + .animation(.easeInOut, value: changeDueMessage) + .onChange(of: textFieldAmountInput) { _ in + errorMessage = nil + } + .onReceive(Publishers.keyboardFrame) { + keyboardFrame = $0 + shouldMinimizePadding = $0.intersects(buttonFrame) + } + .animation(.default, value: shouldMinimizePadding) } - .animation(.default, value: shouldMinimizePadding) } + .frame(maxWidth: .infinity, maxHeight: .infinity) } private func markComplete() async throws { @@ -148,6 +154,7 @@ private extension PointOfSaleCollectCashView { private extension PointOfSaleCollectCashView { enum Constants { static let minimumPadding: CGFloat = POSSpacing.xSmall + static let bottomPadding: CGFloat = POSPadding.medium } private func conditionalPadding(_ padding: CGFloat) -> CGFloat { @@ -159,7 +166,7 @@ private extension PointOfSaleCollectCashView { } private var backgroundColor: Color { - .posSurface + .posSurfaceBright } enum Localization { diff --git a/WooCommerce/Classes/POS/Presentation/TotalsView.swift b/WooCommerce/Classes/POS/Presentation/TotalsView.swift index 3047f557dc1..a1041c1af2f 100644 --- a/WooCommerce/Classes/POS/Presentation/TotalsView.swift +++ b/WooCommerce/Classes/POS/Presentation/TotalsView.swift @@ -37,7 +37,7 @@ struct TotalsView: View { } .transition(.opacity) .accessibilityShowsLargeContentViewer() - .background(backgroundColor) + .background(backgroundColor.ignoresSafeArea(.all)) .dynamicTypeSize(...DynamicTypeSize.accessibility2) .minimumScaleFactor(isShowingTotalsFields ? 0.5 : 1) .geometryGroup() @@ -95,7 +95,7 @@ struct TotalsView: View { case .card(.processingPayment): .posPrimary case .cash(.collectingCash): - .posSurface + .posSurfaceBright default: .clear } diff --git a/WooCommerce/Classes/POS/ViewHelpers/TotalsViewHelper.swift b/WooCommerce/Classes/POS/ViewHelpers/TotalsViewHelper.swift index 9458a1e3825..3cdaa79a7b7 100644 --- a/WooCommerce/Classes/POS/ViewHelpers/TotalsViewHelper.swift +++ b/WooCommerce/Classes/POS/ViewHelpers/TotalsViewHelper.swift @@ -67,7 +67,7 @@ final class TotalsViewHelper { func shouldApplyPadding(paymentState: PointOfSalePaymentState) -> Bool { switch paymentState { - case .card(.cardPaymentSuccessful), .cash(.paymentSuccess): + case .card(.cardPaymentSuccessful), .cash(.paymentSuccess), .cash(.collectingCash): return false default: return true