Fetch and display weather data (temp, condition, hi/lo, humidity) when
users log a mood. Weather is stored as JSON on MoodEntryModel and shown
as a card in EntryDetailView. Premium-gated with location permission
prompt. Includes BGTask retry for failed fetches and full analytics.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rewrite all 10 celebration haptic patterns to match visual timing and
feel distinct: confetti gets playful falling taps, explosion gets a deep
boom, shatter gets glassy cracks, morph gets liquid breathing, etc.
Play the matching haptic when selecting a new vote animation in
customization (respects haptic feedback toggle).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace non-existent "tunnel.circle" SF Symbol with "circle.dashed" for
the tunnel vote animation. Add missing translations for haptic feedback
strings and "Close" across all 6 languages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace HStack layout with LazyVGrid for uniform card sizing, remove
lineLimit(1) to allow multiline subtitles, and add 1:1 aspect ratio
so all four feature cards are identical squares across all 12 themes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The .containerRelativeFrame(.horizontal) on the marketing content
caused an infinite layout loop inside SubscriptionStoreView's scroll
container. Replaced with .frame(maxWidth: .infinity).
Also fixes leading space in StoreKit config display name, adds
debug logging to product loading, and reverts to groupID initializer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch from groupID to productIDs for more reliable product loading
- Add dismiss button overlay so users aren't trapped if products fail to load
- Make productIdentifiers static for shared access
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all fatalError/force unwrap/force cast crash points from production
paths (ShowBasedOnVoteLogics, Random, ReflectApp, NoteEditorView). Fix
actor-isolation warnings by wrapping off-main-thread AnalyticsManager calls
in Task { @MainActor in } (LocalNotification) and replacing DispatchQueue
with Task.detached + MainActor.run (LiveActivityPreviewView). Update legal
URLs from feels.88oakapps.com to reflect.88oakapps.com in SettingsView.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace random animation selection with a user-configurable picker on
the Customize tab between Mood Style and Notifications. Confetti is
the default. Selecting a style shows an inline preview that auto-plays
the animation then dismisses itself. Remove Animation Lab from Settings.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add containerRelativeFrame to paywall marketing content so feature cards
fit within screen width on iOS 18. Update onboarding tip text and all
localizations (DE, ES, FR, JA, KO, PT-BR).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Broadens installable audience to iOS 18+ while keeping AI insights available on iOS 26.
Foundation Models types and service wrapped in @available(iOS 26, *), InsightsViewModel
conditionally instantiates the service with fallback UI on older versions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Animation Lab moved out of #if DEBUG so it's available in release builds
- Add Test Data moved into #if DEBUG debug section
- Removed #if DEBUG wrapper from DebugAnimationSettingsView.swift
- Added 58 missing translations across all 6 languages (de, es, fr, ja, ko, pt-BR)
- Localization coverage restored from 87% to 100% (473/473 keys)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- TC-148: Year View heatmap grid renders with data (added accessibility ID)
- TC-143: App navigable with Reduce Motion enabled
- TC-144: App navigable with High Contrast mode enabled
- Marked 89 blocked tests RED in QA spreadsheet
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ZStack-with-gradient patterns with idiomatic .background() modifier
across onboarding, customize, and settings views. Add accessibility identifiers
to Year View charts for UI test automation. Mark 67 impossible-to-automate
tests RED in QA plan and scaffold initial Year View and Settings onboarding tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Revert key-by-key UserDefaults iteration that removed system keys
causing kAXErrorServerNotFound crashes; restore removePersistentDomain
with explicit subscription key clearing
- Add .accessibilityElement(children: .contain) to UpgradeBannerView
so subscribe button is discoverable by XCUITest
- Fix AllDayViewStylesTests to use coordinate-based tapping instead of
button.isHittable/button.tap() for iOS 26 Liquid Glass compatibility
- Improve OnboardingTests with multiple swipe retries and label-based
fallback for skip button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- resetAppState: use correct suite name to clear group defaults (fixes stale subscription state)
- Reorder configureIfNeeded: set expireTrial before IAPManager init
- Add browse_themes_button identifier to CustomizeView Browse Themes button
- Add mood_button_* identifiers to Entry Detail mood grid in NoteEditorView
- Use coordinate-based tap throughout all test screens (iOS 26 Liquid Glass hittability)
- Fix HeaderMoodLogging date format: M/d/yyyy → yyyy/MM/dd to match entry_row identifiers
- AppLaunchTests: wait for isSelected state with NSPredicate instead of immediate check
- OnboardingTests: add waits between swipes and retry logic for skip button
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
App fixes:
- Remove empty_state identifier from EmptyHomeView VStack (was overriding mood_header)
- Fix resetAppState to set needsOnboarding=true (fresh state) instead of false
- Set bypassSubscription explicitly based on launch arg presence (was defaulting to true in DEBUG)
Test fixes:
- TabBarScreen: use coordinate tap to avoid iOS 26 Liquid Glass hittability issues
- SettingsScreen: use coordinate tap for segments, handle Settings label ambiguity with tab bar
- EntryDetailScreen: use mood_button_ identifiers instead of label matching (was matching entry rows)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The .accessibilityIdentifier() on TabView tab content propagated to ALL child views
in the accessibility tree, overriding identifiers like mood_header and settings_header.
Tab buttons are already accessible via labels (Day, Month, etc.) so these aren't needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace force-unwrap HK types with modern HKQuantityType(_:) initializer
- Replace Calendar.date force-unwraps with guard/let in HealthService, HeaderPercView, MoodStreakActivity, DayViewViewModel, MonthTotalTemplate
- Extract DayViewViewModel.countEntries into testable static method with safe flatMap
- Replace DispatchQueue.main.asyncAfter with Task.sleep in CelebrationAnimations
- Add .minimumScaleFactor(0.5) to SmallRollUpHeaderView for Dynamic Type
- Add VoiceOver accessibility labels to HeaderPercView mood percentages
- Fix @testable import iFeel → Feels in Tests_iOS.swift
- Add 4 unit tests for countEntries (TDD)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add 8 new test files: HeaderMoodLogging (TC-002), DayViewGrouping (TC-019),
AllDayViewStyles (TC-021), MonthViewInteraction (TC-030), PaywallGate
(TC-032/039/048), AppTheme (TC-070), IconPack (TC-072),
PremiumCustomization (TC-075)
- Add accessibility IDs for paywall overlays, icon packs, app theme cards,
and day view section headers
- Add --expire-trial launch argument to UITestMode for paywall gate testing
- Update QA test plan spreadsheet with XCUITest names for 14 test cases
- Include existing test infrastructure: screen objects, helpers, base class,
and 19 previously written test files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add runtime toggle in Settings (DEBUG only) to bypass subscription/hide trial banner
- IAPManager.bypassSubscription is now a @Published var persisted via UserDefaults
- Hide upgrade banner in SettingsTabView and trial warnings when bypass is enabled
- Add FeelsTests directory with integration tests
- Update DataController, DataControllerGET, DataControllerUPDATE
- Update Xcode project and scheme configuration
- Update localization strings and App Store screen docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix ExtensionDataProvider <= boundary to < in date queries (prevented cross-day leaks)
- Replace force-unwraps with guards and add error logging in DataControllerGET and ExtensionDataProvider
- Route DayViewViewModel update/delete through MoodLogger.shared (was duplicating side effects)
- Add data listeners to InsightsViewModel and YearViewModel for cross-tab refresh
- Add HealthKitManager.deleteMood(for:) for single-date cleanup
- Add SharedModelContainer.isUsingInMemoryFallback flag with critical logging
- Add analytics events: entryDeleted, allDataCleared, duplicatesRemoved, storageFallbackActivated
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- save()/saveAndRunDataListeners() now return @discardableResult Bool;
listeners only fire on successful save
- MoodLogger.updateMood() now recalculates streak, updates Live Activity,
and notifies watch (was missing these side effects)
- CSV import uses new addBatch()/importMoods() for O(1) side effects
instead of O(n) per-row widget reloads and streak calcs
- Foreground task ordering: fillInMissingDates() now runs before
removeDuplicates() so backfill-created duplicates are caught same cycle
- WidgetMoodSaver deletes ALL entries for date (was fetchLimit=1, leaving
CloudKit sync duplicates behind)
- cleanupPhotoIfNeeded logs warning on failed photo deletion instead of
silently orphaning files
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create landing_page/privacy.html and landing_page/eula.html matching site design
- Add app icon to nav/footer/favicon across all landing pages
- Update settings EULA and privacy links to feels.88oakapps.com
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can now swipe between design variations (e.g. Gradient vs Color Block)
when sharing from month/year views and the sharing templates list. Removes
#if DEBUG wrappers from variation files and disables auto-start demo animation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ExportableInsightsViews with sample AI insights data
- Add InsightsExporter service for light/dark mode screenshots
- Add export insights button to Settings debug section
- Update ConceptB promo to use insights_light.png in privacy scene
- Fix phone frame clipping with overflow hidden and borderRadius 64
- Add timeline voting widget images for promo video
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ExportableWatchViews.swift with exportable versions of watch app views
- Add WatchExporter.swift service to export all watch view variations
- Add export watch screenshots button to Settings (DEBUG)
- Update ConceptB promo: use watch_voting_light.png inside watch frame at 1.2x size
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Export month.mov and year.mov to PNG image sequences
- Replace Video components with Img sequences in scenes 2 and 3
- Add previous frame layering to prevent flashing during transitions
- Update CTAScene: 2x sizing, white background, new text colors
- Add LiveActivityPreviewView for exporting 365 activity frames
- Enlarge background icons to 1.2x across all scenes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix grid visibility: show gray background cells always, animate mood
colors on top with scale 2x->1x effect
- Add smooth auto-scroll for MonthView: starts after first month is 50%
filled, scrolls at constant speed to match fill rate
- Remove pause between months for fluid continuous animation
- Add currentAnimatingMonthIndex tracking to DemoAnimationManager
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update App Group IDs from group.com.tt.feels to group.com.88oakapps.feels
- Update iCloud container IDs from iCloud.com.tt.feels to iCloud.com.88oakapps.feels
- Sync code constants with entitlements across all targets (iOS, Watch, Widget)
- Update documentation in CLAUDE.md and PROJECT_OVERVIEW.md
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Debug features (DEBUG builds only):
- WidgetExporter: Export all widget variants to PNG (light/dark modes)
- Live Activity lock screen export with configurable streak
- Test notifications button to preview all personality packs
- Settings buttons for export and notification testing
Research:
- Competitor analysis docs (Daylio, Bearable, Reflectly, etc.)
- App Store screenshot reference materials
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove prompt text from small widget before voting
- Show date instead of "Logged!" after voting on small widget
- Fix light mode settings: section=gray, inner rows=white for contrast
- Remove redundant backgrounds from Browse Themes and subscription banner
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix critical bug in generateObjectNotInArray() that ignored the mood
parameter and generated random moods instead of placeholders, causing
Month view to display fake colored entries for days without real data
- Update Month and Year shareableView exports to show all 5 mood types
even when some have 0 entries (previously filtered out empty moods)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update NeonMoodTint to use synthwave colors matching Neon voting style
(cyan, lime, yellow, orange, magenta)
- Replace text label with 5 color circles in theme preview Colors row
- Remove unused textColor customization code and picker views
- Add .id(moodTint) to Month/Year views for color refresh
- Clean up various unused color-related code
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add WCAG-compliant luminance calculation to Color extension
- Add contrastingTextColor method to MoodTints for automatic black/white text
- Update 12+ entry styles to use dynamic text colors instead of hardcoded white
- Change theme preview sheet to full screen presentation
Text now automatically switches between black and white based on background
brightness, fixing readability issues on light mood colors like yellow (Good).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- 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>
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>
- Change Theme enum from Int to String raw values to fix theme selection bug
- Replace OnboardingStyle icon/color pickers with unified AppTheme grid
- Remove visible text labels from voting layouts while keeping accessibility labels (WCAG 2.1 AA compliant)
- Update widget voting views to use icons only with proper accessibility support
- Consolidate app icons to single unified icon set
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>