Integrate recognizeImageRemote
The API below is used for food search.
/**
* This method detect food from image uri.
* @param imageUri - The image uri to detect food.
* @returns A `Promise` resolving to a `PassioAdvisorFoodInfo` array or `null`.
*/
recognizeImageRemote(
imageUri: string
): Promise<PassioAdvisorFoodInfo[] | null>
Example
useRecognizeRemote
import { useState, useCallback } from 'react'
import {
PassioAdvisorFoodInfo,
PassioSDK,
} from '@passiolife/nutritionai-react-native-sdk-v3'
import type { Props } from './RecognizeRemote'
import { launchImageLibrary } from 'react-native-image-picker'
import { Alert } from 'react-native'
const useRecognizeRemote = ({}: Props) => {
const [loading, setLoading] = useState<boolean>(false)
const [passioSpeechRecognitionModel, setPassioSpeechRecognitionModel] =
useState<PassioAdvisorFoodInfo[] | null>()
const onScanImage = useCallback(async () => {
try {
const { assets } = await launchImageLibrary({ mediaType: 'photo' })
if (assets) {
setLoading(true)
setPassioSpeechRecognitionModel(null)
PassioSDK.recognizeImageRemote(
assets?.[0].uri?.replace('file://', '') ?? ''
)
.then(async (candidates) => {
setPassioSpeechRecognitionModel(candidates)
})
.catch(() => {
Alert.alert('Unable to recognized this image')
})
.finally(() => {
setLoading(false)
})
}
} catch (err) {
setLoading(false)
}
}, [])
return {
onScanImage,
passioSpeechRecognitionModel,
loading,
}
}
export default useRecognizeRemote
RecognizeImageRemote
import React from 'react'
import {
ActivityIndicator,
FlatList,
SafeAreaView,
StyleSheet,
Text,
TouchableOpacity,
Image,
View,
} from 'react-native'
import {
PassioIconView,
IconSize,
PassioSDK,
PassioFoodItem,
PassioAdvisorFoodInfo,
} from '@passiolife/nutritionai-react-native-sdk-v3'
import useRecognizeRemote from './useRecognizeRemote'
export interface Props {
onClose: () => void
onFoodDetail: (passioFoodItem: PassioFoodItem) => void
}
// FoodSearchScreen component
export const RecognizeImageRemote = (props: Props) => {
// Get styles object from the searchStyle function
const styles = searchStyle()
// Destructure values from the custom hook
const { loading, passioSpeechRecognitionModel, onScanImage } =
useRecognizeRemote(props)
// Function to render each item in the FlatList
const renderSearchItem = ({ item }: { item: PassioAdvisorFoodInfo }) => {
return (
<TouchableOpacity
style={styles.itemContainer}
onPress={async () => {
if (item.foodDataInfo) {
const dataInfo = await PassioSDK.fetchFoodItemForDataInfo(
item?.foodDataInfo
)
if (dataInfo) {
props.onFoodDetail(dataInfo)
}
}
}}
>
<View style={styles.itemIconContainer}>
<PassioIconView
style={styles.itemIcon}
config={{
passioID: item?.foodDataInfo?.iconID ?? '',
iconSize: IconSize.PX360,
}}
/>
</View>
<View>
<Text style={styles.itemFoodName}>{item?.recognizedName}</Text>
<Text style={styles.itemFoodName}>
{item?.portionSize + ' | ' + item.weightGrams}
</Text>
</View>
</TouchableOpacity>
)
}
// Display loading indicator when results are empty and loading is true
const renderLoading = () => {
return <>{loading ? <ActivityIndicator /> : null}</>
}
// Render the component
return (
<SafeAreaView style={styles.body}>
<View style={styles.closeButton}>
<TouchableOpacity onPress={props.onClose}>
<Image
style={styles.closeText}
source={require('../assets/back.png')}
/>
</TouchableOpacity>
</View>
{/* Search input */}
<TouchableOpacity onPress={onScanImage} style={styles.textInput}>
<Text style={{ color: 'white' }}>Pick Image</Text>
</TouchableOpacity>
<FlatList
data={passioSpeechRecognitionModel}
contentContainerStyle={styles.list}
renderItem={renderSearchItem}
ListEmptyComponent={renderLoading}
keyExtractor={(index) => 'item.advisorInfo?.foodDataInfo' + index}
/>
</SafeAreaView>
)
}
// Styles for the component
const searchStyle = () =>
StyleSheet.create({
closeButton: {},
list: {
marginTop: 16,
},
closeText: {
margin: 16,
height: 24,
width: 24,
},
itemContainer: {
padding: 12,
flex: 1,
marginVertical: 4,
marginHorizontal: 16,
backgroundColor: 'white',
flexDirection: 'row',
borderRadius: 24,
},
itemFoodName: {
flex: 1,
textTransform: 'capitalize',
marginHorizontal: 8,
fontSize: 16,
},
itemBrandName: {
flex: 1,
textTransform: 'capitalize',
marginHorizontal: 8,
fontSize: 12,
},
itemAlternativeContainer: {
overflow: 'hidden',
},
alternativeContainer: {
marginStart: 16,
alignItems: 'center',
overflow: 'hidden',
alignSelf: 'center',
backgroundColor: 'rgba(238, 242, 255, 1)',
shadowColor: '#000',
shadowOffset: { width: 0, height: 0.1 },
shadowOpacity: 0.5,
shadowRadius: 0.5,
marginVertical: 2,
marginBottom: 14,
elevation: 5,
borderRadius: 24,
},
itemAlternativeName: {
textTransform: 'capitalize',
paddingVertical: 8,
paddingHorizontal: 16,
},
itemIconContainer: {
height: 46,
width: 46,
borderRadius: 30,
overflow: 'hidden',
},
itemIcon: {
height: 46,
width: 46,
},
textInput: {
backgroundColor: 'blue',
paddingHorizontal: 16,
padding: 12,
alignItems: 'center',
color: 'white',
borderRadius: 16,
fontWeight: '500',
fontSize: 16,
marginHorizontal: 16,
},
body: {
backgroundColor: 'rgba(242, 245, 251, 1)',
flex: 1,
},
})
Last updated