Commit Graph

105 Commits

Author SHA1 Message Date
Trey T
ed8205cd88 Complete accessibility identifier coverage across all 152 project files
Exhaustive file-by-file audit of every Swift file in the project (iOS app,
Watch app, Widget extension). Every interactive UI element — buttons, toggles,
pickers, links, menus, tap gestures, text editors, color pickers, photo
pickers — now has an accessibilityIdentifier for XCUITest automation.

46 files changed across Shared/, Onboarding/, Watch App/, and Widget targets.
Added ~100 new ID definitions covering settings debug controls, export/photo
views, sharing templates, customization subviews, onboarding flows, tip
modals, widget voting buttons, and watch mood buttons.
2026-03-26 08:34:56 -05:00
Trey T
e7648ddd8a Add missing accessibility identifiers to all interactive UI elements
Audit found ~50+ interactive elements (buttons, toggles, pickers, alerts,
links) missing accessibility identifiers across 13 view files. Added
centralized ID definitions and applied them to every entry detail button,
guided reflection control, settings toggle, paywall unlock button,
subscription/IAP button, lock screen control, and photo action dialog.
2026-03-26 07:59:52 -05:00
Trey T
a71104db05 Add onboarding Next buttons and fix accessibility for paged TabView
App-side changes:
- Added "Get Started" / "Continue" next buttons to all onboarding pages
  (Welcome, Day, Time, Style) with onboarding_next_button accessibility ID
- Added onNext callback plumbing from OnboardingMain to each page
- OnboardingMain now uses TabView(selection:) for programmatic page navigation
- Added .accessibilityElement(children: .contain) to all onboarding pages
  to fix iOS 26 paged TabView not exposing child elements
- Added settings_segmented_picker accessibility ID to Settings Picker
- Reduced padding on onboarding pages to keep buttons in visible area

Test-side changes:
- OnboardingScreen: replaced unreliable swipeToNext() with tapNext()
  that taps the accessibility-identified next button
- OnboardingScreen: multi-strategy skip button detection for subscription page
- SettingsScreen: scoped segment tap to picker element to avoid tab bar collision
- CustomizeScreen: simplified horizontal scroll to plain app.swipeLeft()
- OnboardingVotingTests: uses tapNext() to advance to Day page

Passing: OnboardingTests.CompleteFlow, OnboardingVotingTests
Remaining: OnboardingTests.DoesNotRepeat (session state issue),
  Settings scroll (deep elements), Customize horizontal pickers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 18:37:17 -05:00
Trey T
d97db4910e Rewrite all UI tests following fail-fast TEST_RULES patterns
Rewrote 60+ test files to follow honeydue-style test guidelines:
- defaultTimeout=2s, navigationTimeout=5s — fail fast, no long waits
- No coordinate taps (except onboarding paged TabView swipes)
- No sleep(), no retry loops
- No guard...else { return } silent passes — XCTFail everywhere
- All elements by accessibility ID via UITestID constants
- Screen objects for all navigation/actions/assertions
- One logical assertion per test method

Added missing accessibility identifiers to app views:
- MonthView.swift: added AccessibilityID.MonthView.grid to ScrollView
- YearView.swift: added AccessibilityID.YearView.heatmap to ScrollView

Framework rewrites:
- BaseUITestCase: added session ID, localeArguments, extraLaunchArguments
- WaitHelpers: waitForExistenceOrFail, waitUntilHittableOrFail,
  waitForNonExistence, scrollIntoView, forceTap
- All 7 screen objects rewritten with fail-fast semantics
- TEST_RULES.md added with non-negotiable rules

Known remaining issues:
- OnboardingTests: paged TabView swipes unreliable on iOS 26 simulator
- SettingsLegalLinksTests: EULA/Privacy buttons too deep in DEBUG scroll
- Customization horizontal picker scrolling needs further tuning

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 17:00:30 -05:00
Trey t
8231750cff Simplify guided reflection keyboard toolbar to dismiss-only icon
Remove Back/Next/Done buttons from keyboard toolbar to eliminate
confusion with the bottom action bar. Toolbar now shows only a
keyboard.chevron.compact.down dismiss icon.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 14:38:23 -05:00
Trey T
8ae8d23f95 Add mood-specific selectable chip answers to guided reflection flow
Reduces friction in the guided reflection by offering predefined tappable
chip answers tailored to each mood category's therapeutic framework:
- Positive (Behavioral Activation): savoring emotions + reinforcing actions
- Neutral (ACT Cognitive Defusion): ambivalent feelings + defusion reframes + values
- Negative (CBT Thought Record): automatic negative thoughts + compassionate reframes + grounding actions

Chips appear between the question and text editor. Tapping toggles selection
and auto-fills the text field. "More" expander reveals additional options.
Free text always remains available alongside chips.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:37:55 -05:00
Trey t
751369bca2 Add redeem code button to subscription store
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:11:09 -05:00
Trey t
0f128da154 Allow PDF data export when AI is unavailable on Reports screen
Users without Apple Intelligence can now export their mood data as a
visual PDF with charts and statistics instead of seeing a disabled
Generate button. The existing ExportService.exportPDF is reused for
the non-AI path, gated behind the same privacy confirmation dialog.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:04:50 -05:00
Trey t
c7f05335c8 Move weather into entry detail date header
Display weather inline next to the date in a compact HStack layout
(icon | condition + temps) instead of a separate Weather section.
Removes the standalone weatherSection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:53:30 -05:00
Trey t
99314b8e6a Add CBT-based guided reflection questions with clinical info sheet
Replace generic journaling prompts with evidence-based therapeutic
techniques: CBT thought record for negative moods, ACT cognitive
defusion for neutral, and behavioral activation for positive. Each
question now shows a clinical step label (e.g. SITUATION, REFRAME).
Added info button linking to a new sheet explaining the techniques
with citations to Beck, Harris, and Martell/Dimidjian.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:39:30 -05:00
Trey t
a10a1eae6f Merge fix_sub into main
Brings subscription state fixes and version 1.0.2 bump.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:17:55 -05:00
Trey t
c3e70d34b2 Fix subscription state not updating after purchase or cancellation
- Add force parameter to checkSubscriptionStatus to bypass 5-minute
  throttle when called from transaction listener, purchase completion,
  and restore purchases
- Remove early return for expired/revoked states that prevented
  fallback to trial
- Only trust cached subscription expiration when offline (products
  failed to load); when StoreKit returns products successfully, treat
  the live entitlement check as authoritative
- Add debug logging throughout IAP state machine for diagnostics

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:07:08 -05:00
Trey t
6a8a66546b Enrich test data, fix multi-page PDF export, and polish UI
- Populate debug test data with random notes, guided reflections, and weather
- Fix PDF export to use UIPrintPageRenderer for proper multi-page pagination
- Add journal/reflection indicator icons to day list entry cells
- Fix weather card icon contrast by using secondarySystemBackground
- Align Generate Report and Export PDF button widths in ReportsView

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 18:19:01 -05:00
Trey t
78d09803c3 Fix location/weather error handling and complete localization
Add authorization pre-check and 15s timeout to LocationManager to
prevent hanging continuations. WeatherManager now skips retry queue
when location permission is denied. Settings weather toggle shows
alert directing users to Settings when location is denied. Fill
remaining 32 untranslated strings to reach 100% localization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:37:28 -05:00
Trey t
5bd8f8076a Add guided reflection flow with mood-adaptive CBT/ACT questions
Walks users through 3-4 guided questions based on mood category:
positive (great/good) gets gratitude-oriented questions, neutral
(average) gets exploratory questions, and negative (bad/horrible)
gets empathetic questions. Stored as JSON in MoodEntryModel,
integrated into PDF reports, AI summaries, and CSV export.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 15:52:56 -05:00
Trey t
19b4c8b05b Add AI mood report feature with PDF export for therapist sharing
Adds a Reports tab to the Insights view with date range selection, two report
types (Quick Summary / Detailed), Foundation Models AI generation with batched
concurrent processing, and clinical PDF export via WKWebView HTML rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 10:13:54 -05:00
Trey t
31fb2a7fe2 Add weather feature with WeatherKit integration for mood entries
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>
2026-03-11 00:16:26 -05:00
Trey t
45d83cff89 Redesign haptic patterns per animation and play on selection
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>
2026-03-10 16:43:29 -05:00
Trey t
24a1a7b072 Fix tunnel animation icon and add missing localizations
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>
2026-03-10 16:32:25 -05:00
treyt
1303cb8cbc fix: issue #150 - add haptic feedback option
Automated fix by Tony CI v3.
Refs #150

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-10 16:13:08 -05:00
Trey t
83cca395cf Fix feature card truncation and unequal sizing on subscription screens
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>
2026-02-28 13:50:47 -06:00
Trey t
675547db76 Fix subscription screen hanging on "Loading Subscription"
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>
2026-02-28 11:54:41 -06:00
Trey t
6ce7c508ed Fix subscription screen: use product IDs and add close button
- 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>
2026-02-28 11:13:01 -06:00
treyt
b1713337f6 fix: issue #146 - make trial always says days on every trial banner in the app
Automated fix by Tony CI v3.
Refs #146

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-27 13:00:53 -06:00
Trey t
3a4e60587a Fix production crash points, actor-isolation warnings, and rebrand URLs
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>
2026-02-26 19:31:10 -06:00
Trey t
0442eab1f8 Rebrand entire project from Feels to Reflect
Complete rename across all bundle IDs, App Groups, CloudKit containers,
StoreKit product IDs, data store filenames, URL schemes, logger subsystems,
Swift identifiers, user-facing strings (7 languages), file names, directory
names, Xcode project, schemes, assets, and documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 11:47:16 -06:00
Trey t
36be57e47d Move vote animation to Customize tab as persistent user setting
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>
2026-02-24 11:47:40 -06:00
Trey t
4851eee5f8 Fix paywall width overflow on iOS 18, update onboarding tip from Yesterday to Today
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>
2026-02-23 21:21:41 -06:00
Trey t
b2b6931d7c Lower deployment target from iOS 26 to iOS 18, gate Foundation Models behind @available
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>
2026-02-23 20:21:45 -06:00
Trey t
7660521540 Move Animation Lab to release settings, Add Test Data to debug, fix localization to 100%
- 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>
2026-02-23 19:12:52 -06:00
Trey t
c701bf9d3b Add 3 passing UI tests (batch 7): insights collapse, pull-to-refresh, share no data
- TC-046: Insights section collapse/expand via header tap
- TC-047: Pull-to-refresh gesture on Insights tab
- TC-119: Share with empty data handles gracefully
- Added accessibility IDs to InsightsSectionView sections and MonthView share button
- Marked 6 tests RED: TC-040 (DEBUG triple-tap), TC-041 (dead code),
  TC-091 (DEBUG paywall lab), TC-113/114/115 (SharingListView dead code)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:50:46 -06:00
Trey t
537f8621c6 Add 3 passing UI tests (batch 5): heatmap, reduce motion, high contrast
- 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>
2026-02-20 10:19:55 -06:00
Trey t
6d1f54f451 Add 3 passing UI tests (batch 4): personality pack, Spanish locale, accessibility text size
- TC-052: Personality pack selection in Customize tab with accessibility IDs
- TC-137: Spanish localization verification (Ajustes, tab labels)
- TC-142: App navigable at XXL accessibility text size

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:15:20 -06:00
Trey t
599e54aa72 Add 5 passing UI tests (batches 1-2) and mark 4 blocked tests RED
Batch 1: TC-035 (donut chart), TC-036 (bar chart) — Year View stats
Batch 2: TC-037 (collapse/expand), TC-065 (privacy link), TC-066 (EULA link)
Blocked: TC-124, TC-068 (Settings ScrollView tap issue), TC-038 (share sheet)

New accessibility IDs: bypass subscription toggle, EULA, privacy policy buttons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 10:02:17 -06:00
Trey t
5895b387be Refactor ZStack layouts to .background(), add Year View accessibility IDs, triage QA test plan
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>
2026-02-20 09:17:52 -06:00
Trey t
c22d246865 Fix 25 audit issues: memory leaks, concurrency, performance, accessibility
Address findings from comprehensive audit across 5 workstreams:

- Memory: Token-based DataController listeners (prevent closure leaks),
  static DateFormatters, ImageCache observer cleanup, MotionManager
  reference counting, FoundationModels dedup guard
- Concurrency: Replace Task.detached with Task in FeelsApp (preserve
  MainActor isolation), wrap WatchConnectivity handler in MainActor
- Performance: Cache sortedGroupedData in DayViewViewModel, cache demo
  data in MonthView/YearView, remove broken ReduceMotionModifier
- Accessibility: VoiceOver support for LockScreen, DemoHeatmapCell
  labels, MonthCard button labels, InsightsView header traits,
  Smart Invert protection on neon headers

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:11:48 -06:00
Trey t
56ac783219 Stabilize iOS UI test foundation and fix flaky suites 2026-02-17 22:24:08 -06:00
Trey t
8845ccfd1b Fix cascading crash and remaining UI test failures
- 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>
2026-02-17 19:57:03 -06:00
Trey t
31dfd9cc68 Fix build: use AccessibilityID.Customize (not Settings) for browseThemesButton
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 16:54:03 -06:00
Trey t
224341fd98 Fix remaining 17 UI test failures: group defaults, identifiers, hittability, date format
- 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>
2026-02-17 16:46:18 -06:00
Trey t
44b46f88e2 Fix 23 failing UI tests: accessibility hierarchy, test mode, and interaction issues
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>
2026-02-17 16:14:16 -06:00
Trey t
79a16fb476 Fix UI tests: remove tab content accessibility identifiers that override child identifiers
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>
2026-02-17 15:42:23 -06:00
Trey t
7f27446b94 Fix 8 audit items: remove force-unwraps, improve accessibility and concurrency
- 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>
2026-02-17 11:42:16 -06:00
Trey t
277e277750 Add XCUITest suite with 27 test files covering unmapped P1 test cases
- 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>
2026-02-17 09:37:54 -06:00
Trey t
7639f881da Add debug bypass subscription toggle, tests, and data layer improvements
- 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>
2026-02-15 17:12:56 -06:00
Trey t
7c142568be Fix boundary bugs, route side effects through MoodLogger, add data listeners
- 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>
2026-02-14 23:34:09 -06:00
Trey t
f1cd81c395 Fix 7 data mutation layer risks identified in audit
- 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>
2026-02-14 23:09:11 -06:00
Trey t
9c4e0a35a6 Add privacy policy and EULA pages, update settings URLs
- 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>
2026-02-10 15:50:53 -06:00
Trey t
e0330dbc8d Replace EventLogger with typed AnalyticsManager using PostHog
Complete analytics overhaul: delete EventLogger.swift, create Analytics.swift
with typed event enum (~45 events), screen tracking, super properties
(theme, icon pack, voting layout, etc.), session replay with kill switch,
autocapture, and network telemetry. Replace all 99 call sites across 38 files
with compiler-enforced typed events in object_action naming convention.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 15:12:33 -06:00
Trey t
65460c63b3 Add app icon asset, screenshot exporter, and misc updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 09:31:01 -06:00