Files
Reflect/PROJECT_OVERVIEW.md
Trey t f2c510de50 Refactor StoreKit 2 subscription system and add interactive vote widget
## StoreKit 2 Refactor
- Rewrote IAPManager with clean enum-based state model (SubscriptionState)
- Added native SubscriptionStoreView for iOS 17+ purchase UI
- Subscription status now checked on every app launch
- Synced subscription status to UserDefaults for widget access
- Simplified PurchaseButtonView and IAPWarningView
- Removed unused StatusInfoView

## Interactive Vote Widget
- New FeelsVoteWidget with App Intents for mood voting
- Subscribers can vote directly from widget, shows stats after voting
- Non-subscribers see "Tap to subscribe" which opens subscription store
- Added feels:// URL scheme for deep linking

## Firebase Removal
- Commented out Firebase imports and initialization
- EventLogger now prints to console in DEBUG mode only

## Other Changes
- Added fallback for Core Data when App Group unavailable
- Added new localization strings for subscription UI
- Updated entitlements and Info.plist

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 23:07:16 -06:00

5.6 KiB

Feels - iOS Mood Tracking App

Overview

Feels is a daily mood tracking iOS application that allows users to rate their emotional state each day on a 5-point scale (Horrible, Bad, Average, Good, Great) and visualize patterns over time through multiple view modes.

Core Features

  • Daily Mood Tracking: Rate your day on a 5-point scale
  • Multiple View Modes: Day (chronological list), Month (calendar grid), Year (aggregate stats)
  • Customization: Themes, color schemes, icon packs, notification personalities
  • Widgets: iOS home screen widgets showing recent moods
  • Local Notifications: Daily reminders with action buttons for quick mood entry
  • Data Export/Import: CSV format for data portability
  • Subscription Model: 30-day free trial, then monthly/yearly subscriptions
  • Localization: English and Spanish

Architecture

Pattern: MVVM (Model-View-ViewModel) with SwiftUI

Project Structure

Feels/
├── Shared/                     # Core app code
│   ├── Models/                 # Data models (Mood, Theme, MoodTintable, etc.)
│   ├── Views/                  # SwiftUI views organized by feature
│   │   ├── DayView/           # Chronological list view
│   │   ├── MonthView/         # Calendar grid view
│   │   ├── YearView/          # Yearly statistics view
│   │   ├── CustomizeView/     # Settings and customization
│   │   └── Components/        # Reusable UI components
│   ├── Persisence/            # Core Data persistence layer
│   ├── Onboarding/            # First-run experience
│   └── Protocols/             # Protocol definitions
├── FeelsWidget/               # iOS Widget Extension (3 widget types)
├── en.lproj/                  # English localization
├── es.lproj/                  # Spanish localization
└── Tests iOS/                 # Test targets

Key Files

App Entry

File Purpose
FeelsApp.swift Main app entry, Core Data setup, IAP manager, tab navigation

Data Layer

File Purpose
Feels.xcdatamodeld Core Data model with MoodEntry entity
Persistence.swift Core Data stack, App Group container
PersistenceGET.swift Fetch operations
PersistenceADD.swift Create/fill missing entries
PersistenceUPDATE.swift Update operations
PersistenceDELETE.swift Delete operations

Main Views

File Purpose
MainTabView.swift Root navigation (Day, Month, Year, Customize tabs)
DayView.swift Chronological mood list with edit/delete
MonthView.swift Calendar grid with color-coded moods
YearView.swift Aggregate yearly statistics
CustomizeView.swift Theme, colors, icons, shape settings

Services

File Purpose
IAPManager.swift StoreKit 2 subscriptions, 30-day trial
LocalNotification.swift Daily reminders with quick actions
BGTask.swift Background task for filling missing dates
EventLogger.swift Analytics event tracking

Data Models

MoodEntry (Core Data Entity)

- moodValue: Int16 (0-4 for mood ratings)
- forDate: Date (the day being rated)
- timestamp: Date (when entry was created)
- weekDay: Int16 (1-7)
- canEdit, canDelete: Boolean
- entryType: Int16 (header, list, filled-in-missing)

Mood Enum

enum Mood: Int {
    case horrible = 0
    case bad = 1
    case average = 2
    case good = 3
    case great = 4
    case missing = 5
    case placeholder = 6
}

Customization System

Themes (Theme.swift)

  • System, iFeel (gradient), Dark, Light
  • Protocol: Themeable

Color Schemes (MoodTintable.swift)

  • Default, Neon, Pastel, Custom (user-defined)
  • Each mood has primary and secondary colors

Icon Packs (MoodImagable.swift)

  • FontAwesome, Emoji, Hand Emoji
  • Protocol: MoodImagable

Shapes

  • Circle, Square, Diamond for calendar visualization

Notification Personalities (PersonalityPackable.swift)

  • "Nice": Friendly text
  • "Rude": Sarcastic/aggressive text

Widget System

Three widget types in FeelsWidget/:

  1. FeelsWidget: Small/Medium/Large showing recent moods
  2. FeelsGraphicWidget: Small widget with mood graphic
  3. FeelsIconWidget: Custom icon widget

Data shared via App Groups: group.com.88oakapps.ifeel


Dependencies

Apple Frameworks

  • SwiftUI, CoreData, WidgetKit, StoreKit, UserNotifications, CloudKit, BackgroundTasks

Third-Party

  • CloudKitSyncMonitor
  • Firebase (GoogleService-Info.plist)

Configuration

App Groups

  • Production: group.com.88oakapps.ifeel
  • Debug: group.com.88oakapps.ifeelDebug

Background Tasks

  • Identifier: com.88oak.Feels.dbUpdateMissing

StoreKit Products

  • Monthly subscription
  • Yearly subscription
  • 30-day free trial

Data Flow

User Input → Persistence (Core Data) → ViewModel Update → SwiftUI Re-render
                    ↓
            Widget Update (WidgetCenter.shared.reloadAllTimelines())

Localization

Language File
English en.lproj/Localizable.strings
Spanish es.lproj/Localizable.strings

Covers: Onboarding, mood names, UI labels, notifications, settings


Notable Implementation Details

  1. Automatic Missing Date Fill: Creates placeholder entries for days without ratings
  2. Entry Types: header, listView, filledInMissing - tracks how entries were created
  3. Day Filtering: Users can filter which weekdays appear in visualizations
  4. CSV Export: Full data portability with all metadata preserved