Passio Nutrition-AI
  • Nutrition-AI SDK Overview
  • Guides
    • Nutrition AI SDK
      • SDK Key and minimum requirements
      • Installation
      • Configure the SDK
      • Use Cases
        • Food recognition
        • Nutrition data
        • Barcode scanning
        • Nutrition Facts scanning
        • Search, Food Icons, RefCode
        • Speech recognition
        • Nutrition Advisor
        • Suggestions and Meal Plans
        • User created foods and reports
    • iOS SDK Docs
      • Before getting started
      • Getting the ml models to the device
      • Run the demos first
      • Adding Passio SDK into your project
      • Initialize and configure the SDK
      • Start/Stop food detection
      • Food Recognition Delegate
      • Migration from SDK 1.4.X to 2.x
      • SDK API
      • Quick Start Guide
        • Installation
        • Configure the SDK (UIKit)
        • Recognise food using image
        • Food Details
    • Android SDK Docs
      • Getting started
        • Include the library
        • Camera
        • SDK Initialization and Configuration
        • Food detection session
        • Visual, Barcode and Packaged Food detection
        • Nutritional Database
        • Sandbox app
      • Troubleshooting on Android
      • Migration from SDK version 1.4.x to 2.x
      • Quick Start Guide
        • Importing the Android SDK to a project
        • Configure SDK and handle the result
        • RecognizeImageRemote
        • Food Details
    • React Native SDK Docs
      • Getting Started
        • Installation
        • SDK Initialization and Configuration
      • API Reference
        • configure & requestCameraAuthorization
        • recognizeImageRemote
        • searchForFood & searchForFoodSemantic
        • startFoodDetection
          • FoodDetectionEvent
        • fetchFoodItemForProductCode
        • fetchFoodItemForRefCode
        • fetchFoodItemForDataInfo
        • startNutritionFactsDetection
        • fetchFoodItemForPassioID
        • recognizeSpeechRemote
        • Fetch Nutrients
        • onDowloadingPassioModelCallBacks
        • detectFoodFromImageURI
        • addToPersonalization
        • updateLanguage
        • fetchHiddenIngredients
        • fetchVisualAlternatives
        • fetchPossibleIngredients
      • Properties
        • PassioFoodItem
        • PassioFoodDataInfo
        • PassioFoodAmount
        • PassioIngredient
        • PassioNutrients
        • UnitMass
        • ServingUnit
        • ServingSize
        • PassioSearchResult
        • NutritionFacts
        • PassioNutritionPreview
        • PassioSpeechRecognitionModel
        • PassioLogAction
        • PassioAdvisorFoodInfo
        • FoodCandidates
        • FoodDetectionEvent
        • NutritionDetectionEvent
        • DetectedCandidate
        • BarcodeCandidate
        • PackagedFoodCode
        • AmountEstimate
        • ImagesInfo
        • PassioStatus
        • FoodDetectionEvent
        • NutritionFacts
        • PassioMealPlan
        • PassioMealPlanItem
      • Nutriton Advisor
        • initConversation
        • sendMessage
        • sendImage
        • Guide
          • useNutritionAdvisor
        • Properties
          • PassioAdvisorResponse
          • PassioAdvisorMessageResultStatus
          • PassioAdvisorResultStatus
      • Quick Start Guide
        • Installation
        • Configure the SDK
        • RecognizeImageRemote
        • Food Detail
      • Guide
        • Integrate SDK Setup
        • Integrate Quick Scan
        • Integrate Food Search
        • Integrate Food Editor with Recipe
        • Integrate MealPlan
        • Integrate Suggestions
        • Integrate recognizeImageRemote
      • Components
        • DetectionCameraView
        • PassioIconView
      • Changelog
      • More
        • Display Macro Chart
          • MockFood
          • Utils PassioNutrient
        • Display Micro Progress
        • Getting nutrition value for a FoodItem
        • Getting nutrition value for a Recipe
        • Recalculate the nutrition value based on serving size options.
      • Migrations
        • Migrating from SDK 2.X to version 3.X
        • Structure Migrations From SDK 3.X to SDK 2.X
        • [Deprecated] Migrating from SDK 1.X to version 2.X
        • [Deprecated] Getting Started (v1)
          • Installation
          • SDK Initialization and Configuration
          • Start food detection
          • FoodDetectionEvent
          • Nutritional Database
      • Troubleshooting on RN
      • V2
        • Getting Started
          • Installation
          • SDK Initialization and Configuration
          • Start food detection
          • FoodDetectionEvent
        • RN SDK API
          • Properties
            • PersonalizedAlternative
            • FoodSearchResult
            • PassioNutrient
            • FoodDetectionEvent
            • DownloadModelCallBack
            • UPCProduct
            • ServingUnit
            • PassioStatus
            • PassioIDAttributes
            • PassioIDEntityType
            • PassioFoodItem
            • PassioRecipe
            • ServingSize
            • Measurement
            • UnitMass
            • NutritionFacts
        • Food Image
        • Search Food Item
        • Quick Scan
        • Multi Scan
        • MealPlan
        • Recipe
      • How do I Integrate a Passio SDK in EXPO?
    • Flutter SDK Docs
      • Getting Started
    • Before You Continue
    • Setup For Android
    • Initialize and configure the SDK
  • Fundamentals
    • Nutrition-AI Developer FAQ
      • Nutrition Data
      • Supported Phones
      • Security
      • Testing Volume Estimation
      • Testing Nutrition-AI SDK
      • Nutrition-AI Test Methodology
    • Nutrition API - Mobile SDK interoperability
      • JSON Response parsing
  • Versions
    • 3.2.4
      • SDK Key and minimum requirements
      • Installation
      • Configure the SDK
      • Use Cases
        • Food recognition
        • Nutrition data
        • Barcode scanning
        • Nutrition Facts scanning
        • Search, Food Icons, RefCode
        • Speech recognition
        • Nutrition Advisor
        • Suggestions and Meal Plans
        • User created foods and reports
    • 3.2.2
      • SDK Key and minimum requirements
      • Installation
      • Configure the SDK
      • Use Cases
        • Food recognition
        • Nutrition data
        • Barcode scanning
        • Nutrition Facts scanning
        • Search, Food Icons, RefCode
        • Speech recognition
        • Nutrition Advisor
        • Suggestions and Meal Plans
        • User created foods and reports
    • 3.2.0
      • SDK Key and minimum requirements
      • Installation
      • Configure the SDK
      • Use Cases
        • Food recognition
        • Nutrition data
        • Barcode scanning
        • Nutrition Facts scanning
        • Search, Food Icons, RefCode
        • Speech recognition
        • Nutrition Advisor
        • Suggestions and Meal Plans
    • 3.1.4
      • SDK Key and minimum requirements
      • Installation
      • Configure the SDK
      • Use Cases
        • Food recognition
        • Nutrition data
        • Barcode scanning
        • Search, Food Icons, RefCode
        • Speech recognition
        • Nutrition Advisor
        • Suggestions and Meal Plans
Powered by GitBook
On this page
  • Example
  • useQuickScan
  • QuickScanningScreen
  • QuickFoodResult
Export as PDF
  1. Guides
  2. React Native SDK Docs
  3. Guide

Integrate Quick Scan

The API below is used for Quick Scan.

Make sure the integration setup done before this implementation

/**
   * Begin food detection using the device's camera.
   * @param options - An object to determine which types of scanning should be performed.
   * @param callback - A callback to repeatedly receive food detection events as they occur.
   * @returns A `Subscription` that should be retained by the caller while food detection is running. Call `remove` on the subscription to terminate food detection.
   */
  startFoodDetection(
    options: FoodDetectionConfig,
    callback: (detection: FoodDetectionEvent) => void
  ): Subscription


/**
   * Look up the food item result for a given Passio ID.
   * @param passioID - The Passio ID for the  query.
   * @returns A `Promise` resolving to a `PassioFoodItem` object if the record exists in the database or `null` if not.
   */
  fetchFoodItemForPassioID(passioID: PassioID): Promise<PassioFoodItem | null>
  
  /**
   * Look up the food item result for a given by barcode or packagedFoodCode.
   * @param barcode  - barcode for the  query.
   * or
   * @param packageFoodCode  - packageFoodCode for the query.
   * @returns A `Promise` resolving to a `PassioFoodItem` object if the record exists in the database or `null` if not.
   */
  fetchFoodItemForProductCode(
    code: Barcode | PackagedFoodCode
  ): Promise<PassioFoodItem | null>

Example

useQuickScan

import { useEffect, useRef, useState, useCallback } from 'react'
import {
  PassioSDK,
  type FoodDetectionConfig,
  type FoodDetectionEvent,
  PassioFoodItem,
  DetectedCandidate,
} from '@passiolife/nutritionai-react-native-sdk-v3'

/**
 * Custom hook for handling quick food scanning using PassioSDK.
 * It provides functions and state variables related to food detection and alternative food items.
 */
export const useQuickScan = () => {
  // State variables
  const [passioFoodItem, setPassioFoodItem] = useState<PassioFoodItem | null>(
    null
  )
  const [alternative, setAlternativePassioIDAttributes] = useState<
    DetectedCandidate[] | null | undefined
  >(null)
  const [loading, setLoading] = useState(true)
  const passioFoodItemRef = useRef<PassioFoodItem | null>(null)

  // Function to clear the scanning results
  const onClearResultPress = () => {
    setLoading(true)
    passioFoodItemRef.current = null
    setPassioFoodItem(null)
    setAlternativePassioIDAttributes(null)
  }

  useEffect(() => {
    // Function to handle food detection events
    const handleFoodDetection = async (detection: FoodDetectionEvent) => {
      const { candidates } = detection

      // If no candidates available, return
      if (!candidates) {
        return
      }

      let attributes: PassioFoodItem | null = null

      // Determine the type of food detection and fetch attributes accordingly
      if (candidates.barcodeCandidates?.[0]) {
        const barcode = candidates.barcodeCandidates[0].barcode
        attributes = await PassioSDK.fetchFoodItemForProductCode(barcode)
      } else if (candidates.packagedFoodCode?.[0]) {
        const packagedFoodCode = candidates.packagedFoodCode[0]
        attributes = await PassioSDK.fetchFoodItemForProductCode(
          packagedFoodCode
        )
      } else if (candidates.detectedCandidates?.[0]) {
        const passioID = candidates.detectedCandidates[0].passioID
        attributes = await PassioSDK.fetchFoodItemForPassioID(passioID)
      }

      // If attributes are null, return
      if (attributes === null) {
        return
      }

      // Check if the detected food is different from the previous one
      if (attributes?.id !== passioFoodItemRef.current?.id) {
        passioFoodItemRef.current = attributes

        // Update state variables and fetch alternative food items
        setPassioFoodItem((prev) => {
          if (attributes?.id === prev?.id) {
            return prev
          } else {
            setAlternativePassioIDAttributes(
              candidates.detectedCandidates[0]?.alternatives
            )
            return attributes
          }
        })

        setLoading(false)
      }
    }

    // Configuration for food detection
    const config: FoodDetectionConfig = {
      detectBarcodes: true,
      detectPackagedFood: true,
    }

    // Start food detection and subscribe to events
    const subscription = PassioSDK.startFoodDetection(
      config,
      handleFoodDetection
    )

    // Cleanup function to unsubscribe when the component unmounts
    return () => subscription.remove()
  }, []) // Empty dependency array to run the effect only once during component mount

  // Function to handle changes in alternative food items
  const onAlternativeFoodItemChange = useCallback(
    async (attribute: DetectedCandidate) => {
      const alternatePassioFoodItem = await PassioSDK.fetchFoodItemForPassioID(
        attribute.passioID
      )
      if (alternatePassioFoodItem) {
        passioFoodItemRef.current = alternatePassioFoodItem
        setPassioFoodItem(alternatePassioFoodItem)
      }
    },
    []
  )

  // Return the hook's public API
  return {
    loading,
    passioFoodItem,
    onAlternativeFoodItemChange,
    onClearResultPress,
    alternative,
  }
}

QuickScanningScreen

import {
  ActivityIndicator,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native'

import {
  DetectionCameraView,
  PassioFoodItem,
} from '@passiolife/nutritionai-react-native-sdk-v3'

import { useQuickScan } from './useQuickScan'
import React from 'react'
import { QuickFoodResult } from './view/QuickFoodResult'

interface Props {
  onClose: () => void
  onFoodDetail: (passioFoodItem: PassioFoodItem) => void
}

export const QuickScanningScreen = ({ onClose, onFoodDetail }: Props) => {
  const {
    loading,
    passioFoodItem,
    onClearResultPress,
    alternative,
    onAlternativeFoodItemChange,
  } = useQuickScan()
  const styles = quickScanStyle()

  return (
    <View style={styles.blackBackgroundStyle}>
      <DetectionCameraView style={styles.detectionCamera} />
      {loading ? (
        <View style={styles.loadingIndicator}>
          <ActivityIndicator />
          <Text>Scanning...</Text>
        </View>
      ) : null}
      {passioFoodItem !== null ? (
        <QuickFoodResult
          attribute={passioFoodItem}
          onAlternativeFoodItemChange={onAlternativeFoodItemChange}
          onClearResultPress={onClearResultPress}
          alternativeAttributes={alternative ?? []}
          onItemClick={onFoodDetail}
        />
      ) : null}
      <View style={styles.closeButton}>
        <TouchableOpacity onPress={onClose}>
          <Text style={styles.text}>✕</Text>
        </TouchableOpacity>
      </View>
    </View>
  )
}

const quickScanStyle = () =>
  StyleSheet.create({
    detectionCamera: {
      flex: 1,
      width: '100%',
    },
    blackBackgroundStyle: {
      backgroundColor: 'black',
      width: '100%',
      flex: 1,
      flexDirection: 'column',
    },
    loadingIndicator: {
      backgroundColor: 'white',
      minHeight: 150,
      borderTopRightRadius: 24,
      alignItems: 'center',
      justifyContent: 'center',
      borderTopLeftRadius: 24,
      position: 'absolute',
      bottom: 0,
      right: 0,
      left: 0,
    },
    text: {
      color: 'white',
      fontSize: 30,
    },
    closeButton: {
      position: 'absolute',
      top: 45,
      right: 25,
      zIndex: 1000,
      color: 'white',
    },
  })

QuickFoodResult

import React from 'react'
import { Pressable, StyleSheet, Text, View, Image } from 'react-native'

import {
  IconSize,
  PassioIconView,
  type PassioFoodItem,
  DetectedCandidate,
  PassioSDK,
} from '@passiolife/nutritionai-react-native-sdk-v3'
import { AlternativeFood } from '../../../src/views/AlternativeFood'

export interface QuickFoodResultProps {
  attribute: PassioFoodItem
  alternativeAttributes?: DetectedCandidate[]
  onAlternativeFoodItemChange?: (item: DetectedCandidate) => void
  onClearResultPress?: () => void
  onItemClick?: (passioFoodItem: PassioFoodItem) => void
}

export const QuickFoodResult = ({
  attribute,
  alternativeAttributes,
  onAlternativeFoodItemChange,
  onClearResultPress,
  onItemClick,
}: QuickFoodResultProps) => {
  const styles = quickFoodResultStyle()

  const nutrients =
    PassioSDK.getNutrientsSelectedSizeOfPassioFoodItem(attribute)

  return (
    <Pressable
      onPress={() => {
        onItemClick?.(attribute)
      }}
      style={styles.itemContainer}
    >
      <View style={styles.foodResult}>
        <View style={styles.itemIconContainer}>
          <PassioIconView
            style={styles.itemIcon}
            config={{
              passioID: attribute.iconId ?? attribute.id,
              iconSize: IconSize.PX180,
            }}
          />
        </View>
        <View>
          <Text style={styles.itemFoodName}>{attribute.name}</Text>
          <Text style={styles.itemFoodDetail}>
            {Math.round(attribute.amount?.weight?.value ?? 0) +
              ' ' +
              attribute.amount?.weight?.unit}
          </Text>
          <Text style={styles.itemFoodDetail}>
            {Math.round(nutrients.calories?.value ?? 0) +
              ' ' +
              nutrients?.calories?.unit}
          </Text>
        </View>
      </View>
      {alternativeAttributes && (
        <AlternativeFood
          detectedCandidates={alternativeAttributes}
          onAlternativeFoodItemChange={onAlternativeFoodItemChange}
        />
      )}
      <Pressable style={styles.clearResult} onPress={onClearResultPress}>
        <Image
          source={require('../../assets/close.png')}
          style={styles.close}
        />
      </Pressable>
    </Pressable>
  )
}

const quickFoodResultStyle = () =>
  StyleSheet.create({
    itemContainer: {
      position: 'absolute',
      bottom: 0,
      right: 0,
      padding: 16,
      borderTopLeftRadius: 24,
      borderTopRightRadius: 24,
      backgroundColor: 'white',
      minHeight: 150,
      flex: 1,
      marginVertical: 0,
      left: 0,
    },
    foodResult: {
      flexDirection: 'row',
      alignItems: 'center',
      flex: 1,
    },
    close: {
      width: 24,
      height: 24,
      tintColor: 'white',
    },
    itemFoodName: {
      flex: 1,
      textTransform: 'capitalize',
      paddingHorizontal: 8,
      fontSize: 16,
      fontWeight: '500',
    },
    itemFoodDetail: {
      flex: 1,
      textTransform: 'capitalize',
      marginHorizontal: 8,
      fontSize: 12,
    },
    itemIcon: {
      height: 60,
      width: 60,
    },
    itemIconContainer: {
      height: 60,
      width: 60,
      overflow: 'hidden',
      borderRadius: 30,
    },
    clearResult: {
      flexDirection: 'row',
      backgroundColor: 'red',
      borderRadius: 32,
      alignItems: 'center',
      alignSelf: 'center',
      padding: 8,
      marginVertical: 16,
    },
  })
PreviousIntegrate SDK SetupNextIntegrate Food Search

Last updated 6 months ago