Skip to content
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] Add support for gradient backgrounds #4522

Merged
merged 8 commits into from
Nov 28, 2024

Conversation

MarkVillacampa
Copy link
Member

@MarkVillacampa MarkVillacampa commented Nov 26, 2024

This PR adds support for gradient backgrounds.

Supported gradient types are Radial and Linear.

Screenshot 2024-11-26 at 11 35 52 Screenshot 2024-11-26 at 11 36 03

Additionally, gradients as text foreground style are now supported:

Screenshot 2024-11-27 at 01 17 02

@@ -20,7 +20,6 @@ enum BackgroundStyle {

case color(PaywallComponent.ColorScheme)
case image(PaywallComponent.ThemeImageUrls)
case gradient
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following the spec, gradient is not a different type of background but is encoded as part of the ColorInfo struct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad 😅 Thanks for fixing!

@@ -47,7 +46,26 @@ fileprivate extension View {
func apply(backgroundStyle: BackgroundStyle) -> some View {
switch backgroundStyle {
case .color(let color):
self.background(color.toDynamicColor())
switch color.light {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My assumption is the light and dark colors must be of the same type e.g. both solid or both gradient.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified to support mixed solid and gradient light/dark colors in ColorScheme


private extension UnitPoint {

init(angle: Angle) {
Copy link
Member Author

@MarkVillacampa MarkVillacampa Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little helper to transform the degree orientation of the linear gradient into what SwiftUI expects: the starting and endpoints of the gradient in the enclosing rectangle view.

…pport mixed solid and gradient light/dark colors in ColorScheme
@@ -157,7 +157,7 @@ struct TextComponentStyle {
let visible: Bool
let text: String
let fontWeight: Font.Weight
let color: Color
let color: PaywallComponent.ColorScheme
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing the ColorScheme instead of the dynamic color now because it can potentially be a gradient.

}

@Environment(\.colorScheme)
private var colorScheme
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For completeness, and in case we want to use use GradientView somewhere else, I've kept support for light/dark mode here even though we're controlling it in BackgroundStyle and ForegroundColorScheme.

Copy link
Member

@joshdholtz joshdholtz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is sooooooo good! Thank you 😁

@@ -20,7 +20,6 @@ enum BackgroundStyle {

case color(PaywallComponent.ColorScheme)
case image(PaywallComponent.ThemeImageUrls)
case gradient
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad 😅 Thanks for fixing!

Comment on lines +42 to +58
var body: some View {
switch gradientStyle {
case .linear(let degrees):
LinearGradient(
gradient: gradient,
startPoint: UnitPoint(angle: Angle(degrees: Double(degrees))),
endPoint: UnitPoint(angle: Angle(degrees: Double(degrees+180)))
)
case .radial:
RadialGradient(
gradient: gradient,
center: .center,
startRadius: 0,
endRadius: 100
)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait... it's this easy to do it?! 😅 I had no idea... I love it 😁

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we hadd some SwiftUI previews here of the gradients? 😇

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added 👍

Comment on lines +71 to +72
// Determine the scaling factor to move the point to the edge of the enclosing square
let scaleFactor = max(abs(xPosition), abs(yPosition))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the inspiration here! This was very useful for Android too. 🙏

Quick question: does this work for non-square shapes in SwiftUI, like rectangles? In Compose, I find that the angle isn't quite correct when using a rectangle, as it indeed seems to "pretend" it's a square and draws the angle based on that. Not sure how strict we are with the desired result. There's a bunch of discussion and suggested Compose solutions on this StackOverflow question.

Here's an example of what I mean. Both are set to an angle of 45 degrees, but only the square is actually 45 degrees.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will handle in a new PR 👍

@MarkVillacampa MarkVillacampa merged commit 21a6df8 into main Nov 28, 2024
7 checks passed
@MarkVillacampa MarkVillacampa deleted the paywalls/gradients branch November 28, 2024 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants