Skip to content

feat(demo): grocery scan demo with ingredient check (stethoscope) mode - #283

Merged
arrrrny merged 3 commits into
developmentfrom
feat/demo-ingredients-check
Aug 12, 2026
Merged

feat(demo): grocery scan demo with ingredient check (stethoscope) mode#283
arrrrny merged 3 commits into
developmentfrom
feat/demo-ingredients-check

Conversation

@arrrrny

@arrrrny arrrrny commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Adds the standalone grocery_scan_demo app (apps/grocery_scan_demo) with the full camera UI suite — barcode/text/produce/meat price-compare flows plus the NEW ingredient check (stethoscope) mode:

  • Capture-driven flow: stethoscope dock icon → shutter (stethoscope identity) → scanning stage → on-camera results overlay (never leaves the viewfinder)
  • IngredientsOverlay: gluten verdict pill (contains / may contain / free), nutrition score ring, factor breakdown bars, ingredient chips with gluten sources red-flagged, Re-scan / Back to camera
  • Mock package-back scene + MockGroceryProvider.scanIngredients
  • IngredientsAnalysis model — the AI backend contract for wiring (model: 'ingredients', ZikZakScore-style call)

Verified end-to-end on the Android emulator (dock, capture, overlay, dismiss, re-scan). The zik_zak wiring (upload to MinIO fire-and-forget + base64 AI call + branded overlay) is in progress separately.

Summary by CodeRabbit

  • New Features

    • Added a grocery price-match scanning demo for barcode, text, produce, meat, and ingredient scans.
    • Added interactive camera scanning, product variant selection, nutrition insights, and gluten analysis.
    • Added nearby store price comparisons with best-price highlights and per-unit pricing.
    • Added English and Turkish grocery labels.
    • Added support for Android, iOS, macOS, and web.
  • Documentation

    • Added setup instructions, demo flows, architecture guidance, and extension notes.
  • Tests

    • Added smoke tests covering permissions, scanning, comparisons, and variant selection.

arrrrny added 2 commits August 9, 2026 16:08
Full UI for scanning a product's ingredient list on camera:
- new ScanMode.ingredients (stethoscope dock icon + hint)
- capture flow: shutter (stethoscope identity) → scanning stage →
  on-camera results overlay (never leaves the viewfinder)
- IngredientsOverlay: gluten verdict pill (contains/may/free),
  nutrition score ring, factor breakdown bars, ingredient chips with
  gluten sources red-flagged, Re-scan / Back to camera
- mock package-back scene to frame + MockGroceryProvider.scanIngredients
- IngredientsAnalysis model (productName, brand, verdict, score,
  factors, ingredients, glutenSources) — the AI backend contract when
  wired (model: 'ingredients', ZikZakScore-style)
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5de571da-1495-4ace-b82a-926da2731f16

📥 Commits

Reviewing files that changed from the base of the PR and between 9b7359e and ba17aa5.

⛔ Files ignored due to path filters (39)
  • apps/grocery_scan_demo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png is excluded by !**/*.png
  • apps/grocery_scan_demo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png is excluded by !**/*.png
  • apps/grocery_scan_demo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/grocery_scan_demo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/grocery_scan_demo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata is excluded by !**/*.xcworkspace/contents.xcworkspacedata
  • apps/grocery_scan_demo/ios/Runner.xcworkspace/contents.xcworkspacedata is excluded by !**/*.xcworkspace/contents.xcworkspacedata
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png is excluded by !**/*.png
  • apps/grocery_scan_demo/macos/Runner.xcworkspace/contents.xcworkspacedata is excluded by !**/*.xcworkspace/contents.xcworkspacedata
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png is excluded by !**/*.png
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png is excluded by !**/*.png
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png is excluded by !**/*.png
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png is excluded by !**/*.png
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png is excluded by !**/*.png
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png is excluded by !**/*.png
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png is excluded by !**/*.png
  • apps/grocery_scan_demo/pubspec.lock is excluded by !**/*.lock
  • apps/grocery_scan_demo/web/favicon.png is excluded by !**/*.png
  • apps/grocery_scan_demo/web/icons/Icon-192.png is excluded by !**/*.png
  • apps/grocery_scan_demo/web/icons/Icon-512.png is excluded by !**/*.png
  • apps/grocery_scan_demo/web/icons/Icon-maskable-192.png is excluded by !**/*.png
  • apps/grocery_scan_demo/web/icons/Icon-maskable-512.png is excluded by !**/*.png
📒 Files selected for processing (86)
  • apps/grocery_scan_demo/.gitignore
  • apps/grocery_scan_demo/.metadata
  • apps/grocery_scan_demo/README.md
  • apps/grocery_scan_demo/analysis_options.yaml
  • apps/grocery_scan_demo/android/.gitignore
  • apps/grocery_scan_demo/android/app/build.gradle.kts
  • apps/grocery_scan_demo/android/app/src/debug/AndroidManifest.xml
  • apps/grocery_scan_demo/android/app/src/main/AndroidManifest.xml
  • apps/grocery_scan_demo/android/app/src/main/kotlin/com/zikzak/grocery_scan_demo/MainActivity.kt
  • apps/grocery_scan_demo/android/app/src/main/res/drawable-v21/launch_background.xml
  • apps/grocery_scan_demo/android/app/src/main/res/drawable/launch_background.xml
  • apps/grocery_scan_demo/android/app/src/main/res/values-night/styles.xml
  • apps/grocery_scan_demo/android/app/src/main/res/values/styles.xml
  • apps/grocery_scan_demo/android/app/src/profile/AndroidManifest.xml
  • apps/grocery_scan_demo/android/build.gradle.kts
  • apps/grocery_scan_demo/android/gradle.properties
  • apps/grocery_scan_demo/android/gradle/wrapper/gradle-wrapper.properties
  • apps/grocery_scan_demo/android/settings.gradle.kts
  • apps/grocery_scan_demo/ios/.gitignore
  • apps/grocery_scan_demo/ios/Flutter/AppFrameworkInfo.plist
  • apps/grocery_scan_demo/ios/Flutter/Debug.xcconfig
  • apps/grocery_scan_demo/ios/Flutter/Release.xcconfig
  • apps/grocery_scan_demo/ios/Runner.xcodeproj/project.pbxproj
  • apps/grocery_scan_demo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • apps/grocery_scan_demo/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  • apps/grocery_scan_demo/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  • apps/grocery_scan_demo/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • apps/grocery_scan_demo/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
  • apps/grocery_scan_demo/ios/Runner/AppDelegate.swift
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
  • apps/grocery_scan_demo/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
  • apps/grocery_scan_demo/ios/Runner/Base.lproj/LaunchScreen.storyboard
  • apps/grocery_scan_demo/ios/Runner/Base.lproj/Main.storyboard
  • apps/grocery_scan_demo/ios/Runner/Info.plist
  • apps/grocery_scan_demo/ios/Runner/Runner-Bridging-Header.h
  • apps/grocery_scan_demo/ios/Runner/SceneDelegate.swift
  • apps/grocery_scan_demo/ios/RunnerTests/RunnerTests.swift
  • apps/grocery_scan_demo/lib/main.dart
  • apps/grocery_scan_demo/lib/src/app.dart
  • apps/grocery_scan_demo/lib/src/data/grocery_dictionary.dart
  • apps/grocery_scan_demo/lib/src/data/stores_catalog.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/grocery_scan_page.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/models/scan_mode.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/brand_logo.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/camera_viewfinder.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/count_up_price.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/detection_hud.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/ingredients_overlay.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/location_permission_overlay.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/price_compare_overlay.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/scan_mode_dock.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/scene_geometry.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/scene_painters.dart
  • apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/variation_chooser.dart
  • apps/grocery_scan_demo/lib/src/models/detections.dart
  • apps/grocery_scan_demo/lib/src/models/grocery_item.dart
  • apps/grocery_scan_demo/lib/src/models/ingredients_analysis.dart
  • apps/grocery_scan_demo/lib/src/models/store_offer.dart
  • apps/grocery_scan_demo/lib/src/providers/mock_grocery_provider.dart
  • apps/grocery_scan_demo/lib/src/providers/mock_grocery_scope.dart
  • apps/grocery_scan_demo/lib/src/theme/app_theme.dart
  • apps/grocery_scan_demo/macos/.gitignore
  • apps/grocery_scan_demo/macos/Flutter/Flutter-Debug.xcconfig
  • apps/grocery_scan_demo/macos/Flutter/Flutter-Release.xcconfig
  • apps/grocery_scan_demo/macos/Flutter/GeneratedPluginRegistrant.swift
  • apps/grocery_scan_demo/macos/Runner.xcodeproj/project.pbxproj
  • apps/grocery_scan_demo/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • apps/grocery_scan_demo/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
  • apps/grocery_scan_demo/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  • apps/grocery_scan_demo/macos/Runner/AppDelegate.swift
  • apps/grocery_scan_demo/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
  • apps/grocery_scan_demo/macos/Runner/Base.lproj/MainMenu.xib
  • apps/grocery_scan_demo/macos/Runner/Configs/AppInfo.xcconfig
  • apps/grocery_scan_demo/macos/Runner/Configs/Debug.xcconfig
  • apps/grocery_scan_demo/macos/Runner/Configs/Release.xcconfig
  • apps/grocery_scan_demo/macos/Runner/Configs/Warnings.xcconfig
  • apps/grocery_scan_demo/macos/Runner/DebugProfile.entitlements
  • apps/grocery_scan_demo/macos/Runner/Info.plist
  • apps/grocery_scan_demo/macos/Runner/MainFlutterWindow.swift
  • apps/grocery_scan_demo/macos/Runner/Release.entitlements
  • apps/grocery_scan_demo/macos/RunnerTests/RunnerTests.swift
  • apps/grocery_scan_demo/pubspec.yaml
  • apps/grocery_scan_demo/test/grocery_scan_smoke_test.dart
  • apps/grocery_scan_demo/web/index.html
  • apps/grocery_scan_demo/web/manifest.json

📝 Walkthrough

Walkthrough

This PR adds a new standalone Flutter grocery scan demo. It includes app models, mock scan data, provider logic, a scan-page state machine, camera and overlay widgets, smoke tests, project documentation, and Android, iOS, macOS, and web scaffolding.

Changes

Grocery scan demo app

Layer / File(s) Summary
App shell and shared contracts
apps/grocery_scan_demo/pubspec.yaml, apps/grocery_scan_demo/analysis_options.yaml, apps/grocery_scan_demo/lib/main.dart, apps/grocery_scan_demo/lib/src/app.dart, apps/grocery_scan_demo/lib/src/theme/app_theme.dart, apps/grocery_scan_demo/lib/src/providers/mock_grocery_scope.dart, apps/grocery_scan_demo/lib/src/models/*, apps/grocery_scan_demo/lib/src/features/grocery_scan/models/scan_mode.dart
Added the Flutter package setup, root app widget, theme, inherited provider scope, shared scan mode metadata, and core models for detections, grocery items, ingredient analysis, and store offers.
Mock data and provider logic
apps/grocery_scan_demo/lib/src/data/*, apps/grocery_scan_demo/lib/src/providers/mock_grocery_provider.dart
Added localized grocery dictionary data, deterministic store offers, and mock provider methods for permission, text scans, object scans, price comparison, and ingredient analysis.
Scan page state machine
apps/grocery_scan_demo/lib/src/features/grocery_scan/grocery_scan_page.dart, apps/grocery_scan_demo/test/grocery_scan_smoke_test.dart
Added the main scan page with permission, live, detecting, choosing, comparing, and ingredient states. The page handles async session invalidation, rescan flows, variant prefetch, and smoke tests for the main demo paths.
Camera scenes and overlays
apps/grocery_scan_demo/lib/src/features/grocery_scan/widgets/*
Added the mock camera viewfinder, scene geometry and painters, detection HUD, scan mode dock, permission overlay, variation chooser, ingredient overlay, price comparison overlay, brand logo, and animated price widget.
Project docs and platform scaffolding
apps/grocery_scan_demo/README.md, apps/grocery_scan_demo/.gitignore, apps/grocery_scan_demo/.metadata, apps/grocery_scan_demo/android/..., apps/grocery_scan_demo/ios/..., apps/grocery_scan_demo/macos/..., apps/grocery_scan_demo/web/...
Added project documentation, repository metadata, ignore rules, and full Flutter platform project files for Android, iOS, macOS, and web, including manifests, build settings, Xcode and Gradle configuration, assets, and workspace files.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GroceryScanPage
  participant MockGroceryProvider
  participant StoresCatalog

  User->>GroceryScanPage: grant permission or start scan
  GroceryScanPage->>MockGroceryProvider: scanText() / scanObject() / scanIngredients()
  MockGroceryProvider-->>GroceryScanPage: detection or analysis result
  alt item needs price comparison
    GroceryScanPage->>MockGroceryProvider: comparePrices(item)
    MockGroceryProvider->>StoresCatalog: offersForItem(itemId)
    StoresCatalog-->>MockGroceryProvider: ranked offers
    MockGroceryProvider-->>GroceryScanPage: offers
    GroceryScanPage-->>User: show comparison or variant chooser
  else ingredient mode
    GroceryScanPage-->>User: show ingredients overlay
  end
Loading
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Resolve AGENTS.md herdr rule conflict: adopt base's canonical 'zfa build'
wording (v5 contract) over the branch's 'dart run build_runner build'.
@arrrrny
arrrrny merged commit a2d313d into development Aug 12, 2026
1 of 8 checks passed
@arrrrny
arrrrny deleted the feat/demo-ingredients-check branch August 12, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant