Replace TipKit with custom themed tips modal system

- Add TipModalView with gradient header, themed styling, and spring animations
- Create FeelsTipsManager with global toggle, session tracking, and persistence
- Define FeelsTip protocol and convert all 7 tips to new system
- Add convenience view modifiers (.customizeLayoutTip(), .aiInsightsTip(), etc.)
- Remove TipKit dependency from all views
- Add Tips Preview debug screen in Settings to test all tip modals
- Update documentation for new custom tips system

🤖 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-28 21:33:36 -06:00
parent e98142c72e
commit c59f215535
11 changed files with 809 additions and 222 deletions

View File

@@ -109,38 +109,42 @@ This document covers the new Apple-specific features integrated into Feels, incl
---
## 4. TipKit
## 4. Custom Tips System
**File:** `Shared/FeelsTips.swift`
**Files:**
- `Shared/FeelsTips.swift` (Tips definitions and manager)
- `Shared/Views/TipModalView.swift` (Modal UI)
**What it does:** Shows contextual tips to help users discover features throughout the app.
**What it does:** Shows themed modal tips to help users discover features throughout the app. Tips appear as beautiful sheets that match the app's current theme.
### Available Tips
| Tip | Location | Trigger |
|-----|----------|---------|
| CustomizeLayoutTip | Customize screen | First visit |
| AIInsightsTip | Insights tab | After 7 days of data |
| AIInsightsTip | Insights tab | After 7 moods logged |
| SiriShortcutTip | Settings | After 3 mood logs |
| HealthKitSyncTip | Settings | After 5 mood logs |
| WidgetVotingTip | Day view | After first mood log |
| TimeViewTip | Day view header | After 2 days usage |
| HealthKitSyncTip | Settings | After viewing settings |
| WidgetVotingTip | Day view | After 2 days usage |
| TimeViewTip | Day view | First visit |
| MoodStreakTip | Day view | When streak >= 3 |
### How to Test
1. Tips appear automatically based on conditions
2. To reset tips for testing, add this code temporarily:
1. Tips appear automatically based on conditions (one per session)
2. To reset tips for testing:
```swift
try? Tips.resetDatastore()
FeelsTipsManager.shared.resetAllTips()
```
3. To disable tips globally:
```swift
FeelsTipsManager.shared.tipsEnabled = false
```
3. Or use the Tips debug menu in Xcode:
- Edit Scheme > Run > Arguments
- Add: `-com.apple.TipKit.DisplayFrequency weekly`
### Implementation Details
- `TipsManager.shared.configure()` called in `FeelsApp.init()`
- Each tip has rules based on `@Parameter` events and conditions
- Tips automatically dismiss after user interaction
- `FeelsTipsManager.shared.resetSession()` called in `FeelsApp.init()`
- Each tip has `isEligible` property based on user activity parameters
- Tips show as themed modal sheets with gradient headers
- Only one tip shown per app session
---

View File

@@ -1,12 +1,13 @@
# TipKit Tips Documentation
# Custom Tips System Documentation
This document describes all TipKit tips implemented in the Feels app, including their display conditions and locations.
This document describes all tips implemented in the Feels app, including their display conditions and locations.
## Overview
Tips are managed by `TipsManager` (singleton) and configured with:
- **Display Frequency**: Daily
- **Datastore Location**: Application default
Tips are displayed as themed modal sheets that match the user's chosen app theme. The system is managed by `FeelsTipsManager` (singleton) and configured with:
- **Display Frequency**: One tip per app session
- **Global Toggle**: `tipsEnabled` boolean in UserDefaults
- **Persistence**: Shown tip IDs stored in UserDefaults
---
@@ -15,12 +16,12 @@ Tips are managed by `TipsManager` (singleton) and configured with:
### 1. CustomizeLayoutTip
**Title**: "Personalize Your Experience"
**Message**: "Tap here to customize mood icons, colors, and layouts."
**Icon**: `paintbrush`
**Message**: "Customize mood icons, colors, and layouts to make the app truly yours."
**Icon**: `paintbrush.fill`
**Display Conditions**: Always eligible (no rules)
**Location**: CustomizeContentView (top of the Customize tab in Settings)
**Location**: CustomizeContentView (via `.customizeLayoutTip()`)
---
@@ -28,14 +29,14 @@ Tips are managed by `TipsManager` (singleton) and configured with:
**Title**: "Discover AI Insights"
**Message**: "Get personalized insights about your mood patterns powered by Apple Intelligence."
**Icon**: `brain`
**Icon**: `brain.head.profile`
**Display Conditions**:
- User has logged at least **7 moods**
**Parameter**: `hasLoggedMoods: Int` (incremented via `TipsManager.shared.onMoodLogged()`)
**Parameter**: `moodLogCount: Int` (incremented via `FeelsTipsManager.shared.onMoodLogged()`)
**Location**: InsightsView
**Location**: InsightsView (via `.aiInsightsTip()`)
---
@@ -48,7 +49,7 @@ Tips are managed by `TipsManager` (singleton) and configured with:
**Display Conditions**:
- User has logged at least **3 moods**
**Parameter**: `moodLogCount: Int` (incremented via `TipsManager.shared.onMoodLogged()`)
**Parameter**: `moodLogCount: Int` (incremented via `FeelsTipsManager.shared.onMoodLogged()`)
**Location**: SettingsContentView (Features section header, via `.siriShortcutTip()`)
@@ -63,7 +64,7 @@ Tips are managed by `TipsManager` (singleton) and configured with:
**Display Conditions**:
- User has viewed the Settings screen
**Parameter**: `hasSeenSettings: Bool` (set via `TipsManager.shared.onSettingsViewed()`)
**Parameter**: `hasSeenSettings: Bool` (set via `FeelsTipsManager.shared.onSettingsViewed()`)
**Location**: SettingsContentView (Health Kit toggle, via `.healthKitSyncTip()`)
@@ -73,14 +74,14 @@ Tips are managed by `TipsManager` (singleton) and configured with:
**Title**: "Vote from Your Home Screen"
**Message**: "Add the Mood Vote widget to quickly log your mood without opening the app."
**Icon**: `square.grid.2x2`
**Icon**: `square.grid.2x2.fill`
**Display Conditions**:
- User has been using the app for at least **2 days**
**Parameter**: `daysUsingApp: Int` (updated via `TipsManager.shared.updateDaysUsingApp(_:)`)
**Parameter**: `daysUsingApp: Int`
**Location**: DayView
**Location**: DayView (via `.widgetVotingTip()`)
---
@@ -92,7 +93,7 @@ Tips are managed by `TipsManager` (singleton) and configured with:
**Display Conditions**: Always eligible (no rules)
**Location**: DayView
**Location**: DayView (via `.timeViewTip()`)
---
@@ -105,26 +106,29 @@ Tips are managed by `TipsManager` (singleton) and configured with:
**Display Conditions**:
- User has a current streak of at least **3 days**
**Parameter**: `currentStreak: Int` (updated via `TipsManager.shared.updateStreak(_:)`)
**Parameter**: `currentStreak: Int` (updated via `FeelsTipsManager.shared.updateStreak(_:)`)
**Location**: DayView
**Location**: DayView (via `.moodStreakTip()`)
---
## TipsManager API
## FeelsTipsManager API
```swift
// Configure tips (call on app launch)
TipsManager.shared.configure()
// Reset session flag (call on app launch)
FeelsTipsManager.shared.resetSession()
// Reset all tips (for testing)
TipsManager.shared.resetAllTips()
FeelsTipsManager.shared.resetAllTips()
// Update parameters
TipsManager.shared.onMoodLogged() // Increments mood log count
TipsManager.shared.onSettingsViewed() // Marks settings as viewed
TipsManager.shared.updateDaysUsingApp(_:) // Updates days using app
TipsManager.shared.updateStreak(_:) // Updates current streak
FeelsTipsManager.shared.onMoodLogged() // Increments mood log count
FeelsTipsManager.shared.onSettingsViewed() // Marks settings as viewed
FeelsTipsManager.shared.updateDaysUsingApp(_:) // Updates days using app
FeelsTipsManager.shared.updateStreak(_:) // Updates current streak
// Global toggle
FeelsTipsManager.shared.tipsEnabled = true/false
```
---
@@ -141,12 +145,26 @@ Tips can be attached to views using these convenience modifiers:
.widgetVotingTip()
.timeViewTip()
.moodStreakTip()
// Or use the generic modifier with custom gradient colors:
.feelsTip(FeelsTips.customizeLayout, gradientColors: [.purple, .blue])
```
---
## Modal Design
Tips are displayed as themed modal sheets with:
- Gradient header (130pt) matching tip-specific colors
- SF Symbol icon (44pt, white)
- Title and message with theme text color
- "Got it" dismiss button with gradient background
- Spring animation on appearance
---
## Files
- **Definition**: `Shared/FeelsTips.swift`
- **Manager**: `TipsManager` class in same file
- **Configuration**: Called in `FeelsApp.swift`
- **Tips & Manager**: `Shared/FeelsTips.swift`
- **Modal View**: `Shared/Views/TipModalView.swift`
- **Configuration**: `FeelsTipsManager.shared.resetSession()` called in `FeelsApp.swift`