Commit Graph

2 Commits

Author SHA1 Message Date
Mike Kell 51364a8f4f feat(platform,tests,ci): complete Phase 6 cross-platform hardening, integration tests, and Forgejo CI/CD
- Harden HealthGateway: kIsWeb/defaultTargetPlatform/dart:io guards, Health
  Connect SDK availability probe with graceful degradation, READ_WEIGHT/
  READ_STEPS/READ_TOTAL_CALORIES_BURNED permission validation before reads,
  HealthKit entitlement failures contained (false + debug warning), and a
  desktop/web fallback that serves locally logged biometrics through the new
  ILocalBiometricReader contract (drift-backed adapter wired in health_sync).
- Platform-safe CryptoManager vault: EncryptedSharedPreferences (Android),
  Keychain first_unlock (iOS/macOS), DPAPI-sealed file (Windows), libsecret
  (Linux); vault failures degrade to an ephemeral in-memory SQLCipher key.
- Declare the four Health Connect READ_* permissions in AndroidManifest.xml.
- Extract isAuthenticatedProvider so integration tests can simulate auth
  sessions without booting Supabase.
- Add 24 tests (99 -> 123): steady-state PK suite (Semaglutide 168h /
  Tirzepatide 120h geometric series, superposition, titration, washout),
  real-world recipe JSON-LD fixtures (BBC-style root, AllRecipes @graph),
  pantry unit-conversion group (kg/g, l/ml, dimension guard, synonyms),
  app navigation integration tests (rail + bar, authenticated + dev-bypass
  + unauthenticated), and reactive nutrition progress-bar widget tests.
- Fix NutritionScreen narrow-width overflows: Flexible protein title and
  Wrap action buttons stack cleanly on compact phones.
- Add .forgejo/workflows/ci.yml for git.kellsupport.com/mtkell/glp-companion
  (push to main + PRs, Flutter container: checkout, mock .env, pub get,
  build_runner, analyze --fatal-infos, test --coverage, build bundle + web).
- Remove dead lib/features/recipes/data/recipe_scraper.dart; rewrite
  README.md (architecture, dev setup, SQLCipher details, CI docs); add
  .env.example; allow it through .gitignore; update BUILD_STATE.md with
  Phase 6 deliverables and complete Phases 1-6 checklist.

Verified: build_runner 44 outputs, flutter analyze --fatal-infos clean,
flutter test 123/123, flutter build web and flutter build bundle succeed.
2026-10-16 14:59:15 -04:00
Mike Kell bdee2de35f feat(meal_planner): complete Phase 4 recipe scraper and meal planning calendar
Domain (pure Dart):
- Add Recipe, MacroProfile, and RecipeIngredient entities (quantity/unit/
  item parsing: decimals, ASCII/unicode/mixed fractions, known-unit
  vocabulary) plus MealPlanSlot reusing the nutrition MealType enum
- Define IRecipeRepository and IMealPlanRepository contracts
- Add ScrapeRecipeFromUrl use case: package:http download with injectable
  fetcher, package:html DOM parse, JSON-LD @graph/root/array/list-@type
  navigation, HowToStep/HowToSection flattening, ISO-8601 prep/cook times,
  recipeYield, regex nutrition parsing, OpenGraph fallback, and typed
  RecipeScrapeException
- Add core/utils/uuid.dart RFC-4122 v4 generator (no new dependency)

Data:
- Bump AppDatabase to schema v3 (migration for v1/v2 installs) with
  RecipesTable (UUID PK, JSON ingredient/instruction columns, macros) and
  MealPlanSlotsTable (UUID PK, nullable recipeId FK ON DELETE SET NULL)
- Implement DriftRecipeRepository (URL-deduplicated importRecipe, createdAt
  preserved on re-import) and DriftMealPlanRepository (half-open [from, to)
  window, upsert by id)

Presentation:
- Add RecipeImportController (URL submit -> loading -> preview modal state,
  live catalog watch stream, confirm-save/dismiss/delete) and
  MealPlanCalendarController (Monday-Sunday window navigation, slot
  assign/upsert/clear, prepared toggles, per-day protein rollup against the
  100 g target, deleted-recipe slot normalization)
- Rework MealPlannerScreen: URL import bar with spinner, RecipePreviewDialog
  (macros, ingredients, steps, save with error surface), draggable
  SavedRecipesTray with protein badges, responsive WeeklyCalendarView
  (>=900 dp: 7-column grid, below: tabbed pager) with DragTarget slots and
  daily protein indicators, AssignSlotDialog quick-assign modal

Fixes:
- Eliminate desktop resize overflow (RenderFlex hatched stripes): wide-mode
  day columns scroll vertically, and a LayoutBuilder collapses the page
  into a single scrollable column with a fixed-height calendar when the
  window body is shorter than ~520 dp

Testing:
- 29 new tests: recipe scraper (JSON-LD variants, macro/ingredient/
  instruction/duration parsing, OG fallback, execute error mapping),
  meal-plan repositories (window filter, upsert, dedup), calendar
  controller (rollup, navigation, prepared/custom entries), and screen
  widget tests pumping short-compact/short-wide/tall/extremely-short
  window sizes to prove no overflow; full suite green (89/89)
- BUILD_STATE.md: mark Phase 4 complete and record all verification gates
2026-10-16 09:07:41 -04:00