Improve subscription UI and fix trial date handling

Lock Screen:
- Add light/dark mode support with adaptive colors
- Make passcode text tappable to trigger authentication

Trial Date Fixes:
- Fix IAPManager to read firstLaunchDate directly from UserDefaults
- Add expiration date check (> Date()) before showing "expires in" text
- Show "Trial expired" when trial end date is in the past
- Disable subscription bypass in DEBUG mode for testing

Month/Year Subscribe Prompts:
- Redesign with gradient icons and compelling copy
- Add fade mask (100% at top to 0% at 50%) for content behind
- Position subscribe overlay on bottom half of screen
- Month: purple/pink theme with calendar icon
- Year: orange/pink theme with chart icon

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-12-24 10:54:01 -06:00
parent 745e226ecb
commit cc9f9f9427
8 changed files with 275 additions and 78 deletions

View File

@@ -109,6 +109,21 @@ struct MonthView: View {
)
}
.scrollDisabled(iapManager.shouldShowPaywall)
.mask(
// Fade effect when paywall should show: 100% at top, 0% halfway down
iapManager.shouldShowPaywall ?
AnyView(
LinearGradient(
gradient: Gradient(stops: [
.init(color: .black, location: 0),
.init(color: .black, location: 0.3),
.init(color: .clear, location: 0.5)
]),
startPoint: .top,
endPoint: .bottom
)
) : AnyView(Color.black)
)
}
// Hidden text to trigger updates when custom tint changes
@@ -116,27 +131,72 @@ struct MonthView: View {
.hidden()
if iapManager.shouldShowPaywall {
// Paywall overlay - tap to show subscription store
Color.black.opacity(0.3)
.ignoresSafeArea()
.onTapGesture {
showSubscriptionStore = true
// Premium month history prompt - bottom half
VStack(spacing: 20) {
// Icon
ZStack {
Circle()
.fill(
LinearGradient(
colors: [.purple.opacity(0.2), .pink.opacity(0.2)],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
.frame(width: 80, height: 80)
Image(systemName: "calendar.badge.clock")
.font(.title)
.foregroundStyle(
LinearGradient(
colors: [.purple, .pink],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
}
VStack {
Spacer()
// Text
VStack(spacing: 10) {
Text("Explore Your Mood History")
.font(.title3.weight(.bold))
.foregroundColor(textColor)
.multilineTextAlignment(.center)
Text("See your complete monthly journey. Track patterns and understand what shapes your days.")
.font(.subheadline)
.foregroundColor(textColor.opacity(0.7))
.multilineTextAlignment(.center)
.padding(.horizontal, 24)
}
// Subscribe button
Button {
showSubscriptionStore = true
} label: {
Text(String(localized: "subscription_required_button"))
.font(.headline)
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding()
.background(RoundedRectangle(cornerRadius: 10).fill(Color.pink))
HStack {
Image(systemName: "calendar")
Text("Unlock Full History")
}
.font(.headline.weight(.bold))
.foregroundColor(.white)
.frame(maxWidth: .infinity)
.padding(.vertical, 14)
.background(
LinearGradient(
colors: [.purple, .pink],
startPoint: .leading,
endPoint: .trailing
)
)
.clipShape(RoundedRectangle(cornerRadius: 14))
}
.padding()
.padding(.horizontal, 24)
}
.padding(.vertical, 24)
.frame(maxWidth: .infinity)
.background(theme.currentTheme.bg)
.frame(maxHeight: .infinity, alignment: .bottom)
} else if iapManager.shouldShowTrialWarning {
VStack {
Spacer()