Release 1.4.0 (build 31): retención, quick update, streak, what's new
- 1A: Notificación mensual de resumen de portfolio (día 5 de cada mes) - 1B: Badge de racha mensual en Dashboard (streak counter) - 1C: Empty states mejorados en Goals y Journal con CTAs claros - 2A: Quick Update sheet — actualiza todas las fuentes desde una pantalla - 2B: Notificación batch update redirige al Quick Update sheet - 2C: Widget deep link portfoliojournal://quickupdate abre Quick Update - 3A: App Store version check banner en Settings - 3C: What's New sheet en primer launch de versión nueva - Localización completa en 7 idiomas para todas las nuevas strings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import SwiftUI
|
||||
|
||||
struct WhatsNewFeature {
|
||||
let icon: String
|
||||
let color: Color
|
||||
let title: String
|
||||
let description: String
|
||||
}
|
||||
|
||||
struct WhatsNewView: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
private let features: [WhatsNewFeature] = [
|
||||
WhatsNewFeature(
|
||||
icon: "bolt.circle.fill",
|
||||
color: .appPrimary,
|
||||
title: String(localized: "whats_new_quick_update_title"),
|
||||
description: String(localized: "whats_new_quick_update_body")
|
||||
),
|
||||
WhatsNewFeature(
|
||||
icon: "flame.fill",
|
||||
color: .orange,
|
||||
title: String(localized: "whats_new_streak_title"),
|
||||
description: String(localized: "whats_new_streak_body")
|
||||
),
|
||||
WhatsNewFeature(
|
||||
icon: "target",
|
||||
color: .appSecondary,
|
||||
title: String(localized: "whats_new_goals_title"),
|
||||
description: String(localized: "whats_new_goals_body")
|
||||
)
|
||||
]
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
AppBackground()
|
||||
|
||||
VStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
VStack(spacing: 32) {
|
||||
VStack(spacing: 8) {
|
||||
Text("🎉")
|
||||
.font(.system(size: 56))
|
||||
Text(String(localized: "whats_new_title"))
|
||||
.font(.title.weight(.bold))
|
||||
Text(String(localized: "whats_new_subtitle"))
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
}
|
||||
|
||||
VStack(spacing: 20) {
|
||||
ForEach(features, id: \.title) { feature in
|
||||
HStack(spacing: 16) {
|
||||
Image(systemName: feature.icon)
|
||||
.font(.title2)
|
||||
.foregroundColor(feature.color)
|
||||
.frame(width: 40)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(feature.title)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
Text(feature.description)
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(Color(.systemBackground))
|
||||
.cornerRadius(16)
|
||||
.shadow(color: .black.opacity(0.05), radius: 8, y: 2)
|
||||
}
|
||||
.padding()
|
||||
|
||||
Spacer()
|
||||
|
||||
Button {
|
||||
dismiss()
|
||||
} label: {
|
||||
Text(String(localized: "whats_new_continue"))
|
||||
.font(.headline)
|
||||
.foregroundColor(.white)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding()
|
||||
.background(Color.appPrimary)
|
||||
.cornerRadius(14)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
.interactiveDismissDisabled()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user