Skip to content

Commit e3950f9

Browse files
authored
[Woo POS] Centring of views (#13789)
2 parents 9130091 + 31fb5d5 commit e3950f9

File tree

9 files changed

+144
-63
lines changed

9 files changed

+144
-63
lines changed

WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/PointOfSaleItemListEmptyView.swift

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,27 @@ import SwiftUI
22

33
struct PointOfSaleItemListEmptyView: View {
44
var body: some View {
5-
VStack(alignment: .center, spacing: PointOfSaleItemListErrorLayout.headerSpacing) {
6-
POSHeaderTitleView(foregroundColor: .posSecondaryText)
7-
Spacer()
8-
Image(systemName: Constants.iconSystemName)
9-
.resizable()
10-
.aspectRatio(contentMode: .fit)
11-
.frame(width: Constants.iconSize, height: Constants.iconSize)
12-
.foregroundColor(.posSecondaryText)
13-
.scaleEffect(x: -1, y: 1)
14-
.accessibilityHidden(true)
15-
Text(Localization.emptyProductsTitle)
16-
.foregroundStyle(Color.posSecondaryText)
17-
.font(.posTitleEmphasized)
18-
Text(Localization.emptyProductsSubtitle)
19-
.foregroundStyle(Color.posSecondaryText)
20-
.font(.posBodyRegular)
21-
.padding([.leading, .trailing])
22-
Text(Localization.emptyProductsHint)
23-
.foregroundStyle(Color.posSecondaryText)
24-
.font(.posBodyRegular)
25-
.padding([.leading, .trailing])
26-
Spacer()
5+
PointOfSaleItemListFullscreenView {
6+
VStack(alignment: .center, spacing: PointOfSaleItemListErrorLayout.headerSpacing) {
7+
Spacer()
8+
Image(decorative: PointOfSaleAssets.magnifierNotFound.imageName)
9+
.resizable()
10+
.aspectRatio(contentMode: .fit)
11+
.frame(width: Constants.iconSize, height: Constants.iconSize)
12+
.foregroundColor(.posSecondaryText)
13+
Text(Localization.emptyProductsTitle)
14+
.foregroundStyle(Color.posSecondaryText)
15+
.font(.posTitleEmphasized)
16+
Text(Localization.emptyProductsSubtitle)
17+
.foregroundStyle(Color.posSecondaryText)
18+
.font(.posBodyRegular)
19+
.padding([.leading, .trailing])
20+
Text(Localization.emptyProductsHint)
21+
.foregroundStyle(Color.posSecondaryText)
22+
.font(.posBodyRegular)
23+
.padding([.leading, .trailing])
24+
Spacer()
25+
}
2726
}
2827
}
2928
}

WooCommerce/Classes/POS/Presentation/CardReaderConnection/UI States/PointOfSaleItemListErrorView.swift

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,32 @@ struct PointOfSaleItemListErrorView: View {
1010
}
1111

1212
var body: some View {
13-
VStack(alignment: .center, spacing: PointOfSaleItemListErrorLayout.headerSpacing) {
14-
POSHeaderTitleView(foregroundColor: .posSecondaryText)
15-
Spacer()
16-
VStack(alignment: .center) {
17-
POSErrorExclamationMark()
18-
.padding(.bottom)
19-
Text(error.title)
20-
.foregroundStyle(Color.posPrimaryText)
21-
.font(.posTitleEmphasized)
22-
.padding(.bottom, PointOfSaleItemListErrorLayout.verticalPadding)
23-
Text(error.subtitle)
24-
.foregroundStyle(Color.posPrimaryText)
25-
.font(.posBodyRegular)
26-
.padding([.leading, .trailing])
27-
.padding(.bottom, PointOfSaleItemListErrorLayout.verticalPadding)
28-
Button(action: {
29-
onRetry?()
30-
}, label: {
31-
Text(error.buttonText)
32-
})
33-
.buttonStyle(POSPrimaryButtonStyle())
34-
.frame(width: PointOfSaleItemListErrorLayout.buttonWidth)
13+
PointOfSaleItemListFullscreenView {
14+
VStack {
15+
Spacer()
16+
VStack(alignment: .center) {
17+
POSErrorExclamationMark()
18+
.padding(.bottom)
19+
Text(error.title)
20+
.accessibilityAddTraits(.isHeader)
21+
.foregroundStyle(Color.posPrimaryText)
22+
.font(.posTitleEmphasized)
23+
.padding(.bottom, PointOfSaleItemListErrorLayout.verticalPadding)
24+
Text(error.subtitle)
25+
.foregroundStyle(Color.posPrimaryText)
26+
.font(.posBodyRegular)
27+
.padding([.leading, .trailing])
28+
.padding(.bottom, PointOfSaleItemListErrorLayout.verticalPadding)
29+
Button(action: {
30+
onRetry?()
31+
}, label: {
32+
Text(error.buttonText)
33+
})
34+
.buttonStyle(POSPrimaryButtonStyle())
35+
.frame(width: PointOfSaleItemListErrorLayout.buttonWidth)
36+
}
37+
Spacer()
3538
}
36-
Spacer()
3739
}
3840
}
3941
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import SwiftUI
2+
3+
struct PointOfSaleItemListFullscreenView<Content: View>: View {
4+
let content: () -> Content
5+
6+
var body: some View {
7+
ZStack {
8+
VStack(alignment: .center, spacing: PointOfSaleItemListErrorLayout.headerSpacing) {
9+
POSHeaderTitleView(foregroundColor: .posSecondaryText)
10+
Spacer()
11+
}
12+
13+
content()
14+
.zIndex(1)
15+
}
16+
}
17+
}
18+
19+
#Preview {
20+
PointOfSaleItemListFullscreenView(
21+
content: {
22+
PointOfSaleItemListErrorView(
23+
error: .init(title: "Error", subtitle: "Something went wrong", buttonText: "Fix it"))
24+
})
25+
}

WooCommerce/Classes/POS/Presentation/CartView.swift

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -69,20 +69,7 @@ struct CartView: View {
6969
.padding(.vertical, POSHeaderLayoutConstants.sectionVerticalPadding)
7070
.if(shouldApplyHeaderBottomShadow, transform: { $0.applyBottomShadow() })
7171

72-
if cartViewModel.isCartEmpty {
73-
VStack(spacing: Constants.cartEmptyViewSpacing) {
74-
Spacer()
75-
Image(decorative: PointOfSaleAssets.shoppingBags.imageName)
76-
.resizable()
77-
.frame(width: Constants.shoppingBagImageSize, height: Constants.shoppingBagImageSize)
78-
.aspectRatio(contentMode: .fit)
79-
Text(Localization.addItemsToCartHint)
80-
.font(Constants.secondaryFont)
81-
.foregroundColor(Color.posTertiaryText)
82-
.multilineTextAlignment(.center)
83-
Spacer()
84-
}
85-
} else {
72+
if !cartViewModel.isCartEmpty {
8673
ScrollViewReader { proxy in
8774
ScrollView {
8875
VStack(spacing: 0) {
@@ -133,6 +120,11 @@ struct CartView: View {
133120
}
134121
.animation(Constants.cartAnimation, value: cartViewModel.isCartEmpty)
135122
.frame(maxWidth: .infinity)
123+
.background(content: {
124+
if cartViewModel.isCartEmpty {
125+
cartEmptyView
126+
}
127+
})
136128
.background(backgroundColor.ignoresSafeArea(.all))
137129
.accessibilityElement(children: .contain)
138130
}
@@ -161,6 +153,7 @@ private extension CartView {
161153
enum Constants {
162154
static let primaryFont: POSFontStyle = .posTitleEmphasized
163155
static let secondaryFont: POSFontStyle = .posBodyRegular
156+
static let cartEmptyViewTextLineHeight: CGFloat = 12
164157
static let itemsFont: POSFontStyle = .posDetailRegular
165158
static let clearButtonFont: POSFontStyle = .posDetailEmphasized
166159
static let clearButtonCornerRadius: CGFloat = 4
@@ -169,7 +162,7 @@ private extension CartView {
169162
static let itemHorizontalPadding: CGFloat = 8
170163
static let shoppingBagImageSize: CGFloat = 104
171164
static let scrollViewCoordinateSpaceIdentifier: String = "CartScrollView"
172-
static let cartEmptyViewSpacing: CGFloat = 40
165+
static let emptyViewImageTextSpacing: CGFloat = 30 // This should be 40 by designs, but the overlay technique means we have to tweak it
173166
static let cartHeaderSpacing: CGFloat = 8
174167
static let backButtonSymbol: String = "chevron.backward"
175168
static let cartHeaderElementSpacing: CGFloat = 16
@@ -224,6 +217,30 @@ private extension CartView {
224217
}
225218
}
226219
}
220+
221+
var cartEmptyView: some View {
222+
VStack {
223+
Spacer()
224+
// By designs, the text should be vertically centred with the image 40px above it.
225+
// SwiftUI doesn't allow us to absolutely pin a view to the centre then position other views relative to it
226+
// Instead, we can centre the text, and then put the image in an offset overlay. Offsetting from the top
227+
// avoids issues when the text size is changed through dynamic type.
228+
Text(Localization.addItemsToCartHint)
229+
.font(Constants.secondaryFont)
230+
.lineSpacing(Constants.cartEmptyViewTextLineHeight)
231+
.foregroundColor(Color.posTertiaryText)
232+
.multilineTextAlignment(.center)
233+
.overlay(alignment: .top) {
234+
Image(decorative: PointOfSaleAssets.shoppingBags.imageName)
235+
.resizable()
236+
.frame(width: Constants.shoppingBagImageSize, height: Constants.shoppingBagImageSize, alignment: .bottom)
237+
.offset(y: -(Constants.shoppingBagImageSize + Constants.emptyViewImageTextSpacing))
238+
.aspectRatio(contentMode: .fit)
239+
}
240+
Spacer()
241+
}
242+
.background(backgroundColor.ignoresSafeArea(.all))
243+
}
227244
}
228245

229246
#if DEBUG

WooCommerce/Classes/POS/Presentation/PointOfSaleAssets.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Foundation
22

33
enum PointOfSaleAssets: CaseIterable {
4+
case magnifierNotFound
45
case readyForPayment
56
case readerConnectionScanning
67
case readerConnectionDoYouWantToConnect
@@ -12,6 +13,8 @@ enum PointOfSaleAssets: CaseIterable {
1213

1314
var imageName: String {
1415
switch self {
16+
case .magnifierNotFound:
17+
"pos-magnifier-not-found"
1518
case .readyForPayment:
1619
"pos-ready-for-payment"
1720
case .readerConnectionScanning:

WooCommerce/Classes/POS/Presentation/TotalsView.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,15 +267,31 @@ private extension TotalsView {
267267
topPadding: 40,
268268
bottomPadding: 40
269269
)
270+
271+
static let topAligned = CardReaderViewLayout(
272+
backgroundColor: .clear,
273+
topPadding: 96,
274+
bottomPadding: 96
275+
)
270276
}
271277

272278
private var cardReaderViewLayout: CardReaderViewLayout {
273279
guard viewModel.isShowingCardReaderStatus else {
274280
return .primary
275281
}
276282

277-
if viewModel.paymentState == .validatingOrderError {
283+
switch viewModel.paymentState {
284+
case .validatingOrderError:
278285
return .outlined
286+
case .paymentError:
287+
return .topAligned
288+
case .idle,
289+
.acceptingCard,
290+
.validatingOrder,
291+
.preparingReader,
292+
.processingPayment,
293+
.cardPaymentSuccessful:
294+
break
279295
}
280296

281297
if viewModel.connectionStatus == .disconnected {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "pos-magnifier-not-found.pdf",
5+
"idiom" : "universal"
6+
}
7+
],
8+
"info" : {
9+
"author" : "xcode",
10+
"version" : 1
11+
},
12+
"properties" : {
13+
"preserves-vector-representation" : true
14+
}
15+
}

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,7 @@
741741
174CA86A27D90A6200126524 /* AutomatticAbout in Frameworks */ = {isa = PBXBuildFile; productRef = 174CA86927D90A6200126524 /* AutomatticAbout */; };
742742
174CA86C27D90E8900126524 /* WooAboutScreenConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 174CA86B27D90E8900126524 /* WooAboutScreenConfiguration.swift */; };
743743
174CA86E27DBFD2D00126524 /* ShareAppTextItemActivitySource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 174CA86D27DBFD2D00126524 /* ShareAppTextItemActivitySource.swift */; };
744+
200190002C80AEAC002C1E4B /* PointOfSaleItemListFullscreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20018FFF2C80AEAC002C1E4B /* PointOfSaleItemListFullscreenView.swift */; };
744745
2004E2C22C076CED00D62521 /* CardPresentPaymentFacade.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2004E2C12C076CED00D62521 /* CardPresentPaymentFacade.swift */; };
745746
2004E2C42C076D3800D62521 /* CardPresentPaymentEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2004E2C32C076D3800D62521 /* CardPresentPaymentEvent.swift */; };
746747
2004E2C62C076D4500D62521 /* CardPresentPaymentResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2004E2C52C076D4500D62521 /* CardPresentPaymentResult.swift */; };
@@ -843,8 +844,8 @@
843844
20CC1EDD2AFA99DF006BD429 /* InPersonPaymentsMenuViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20CC1EDC2AFA99DF006BD429 /* InPersonPaymentsMenuViewModel.swift */; };
844845
20CCBF212B0E15C0003102E6 /* WooPaymentsDepositsCurrencyOverviewViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20CCBF202B0E15C0003102E6 /* WooPaymentsDepositsCurrencyOverviewViewModelTests.swift */; };
845846
20D210BE2B14C9B90099E517 /* WooPaymentsDepositStatusDisplayDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D210BD2B14C9B90099E517 /* WooPaymentsDepositStatusDisplayDetails.swift */; };
846-
20D2CCA52C7E328300051705 /* POSModalCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D2CCA42C7E328300051705 /* POSModalCloseButton.swift */; };
847847
20D2CCA32C7E175700051705 /* WavesProgressViewStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D2CCA22C7E175700051705 /* WavesProgressViewStyle.swift */; };
848+
20D2CCA52C7E328300051705 /* POSModalCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D2CCA42C7E328300051705 /* POSModalCloseButton.swift */; };
848849
20D3D42B2C64D7CC004CE6E3 /* SimpleProductsOnlyInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D3D42A2C64D7CC004CE6E3 /* SimpleProductsOnlyInformation.swift */; };
849850
20D3D42F2C64F175004CE6E3 /* POSSecondaryButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D3D42E2C64F175004CE6E3 /* POSSecondaryButtonStyle.swift */; };
850851
20D3D4312C64F202004CE6E3 /* POSButtonStyleConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 20D3D4302C64F202004CE6E3 /* POSButtonStyleConstants.swift */; };
@@ -3784,6 +3785,7 @@
37843785
09F5DE5C27CF948000E5A4D2 /* BulkUpdateOptionsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BulkUpdateOptionsModel.swift; sourceTree = "<group>"; };
37853786
174CA86B27D90E8900126524 /* WooAboutScreenConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooAboutScreenConfiguration.swift; sourceTree = "<group>"; };
37863787
174CA86D27DBFD2D00126524 /* ShareAppTextItemActivitySource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAppTextItemActivitySource.swift; sourceTree = "<group>"; };
3788+
20018FFF2C80AEAC002C1E4B /* PointOfSaleItemListFullscreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PointOfSaleItemListFullscreenView.swift; sourceTree = "<group>"; };
37873789
2004E2C12C076CED00D62521 /* CardPresentPaymentFacade.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentPaymentFacade.swift; sourceTree = "<group>"; };
37883790
2004E2C32C076D3800D62521 /* CardPresentPaymentEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentPaymentEvent.swift; sourceTree = "<group>"; };
37893791
2004E2C52C076D4500D62521 /* CardPresentPaymentResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentPaymentResult.swift; sourceTree = "<group>"; };
@@ -3887,8 +3889,8 @@
38873889
20CC1EDC2AFA99DF006BD429 /* InPersonPaymentsMenuViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InPersonPaymentsMenuViewModel.swift; sourceTree = "<group>"; };
38883890
20CCBF202B0E15C0003102E6 /* WooPaymentsDepositsCurrencyOverviewViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooPaymentsDepositsCurrencyOverviewViewModelTests.swift; sourceTree = "<group>"; };
38893891
20D210BD2B14C9B90099E517 /* WooPaymentsDepositStatusDisplayDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WooPaymentsDepositStatusDisplayDetails.swift; sourceTree = "<group>"; };
3890-
20D2CCA42C7E328300051705 /* POSModalCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSModalCloseButton.swift; sourceTree = "<group>"; };
38913892
20D2CCA22C7E175700051705 /* WavesProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WavesProgressViewStyle.swift; sourceTree = "<group>"; };
3893+
20D2CCA42C7E328300051705 /* POSModalCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSModalCloseButton.swift; sourceTree = "<group>"; };
38923894
20D3D42A2C64D7CC004CE6E3 /* SimpleProductsOnlyInformation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleProductsOnlyInformation.swift; sourceTree = "<group>"; };
38933895
20D3D42E2C64F175004CE6E3 /* POSSecondaryButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSSecondaryButtonStyle.swift; sourceTree = "<group>"; };
38943896
20D3D4302C64F202004CE6E3 /* POSButtonStyleConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = POSButtonStyleConstants.swift; sourceTree = "<group>"; };
@@ -6757,6 +6759,7 @@
67576759
2004E2E82C0DFE2B00D62521 /* PointOfSaleCardPresentPaymentAlert.swift */,
67586760
2023E2AD2C21D8EA00FC365A /* PointOfSaleCardPresentPaymentInLineMessage.swift */,
67596761
68600A8E2C65BC5500252EDD /* PointOfSaleItemListErrorView.swift */,
6762+
20018FFF2C80AEAC002C1E4B /* PointOfSaleItemListFullscreenView.swift */,
67606763
68600A902C65BC9C00252EDD /* PointOfSaleItemListEmptyView.swift */,
67616764
68C7E5C32C69B3CD00856513 /* PointOfSaleItemListErrorLayout.swift */,
67626765
205E79492C204B2D001BA266 /* Reader Messages */,
@@ -15550,6 +15553,7 @@
1555015553
2631D4F829ED0B5C00F13F20 /* WPComPlanNameSanitizer.swift in Sources */,
1555115554
CE4296B920A5E9E400B2AFBD /* CNContact+Helpers.swift in Sources */,
1555215555
02A723262AB2E1A6003AEC7E /* GiftCardInputView.swift in Sources */,
15556+
200190002C80AEAC002C1E4B /* PointOfSaleItemListFullscreenView.swift in Sources */,
1555315557
DE7E5E812B4BCC06002E28D2 /* BlazeTargetLanguagePickerViewModel.swift in Sources */,
1555415558
0230B4D22C333E0800F2F660 /* PointOfSaleCardPresentPaymentCaptureErrorMessageViewModel.swift in Sources */,
1555515559
0211252825773F220075AD2A /* Models+Copiable.generated.swift in Sources */,

0 commit comments

Comments
 (0)