The native Kotlin/Compose app is replaced by a Capacitor shell that
loads the existing Svelte web app from the self-hosted server URL,
set via APP_SERVER_URL secret at build time.
- web/capacitor.config.ts: appId com.danvics.calorieai, reads
APP_SERVER_URL env var so the WebView points at the live server
- web/android/: Capacitor-generated Android project (gradlew included)
- AndroidManifest.xml: added CAMERA, READ_MEDIA_IMAGES, READ_EXTERNAL_STORAGE
- MealForm.svelte: split file input into Camera (capture=environment)
and Gallery buttons so both options are accessible natively
- release.yml: npm ci → npm run build → cap sync → gradlew assembleDebug;
removed manual Gradle installation, uses bundled gradlew instead
- package.json: Capacitor packages as devDependencies (not shipped in
the Docker server image)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All generated and tuned plans now share the title "Weight-loss plan"
with version number tracked separately, matching the PlansPage display
which already shows "Version N" beneath the title.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Web: buildTodayHistory() computes today's logged meals and passes them
to requestMealEstimate so the AI can give personalized notes
- Web: system prompt updated to instruct AI to use notes field for
dietary observations (macro balance, variety, goal progress)
- Android: same diet history + notes guidance already applied to MainActivity
- Tests: fix NutritionParserTest to use exact key names (proteinGrams,
carbsGrams, fatGrams) matching the standardised AI prompt format
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- NutritionParser now handles short key aliases (protein/carbs/fat instead of
proteinGrams/carbsGrams/fatGrams), string-typed numbers, surrounding prose,
and multi-line markdown fences reliably
- safeInt/safeDouble helpers check multiple key names in priority order and
handle Number, String, and missing values without throwing
- Nutrition prompt now includes an explicit JSON example so all models return
the expected format regardless of their default style
- Same fixes applied to web app parseEstimate (aliases + fence stripping)
- Extended NutritionParserTest to cover aliases, string numbers, surrounding text
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace TakePicturePreview with TakePicture + FileProvider for reliable full-res camera capture
- Add FileProvider to manifest with cache-path for camera photos
- Show selected photo as a thumbnail preview in the Log screen
- Replace plain date/time text fields with clickable fields that open native Android pickers
- After AI analysis or manual edit save, auto-navigate to Dashboard so results are visible immediately
- Clear editing/image state after successful save so Log screen resets for next entry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Image reading moved to IO thread with runCatching to prevent main thread crash and OOM on large gallery images
- 7-day calorie bar chart added to dashboard using Canvas
- Version bumped to 1.2 (code 3)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ConnectScreen:
- Keyboard types: Uri for URL, Password for password
- IME chain: Next→Next→Done across all three fields
- Pressing Done on password submits the form
- Password visibility toggle (show/hide button)
PlansScreen:
- Delete plan now requires confirmation dialog
- Plan content bumped to bodyMedium (was too small)
- Plan history uses Card with primaryContainer highlight for active plan
- "Active" badge on selected plan instead of just bold text
SettingsScreen:
- "Profile saved" status auto-clears after 3 seconds
CalorieAiApp:
- Top bar title shows "Edit meal" when editing an existing entry
DiaryScreen:
- "Deselect" button next to "Trash" when items are selected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Single "Add photo" button opens a ModalBottomSheet with camera
and gallery options, matching standard mobile UX patterns.
Switches to material-icons-extended for CameraAlt/PhotoLibrary icons.
Button label changes to "Change photo" once an image is selected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Android:
- Add adaptive app icon (blue background, white flame foreground)
- Add android:icon and roundIcon references to manifest
- Add windowSoftInputMode=adjustResize for keyboard handling
- Dark mode support via isSystemInDarkTheme() in Theme.kt
- Bump versionCode 1→2, versionName 1.0→1.1, named APK output
- Merge Trash into Diary as a tab (was a 6th bottom-nav item)
- Add sync refresh button in top bar with loading indicator
- Add CalorieGoalBar progress indicator on dashboard
- Add calorieTarget to ServerSettings, Settings screen, and API
- Add clearTrash() to ApiRepository (server route was unused)
- Fix onCancelEdit to also clear selected image state
- AiClient.kt: remove old pre-server AiClient class (replaced by ApiRepository)
- LogMealScreen: side-by-side field rows, DropdownField for meal type
Web server:
- Add calorieTarget to settings defaults and allowed field list
- Remove dead handleRequest() function (never called, Express routes it)
CI:
- Fix APK paths in android.yml and release.yml for renamed output
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>