Add premium features and reorganize Settings tab

Premium Features:
- Journal notes and photo attachments for mood entries
- Data export (CSV and PDF reports)
- Privacy lock with Face ID/Touch ID
- Apple Health integration for mood correlation
- 4 new personality packs (Motivational Coach, Zen Master, Best Friend, Data Analyst)

Settings Tab Reorganization:
- Combined Customize and Settings into single tab with segmented control
- Added upgrade banner with trial countdown above segment
- "Why Upgrade?" sheet showing all premium benefits
- Subscribe button opens improved StoreKit 2 subscription view

UI Improvements:
- Enhanced subscription store with feature highlights
- Entry detail view for viewing/editing notes and photos
- Removed duplicate subscription banners from tab content

🤖 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-13 12:22:06 -06:00
parent 6c92cf4ec3
commit 920aaee35c
26 changed files with 4295 additions and 99 deletions

View File

@@ -97,6 +97,14 @@ class FoundationModelsInsightService: ObservableObject {
return defaultSystemInstructions
case .Rude:
return rudeSystemInstructions
case .MotivationalCoach:
return coachSystemInstructions
case .ZenMaster:
return zenSystemInstructions
case .BestFriend:
return bestFriendSystemInstructions
case .DataAnalyst:
return analystSystemInstructions
}
}
@@ -122,6 +130,54 @@ class FoundationModelsInsightService: ObservableObject {
"""
}
private var coachSystemInstructions: String {
"""
You are a HIGH ENERGY motivational coach analyzing mood data! Think Tony Robbins meets sports coach.
Style: Enthusiastic, empowering, action-oriented! Use exclamations! Celebrate wins BIG, frame struggles as opportunities for GROWTH. Every insight ends with a call to action.
Phrases: "Let's GO!", "Champion move!", "That's the winner's mindset!", "You're in the ZONE!", "Level up!"
SF Symbols: figure.run, trophy.fill, flame.fill, bolt.fill, star.fill, flag.checkered, medal.fill
"""
}
private var zenSystemInstructions: String {
"""
You are a calm, mindful Zen master reflecting on mood data. Think Buddhist monk meets gentle therapist.
Style: Serene, philosophical, uses nature metaphors. Speak in calm, measured tones. Find wisdom in all emotions. No judgment, only observation and acceptance.
Phrases: "Like the seasons...", "The river of emotion...", "In stillness we find...", "This too shall pass...", "With gentle awareness..."
SF Symbols: leaf.fill, moon.fill, drop.fill, wind, cloud.fill, sunrise.fill, sparkles, peacesign
"""
}
private var bestFriendSystemInstructions: String {
"""
You are their supportive best friend analyzing their mood data! Think caring bestie who's always got their back.
Style: Warm, casual, uses "you" and "we" language. Validate feelings, celebrate with them, commiserate together. Use conversational tone with occasional gentle humor.
Phrases: "Okay but...", "Not gonna lie...", "I see you!", "That's so valid!", "Girl/Dude...", "Honestly though..."
SF Symbols: heart.fill, hand.thumbsup.fill, sparkles, star.fill, sun.max.fill, face.smiling.fill, balloon.fill
"""
}
private var analystSystemInstructions: String {
"""
You are a clinical data analyst examining mood metrics. Think spreadsheet expert meets research scientist.
Style: Objective, statistical, data-driven. Reference exact numbers, percentages, and trends. Avoid emotional language. Present findings like a research report.
Phrases: "Data indicates...", "Statistically significant...", "Correlation observed...", "Trend analysis shows...", "Based on the metrics..."
SF Symbols: chart.bar.fill, chart.line.uptrend.xyaxis, function, number, percent, chart.pie.fill, doc.text.magnifyingglass
"""
}
// MARK: - Insight Generation
/// Generate AI-powered insights for the given mood entries
@@ -129,11 +185,13 @@ class FoundationModelsInsightService: ObservableObject {
/// - entries: Array of mood entries to analyze
/// - periodName: The time period name (e.g., "this month", "this year", "all time")
/// - count: Number of insights to generate (default 5)
/// - healthCorrelations: Optional health data correlations to include
/// - Returns: Array of Insight objects
func generateInsights(
for entries: [MoodEntryModel],
periodName: String,
count: Int = 5
count: Int = 5,
healthCorrelations: [HealthCorrelation] = []
) async throws -> [Insight] {
// Check cache first
if let cached = cachedInsights[periodName],
@@ -158,8 +216,8 @@ class FoundationModelsInsightService: ObservableObject {
isGenerating = true
defer { isGenerating = false }
// Prepare data summary
let summary = summarizer.summarize(entries: validEntries, periodName: periodName)
// Prepare data summary with health correlations
let summary = summarizer.summarize(entries: validEntries, periodName: periodName, healthCorrelations: healthCorrelations)
let prompt = buildPrompt(from: summary, count: count)
do {