Skip to content

Commit 911f10c

Browse files
authored
Enhance POS ineligible view accessibility and scrolling behavior (#15936)
2 parents 9db935b + e5b0053 commit 911f10c

File tree

1 file changed

+86
-59
lines changed

1 file changed

+86
-59
lines changed

WooCommerce/Classes/POS/TabBar/POSIneligibleView.swift

Lines changed: 86 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,79 +7,106 @@ struct POSIneligibleView: View {
77
let reason: POSIneligibleReason
88
let onRefresh: () async throws -> Void
99
@Environment(\.dismiss) private var dismiss
10+
@Environment(\.sizeCategory) private var sizeCategory
1011
@State private var isLoading: Bool = false
12+
@State private var scrollViewHeight: CGFloat = 0
13+
@State private var contentHeight: CGFloat = 0
1114

12-
var body: some View {
13-
VStack(spacing: POSSpacing.none) {
14-
Spacer()
15+
/// Returns the frame width multiplier for the content view based on accessibility size category.
16+
private var frameWidthMultiplier: Double {
17+
if sizeCategory >= .accessibilityMedium {
18+
return 0.9 // Use more horizontal space for larger accessibility sizes
19+
} else {
20+
return 0.5 // Standard multiplier for regular sizes
21+
}
22+
}
1523

16-
VStack(alignment: .center, spacing: POSSpacing.none) {
17-
POSErrorXMark()
24+
/// Returns true if scrolling should be disabled (content fits within scroll view).
25+
private var shouldDisableScrolling: Bool {
26+
scrollViewHeight > 0 && contentHeight > 0 && contentHeight <= scrollViewHeight
27+
}
1828

29+
var body: some View {
30+
ScrollView {
31+
VStack(spacing: POSSpacing.none) {
1932
Spacer()
20-
.frame(height: POSSpacing.medium)
21-
22-
VStack(spacing: POSSpacing.small) {
23-
Text(Localization.title)
24-
.font(POSFontStyle.posHeadingBold.font())
25-
.multilineTextAlignment(.center)
26-
.foregroundColor(Color.posOnSurface)
27-
28-
Text(suggestionText)
29-
.font(POSFontStyle.posBodyLargeRegular().font())
30-
.multilineTextAlignment(.center)
31-
.foregroundColor(Color.posOnSurface)
32-
}
33-
.containerRelativeFrame(.horizontal) { length, _ in
34-
max(length * 0.5, 300)
35-
}
3633

37-
Spacer()
38-
.frame(height: POSSpacing.large)
39-
40-
VStack(spacing: POSSpacing.medium) {
41-
Button {
42-
Task { @MainActor in
43-
do {
44-
isLoading = true
45-
ServiceLocator.analytics.track(
46-
event: .PointOfSaleIneligibleUI.ineligibleUIRetryTapped(reason: reason)
47-
)
48-
try await onRefresh()
49-
isLoading = false
50-
} catch {
51-
// TODO: WOOMOB-720 - handle error if needed, e.g., show an error message
52-
DDLogError("Error refreshing eligibility: \(error)")
53-
isLoading = false
34+
VStack(alignment: .center, spacing: POSSpacing.none) {
35+
POSErrorXMark()
36+
37+
Spacer()
38+
.frame(height: POSSpacing.medium)
39+
40+
VStack(spacing: POSSpacing.small) {
41+
Text(Localization.title)
42+
.font(POSFontStyle.posHeadingBold.font())
43+
.multilineTextAlignment(.center)
44+
.foregroundColor(Color.posOnSurface)
45+
46+
Text(suggestionText)
47+
.font(POSFontStyle.posBodyLargeRegular().font())
48+
.multilineTextAlignment(.center)
49+
.foregroundColor(Color.posOnSurface)
50+
}
51+
.containerRelativeFrame(.horizontal) { length, _ in
52+
max(length * frameWidthMultiplier, 300)
53+
}
54+
55+
Spacer()
56+
.frame(height: POSSpacing.large)
57+
58+
VStack(spacing: POSSpacing.medium) {
59+
Button {
60+
Task { @MainActor in
61+
do {
62+
isLoading = true
63+
ServiceLocator.analytics.track(
64+
event: .PointOfSaleIneligibleUI.ineligibleUIRetryTapped(reason: reason)
65+
)
66+
try await onRefresh()
67+
isLoading = false
68+
} catch {
69+
DDLogError("Error refreshing eligibility: \(error)")
70+
isLoading = false
71+
}
5472
}
73+
} label: {
74+
Text(reason.refreshEligibilityTitle)
5575
}
56-
} label: {
57-
Text(reason.refreshEligibilityTitle)
58-
}
59-
.buttonStyle(POSFilledButtonStyle(size: .normal, isLoading: isLoading))
60-
.renderedIf(reason.shouldShowRetryButton)
76+
.buttonStyle(POSFilledButtonStyle(size: .normal, isLoading: isLoading))
77+
.renderedIf(reason.shouldShowRetryButton)
6178

62-
Button {
63-
dismiss()
64-
} label: {
65-
Text(Localization.dismiss)
79+
Button {
80+
dismiss()
81+
} label: {
82+
Text(Localization.dismiss)
83+
}
84+
.buttonStyle(POSOutlinedButtonStyle(size: .normal))
85+
}
86+
.containerRelativeFrame(.horizontal) { length, _ in
87+
max(length * frameWidthMultiplier - 132, 300)
6688
}
67-
.buttonStyle(POSOutlinedButtonStyle(size: .normal))
68-
}
69-
.containerRelativeFrame(.horizontal) { length, _ in
70-
max(length * 0.5 - 132, 300)
7189
}
72-
}
7390

74-
Spacer()
75-
}
76-
.padding(POSPadding.large)
77-
.onAppear {
78-
ServiceLocator.analytics.track(event: .PointOfSaleIneligibleUI.ineligibleUIShown(reason: reason))
91+
Spacer()
92+
}
93+
.padding(POSPadding.large)
94+
.frame(maxWidth: .infinity, minHeight: scrollViewHeight > 0 ? scrollViewHeight : nil)
95+
.measureHeight { height in
96+
contentHeight = height
97+
}
98+
.onAppear {
99+
ServiceLocator.analytics.track(event: .PointOfSaleIneligibleUI.ineligibleUIShown(reason: reason))
100+
}
101+
.onChange(of: reason) { newReason in
102+
ServiceLocator.analytics.track(event: .PointOfSaleIneligibleUI.ineligibleUIShown(reason: newReason))
103+
}
79104
}
80-
.onChange(of: reason) { newReason in
81-
ServiceLocator.analytics.track(event: .PointOfSaleIneligibleUI.ineligibleUIShown(reason: newReason))
105+
.scrollDisabled(shouldDisableScrolling)
106+
.measureHeight { height in
107+
scrollViewHeight = height
82108
}
109+
.frame(maxWidth: .infinity, maxHeight: .infinity)
83110
}
84111

85112
private var suggestionText: String {

0 commit comments

Comments
 (0)