DonutChart was hardcoded to a 180dp Canvas. When placed in a 50/50 Row
inside the "Where it went" card on the S24 Ultra, the canvas overflowed
the parent column and clipped into an oval. Switched to
fillMaxWidth + aspectRatio(1f) + fillMaxSize Canvas so the donut always
stays circular and scales to whatever the parent gives it. Stroke width
also scales (18% of the box, capped at 32dp).
Home screen lost the Today / This Week / Month period selector in the
bento rewrite (HomeViewModel still exposed it, the UI just never
rendered it). Restored as a LedgaChip row above the hero card. The
hero overline now also tracks the selection ("SPENT TODAY" /
"SPENT THIS WEEK" / "SPENT THIS MONTH").
MIGRATION_1_2 was using ALTER TABLE to add transactions.accountId, but
SQLite can't add a FOREIGN KEY via ALTER. Room validates schema after
migration and threw IllegalStateException ("Migration didn't properly
handle: transactions") because the FK to mpesa_accounts was missing.
The whole DB stayed at v1, blocking every read/write — which is why
SMS import + SMS receive looked dead too.
Fix: standard SQLite table-swap dance. Create transactions_new with
both FKs declared, INSERT … SELECT old rows in, drop the old table,
rename. All indices recreated. Defensive DROP IF EXISTS in case a
prior failed run left junk.
BentoCard now picks title + overline colors from the tonal background
luminance instead of unconditionally using onSurface. On dark theme
the Insights teaser had near-white text on the (light-theme) pale
green bg — invisible. Now it adapts:
- light tonal bg → dark ink
- dark tonal bg → light ink
HomeScreen Insights teaser switched from hardcoded LedgaAccentSoft to
MaterialTheme.colorScheme.primaryContainer so the bg itself also
adapts to theme.
- LedgaTopBar now applies WindowInsets.statusBars padding. Previously
enableEdgeToEdge was on but the top bar drew at y=0, so the avatar
and trailing icons sat under the system clock / WiFi indicator.
- PillTabBar uses WindowInsets.navigationBars padding instead of a
hardcoded 21dp bottom so the floating pill sits above the system
gesture pill on devices like the S24 Ultra.
- Typography switched from Google-Fonts Inter to FontFamily.SansSerif.
Inter requires a downloadable-fonts round-trip via Google Play
Services that doesn't always succeed; the fallback was hitting
FontFamily.Default, which inherits the user's system font choice —
on Samsung One UI that's frequently a handwritten / script style
and broke the type rhythm everywhere. SansSerif uses the platform
sans (One UI Sans on Galaxy, Roboto elsewhere) regardless of user
preference.
Settings > Data now has "Re-parse Unparsed Messages" button that
re-runs the fixed parser on all UNKNOWN transactions, properly
categorizing previously missed Fuliza auto-deductions, withdrawals,
airtime, and reversals.
Complete Android app (Kotlin/Jetpack Compose) with:
- SMS parser for all 17 M-Pesa transaction types
- Room database with auto-categorization engine
- Real-time SMS capture via BroadcastReceiver
- Onboarding flow with SMS history import
- Home dashboard with balance, spending, donut chart
- Transactions list with search, filters, day grouping
- Trends screen with Vico bar charts, top merchants
- Budget system with progress tracking
- Transaction detail sheet with re-categorization
- Notifications (daily/weekly summaries, budget alerts)
- Google Drive backup & restore
- Manual export/import (CSV + JSON ZIP)
- Self-update system via GitHub Releases API
- Theme system (System/Light/Dark) + font scaling
- Adaptive app icon with splash screen
- GitHub Actions CI/CD for release APK builds