-
Notifications
You must be signed in to change notification settings - Fork 335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Paywalls V2] Added overflow
property to stack
#4767
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,17 +34,20 @@ struct StackComponentView: View { | |
private var screenCondition | ||
|
||
private let viewModel: StackComponentViewModel | ||
private let isScrollableByDefault: Bool | ||
private let onDismiss: () -> Void | ||
/// Used when this stack needs more padding than defined in the component, e.g. to avoid being drawn in the safe | ||
/// area when displayed as a sticky footer. | ||
private let additionalPadding: EdgeInsets | ||
|
||
init( | ||
viewModel: StackComponentViewModel, | ||
isScrollableByDefault: Bool = false, | ||
onDismiss: @escaping () -> Void, | ||
additionalPadding: EdgeInsets? = nil | ||
) { | ||
self.viewModel = viewModel | ||
self.isScrollableByDefault = isScrollableByDefault | ||
self.onDismiss = onDismiss | ||
self.additionalPadding = additionalPadding ?? EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) | ||
} | ||
|
@@ -114,13 +117,52 @@ struct StackComponentView: View { | |
uiConfigProvider: self.viewModel.uiConfigProvider) | ||
.apply(badge: style.badge, border: style.border, shadow: style.shadow, shape: style.shape) | ||
.padding(style.margin) | ||
.scrollableIfEnabled( | ||
style.dimension, | ||
enabled: style.scrollable ?? self.isScrollableByDefault | ||
) | ||
} | ||
|
||
} | ||
|
||
private extension Axis { | ||
|
||
var scrollViewAxis: Axis.Set { | ||
switch self { | ||
case .horizontal: return .horizontal | ||
case .vertical: return .vertical | ||
} | ||
} | ||
|
||
} | ||
|
||
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) | ||
fileprivate extension View { | ||
|
||
@ViewBuilder | ||
// @PublicForExternalTesting | ||
func scrollableIfEnabled( | ||
_ dimension: PaywallComponent.Dimension, | ||
enabled: Bool = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps this default value is not needed if we're always passing the parameter |
||
) -> some View { | ||
if enabled { | ||
switch dimension { | ||
case .horizontal: | ||
ScrollView(.horizontal) { | ||
self | ||
} | ||
case .vertical: | ||
ScrollView(.vertical) { | ||
self | ||
} | ||
case .zlayer: | ||
self | ||
} | ||
} else { | ||
self | ||
} | ||
} | ||
|
||
// Helper to compute the order or application of border, shadow and badge. | ||
@ViewBuilder | ||
func apply(badge: BadgeModifier.BadgeInfo?, | ||
|
@@ -401,6 +443,58 @@ struct StackComponentView_Previews: PreviewProvider { | |
.previewLayout(.sizeThatFits) | ||
.previewDisplayName("Default - Fill Fit Fixed Fill") | ||
|
||
// Scrollable - HStack | ||
HStack(spacing: 0) { | ||
StackComponentView( | ||
// swiftlint:disable:next force_try | ||
viewModel: try! .init( | ||
component: .init( | ||
components: [ | ||
.stack(.init( | ||
components: [], | ||
size: .init(width: .fixed(300), height: .fixed(50)), | ||
backgroundColor: .init(light: .hex("#ff0000")) | ||
)), | ||
.stack(.init( | ||
components: [], | ||
size: .init(width: .fixed(300), height: .fixed(50)), | ||
backgroundColor: .init(light: .hex("#00ff00")) | ||
)), | ||
.stack(.init( | ||
components: [], | ||
size: .init(width: .fixed(300), height: .fixed(50)), | ||
backgroundColor: .init(light: .hex("#0000ff")) | ||
)), | ||
.stack(.init( | ||
components: [], | ||
size: .init(width: .fixed(300), height: .fixed(50)), | ||
backgroundColor: .init(light: .hex("#000000")) | ||
)) | ||
], | ||
dimension: .horizontal(.center, .start), | ||
size: .init( | ||
width: .fixed(400), | ||
height: .fit | ||
), | ||
spacing: 10, | ||
backgroundColor: .init(light: .hex("#ffcc00")), | ||
padding: .init(top: 80, bottom: 80, leading: 20, trailing: 20), | ||
overflow: .scroll | ||
), | ||
localizationProvider: .init( | ||
locale: Locale.current, | ||
localizedStrings: [ | ||
"text_1": .string("Hey") | ||
] | ||
) | ||
), | ||
onDismiss: {} | ||
) | ||
} | ||
.previewRequiredEnvironmentProperties() | ||
.previewLayout(.sizeThatFits) | ||
.previewDisplayName("Scrollable - HStack") | ||
|
||
// Fits don't expand | ||
StackComponentView( | ||
// swiftlint:disable:next force_try | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,7 +73,8 @@ class StackComponentViewModel { | |
shape: partial?.shape ?? self.component.shape, | ||
border: partial?.border ?? self.component.border, | ||
shadow: partial?.shadow ?? self.component.shadow, | ||
badge: partial?.badge ?? self.component.badge | ||
badge: partial?.badge ?? self.component.badge, | ||
overflow: partial?.overflow ?? self.component.overflow | ||
) | ||
|
||
apply(style) | ||
|
@@ -135,6 +136,7 @@ struct StackComponentStyle { | |
let border: ShapeModifier.BorderInfo? | ||
let shadow: ShadowModifier.ShadowInfo? | ||
let badge: BadgeModifier.BadgeInfo? | ||
let scrollable: Bool? | ||
|
||
init( | ||
uiConfigProvider: UIConfigProvider, | ||
|
@@ -150,7 +152,8 @@ struct StackComponentStyle { | |
shape: PaywallComponent.Shape?, | ||
border: PaywallComponent.Border?, | ||
shadow: PaywallComponent.Shadow?, | ||
badge: PaywallComponent.Badge? | ||
badge: PaywallComponent.Badge?, | ||
overflow: PaywallComponent.StackComponent.Overflow? | ||
) { | ||
self.visible = visible | ||
self.dimension = dimension | ||
|
@@ -167,6 +170,15 @@ struct StackComponentStyle { | |
stackBorder: self.border, | ||
badgeViewModels: badgeViewModels, | ||
uiConfigProvider: uiConfigProvider) | ||
|
||
self.scrollable = overflow.flatMap({ overflow in | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just a huge nit, but for me it has been a TIL. I usually use the |
||
switch overflow { | ||
case .default: | ||
return false | ||
case .scroll: | ||
return true | ||
} | ||
}) | ||
} | ||
|
||
var vstackStrategy: StackStrategy { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make sure, we won’t allow scrolling in the opposite direction than the axis of the stack then? I think that can make sense for now (in the android PR I was assuming a direction would be given by the backend to make it more flexible… but we might not need that flexibility)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tonidero Correct correct! That might make it a bit more confusing to use 😅