|
@@ -11,12 +11,16 @@ struct PaywallView: View {
|
|
|
let availableWidth = max(320, proxy.size.width - (horizontalInset * 2))
|
|
let availableWidth = max(320, proxy.size.width - (horizontalInset * 2))
|
|
|
let availableHeight = max(420, proxy.size.height - 24)
|
|
let availableHeight = max(420, proxy.size.height - 24)
|
|
|
let baseWidth: CGFloat = 860
|
|
let baseWidth: CGFloat = 860
|
|
|
|
|
+ let baseHeight: CGFloat = 680
|
|
|
let contentWidth = min(baseWidth, availableWidth)
|
|
let contentWidth = min(baseWidth, availableWidth)
|
|
|
- let heightScale = min(max(availableHeight / 680, 0.82), 1.2)
|
|
|
|
|
- let verticalSpacing: CGFloat = 18
|
|
|
|
|
|
|
+ let widthScale = contentWidth / baseWidth
|
|
|
|
|
+ let heightScale = availableHeight / baseHeight
|
|
|
|
|
+ // Keep growth balanced to avoid oversized cards on tall/large windows.
|
|
|
|
|
+ let layoutScale = min(max((widthScale * 0.65) + (heightScale * 0.35), 0.86), 1.0)
|
|
|
|
|
+ let verticalSpacing = max(14, min(18, 18 * layoutScale))
|
|
|
let topPadding: CGFloat = 10
|
|
let topPadding: CGFloat = 10
|
|
|
- let featureHeight = max(72, min(108, 84 * heightScale))
|
|
|
|
|
- let planHeight = max(150, min(210, 170 * heightScale))
|
|
|
|
|
|
|
+ let featureHeight = max(74, min(92, 84 * layoutScale))
|
|
|
|
|
+ let planHeight = max(160, min(174, 166 * layoutScale))
|
|
|
|
|
|
|
|
VStack(spacing: 0) {
|
|
VStack(spacing: 0) {
|
|
|
VStack(spacing: verticalSpacing) {
|
|
VStack(spacing: verticalSpacing) {
|
|
@@ -28,8 +32,9 @@ struct PaywallView: View {
|
|
|
}
|
|
}
|
|
|
.frame(width: contentWidth, alignment: .top)
|
|
.frame(width: contentWidth, alignment: .top)
|
|
|
.padding(.top, topPadding)
|
|
.padding(.top, topPadding)
|
|
|
|
|
+ .padding(.bottom, topPadding)
|
|
|
}
|
|
}
|
|
|
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
|
|
|
|
|
|
|
+ .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
|
|
|
.background(Color.white.ignoresSafeArea())
|
|
.background(Color.white.ignoresSafeArea())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -75,6 +80,7 @@ struct PaywallView: View {
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+ .frame(height: planHeight)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private var ctaSection: some View {
|
|
private var ctaSection: some View {
|
|
@@ -227,12 +233,11 @@ private struct PaywallPlanCardView: View {
|
|
|
.padding(.horizontal, 14)
|
|
.padding(.horizontal, 14)
|
|
|
.padding(.top, 12)
|
|
.padding(.top, 12)
|
|
|
|
|
|
|
|
- Spacer(minLength: 8)
|
|
|
|
|
-
|
|
|
|
|
Text(plan.title)
|
|
Text(plan.title)
|
|
|
.font(.system(size: 15, weight: .semibold))
|
|
.font(.system(size: 15, weight: .semibold))
|
|
|
.foregroundStyle(Color(red: 0.16, green: 0.20, blue: 0.26))
|
|
.foregroundStyle(Color(red: 0.16, green: 0.20, blue: 0.26))
|
|
|
.padding(.horizontal, 14)
|
|
.padding(.horizontal, 14)
|
|
|
|
|
+ .padding(.top, 14)
|
|
|
|
|
|
|
|
Text(plan.mainPrice)
|
|
Text(plan.mainPrice)
|
|
|
.font(.system(size: 21, weight: .heavy, design: .rounded))
|
|
.font(.system(size: 21, weight: .heavy, design: .rounded))
|
|
@@ -241,8 +246,7 @@ private struct PaywallPlanCardView: View {
|
|
|
.minimumScaleFactor(0.75)
|
|
.minimumScaleFactor(0.75)
|
|
|
.padding(.horizontal, 14)
|
|
.padding(.horizontal, 14)
|
|
|
.padding(.top, 2)
|
|
.padding(.top, 2)
|
|
|
-
|
|
|
|
|
- Spacer(minLength: 8)
|
|
|
|
|
|
|
+ .padding(.bottom, 12)
|
|
|
|
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
|
HStack {
|
|
HStack {
|
|
@@ -267,7 +271,8 @@ private struct PaywallPlanCardView: View {
|
|
|
RoundedRectangle(cornerRadius: 0)
|
|
RoundedRectangle(cornerRadius: 0)
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
- .frame(maxWidth: .infinity, minHeight: minHeight, alignment: .topLeading)
|
|
|
|
|
|
|
+ .frame(maxWidth: .infinity)
|
|
|
|
|
+ .frame(height: minHeight, alignment: .topLeading)
|
|
|
.background((isSelected || isHovered) ? AppTheme.tealLight.opacity(isSelected ? 0.28 : 0.16) : AppTheme.cardBackground)
|
|
.background((isSelected || isHovered) ? AppTheme.tealLight.opacity(isSelected ? 0.28 : 0.16) : AppTheme.cardBackground)
|
|
|
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
|
.clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
|
|
|
.overlay(
|
|
.overlay(
|