- Crashlytics: add FirebaseCrashlytics framework + dSYM upload build phase
- Onboarding: useSampleData off by default, Add First Investment as primary CTA
- AddSourceView: contextual placeholder and footer explaining what a source is
- Charts: CompactPaywallBanner visible to free users on every visit
- Notifications: re-engagement (7d) and monthly check-in local notifications
- Paywall: decorative chart preview replacing static crown icon
- Localization: all new strings in en + es-ES
iCloud sync:
- Force viewContext.refreshAllObjects() on remote change notifications so
data from other devices is picked up immediately without app restart
- Call refreshFromCloudKit() on foreground to merge any changes made while
the device was inactive
- Wait up to 10s for initial CloudKit sync on launch before showing onboarding
(shows "Checking iCloud..." during the wait)
- New OnboardingICloudCheckView: shown on fresh installs with iCloud available,
lets user restore from iCloud before starting onboarding from scratch
Localization:
- Added de, fr, it, ja, pt-BR lproj folders
- New iCloud onboarding strings in en + es-ES (+ button literals)
ASO metadata (fastlane):
- Updated en-US: new subtitle, keywords, description (fixed "no cloud sync"
claim), promotional text, release notes
- Added full metadata for es-ES, de-DE, fr-FR, it, ja, pt-BR (63 files total)
- All keyword fields validated ≤100 Unicode chars
Infrastructure:
- Gemfile + Gemfile.lock for fastlane
- Scripts/archive_and_upload_appstore.sh for CI/CD
Version: 1.2.1 (build 7)
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
BatchUpdateView now accepts a saveDate parameter. When saving from a past-month
check-in, the call site passes referenceDate.endOfMonth so snapshots are dated
within the correct month instead of today. For the current month, Date() is used.
Widget forward-fills missing month buckets (trend and category series) using the
most recent earlier month's value, preventing gaps when a check-in is done in the
following month.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Period now starts at startOfMonth of the first month in the interval,
not 30 days before the deadline. For monthly: Feb 1 → Feb 28.
For quarterly: Jan 1 → Mar 31. Formula: startOfMonth(nextDate - (interval-1) months).
Feb 20 with next check-in Feb 28: 19/27 days ≈ 70% instead of 0%.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous logic measured elapsed days from lastCompletionDate to nextCheckInDate,
so completing a check-in today reset the bar to 0/8 days instead of showing
how far through the full monthly period we are.
New logic: the bar represents the full interval (e.g. 1 month) ending at
nextCheckInDate, starting from nextCheckInDate minus that interval.
Today (Feb 20) with next check-in Feb 28 now shows ~74% progress
(23 of 31 days elapsed since Jan 28) instead of 0%.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- OnboardingView: wrap page titles/descriptions with String(localized:)
using symbolic keys so SwiftUI can look them up correctly
- IAPService.paywallBenefits: change from static let to static var,
wrap all strings with String(localized:) using symbolic keys
- en.lproj: add symbolic keys for new onboarding pages and paywall benefits
- es-ES.lproj: add Spanish translations for all new keys (onboarding pages,
paywall benefits, batch update, contribution fields) plus pre-existing
gaps (Monthly Highlights, Best/Worst Performer, Best Contributor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AddSnapshotView: restore inputMode == .detailed guard for contribution section.
BatchUpdateView: show contribution field per row only when the source's
account is configured with inputMode == .detailed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BUG FIX: parseDecimal ignored locale mismatch between currency and device.
CurrencyFormatter.locale(for: "EUR") could return any EUR locale (e.g.
en_IE with decimal='.'), causing "408857,62" to be parsed as 40,885,762.
New CurrencyFormatter.parseUserInput() uses digit-position detection:
a separator followed by ≤2 digits at the end is decimal, otherwise
it is a thousands separator. Fully locale-independent.
FEATURE: Contribution field now always visible in AddSnapshotView.
Previously gated behind inputMode == .detailed; now a toggle available
regardless of account mode.
FEATURE: BatchUpdateView pre-fills each text field with the source's
current value so the user only edits what changed. Adds an optional
contribution field per source row, persisted on save.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Onboarding: replace feature-focused slides with outcome-focused copy
("Know exactly where you stand", "5 minutes a month is enough", etc.)
- Paywall: non-scrollable layout, reduce from 8 to 4 key benefits,
remove transactional language (Unlock/Upgrade/Premium),
new CTA "Get Full Access", floating close button
- Add IAPService.paywallBenefits for the condensed 4-item paywall list
- Update CompactPaywallBanner and PremiumLockOverlay copy
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove unnecessary optional binding for non-optional source.id
- Break up AllocationEvolutionChart body to help Swift type-checker
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces the simple progress bar with a custom milestone bar showing
individual circles for each achievement, filled when unlocked with a
checkmark indicator.
Fixes#27
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a "Show Forecast" toggle in Settings > Long-Term Focus section.
When disabled, hides the forecast from the total portfolio card and
removes the prediction chart type from the charts tab.
Fixes#26
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a stacked area chart under the Allocation tab that displays how the
portfolio allocation percentages have changed across months.
Fixes#25
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds multi-source selection to the evolution chart source filter.
Users can now tap multiple sources to compare their evolution side by side,
regardless of which category they belong to.
Fixes#24
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When toggling Face ID off, users must now verify their PIN first.
Adds a PinVerifyView component for PIN verification.
Fixes#23
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows a highlights card with the best and worst performing sources by
percentage change, displayed between the summary and reflection cards.
Fixes#22
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a source has been updated this cycle, shows the value change from the
previous snapshot in green (increase) or red (decrease).
Fixes#21
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds chevron buttons to navigate between months, similar to Lose It Log view.
The next month button is disabled when already at the current month.
Fixes#20
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows a warning-colored banner when sources need updating, with an X to dismiss.
The existing Pending Updates section lower in the dashboard remains unchanged.
Fixes#18
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces confirmationDialog with a custom sheet for better title styling.
Increases share icon trailing padding in TotalValueCard.
Fixes#17
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>