- 151: contribución editable por snapshot en cualquier modo (quitado gate detailed)
con diálogo de propagación al editar: solo este / adelante / atrás / todos
(SnapshotRepository.propagateContribution, SnapshotFormViewModel.contributionChanged)
- 148: Period vs Period mostraba mal el último mes del period B — la agrupación usaba
chartMonth(for:) que aplicaba el grace-period del check-in a snapshots históricos;
ahora agrupa por mes calendario crudo
- 152: iPad Sources no saltaba entre fuentes — añadido .id() al SourceDetailView para
recrear el StateObject al cambiar de selección
- 146/147: Year vs Year con forecast del año en curso (asterisco de estimado) y KPIs
arriba / detalle debajo
- 145: card de contribución mensual en SourceDetailView
- Nuevas claves snapshot_contribution_propagate_* en los 7 idiomas
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015qUZrBusG82T37R7PeokqJ
- Compare (free): multi-source overlay chart, Base 100 / Return % / Value modes,
chip selector, reactive to time range filter
- What If (premium): allocation simulator with sliders per source, dual-line chart
actual vs simulated indexed to 100, orange warning when weights ≠ 100%
- Period vs Period (free): date-picker-driven comparison of any two custom periods,
return % normalized from month 1 = 0%, color-coded legend with period labels
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- completedMonthKeys: remove UserDefaults-based MonthlyCheckInStore check (not synced via iCloud)
- MonthlyCheckInCard.effectiveLastCheckInDate: use max() instead of ?? to prefer newer synced snapshot date
- MonthlyCheckInView.lastCompletionDate: use max() of local + latest CoreData snapshot via @FetchRequest
- FirebaseService.logPaywallShown: fix parameter key to paywall_trigger (matches GA4 custom dimension)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 1A: Notificación mensual de resumen de portfolio (día 5 de cada mes)
- 1B: Badge de racha mensual en Dashboard (streak counter)
- 1C: Empty states mejorados en Goals y Journal con CTAs claros
- 2A: Quick Update sheet — actualiza todas las fuentes desde una pantalla
- 2B: Notificación batch update redirige al Quick Update sheet
- 2C: Widget deep link portfoliojournal://quickupdate abre Quick Update
- 3A: App Store version check banner en Settings
- 3C: What's New sheet en primer launch de versión nueva
- Localización completa en 7 idiomas para todas las nuevas strings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>