The Problem
The codebase is functionally complete but carries measurable structural debt that slows future changes and introduces avoidable risk. Six‑level deep nesting in core UI and database modules makes control flow hard to follow, the test suite covers only 2 % of source files, and CI workflows inherit overly‑permissive GitHub‑token rights and use unpinned third‑party actions. These issues raise the cost of each feature or bug fix and increase the surface for supply‑chain incidents.
What This Does
FoodYou is a privacy‑first food‑diary and nutrition tracker built with Jetpack Compose and Kotlin. The app’s core data flow starts at app/src/commonMain/kotlin/com/maksimowiczm/foodyou/app/FoodYouApp.kt, which sets up Koin dependency injection via app/di/AppModule.kt and app/di/InitKoin.kt. From there navigation is provided by app/navigation/FoodYouAppNavHost.kt and app/navigation/DownloadProductAppNavHost.kt, feeding composable screens such as the home screen, diary entry, and export/import views.
Database operations live in app/src/commonMain/kotlin/com/maksimowiczm/foodyou/app/infrastructure/room/FoodYouDatabase.kt and its migration files (.../migration/*.kt). The Room module (app/src/commonMain/.../RoomModule.kt) exposes DAOs for foods, diary entries, and nutrition targets. UI screens such as ExportProductsViewModel.kt and ImportCsvProductsViewModel.kt read/write CSV‑based data, while ExternalDatabasesViewModel.kt coordinates connections to Open Food Facts and USDA APIs.
Resource files under app/src/commonMain/composeResources/files/meals/ provide multilingual food composition data, and the shared/barcodescanner module supplies barcode‑driven food lookup. The app’s theming and typography are defined in app/src/commonMain/.../theme/FoodYouTheme.kt and BrandTypography.kt.
How It Is Wired
- Entry point:
MainActivity.kt(androidMain) launches the Compose‑based UI; theFoodYouApplication.ktinitializes Koin and theFoodYouLogger. - Dependency graph: 602 Kotlin files were analyzed; the import graph shows 0 internal modules and 0 circular dependencies, meaning each module is relatively isolated but also requires explicit wiring via Koin.
- Key call paths: 1.
FoodYouApp.kt→InitKoin.kt→AppModule.ktprovidesKoinComponentinstances. 2. ViewModels (ExportProductsViewModel.kt,ImportCsvProductsViewModel.kt) depend onFoodYouDatabaseandDataStoreModule.android.kt. 3. Database migrations (FoodYou3Migration.kt,FoodSearchFtsMigration.kt) run on app start; 32 schema files (.../schemas/*.json) define the evolution path. 4. Network calls to Open Food Facts and USDA are mediated byExternalDatabasesModule.ktand respective login dialogs. - Blast‑radius hubs:
DeveloperActivity.ktandSecureActivityTest.kteach exhibit max indentation depth 8, indicating deeply nested control flow that widens the impact of any change.
How To Use It
Setup
# Clone the repo (verbatim URL)
git clone https://github.com/moses-y/FoodYou.git
# Build the release APK (Gradle wrapper)
./gradlew assembleRelease
The README does not list environment variables, but the app integrates Open Food Facts and USDA APIs; keys should be placed in res/xml/locales_config.xml or supplied via Gradle defaultConfig flavor variables (not currently documented).
Running the app
- Install the debug APK:
./gradlew installDebug - Launch the app; the home screen (
ModularHomeScreen) lets users add meals, view nutrition targets, and export/import CSV records.
Configuration
- API keys for Open Food Facts and USDA are referenced in
app/src/main/res/xml/locales_config.xml; add your credentials there or override via Gradleextproperties.
Real‑World Use
A user opens the app, selects “Add meal,” scans a barcode (via FullScreenCameraBarcodeScanner.kt), and the selected food’s nutrients are instantly added to the diary (ImportCsvProductsViewModel.kt). The view model updates UiState.kt, which drives the Compose UI to display calories, macros, and selected vitamins. When the user chooses “Export CSV,” ExportProductsViewModel.kt writes the current diary to app/src/main/res/xml/backup_rules.xml‑compatible format, storable locally or synced via a personal cloud.
Code Health & Issues
- Cognitive‑load (HIGH) – Deep nesting x60 in
DeveloperActivity.kt,SecureActivityTest.kt,ExportProductsViewModel.kt; max indentation depth 8 makes flow hard to follow. Fix: flatten with guard clauses / extract inner blocks. - GitHub Actions pinning (HIGH) –
.github/workflows/release-apk.ymlusesandroid-actions/setup-android@v3without a commit SHA; a tag move could execute arbitrary code with repo secrets. Fix: pin to 40‑char SHA and let Dependabot bump. - GITHUB_TOKEN permissions (MEDIUM) – Two workflows declare no
permissions:; the token inherits repo defaults, allowing steps to push or mint releases. Fix: addpermissions: contents: readat the top and widen per‑job. - Persist‑credentials (MEDIUM) –
.github/workflows/docs.ymlcheckout keeps the token for later steps; a malicious post‑install script could read pushable credentials. Fix: addwith: persist-credentials: falseand pass an explicit token only to the push step. - Test coverage (MEDIUM) – 13 test files vs 605 source files (ratio 0.021); a green badge may mask untested paths. Fix: add tests for highest‑fan‑in modules first.
- Job timeouts (LOW) – Three workflows (
docs.yml,release‑apk.yml,validate‑meals.yml) have notimeout-minutes; a wedged step could run six hours, overlapping scheduled runs. Fix: set realistictimeout-minutesper job.
The Bottom Line
FoodYou delivers a solid, privacy‑first nutrition‑tracking experience with a modular UI and multilingual food databases, but the codebase suffers from deep nesting, sparse testing, and CI security gaps. Teams comfortable with Kotlin/Compose can extend features quickly, yet anyone planning sustained maintenance should allocate time to flatten control flow, broaden test coverage, and pin third‑party actions. It is well‑suited for individual users or small organizations that value local data storage and are willing to invest in the listed code‑health improvements.