// // FeelsTips.swift // Feels // // TipKit implementation for feature discovery and onboarding // import TipKit import SwiftUI // MARK: - Tip Definitions /// Tip for customizing mood layouts struct CustomizeLayoutTip: Tip { var title: Text { Text("Personalize Your Experience") } var message: Text? { Text("Tap here to customize mood icons, colors, and layouts.") } var image: Image? { Image(systemName: "paintbrush") } } /// Tip for AI Insights feature struct AIInsightsTip: Tip { var title: Text { Text("Discover AI Insights") } var message: Text? { Text("Get personalized insights about your mood patterns powered by Apple Intelligence.") } var image: Image? { Image(systemName: "brain") } var rules: [Rule] { #Rule(Self.$hasLoggedMoods) { $0 >= 7 } } @Parameter static var hasLoggedMoods: Int = 0 } /// Tip for Siri shortcuts struct SiriShortcutTip: Tip { var title: Text { Text("Use Siri to Log Moods") } var message: Text? { Text("Say \"Hey Siri, log my mood as great in Feels\" for hands-free logging.") } var image: Image? { Image(systemName: "mic.fill") } var rules: [Rule] { #Rule(Self.$moodLogCount) { $0 >= 3 } } @Parameter static var moodLogCount: Int = 0 } /// Tip for HealthKit sync struct HealthKitSyncTip: Tip { var title: Text { Text("Sync with Apple Health") } var message: Text? { Text("Connect to Apple Health to see your mood data alongside sleep, exercise, and more.") } var image: Image? { Image(systemName: "heart.fill") } var rules: [Rule] { #Rule(Self.$hasSeenSettings) { $0 == true } } @Parameter static var hasSeenSettings: Bool = false } /// Tip for widget voting struct WidgetVotingTip: Tip { var title: Text { Text("Vote from Your Home Screen") } var message: Text? { Text("Add the Mood Vote widget to quickly log your mood without opening the app.") } var image: Image? { Image(systemName: "square.grid.2x2") } var rules: [Rule] { #Rule(Self.$daysUsingApp) { $0 >= 2 } } @Parameter static var daysUsingApp: Int = 0 } /// Tip for viewing different time periods struct TimeViewTip: Tip { var title: Text { Text("View Your History") } var message: Text? { Text("Switch between Day, Month, and Year views to see your mood patterns over time.") } var image: Image? { Image(systemName: "calendar") } } /// Tip for mood streaks struct MoodStreakTip: Tip { var title: Text { Text("Build Your Streak!") } var message: Text? { Text("Log your mood daily to build a streak. Consistency helps you understand your patterns.") } var image: Image? { Image(systemName: "flame.fill") } var rules: [Rule] { #Rule(Self.$currentStreak) { $0 >= 3 } } @Parameter static var currentStreak: Int = 0 } /// Tip for Control Center widget struct ControlCenterTip: Tip { var title: Text { Text("Quick Access from Control Center") } var message: Text? { Text("Add Feels to Control Center for one-tap mood logging from anywhere.") } var image: Image? { Image(systemName: "slider.horizontal.3") } var rules: [Rule] { #Rule(Self.$daysUsingApp) { $0 >= 5 } } @Parameter static var daysUsingApp: Int = 0 } // MARK: - Tips Manager @MainActor class TipsManager { static let shared = TipsManager() private init() {} func configure() { try? Tips.configure([ .displayFrequency(.daily), .datastoreLocation(.applicationDefault) ]) } func resetAllTips() { try? Tips.resetDatastore() } // Update tip parameters based on user actions func onMoodLogged() { SiriShortcutTip.moodLogCount += 1 AIInsightsTip.hasLoggedMoods += 1 } func onSettingsViewed() { HealthKitSyncTip.hasSeenSettings = true } func updateDaysUsingApp(_ days: Int) { WidgetVotingTip.daysUsingApp = days ControlCenterTip.daysUsingApp = days } func updateStreak(_ streak: Int) { MoodStreakTip.currentStreak = streak } } // MARK: - Tip View Modifiers extension View { func customizeLayoutTip() -> some View { self.popoverTip(CustomizeLayoutTip()) } func aiInsightsTip() -> some View { self.popoverTip(AIInsightsTip()) } func siriShortcutTip() -> some View { self.popoverTip(SiriShortcutTip()) } func healthKitSyncTip() -> some View { self.popoverTip(HealthKitSyncTip()) } func widgetVotingTip() -> some View { self.popoverTip(WidgetVotingTip()) } func timeViewTip() -> some View { self.popoverTip(TimeViewTip()) } func moodStreakTip() -> some View { self.popoverTip(MoodStreakTip()) } func controlCenterTip() -> some View { self.popoverTip(ControlCenterTip()) } } // MARK: - Inline Tip View struct InlineTipView: View { let tip: any Tip var body: some View { TipView(tip) .tipBackground(Color(.secondarySystemBackground)) } }