Files
Reflect/Shared/FeelsTips.swift
Trey t e98142c72e Fix memory leaks and add debug tools, remove ControlCenterTip
Memory optimization:
- Add onDisappear cleanup for repeatForever animations in LockScreenView
- Add onDisappear cleanup for animations in FeelsSubscriptionStoreView
- Add onDisappear cleanup in AddMoodHeaderView and PaywallPreviewSettingsView

Debug improvements:
- Add test data and clear data buttons to Settings (debug builds only)

TipKit changes:
- Remove ControlCenterTip (unused)
- Add TipKit-Tips.md documentation

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 21:07:22 -06:00

233 lines
4.7 KiB
Swift

//
// 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
}
// 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
}
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())
}
}
// MARK: - Inline Tip View
struct InlineTipView: View {
let tip: any Tip
var body: some View {
TipView(tip)
.tipBackground(Color(.secondarySystemBackground))
}
}