Compare commits
2 Commits
master
...
feat/hooks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55ff9809ac | ||
|
|
e5b2f4e7d5 |
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import React from 'react';
|
import React, {useState, useReducer, useRef} from 'react';
|
||||||
import {
|
import {
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
Text,
|
Text,
|
||||||
@ -30,61 +30,87 @@ const wbOrder = {
|
|||||||
|
|
||||||
const landmarkSize = 2;
|
const landmarkSize = 2;
|
||||||
|
|
||||||
export default class CameraScreen extends React.Component {
|
const stateReducer = (state, action) => {
|
||||||
state = {
|
switch (action.type) {
|
||||||
flash: 'off',
|
case 'toggleFlash':
|
||||||
zoom: 0,
|
return { state.flash === flashModeOrder[ state.flash] }
|
||||||
autoFocus: 'on',
|
break;
|
||||||
autoFocusPoint: {
|
case 'toggleZoom':
|
||||||
normalized: { x: 0.5, y: 0.5 }, // normalized values required for autoFocusPointOfInterest
|
return { state.flash === flashModeOrder[ state.flash] }
|
||||||
drawRectPosition: {
|
break;
|
||||||
x: Dimensions.get('window').width * 0.5 - 32,
|
default:
|
||||||
y: Dimensions.get('window').height * 0.5 - 32,
|
break;
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
flash: 'off',
|
||||||
|
zoom: 0,
|
||||||
|
autoFocus: 'on',
|
||||||
|
depth: 0,
|
||||||
|
type: 'back',
|
||||||
|
whiteBalance: 'auto',
|
||||||
|
ratio: '16:9',
|
||||||
|
isRecording: false,
|
||||||
|
canDetectFaces: false,
|
||||||
|
canDetectText: false,
|
||||||
|
canDetectBarcode: false,
|
||||||
|
faces: [],
|
||||||
|
textBlocks: [],
|
||||||
|
barcodes: [],
|
||||||
|
|
||||||
|
recordOptions: {
|
||||||
|
mute: false,
|
||||||
|
maxDuration: 5,
|
||||||
|
quality: RNCamera.Constants.VideoQuality['288p'],
|
||||||
|
},
|
||||||
|
autoFocusPoint: {
|
||||||
|
normalized: { x: 0.5, y: 0.5 }, // normalized values required for autoFocusPointOfInterest
|
||||||
|
drawRectPosition: {
|
||||||
|
x: Dimensions.get('window').width * 0.5 - 32,
|
||||||
|
y: Dimensions.get('window').height * 0.5 - 32,
|
||||||
},
|
},
|
||||||
depth: 0,
|
},
|
||||||
type: 'back',
|
|
||||||
whiteBalance: 'auto',
|
|
||||||
ratio: '16:9',
|
|
||||||
recordOptions: {
|
|
||||||
mute: false,
|
|
||||||
maxDuration: 5,
|
|
||||||
quality: RNCamera.Constants.VideoQuality['288p'],
|
|
||||||
},
|
|
||||||
isRecording: false,
|
|
||||||
canDetectFaces: false,
|
|
||||||
canDetectText: false,
|
|
||||||
canDetectBarcode: false,
|
|
||||||
faces: [],
|
|
||||||
textBlocks: [],
|
|
||||||
barcodes: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
toggleFacing() {
|
};
|
||||||
this.setState({
|
|
||||||
type: this.state.type === 'back' ? 'front' : 'back',
|
|
||||||
});
|
|
||||||
|
const CameraScreen = () => {
|
||||||
|
const [state, setState] = useState(initialState);
|
||||||
|
const [recordOptions, togglerecordOptions] = useReducer(reducer, initialState.recordOptions);
|
||||||
|
const [autoFocusPoint, touchToFocus] = useReducer(reducer, initialState.autoFocusPoint);
|
||||||
|
const cameraRef = useRef(null);
|
||||||
|
|
||||||
|
toggleFacing =() =>{
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
type: type === 'back' ? 'front' : 'back',
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleFlash() {
|
toggleFlash =() => {
|
||||||
this.setState({
|
setState({
|
||||||
flash: flashModeOrder[this.state.flash],
|
...state,
|
||||||
});
|
flash: flashModeOrder[flash]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleWB() {
|
toggleWB =() => {
|
||||||
this.setState({
|
setState({
|
||||||
whiteBalance: wbOrder[this.state.whiteBalance],
|
...state,
|
||||||
});
|
whiteBalance: wbOrder[whiteBalance]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleFocus() {
|
toggleFocus =() =>{
|
||||||
this.setState({
|
setState({
|
||||||
autoFocus: this.state.autoFocus === 'on' ? 'off' : 'on',
|
...state,
|
||||||
});
|
autoFocus: autoFocus === 'on' ? 'off' : 'on'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
touchToFocus(event) {
|
touchToFocus =(event) => {
|
||||||
const { pageX, pageY } = event.nativeEvent;
|
const { pageX, pageY } = event.nativeEvent;
|
||||||
const screenWidth = Dimensions.get('window').width;
|
const screenWidth = Dimensions.get('window').width;
|
||||||
const screenHeight = Dimensions.get('window').height;
|
const screenHeight = Dimensions.get('window').height;
|
||||||
@ -97,49 +123,56 @@ export default class CameraScreen extends React.Component {
|
|||||||
x = pageY / screenHeight;
|
x = pageY / screenHeight;
|
||||||
y = -(pageX / screenWidth) + 1;
|
y = -(pageX / screenWidth) + 1;
|
||||||
}
|
}
|
||||||
|
return {
|
||||||
this.setState({
|
|
||||||
autoFocusPoint: {
|
autoFocusPoint: {
|
||||||
normalized: { x, y },
|
normalized: { x, y },
|
||||||
drawRectPosition: { x: pageX, y: pageY },
|
drawRectPosition: { x: pageX, y: pageY },
|
||||||
},
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
zoomOut =() =>{
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
zoom: state.zoom - 0.1 < 0 ? 0 : state.zoom - 0.1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
zoomIn =() => {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
zoom: state.zoom + 0.1 > 1 ? 1 : state.zoom + 0.1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomOut() {
|
setFocusDepth = (depth) => {
|
||||||
this.setState({
|
setState({
|
||||||
zoom: this.state.zoom - 0.1 < 0 ? 0 : this.state.zoom - 0.1,
|
...state,
|
||||||
});
|
depth: depth
|
||||||
}
|
|
||||||
|
|
||||||
zoomIn() {
|
|
||||||
this.setState({
|
|
||||||
zoom: this.state.zoom + 0.1 > 1 ? 1 : this.state.zoom + 0.1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setFocusDepth(depth) {
|
|
||||||
this.setState({
|
|
||||||
depth,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
takePicture = async function() {
|
takePicture = async function() {
|
||||||
if (this.camera) {
|
if (cameraRef) {
|
||||||
const data = await this.camera.takePictureAsync();
|
const data = await cameraRef.takePictureAsync();
|
||||||
console.warn('takePicture ', data);
|
console.warn('takePicture ', data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
takeVideo = async function() {
|
takeVideo = async function() {
|
||||||
if (this.camera) {
|
if (cameraRef) {
|
||||||
try {
|
try {
|
||||||
const promise = this.camera.recordAsync(this.state.recordOptions);
|
const promise = cameraRef.recordAsync( state.recordOptions);
|
||||||
|
|
||||||
if (promise) {
|
if (promise) {
|
||||||
this.setState({ isRecording: true });
|
setState({
|
||||||
|
...state,
|
||||||
|
isRecording: true
|
||||||
|
});
|
||||||
const data = await promise;
|
const data = await promise;
|
||||||
this.setState({ isRecording: false });
|
setState({
|
||||||
|
...state,
|
||||||
|
isRecording: false
|
||||||
|
});
|
||||||
console.warn('takeVideo', data);
|
console.warn('takeVideo', data);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -148,9 +181,19 @@ export default class CameraScreen extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
toggle = value => () => this.setState(prevState => ({ [value]: !prevState[value] }));
|
toggle = value => () => {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
[value]: !prevState[value]
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
facesDetected = ({ faces }) => this.setState({ faces });
|
facesDetected = ({ faces }) => {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
faces: faces
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
renderFace = ({ bounds, faceID, rollAngle, yawAngle }) => (
|
renderFace = ({ bounds, faceID, rollAngle, yawAngle }) => (
|
||||||
<View
|
<View
|
||||||
@ -175,7 +218,7 @@ export default class CameraScreen extends React.Component {
|
|||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
renderLandmarksOfFace(face) {
|
renderLandmarksOfFace =(face) => {
|
||||||
const renderLandmark = position =>
|
const renderLandmark = position =>
|
||||||
position && (
|
position && (
|
||||||
<View
|
<View
|
||||||
@ -207,19 +250,19 @@ export default class CameraScreen extends React.Component {
|
|||||||
|
|
||||||
renderFaces = () => (
|
renderFaces = () => (
|
||||||
<View style={styles.facesContainer} pointerEvents="none">
|
<View style={styles.facesContainer} pointerEvents="none">
|
||||||
{this.state.faces.map(this.renderFace)}
|
{ state.faces.map(() => renderFace())}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
renderLandmarks = () => (
|
renderLandmarks = () => (
|
||||||
<View style={styles.facesContainer} pointerEvents="none">
|
<View style={styles.facesContainer} pointerEvents="none">
|
||||||
{this.state.faces.map(this.renderLandmarksOfFace)}
|
{ state.faces.map(() => renderLandmarksOfFace())}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
renderTextBlocks = () => (
|
renderTextBlocks = () => (
|
||||||
<View style={styles.facesContainer} pointerEvents="none">
|
<View style={styles.facesContainer} pointerEvents="none">
|
||||||
{this.state.textBlocks.map(this.renderTextBlock)}
|
{ state.textBlocks.map(() => renderTextBlock())}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -243,14 +286,22 @@ export default class CameraScreen extends React.Component {
|
|||||||
|
|
||||||
textRecognized = object => {
|
textRecognized = object => {
|
||||||
const { textBlocks } = object;
|
const { textBlocks } = object;
|
||||||
this.setState({ textBlocks });
|
setState({
|
||||||
|
...state,
|
||||||
|
textBlocks: textBlocks
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
barcodeRecognized = ({ barcodes }) => this.setState({ barcodes });
|
barcodeRecognized = ({ barcodes }) => {
|
||||||
|
setState({
|
||||||
|
...stat,
|
||||||
|
barcodes
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
renderBarcodes = () => (
|
renderBarcodes = () => (
|
||||||
<View style={styles.facesContainer} pointerEvents="none">
|
<View style={styles.facesContainer} pointerEvents="none">
|
||||||
{this.state.barcodes.map(this.renderBarcode)}
|
{ state.barcodes.map( renderBarcode)}
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -271,30 +322,30 @@ export default class CameraScreen extends React.Component {
|
|||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
renderCamera() {
|
renderCamera = () => {
|
||||||
const { canDetectFaces, canDetectText, canDetectBarcode } = this.state;
|
const { canDetectFaces, canDetectText, canDetectBarcode } = state;
|
||||||
|
|
||||||
const drawFocusRingPosition = {
|
const drawFocusRingPosition = {
|
||||||
top: this.state.autoFocusPoint.drawRectPosition.y - 32,
|
top: state.autoFocusPoint.drawRectPosition.y - 32,
|
||||||
left: this.state.autoFocusPoint.drawRectPosition.x - 32,
|
left: state.autoFocusPoint.drawRectPosition.x - 32,
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<RNCamera
|
<RNCamera
|
||||||
ref={ref => {
|
ref={ref => {
|
||||||
this.camera = ref;
|
cameraRef = ref;
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
}}
|
}}
|
||||||
type={this.state.type}
|
type={ state.type}
|
||||||
flashMode={this.state.flash}
|
flashMode={ state.flash}
|
||||||
autoFocus={this.state.autoFocus}
|
autoFocus={ state.autoFocus}
|
||||||
autoFocusPointOfInterest={this.state.autoFocusPoint.normalized}
|
autoFocusPointOfInterest={ state.autoFocusPoint.normalized}
|
||||||
zoom={this.state.zoom}
|
zoom={ state.zoom}
|
||||||
whiteBalance={this.state.whiteBalance}
|
whiteBalance={ state.whiteBalance}
|
||||||
ratio={this.state.ratio}
|
ratio={ state.ratio}
|
||||||
focusDepth={this.state.depth}
|
focusDepth={ state.depth}
|
||||||
androidCameraPermissionOptions={{
|
androidCameraPermissionOptions={{
|
||||||
title: 'Permission to use camera',
|
title: 'Permission to use camera',
|
||||||
message: 'We need your permission to use your camera',
|
message: 'We need your permission to use your camera',
|
||||||
@ -306,13 +357,13 @@ export default class CameraScreen extends React.Component {
|
|||||||
? RNCamera.Constants.FaceDetection.Landmarks.all
|
? RNCamera.Constants.FaceDetection.Landmarks.all
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
onFacesDetected={canDetectFaces ? this.facesDetected : null}
|
onFacesDetected={canDetectFaces ? facesDetected() : null}
|
||||||
onTextRecognized={canDetectText ? this.textRecognized : null}
|
onTextRecognized={canDetectText ? textRecognized() : null}
|
||||||
onGoogleVisionBarcodesDetected={canDetectBarcode ? this.barcodeRecognized : null}
|
onGoogleVisionBarcodesDetected={canDetectBarcode ? barcodeRecognized() : null}
|
||||||
>
|
>
|
||||||
<View style={StyleSheet.absoluteFill}>
|
<View style={StyleSheet.absoluteFill}>
|
||||||
<View style={[styles.autoFocusBox, drawFocusRingPosition]} />
|
<View style={[styles.autoFocusBox, drawFocusRingPosition]} />
|
||||||
<TouchableWithoutFeedback onPress={this.touchToFocus.bind(this)}>
|
<TouchableWithoutFeedback onPress={() => touchToFocus()}>
|
||||||
<View style={{ flex: 1 }} />
|
<View style={{ flex: 1 }} />
|
||||||
</TouchableWithoutFeedback>
|
</TouchableWithoutFeedback>
|
||||||
</View>
|
</View>
|
||||||
@ -332,14 +383,14 @@ export default class CameraScreen extends React.Component {
|
|||||||
justifyContent: 'space-around',
|
justifyContent: 'space-around',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TouchableOpacity style={styles.flipButton} onPress={this.toggleFacing.bind(this)}>
|
<TouchableOpacity style={styles.flipButton} onPress={() => toggleFacing()}>
|
||||||
<Text style={styles.flipText}> FLIP </Text>
|
<Text style={styles.flipText}> FLIP </Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.flipButton} onPress={this.toggleFlash.bind(this)}>
|
<TouchableOpacity style={styles.flipButton} onPress={() => toggleFlash()}>
|
||||||
<Text style={styles.flipText}> FLASH: {this.state.flash} </Text>
|
<Text style={styles.flipText}> FLASH: { state.flash} </Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity style={styles.flipButton} onPress={this.toggleWB.bind(this)}>
|
<TouchableOpacity style={styles.flipButton} onPress={() => toggleWB()}>
|
||||||
<Text style={styles.flipText}> WB: {this.state.whiteBalance} </Text>
|
<Text style={styles.flipText}> WB: { state.whiteBalance} </Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
@ -349,17 +400,17 @@ export default class CameraScreen extends React.Component {
|
|||||||
justifyContent: 'space-around',
|
justifyContent: 'space-around',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TouchableOpacity onPress={this.toggle('canDetectFaces')} style={styles.flipButton}>
|
<TouchableOpacity onPress={()=> toggle('canDetectFaces')} style={styles.flipButton}>
|
||||||
<Text style={styles.flipText}>
|
<Text style={styles.flipText}>
|
||||||
{!canDetectFaces ? 'Detect Faces' : 'Detecting Faces'}
|
{!canDetectFaces ? 'Detect Faces' : 'Detecting Faces'}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={this.toggle('canDetectText')} style={styles.flipButton}>
|
<TouchableOpacity onPress={()=> toggle('canDetectText')} style={styles.flipButton}>
|
||||||
<Text style={styles.flipText}>
|
<Text style={styles.flipText}>
|
||||||
{!canDetectText ? 'Detect Text' : 'Detecting Text'}
|
{!canDetectText ? 'Detect Text' : 'Detecting Text'}
|
||||||
</Text>
|
</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity onPress={this.toggle('canDetectBarcode')} style={styles.flipButton}>
|
<TouchableOpacity onPress={()=> toggle('canDetectBarcode')} style={styles.flipButton}>
|
||||||
<Text style={styles.flipText}>
|
<Text style={styles.flipText}>
|
||||||
{!canDetectBarcode ? 'Detect Barcode' : 'Detecting Barcode'}
|
{!canDetectBarcode ? 'Detect Barcode' : 'Detecting Barcode'}
|
||||||
</Text>
|
</Text>
|
||||||
@ -377,9 +428,9 @@ export default class CameraScreen extends React.Component {
|
|||||||
>
|
>
|
||||||
<Slider
|
<Slider
|
||||||
style={{ width: 150, marginTop: 15, alignSelf: 'flex-end' }}
|
style={{ width: 150, marginTop: 15, alignSelf: 'flex-end' }}
|
||||||
onValueChange={this.setFocusDepth.bind(this)}
|
onValueChange={() => setFocusDepth()}
|
||||||
step={0.1}
|
step={0.1}
|
||||||
disabled={this.state.autoFocus === 'on'}
|
disabled={ state.autoFocus === 'on'}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
@ -396,20 +447,20 @@ export default class CameraScreen extends React.Component {
|
|||||||
{
|
{
|
||||||
flex: 0.3,
|
flex: 0.3,
|
||||||
alignSelf: 'flex-end',
|
alignSelf: 'flex-end',
|
||||||
backgroundColor: this.state.isRecording ? 'white' : 'darkred',
|
backgroundColor: state.isRecording ? 'white' : 'darkred',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
onPress={this.state.isRecording ? () => {} : this.takeVideo.bind(this)}
|
onPress={ state.isRecording ? () => {} : () => takeVideo()}
|
||||||
>
|
>
|
||||||
{this.state.isRecording ? (
|
{ state.isRecording ? (
|
||||||
<Text style={styles.flipText}> ☕ </Text>
|
<Text style={styles.flipText}> ☕ </Text>
|
||||||
) : (
|
) : (
|
||||||
<Text style={styles.flipText}> REC </Text>
|
<Text style={styles.flipText}> REC </Text>
|
||||||
)}
|
)}
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
{this.state.zoom !== 0 && (
|
{ state.zoom !== 0 && (
|
||||||
<Text style={[styles.flipText, styles.zoomText]}>Zoom: {this.state.zoom}</Text>
|
<Text style={[styles.flipText, styles.zoomText]}>Zoom: { state.zoom}</Text>
|
||||||
)}
|
)}
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@ -421,43 +472,44 @@ export default class CameraScreen extends React.Component {
|
|||||||
>
|
>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
||||||
onPress={this.zoomIn.bind(this)}
|
onPress={() => zoomIn()}
|
||||||
>
|
>
|
||||||
<Text style={styles.flipText}> + </Text>
|
<Text style={styles.flipText}> + </Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
|
||||||
onPress={this.zoomOut.bind(this)}
|
onPress={() => zoomOut()}
|
||||||
>
|
>
|
||||||
<Text style={styles.flipText}> - </Text>
|
<Text style={styles.flipText}> - </Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.flipButton, { flex: 0.25, alignSelf: 'flex-end' }]}
|
style={[styles.flipButton, { flex: 0.25, alignSelf: 'flex-end' }]}
|
||||||
onPress={this.toggleFocus.bind(this)}
|
onPress={() => toggleFocus()}
|
||||||
>
|
>
|
||||||
<Text style={styles.flipText}> AF : {this.state.autoFocus} </Text>
|
<Text style={styles.flipText}> AF : { state.autoFocus} </Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
style={[styles.flipButton, styles.picButton, { flex: 0.3, alignSelf: 'flex-end' }]}
|
style={[styles.flipButton, styles.picButton, { flex: 0.3, alignSelf: 'flex-end' }]}
|
||||||
onPress={this.takePicture.bind(this)}
|
onPress={() => takePicture()}
|
||||||
>
|
>
|
||||||
<Text style={styles.flipText}> SNAP </Text>
|
<Text style={styles.flipText}> SNAP </Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{!!canDetectFaces && this.renderFaces()}
|
{!!canDetectFaces && renderFaces()}
|
||||||
{!!canDetectFaces && this.renderLandmarks()}
|
{!!canDetectFaces && renderLandmarks()}
|
||||||
{!!canDetectText && this.renderTextBlocks()}
|
{!!canDetectText && renderTextBlocks()}
|
||||||
{!!canDetectBarcode && this.renderBarcodes()}
|
{!!canDetectBarcode && renderBarcodes()}
|
||||||
</RNCamera>
|
</RNCamera>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return (
|
||||||
render() {
|
<View style={styles.container}>{() => renderCamera()}</View>
|
||||||
return <View style={styles.container}>{this.renderCamera()}</View>;
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default CameraScreen;
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|||||||
812
src/RNCamera.js
812
src/RNCamera.js
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import {
|
||||||
findNodeHandle,
|
findNodeHandle,
|
||||||
@ -342,159 +342,258 @@ const mapValues = (input, mapper) => {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class Camera extends React.Component<PropsType, StateType> {
|
export const Constants = {
|
||||||
static Constants = {
|
Type: CameraManager.Type,
|
||||||
Type: CameraManager.Type,
|
FlashMode: CameraManager.FlashMode,
|
||||||
FlashMode: CameraManager.FlashMode,
|
AutoFocus: CameraManager.AutoFocus,
|
||||||
AutoFocus: CameraManager.AutoFocus,
|
WhiteBalance: CameraManager.WhiteBalance,
|
||||||
WhiteBalance: CameraManager.WhiteBalance,
|
VideoQuality: CameraManager.VideoQuality,
|
||||||
VideoQuality: CameraManager.VideoQuality,
|
VideoCodec: CameraManager.VideoCodec,
|
||||||
VideoCodec: CameraManager.VideoCodec,
|
BarCodeType: CameraManager.BarCodeType,
|
||||||
BarCodeType: CameraManager.BarCodeType,
|
GoogleVisionBarcodeDetection: CameraManager.GoogleVisionBarcodeDetection,
|
||||||
GoogleVisionBarcodeDetection: CameraManager.GoogleVisionBarcodeDetection,
|
FaceDetection: CameraManager.FaceDetection,
|
||||||
FaceDetection: CameraManager.FaceDetection,
|
CameraStatus,
|
||||||
CameraStatus,
|
RecordAudioPermissionStatus: RecordAudioPermissionStatusEnum,
|
||||||
RecordAudioPermissionStatus: RecordAudioPermissionStatusEnum,
|
VideoStabilization: CameraManager.VideoStabilization,
|
||||||
VideoStabilization: CameraManager.VideoStabilization,
|
Orientation: {
|
||||||
Orientation: {
|
auto: 'auto',
|
||||||
auto: 'auto',
|
landscapeLeft: 'landscapeLeft',
|
||||||
landscapeLeft: 'landscapeLeft',
|
landscapeRight: 'landscapeRight',
|
||||||
landscapeRight: 'landscapeRight',
|
portrait: 'portrait',
|
||||||
portrait: 'portrait',
|
portraitUpsideDown: 'portraitUpsideDown',
|
||||||
portraitUpsideDown: 'portraitUpsideDown',
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ConversionTables = {
|
||||||
|
type: CameraManager.Type,
|
||||||
|
flashMode: CameraManager.FlashMode,
|
||||||
|
exposure: CameraManager.Exposure,
|
||||||
|
autoFocus: CameraManager.AutoFocus,
|
||||||
|
whiteBalance: CameraManager.WhiteBalance,
|
||||||
|
faceDetectionMode: (CameraManager.FaceDetection || {}).Mode,
|
||||||
|
faceDetectionLandmarks: (CameraManager.FaceDetection || {}).Landmarks,
|
||||||
|
faceDetectionClassifications: (CameraManager.FaceDetection || {}).Classifications,
|
||||||
|
googleVisionBarcodeType: (CameraManager.GoogleVisionBarcodeDetection || {}).BarcodeType,
|
||||||
|
videoStabilizationMode: CameraManager.VideoStabilization || {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function Camera(props) {
|
||||||
|
let _cameraRef = useRef((ref) => setReference(ref));
|
||||||
|
let _cameraHandle: ?number;
|
||||||
|
let _lastEvents: { [string]: string };
|
||||||
|
let _lastEventsTimes: { [string]: Date };
|
||||||
|
let _isMounted: boolean;
|
||||||
|
|
||||||
|
const [isAuthorized, setIsAuthorized] = useState<boolean>(false);
|
||||||
|
const [isAuthorizationChecked, setIsAuthorizationChecked] = useState<boolean>(false);
|
||||||
|
const [recordAudioPermissionStatus, setRecordAudioPermissionStatus] = useState(
|
||||||
|
RecordAudioPermissionStatusEnum.PENDING_AUTHORIZATION,
|
||||||
|
);
|
||||||
|
|
||||||
|
const convertProp = useMemo((value: *, key: string) => {
|
||||||
|
if (typeof value === 'string' && Camera.ConversionTables[key]) {
|
||||||
|
return Camera.ConversionTables[key][value];
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}, []);
|
||||||
|
const convertNativeProps = useCallback(
|
||||||
|
(nativeProps: PropsType) => () => {
|
||||||
|
const { children, ...props } = nativeProps;
|
||||||
|
const newProps = mapValues(props, convertProp);
|
||||||
|
|
||||||
|
if (props.onBarCodeRead) {
|
||||||
|
newProps.barCodeScannerEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.onGoogleVisionBarcodesDetected) {
|
||||||
|
newProps.googleVisionBarcodeDetectorEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.onFacesDetected) {
|
||||||
|
newProps.faceDetectorEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.onTextRecognized) {
|
||||||
|
newProps.textRecognizerEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Platform.OS === 'ios') {
|
||||||
|
delete newProps.googleVisionBarcodeMode;
|
||||||
|
delete newProps.ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newProps;
|
||||||
},
|
},
|
||||||
};
|
[],
|
||||||
|
);
|
||||||
// Values under keys from this object will be transformed to native options
|
const hasFaCC = useMemo(() => typeof props.children === 'function', [props.children]);
|
||||||
static ConversionTables = {
|
const setReference = useCallback(
|
||||||
type: CameraManager.Type,
|
(ref) => {
|
||||||
flashMode: CameraManager.FlashMode,
|
if (ref) {
|
||||||
exposure: CameraManager.Exposure,
|
_cameraHandle = findNodeHandle(ref);
|
||||||
autoFocus: CameraManager.AutoFocus,
|
} else {
|
||||||
whiteBalance: CameraManager.WhiteBalance,
|
_cameraRef = null;
|
||||||
faceDetectionMode: (CameraManager.FaceDetection || {}).Mode,
|
_cameraHandle = null;
|
||||||
faceDetectionLandmarks: (CameraManager.FaceDetection || {}).Landmarks,
|
}
|
||||||
faceDetectionClassifications: (CameraManager.FaceDetection || {}).Classifications,
|
|
||||||
googleVisionBarcodeType: (CameraManager.GoogleVisionBarcodeDetection || {}).BarcodeType,
|
|
||||||
videoStabilizationMode: CameraManager.VideoStabilization || {},
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
...ViewPropTypes,
|
|
||||||
zoom: PropTypes.number,
|
|
||||||
maxZoom: PropTypes.number,
|
|
||||||
ratio: PropTypes.string,
|
|
||||||
focusDepth: PropTypes.number,
|
|
||||||
onMountError: PropTypes.func,
|
|
||||||
onCameraReady: PropTypes.func,
|
|
||||||
onAudioInterrupted: PropTypes.func,
|
|
||||||
onAudioConnected: PropTypes.func,
|
|
||||||
onStatusChange: PropTypes.func,
|
|
||||||
onBarCodeRead: PropTypes.func,
|
|
||||||
onPictureTaken: PropTypes.func,
|
|
||||||
onPictureSaved: PropTypes.func,
|
|
||||||
onGoogleVisionBarcodesDetected: PropTypes.func,
|
|
||||||
onFacesDetected: PropTypes.func,
|
|
||||||
onTextRecognized: PropTypes.func,
|
|
||||||
onSubjectAreaChanged: PropTypes.func,
|
|
||||||
trackingEnabled: PropTypes.bool,
|
|
||||||
faceDetectionMode: PropTypes.number,
|
|
||||||
faceDetectionLandmarks: PropTypes.number,
|
|
||||||
faceDetectionClassifications: PropTypes.number,
|
|
||||||
barCodeTypes: PropTypes.arrayOf(PropTypes.string),
|
|
||||||
googleVisionBarcodeType: PropTypes.number,
|
|
||||||
googleVisionBarcodeMode: PropTypes.number,
|
|
||||||
type: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
cameraId: PropTypes.string,
|
|
||||||
flashMode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
exposure: PropTypes.number,
|
|
||||||
whiteBalance: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
autoFocus: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
|
|
||||||
autoFocusPointOfInterest: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }),
|
|
||||||
permissionDialogTitle: PropTypes.string,
|
|
||||||
permissionDialogMessage: PropTypes.string,
|
|
||||||
androidCameraPermissionOptions: Rationale,
|
|
||||||
androidRecordAudioPermissionOptions: Rationale,
|
|
||||||
notAuthorizedView: PropTypes.element,
|
|
||||||
pendingAuthorizationView: PropTypes.element,
|
|
||||||
captureAudio: PropTypes.bool,
|
|
||||||
keepAudioSession: PropTypes.bool,
|
|
||||||
useCamera2Api: PropTypes.bool,
|
|
||||||
playSoundOnCapture: PropTypes.bool,
|
|
||||||
videoStabilizationMode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
pictureSize: PropTypes.string,
|
|
||||||
mirrorVideo: PropTypes.bool,
|
|
||||||
rectOfInterest: PropTypes.any,
|
|
||||||
defaultVideoQuality: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps: Object = {
|
|
||||||
zoom: 0,
|
|
||||||
maxZoom: 0,
|
|
||||||
ratio: '4:3',
|
|
||||||
focusDepth: 0,
|
|
||||||
type: CameraManager.Type.back,
|
|
||||||
cameraId: null,
|
|
||||||
autoFocus: CameraManager.AutoFocus.on,
|
|
||||||
flashMode: CameraManager.FlashMode.off,
|
|
||||||
exposure: -1,
|
|
||||||
whiteBalance: CameraManager.WhiteBalance.auto,
|
|
||||||
faceDetectionMode: (CameraManager.FaceDetection || {}).fast,
|
|
||||||
barCodeTypes: Object.values(CameraManager.BarCodeType),
|
|
||||||
googleVisionBarcodeType: ((CameraManager.GoogleVisionBarcodeDetection || {}).BarcodeType || {})
|
|
||||||
.None,
|
|
||||||
googleVisionBarcodeMode: ((CameraManager.GoogleVisionBarcodeDetection || {}).BarcodeMode || {})
|
|
||||||
.NORMAL,
|
|
||||||
faceDetectionLandmarks: ((CameraManager.FaceDetection || {}).Landmarks || {}).none,
|
|
||||||
faceDetectionClassifications: ((CameraManager.FaceDetection || {}).Classifications || {}).none,
|
|
||||||
permissionDialogTitle: '',
|
|
||||||
permissionDialogMessage: '',
|
|
||||||
androidCameraPermissionOptions: {
|
|
||||||
title: '',
|
|
||||||
message: '',
|
|
||||||
},
|
},
|
||||||
androidRecordAudioPermissionOptions: {
|
[_cameraRef, _cameraHandle],
|
||||||
title: '',
|
);
|
||||||
message: '',
|
const _onMountError = useCallback(
|
||||||
|
({ nativeEvent }: EventCallbackArgumentsType) => {
|
||||||
|
if (props.onMountError) {
|
||||||
|
props.onMountError(nativeEvent);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
notAuthorizedView: (
|
[props.onMountError],
|
||||||
<View style={styles.authorizationContainer}>
|
);
|
||||||
<Text style={styles.notAuthorizedText}>Camera not authorized</Text>
|
const _onCameraReady = useCallback(() => {
|
||||||
</View>
|
if (props.onCameraReady) {
|
||||||
),
|
props.onCameraReady();
|
||||||
pendingAuthorizationView: (
|
}
|
||||||
<View style={styles.authorizationContainer}>
|
}, [props.onCameraReady]);
|
||||||
<ActivityIndicator size="small" />
|
const _onAudioInterrupted = useCallback(() => {
|
||||||
</View>
|
if (props.onAudioInterrupted) {
|
||||||
),
|
props.onAudioInterrupted();
|
||||||
captureAudio: true,
|
}
|
||||||
keepAudioSession: false,
|
}, [props.onAudioInterrupted]);
|
||||||
useCamera2Api: false,
|
const _onAudioConnected = useCallback(() => {
|
||||||
playSoundOnCapture: false,
|
if (props.onAudioConnected) {
|
||||||
pictureSize: 'None',
|
props.onAudioConnected();
|
||||||
videoStabilizationMode: 0,
|
}
|
||||||
mirrorVideo: false,
|
}, [props.onAudioConnected]);
|
||||||
|
const _onObjectDetected = useCallback(
|
||||||
|
(callback: ?Function) => ({ nativeEvent }: EventCallbackArgumentsType) => {
|
||||||
|
const { type } = nativeEvent;
|
||||||
|
if (
|
||||||
|
_lastEvents[type] &&
|
||||||
|
_lastEventsTimes[type] &&
|
||||||
|
JSON.stringify(nativeEvent) === _lastEvents[type] &&
|
||||||
|
new Date() - _lastEventsTimes[type] < EventThrottleMs
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
callback(nativeEvent);
|
||||||
|
_lastEventsTimes[type] = new Date();
|
||||||
|
_lastEvents[type] = JSON.stringify(nativeEvent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const _onPictureSaved = useCallback(
|
||||||
|
({ nativeEvent }: EventCallbackArgumentsType) => {
|
||||||
|
if (props.onPictureSaved) {
|
||||||
|
props.onPictureSaved(nativeEvent);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[props.onPictureSaved],
|
||||||
|
);
|
||||||
|
const _onSubjectAreaChanged = useCallback(
|
||||||
|
e => () => {
|
||||||
|
if (props.onSubjectAreaChanged) {
|
||||||
|
props.onSubjectAreaChanged(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[props.onSubjectAreaChanged],
|
||||||
|
);
|
||||||
|
const getStatus = useMemo(() => {
|
||||||
|
if (isAuthorizationChecked === false) {
|
||||||
|
return CameraStatus.PENDING_AUTHORIZATION;
|
||||||
|
}
|
||||||
|
return isAuthorized ? CameraStatus.READY : CameraStatus.NOT_AUTHORIZED;
|
||||||
|
}, [isAuthorizationChecked, isAuthorized]);
|
||||||
|
const renderChildren = useMemo(() => {
|
||||||
|
if (hasFaCC) {
|
||||||
|
return props.children({
|
||||||
|
camera: this,
|
||||||
|
status: getStatus,
|
||||||
|
recordAudioPermissionStatus: recordAudioPermissionStatus,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return props.children;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const { style, ...nativeProps } = convertNativeProps(props);
|
||||||
|
|
||||||
|
const arePermissionsGranted = async () => {
|
||||||
|
const {
|
||||||
|
permissionDialogTitle,
|
||||||
|
permissionDialogMessage,
|
||||||
|
androidCameraPermissionOptions,
|
||||||
|
androidRecordAudioPermissionOptions,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
let cameraPermissions = androidCameraPermissionOptions;
|
||||||
|
let audioPermissions = androidRecordAudioPermissionOptions;
|
||||||
|
if (permissionDialogTitle || permissionDialogMessage) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
'permissionDialogTitle and permissionDialogMessage are deprecated. Please use androidCameraPermissionOptions instead.',
|
||||||
|
);
|
||||||
|
cameraPermissions = {
|
||||||
|
...cameraPermissions,
|
||||||
|
title: permissionDialogTitle,
|
||||||
|
message: permissionDialogMessage,
|
||||||
|
};
|
||||||
|
audioPermissions = {
|
||||||
|
...audioPermissions,
|
||||||
|
title: permissionDialogTitle,
|
||||||
|
message: permissionDialogMessage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { hasCameraPermissions, hasRecordAudioPermissions } = await requestPermissions(
|
||||||
|
props.captureAudio,
|
||||||
|
CameraManager,
|
||||||
|
cameraPermissions,
|
||||||
|
audioPermissions,
|
||||||
|
);
|
||||||
|
|
||||||
|
const recordAudioPermissionStatus = hasRecordAudioPermissions
|
||||||
|
? RecordAudioPermissionStatusEnum.AUTHORIZED
|
||||||
|
: RecordAudioPermissionStatusEnum.NOT_AUTHORIZED;
|
||||||
|
return { hasCameraPermissions, recordAudioPermissionStatus };
|
||||||
};
|
};
|
||||||
|
|
||||||
_cameraRef: ?Object;
|
const refreshAuthorizationStatus = async () => {
|
||||||
_cameraHandle: ?number;
|
const { hasCameraPermissions, recordAudioPermissionStatus } = await arePermissionsGranted();
|
||||||
_lastEvents: { [string]: string };
|
if (_isMounted === false) {
|
||||||
_lastEventsTimes: { [string]: Date };
|
return;
|
||||||
_isMounted: boolean;
|
}
|
||||||
|
|
||||||
constructor(props: PropsType) {
|
setIsAuthorized(hasCameraPermissions);
|
||||||
super(props);
|
setIsAuthorizationChecked(true);
|
||||||
this._lastEvents = {};
|
setRecordAudioPermissionStatus(recordAudioPermissionStatus);
|
||||||
this._lastEventsTimes = {};
|
};
|
||||||
this._isMounted = true;
|
|
||||||
this.state = {
|
|
||||||
isAuthorized: false,
|
|
||||||
isAuthorizationChecked: false,
|
|
||||||
recordAudioPermissionStatus: RecordAudioPermissionStatusEnum.PENDING_AUTHORIZATION,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async takePictureAsync(options?: PictureOptions) {
|
const _onStatusChange = useCallback(() => {
|
||||||
|
if (props.onStatusChange) {
|
||||||
|
props.onStatusChange({
|
||||||
|
cameraStatus: getStatus(),
|
||||||
|
recordAudioPermissionStatus,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [props.onStatusChange]);
|
||||||
|
|
||||||
|
const stopRecording = useCallback(() => {
|
||||||
|
CameraManager.stopRecording(_cameraHandle);
|
||||||
|
}, [_cameraHandle]);
|
||||||
|
|
||||||
|
const pausePreview = useCallback(() => {
|
||||||
|
CameraManager.pausePreview(_cameraHandle);
|
||||||
|
}, [_cameraHandle]);
|
||||||
|
|
||||||
|
const isRecording = useCallback(() => {
|
||||||
|
return CameraManager.isRecording(_cameraHandle);
|
||||||
|
}, [_cameraHandle]);
|
||||||
|
|
||||||
|
const resumePreview = useCallback(() => {
|
||||||
|
CameraManager.resumePreview(_cameraHandle);
|
||||||
|
}, [_cameraHandle]);
|
||||||
|
|
||||||
|
const takePicture = async (options?: PictureOptions) => {
|
||||||
if (!options) {
|
if (!options) {
|
||||||
options = {};
|
options = {};
|
||||||
}
|
}
|
||||||
@ -519,35 +618,35 @@ export default class Camera extends React.Component<PropsType, StateType> {
|
|||||||
options.pauseAfterCapture = false;
|
options.pauseAfterCapture = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._cameraHandle) {
|
if (!_cameraHandle) {
|
||||||
throw 'Camera handle cannot be null';
|
throw 'Camera handle cannot be null';
|
||||||
}
|
}
|
||||||
|
|
||||||
return await CameraManager.takePicture(options, this._cameraHandle);
|
return await CameraManager.takePicture(options, _cameraHandle);
|
||||||
}
|
};
|
||||||
|
|
||||||
async getSupportedRatiosAsync() {
|
const getSupportedRatiosAsync = async () => {
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
return await CameraManager.getSupportedRatios(this._cameraHandle);
|
return await CameraManager.getSupportedRatios(_cameraHandle);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Ratio is not supported on iOS');
|
throw new Error('Ratio is not supported on iOS');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
async getCameraIdsAsync() {
|
const getCameraIdsAsync = async () => {
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
return await CameraManager.getCameraIds(this._cameraHandle);
|
return await CameraManager.getCameraIds(_cameraHandle);
|
||||||
} else {
|
} else {
|
||||||
return await CameraManager.getCameraIds(); // iOS does not need a camera instance
|
return await CameraManager.getCameraIds(); // iOS does not need a camera instance
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
getAvailablePictureSizes = async (): string[] => {
|
|
||||||
//$FlowFixMe
|
|
||||||
return await CameraManager.getAvailablePictureSizes(this.props.ratio, this._cameraHandle);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async recordAsync(options?: RecordingOptions) {
|
const getAvailablePictureSizes = async (): string[] => {
|
||||||
|
//$FlowFixMe
|
||||||
|
return await CameraManager.getAvailablePictureSizes(props.ratio, _cameraHandle);
|
||||||
|
};
|
||||||
|
|
||||||
|
const recordAsync = async (options?: RecordingOptions) => {
|
||||||
if (!options || typeof options !== 'object') {
|
if (!options || typeof options !== 'object') {
|
||||||
options = {};
|
options = {};
|
||||||
} else if (typeof options.quality === 'string') {
|
} else if (typeof options.quality === 'string') {
|
||||||
@ -573,8 +672,7 @@ export default class Camera extends React.Component<PropsType, StateType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { recordAudioPermissionStatus } = this.state;
|
const { captureAudio } = props;
|
||||||
const { captureAudio } = this.props;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!captureAudio ||
|
!captureAudio ||
|
||||||
@ -593,269 +691,153 @@ export default class Camera extends React.Component<PropsType, StateType> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return await CameraManager.record(options, this._cameraHandle);
|
return await CameraManager.record(options, _cameraHandle);
|
||||||
}
|
|
||||||
|
|
||||||
stopRecording() {
|
|
||||||
CameraManager.stopRecording(this._cameraHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
pausePreview() {
|
|
||||||
CameraManager.pausePreview(this._cameraHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
isRecording() {
|
|
||||||
return CameraManager.isRecording(this._cameraHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
resumePreview() {
|
|
||||||
CameraManager.resumePreview(this._cameraHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMountError = ({ nativeEvent }: EventCallbackArgumentsType) => {
|
|
||||||
if (this.props.onMountError) {
|
|
||||||
this.props.onMountError(nativeEvent);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_onCameraReady = () => {
|
useEffect(() => {
|
||||||
if (this.props.onCameraReady) {
|
async function getPermissionsAndSetState() {
|
||||||
this.props.onCameraReady();
|
const { hasCameraPermissions, recordAudioPermissionStatus } = await arePermissionsGranted();
|
||||||
}
|
if (_isMounted === false) {
|
||||||
};
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_onAudioInterrupted = () => {
|
setIsAuthorized(hasCameraPermissions);
|
||||||
if (this.props.onAudioInterrupted) {
|
setIsAuthorizationChecked(true);
|
||||||
this.props.onAudioInterrupted();
|
setRecordAudioPermissionStatus(recordAudioPermissionStatus);
|
||||||
}
|
_onStatusChange();
|
||||||
};
|
|
||||||
|
|
||||||
_onAudioConnected = () => {
|
|
||||||
if (this.props.onAudioConnected) {
|
|
||||||
this.props.onAudioConnected();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_onStatusChange = () => {
|
|
||||||
if (this.props.onStatusChange) {
|
|
||||||
this.props.onStatusChange({
|
|
||||||
cameraStatus: this.getStatus(),
|
|
||||||
recordAudioPermissionStatus: this.state.recordAudioPermissionStatus,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_onPictureSaved = ({ nativeEvent }: EventCallbackArgumentsType) => {
|
|
||||||
if (this.props.onPictureSaved) {
|
|
||||||
this.props.onPictureSaved(nativeEvent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_onObjectDetected = (callback: ?Function) => ({ nativeEvent }: EventCallbackArgumentsType) => {
|
|
||||||
const { type } = nativeEvent;
|
|
||||||
if (
|
|
||||||
this._lastEvents[type] &&
|
|
||||||
this._lastEventsTimes[type] &&
|
|
||||||
JSON.stringify(nativeEvent) === this._lastEvents[type] &&
|
|
||||||
new Date() - this._lastEventsTimes[type] < EventThrottleMs
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
getPermissionsAndSetState();
|
||||||
callback(nativeEvent);
|
|
||||||
this._lastEventsTimes[type] = new Date();
|
|
||||||
this._lastEvents[type] = JSON.stringify(nativeEvent);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
_onSubjectAreaChanged = e => {
|
return () => {
|
||||||
if (this.props.onSubjectAreaChanged) {
|
_isMounted = false;
|
||||||
this.props.onSubjectAreaChanged(e);
|
};
|
||||||
}
|
}, []);
|
||||||
};
|
|
||||||
|
|
||||||
_setReference = (ref: ?Object) => {
|
if (isAuthorized || hasFaCC) {
|
||||||
if (ref) {
|
return (
|
||||||
this._cameraRef = ref;
|
<View style={style}>
|
||||||
this._cameraHandle = findNodeHandle(ref);
|
<RNCamera
|
||||||
} else {
|
{...nativeProps}
|
||||||
this._cameraRef = null;
|
style={StyleSheet.absoluteFill}
|
||||||
this._cameraHandle = null;
|
ref={cameraRef}
|
||||||
}
|
onMountError={_onMountError}
|
||||||
};
|
onCameraReady={_onCameraReady}
|
||||||
|
onAudioInterrupted={_onAudioInterrupted}
|
||||||
componentWillUnmount() {
|
onAudioConnected={_onAudioConnected}
|
||||||
this._isMounted = false;
|
onGoogleVisionBarcodesDetected={_onObjectDetected(props.onGoogleVisionBarcodesDetected)}
|
||||||
}
|
onBarCodeRead={_onObjectDetected(props.onBarCodeRead)}
|
||||||
|
onFacesDetected={_onObjectDetected(props.onFacesDetected)}
|
||||||
async arePermissionsGranted() {
|
onTextRecognized={_onObjectDetected(props.onTextRecognized)}
|
||||||
const {
|
onPictureSaved={_onPictureSaved}
|
||||||
permissionDialogTitle,
|
onSubjectAreaChanged={_onSubjectAreaChanged}
|
||||||
permissionDialogMessage,
|
/>
|
||||||
androidCameraPermissionOptions,
|
{renderChildren}
|
||||||
androidRecordAudioPermissionOptions,
|
</View>
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
let cameraPermissions = androidCameraPermissionOptions;
|
|
||||||
let audioPermissions = androidRecordAudioPermissionOptions;
|
|
||||||
if (permissionDialogTitle || permissionDialogMessage) {
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.warn(
|
|
||||||
'permissionDialogTitle and permissionDialogMessage are deprecated. Please use androidCameraPermissionOptions instead.',
|
|
||||||
);
|
|
||||||
cameraPermissions = {
|
|
||||||
...cameraPermissions,
|
|
||||||
title: permissionDialogTitle,
|
|
||||||
message: permissionDialogMessage,
|
|
||||||
};
|
|
||||||
audioPermissions = {
|
|
||||||
...audioPermissions,
|
|
||||||
title: permissionDialogTitle,
|
|
||||||
message: permissionDialogMessage,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const { hasCameraPermissions, hasRecordAudioPermissions } = await requestPermissions(
|
|
||||||
this.props.captureAudio,
|
|
||||||
CameraManager,
|
|
||||||
cameraPermissions,
|
|
||||||
audioPermissions,
|
|
||||||
);
|
);
|
||||||
|
} else if (!isAuthorizationChecked) {
|
||||||
const recordAudioPermissionStatus = hasRecordAudioPermissions
|
return props.pendingAuthorizationView;
|
||||||
? RecordAudioPermissionStatusEnum.AUTHORIZED
|
} else {
|
||||||
: RecordAudioPermissionStatusEnum.NOT_AUTHORIZED;
|
return props.notAuthorizedView;
|
||||||
return { hasCameraPermissions, recordAudioPermissionStatus };
|
|
||||||
}
|
|
||||||
|
|
||||||
async refreshAuthorizationStatus() {
|
|
||||||
const {
|
|
||||||
hasCameraPermissions,
|
|
||||||
recordAudioPermissionStatus,
|
|
||||||
} = await this.arePermissionsGranted();
|
|
||||||
if (this._isMounted === false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
isAuthorized: hasCameraPermissions,
|
|
||||||
isAuthorizationChecked: true,
|
|
||||||
recordAudioPermissionStatus,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async componentDidMount() {
|
|
||||||
const {
|
|
||||||
hasCameraPermissions,
|
|
||||||
recordAudioPermissionStatus,
|
|
||||||
} = await this.arePermissionsGranted();
|
|
||||||
if (this._isMounted === false) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
isAuthorized: hasCameraPermissions,
|
|
||||||
isAuthorizationChecked: true,
|
|
||||||
recordAudioPermissionStatus,
|
|
||||||
},
|
|
||||||
this._onStatusChange,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getStatus = (): Status => {
|
|
||||||
const { isAuthorized, isAuthorizationChecked } = this.state;
|
|
||||||
if (isAuthorizationChecked === false) {
|
|
||||||
return CameraStatus.PENDING_AUTHORIZATION;
|
|
||||||
}
|
|
||||||
return isAuthorized ? CameraStatus.READY : CameraStatus.NOT_AUTHORIZED;
|
|
||||||
};
|
|
||||||
|
|
||||||
// FaCC = Function as Child Component;
|
|
||||||
hasFaCC = (): * => typeof this.props.children === 'function';
|
|
||||||
|
|
||||||
renderChildren = (): * => {
|
|
||||||
if (this.hasFaCC()) {
|
|
||||||
return this.props.children({
|
|
||||||
camera: this,
|
|
||||||
status: this.getStatus(),
|
|
||||||
recordAudioPermissionStatus: this.state.recordAudioPermissionStatus,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return this.props.children;
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { style, ...nativeProps } = this._convertNativeProps(this.props);
|
|
||||||
|
|
||||||
if (this.state.isAuthorized || this.hasFaCC()) {
|
|
||||||
return (
|
|
||||||
<View style={style}>
|
|
||||||
<RNCamera
|
|
||||||
{...nativeProps}
|
|
||||||
style={StyleSheet.absoluteFill}
|
|
||||||
ref={this._setReference}
|
|
||||||
onMountError={this._onMountError}
|
|
||||||
onCameraReady={this._onCameraReady}
|
|
||||||
onAudioInterrupted={this._onAudioInterrupted}
|
|
||||||
onAudioConnected={this._onAudioConnected}
|
|
||||||
onGoogleVisionBarcodesDetected={this._onObjectDetected(
|
|
||||||
this.props.onGoogleVisionBarcodesDetected,
|
|
||||||
)}
|
|
||||||
onBarCodeRead={this._onObjectDetected(this.props.onBarCodeRead)}
|
|
||||||
onFacesDetected={this._onObjectDetected(this.props.onFacesDetected)}
|
|
||||||
onTextRecognized={this._onObjectDetected(this.props.onTextRecognized)}
|
|
||||||
onPictureSaved={this._onPictureSaved}
|
|
||||||
onSubjectAreaChanged={this._onSubjectAreaChanged}
|
|
||||||
/>
|
|
||||||
{this.renderChildren()}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
} else if (!this.state.isAuthorizationChecked) {
|
|
||||||
return this.props.pendingAuthorizationView;
|
|
||||||
} else {
|
|
||||||
return this.props.notAuthorizedView;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_convertNativeProps({ children, ...props }: PropsType) {
|
|
||||||
const newProps = mapValues(props, this._convertProp);
|
|
||||||
|
|
||||||
if (props.onBarCodeRead) {
|
|
||||||
newProps.barCodeScannerEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.onGoogleVisionBarcodesDetected) {
|
|
||||||
newProps.googleVisionBarcodeDetectorEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.onFacesDetected) {
|
|
||||||
newProps.faceDetectorEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.onTextRecognized) {
|
|
||||||
newProps.textRecognizerEnabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Platform.OS === 'ios') {
|
|
||||||
delete newProps.googleVisionBarcodeMode;
|
|
||||||
delete newProps.ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newProps;
|
|
||||||
}
|
|
||||||
|
|
||||||
_convertProp(value: *, key: string): * {
|
|
||||||
if (typeof value === 'string' && Camera.ConversionTables[key]) {
|
|
||||||
return Camera.ConversionTables[key][value];
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Constants = Camera.Constants;
|
Camera.propTypes = {
|
||||||
|
...ViewPropTypes,
|
||||||
|
zoom: PropTypes.number,
|
||||||
|
maxZoom: PropTypes.number,
|
||||||
|
ratio: PropTypes.string,
|
||||||
|
focusDepth: PropTypes.number,
|
||||||
|
onMountError: PropTypes.func,
|
||||||
|
onCameraReady: PropTypes.func,
|
||||||
|
onAudioInterrupted: PropTypes.func,
|
||||||
|
onAudioConnected: PropTypes.func,
|
||||||
|
onStatusChange: PropTypes.func,
|
||||||
|
onBarCodeRead: PropTypes.func,
|
||||||
|
onPictureTaken: PropTypes.func,
|
||||||
|
onPictureSaved: PropTypes.func,
|
||||||
|
onGoogleVisionBarcodesDetected: PropTypes.func,
|
||||||
|
onFacesDetected: PropTypes.func,
|
||||||
|
onTextRecognized: PropTypes.func,
|
||||||
|
onSubjectAreaChanged: PropTypes.func,
|
||||||
|
trackingEnabled: PropTypes.bool,
|
||||||
|
faceDetectionMode: PropTypes.number,
|
||||||
|
faceDetectionLandmarks: PropTypes.number,
|
||||||
|
faceDetectionClassifications: PropTypes.number,
|
||||||
|
barCodeTypes: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
googleVisionBarcodeType: PropTypes.number,
|
||||||
|
googleVisionBarcodeMode: PropTypes.number,
|
||||||
|
type: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
cameraId: PropTypes.string,
|
||||||
|
flashMode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
exposure: PropTypes.number,
|
||||||
|
whiteBalance: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
autoFocus: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
|
||||||
|
autoFocusPointOfInterest: PropTypes.shape({ x: PropTypes.number, y: PropTypes.number }),
|
||||||
|
permissionDialogTitle: PropTypes.string,
|
||||||
|
permissionDialogMessage: PropTypes.string,
|
||||||
|
androidCameraPermissionOptions: Rationale,
|
||||||
|
androidRecordAudioPermissionOptions: Rationale,
|
||||||
|
notAuthorizedView: PropTypes.element,
|
||||||
|
pendingAuthorizationView: PropTypes.element,
|
||||||
|
captureAudio: PropTypes.bool,
|
||||||
|
keepAudioSession: PropTypes.bool,
|
||||||
|
useCamera2Api: PropTypes.bool,
|
||||||
|
playSoundOnCapture: PropTypes.bool,
|
||||||
|
videoStabilizationMode: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
pictureSize: PropTypes.string,
|
||||||
|
mirrorVideo: PropTypes.bool,
|
||||||
|
rectOfInterest: PropTypes.any,
|
||||||
|
defaultVideoQuality: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
};
|
||||||
|
|
||||||
|
Camera.defaultProps = {
|
||||||
|
zoom: 0,
|
||||||
|
maxZoom: 0,
|
||||||
|
ratio: '4:3',
|
||||||
|
focusDepth: 0,
|
||||||
|
type: CameraManager.Type.back,
|
||||||
|
cameraId: null,
|
||||||
|
autoFocus: CameraManager.AutoFocus.on,
|
||||||
|
flashMode: CameraManager.FlashMode.off,
|
||||||
|
exposure: -1,
|
||||||
|
whiteBalance: CameraManager.WhiteBalance.auto,
|
||||||
|
faceDetectionMode: (CameraManager.FaceDetection || {}).fast,
|
||||||
|
barCodeTypes: Object.values(CameraManager.BarCodeType),
|
||||||
|
googleVisionBarcodeType: ((CameraManager.GoogleVisionBarcodeDetection || {}).BarcodeType || {})
|
||||||
|
.None,
|
||||||
|
googleVisionBarcodeMode: ((CameraManager.GoogleVisionBarcodeDetection || {}).BarcodeMode || {})
|
||||||
|
.NORMAL,
|
||||||
|
faceDetectionLandmarks: ((CameraManager.FaceDetection || {}).Landmarks || {}).none,
|
||||||
|
faceDetectionClassifications: ((CameraManager.FaceDetection || {}).Classifications || {}).none,
|
||||||
|
permissionDialogTitle: '',
|
||||||
|
permissionDialogMessage: '',
|
||||||
|
androidCameraPermissionOptions: {
|
||||||
|
title: '',
|
||||||
|
message: '',
|
||||||
|
},
|
||||||
|
androidRecordAudioPermissionOptions: {
|
||||||
|
title: '',
|
||||||
|
message: '',
|
||||||
|
},
|
||||||
|
notAuthorizedView: (
|
||||||
|
<View style={styles.authorizationContainer}>
|
||||||
|
<Text style={styles.notAuthorizedText}>Camera not authorized</Text>
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
pendingAuthorizationView: (
|
||||||
|
<View style={styles.authorizationContainer}>
|
||||||
|
<ActivityIndicator size="small" />
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
captureAudio: true,
|
||||||
|
keepAudioSession: false,
|
||||||
|
useCamera2Api: false,
|
||||||
|
playSoundOnCapture: false,
|
||||||
|
pictureSize: 'None',
|
||||||
|
videoStabilizationMode: 0,
|
||||||
|
mirrorVideo: false,
|
||||||
|
};
|
||||||
|
|
||||||
const RNCamera = requireNativeComponent('RNCamera', Camera, {
|
const RNCamera = requireNativeComponent('RNCamera', Camera, {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import RNCamera, { type Status as _CameraStatus } from './RNCamera';
|
import RNCamera, {
|
||||||
|
type Status as _CameraStatus,
|
||||||
|
Constants as RNCConstants,
|
||||||
|
ConversionTables,
|
||||||
|
} from './RNCamera';
|
||||||
import FaceDetector from './FaceDetector';
|
import FaceDetector from './FaceDetector';
|
||||||
|
|
||||||
export type CameraStatus = _CameraStatus;
|
export type CameraStatus = _CameraStatus;
|
||||||
export { RNCamera, FaceDetector };
|
export { RNCamera, FaceDetector, RNCConstants, ConversionTables };
|
||||||
|
|||||||
70
types/index.d.ts
vendored
70
types/index.d.ts
vendored
@ -94,13 +94,11 @@ type RecordAudioPermissionStatus = Readonly<
|
|||||||
NOT_AUTHORIZED: 'NOT_AUTHORIZED';
|
NOT_AUTHORIZED: 'NOT_AUTHORIZED';
|
||||||
}>
|
}>
|
||||||
>;
|
>;
|
||||||
type FaCC = (
|
type FaCC = (params: {
|
||||||
params: {
|
|
||||||
camera: RNCamera;
|
camera: RNCamera;
|
||||||
status: keyof CameraStatus;
|
status: keyof CameraStatus;
|
||||||
recordAudioPermissionStatus: keyof RecordAudioPermissionStatus;
|
recordAudioPermissionStatus: keyof RecordAudioPermissionStatus;
|
||||||
},
|
}) => JSX.Element;
|
||||||
) => JSX.Element;
|
|
||||||
|
|
||||||
export interface Constants {
|
export interface Constants {
|
||||||
CameraStatus: CameraStatus;
|
CameraStatus: CameraStatus;
|
||||||
@ -135,7 +133,7 @@ export interface RNCameraProps {
|
|||||||
autoFocus?: keyof AutoFocus;
|
autoFocus?: keyof AutoFocus;
|
||||||
autoFocusPointOfInterest?: Point;
|
autoFocusPointOfInterest?: Point;
|
||||||
/* iOS only */
|
/* iOS only */
|
||||||
onSubjectAreaChanged?: (event: { nativeEvent: { prevPoint: { x: number; y: number; } } }) => void;
|
onSubjectAreaChanged?: (event: { nativeEvent: { prevPoint: { x: number; y: number } } }) => void;
|
||||||
type?: keyof CameraType;
|
type?: keyof CameraType;
|
||||||
flashMode?: keyof FlashMode;
|
flashMode?: keyof FlashMode;
|
||||||
notAuthorizedView?: JSX.Element;
|
notAuthorizedView?: JSX.Element;
|
||||||
@ -178,12 +176,12 @@ export interface RNCameraProps {
|
|||||||
* @description For Android use `{ width: number, height: number, origin: Array<Point<string>> }`
|
* @description For Android use `{ width: number, height: number, origin: Array<Point<string>> }`
|
||||||
* @description For iOS use `{ origin: Point<string>, size: Size<string> }`
|
* @description For iOS use `{ origin: Point<string>, size: Size<string> }`
|
||||||
*/
|
*/
|
||||||
bounds: { width: number, height: number, origin: Array<Point<string>> } | { origin: Point<string>; size: Size<string> };
|
bounds:
|
||||||
|
| { width: number; height: number; origin: Array<Point<string>> }
|
||||||
|
| { origin: Point<string>; size: Size<string> };
|
||||||
}): void;
|
}): void;
|
||||||
|
|
||||||
onGoogleVisionBarcodesDetected?(event: {
|
onGoogleVisionBarcodesDetected?(event: { barcodes: Barcode[] }): void;
|
||||||
barcodes: Barcode[];
|
|
||||||
}): void;
|
|
||||||
|
|
||||||
// -- FACE DETECTION PROPS
|
// -- FACE DETECTION PROPS
|
||||||
|
|
||||||
@ -257,9 +255,9 @@ export interface Barcode {
|
|||||||
firstName?: string;
|
firstName?: string;
|
||||||
lastName?: string;
|
lastName?: string;
|
||||||
middleName?: string;
|
middleName?: string;
|
||||||
prefix?:string;
|
prefix?: string;
|
||||||
pronounciation?:string;
|
pronounciation?: string;
|
||||||
suffix?:string;
|
suffix?: string;
|
||||||
formattedName?: string;
|
formattedName?: string;
|
||||||
};
|
};
|
||||||
phone?: Phone;
|
phone?: Phone;
|
||||||
@ -298,29 +296,29 @@ export interface Barcode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type BarcodeType =
|
export type BarcodeType =
|
||||||
|"EMAIL"
|
|'EMAIL'
|
||||||
|"PHONE"
|
|'PHONE'
|
||||||
|"CALENDAR_EVENT"
|
|'CALENDAR_EVENT'
|
||||||
|"DRIVER_LICENSE"
|
|'DRIVER_LICENSE'
|
||||||
|"GEO"
|
|'GEO'
|
||||||
|"SMS"
|
|'SMS'
|
||||||
|"CONTACT_INFO"
|
|'CONTACT_INFO'
|
||||||
|"WIFI"
|
|'WIFI'
|
||||||
|"TEXT"
|
|'TEXT'
|
||||||
|"ISBN"
|
|'ISBN'
|
||||||
|"PRODUCT"
|
|'PRODUCT'
|
||||||
|"URL"
|
|'URL'
|
||||||
|
|
||||||
export interface Email {
|
export interface Email {
|
||||||
address?: string;
|
address?: string;
|
||||||
body?: string;
|
body?: string;
|
||||||
subject?: string;
|
subject?: string;
|
||||||
emailType?: "UNKNOWN" | "Work" | "Home";
|
emailType?: 'UNKNOWN' | 'Work' | 'Home';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Phone {
|
export interface Phone {
|
||||||
number?: string;
|
number?: string;
|
||||||
phoneType?: "UNKNOWN" | "Work" | "Home" | "Fax" | "Mobile";
|
phoneType?: 'UNKNOWN' | 'Work' | 'Home' | 'Fax' | 'Mobile';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Face {
|
export interface Face {
|
||||||
@ -409,26 +407,8 @@ export interface RecordResponse {
|
|||||||
codec: VideoCodec[keyof VideoCodec];
|
codec: VideoCodec[keyof VideoCodec];
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RNCamera extends Component<RNCameraProps & ViewProperties> {
|
export function RNCamera(props: RNCameraProps & ViewProperties): Component;
|
||||||
static Constants: Constants;
|
|
||||||
|
|
||||||
_cameraRef: null | NativeMethodsMixinStatic;
|
|
||||||
_cameraHandle: ReturnType<typeof findNodeHandle>;
|
|
||||||
|
|
||||||
takePictureAsync(options?: TakePictureOptions): Promise<TakePictureResponse>;
|
|
||||||
recordAsync(options?: RecordOptions): Promise<RecordResponse>;
|
|
||||||
refreshAuthorizationStatus(): Promise<void>;
|
|
||||||
stopRecording(): void;
|
|
||||||
pausePreview(): void;
|
|
||||||
resumePreview(): void;
|
|
||||||
getAvailablePictureSizes(): Promise<string[]>;
|
|
||||||
|
|
||||||
/** Android only */
|
|
||||||
getSupportedRatiosAsync(): Promise<string[]>;
|
|
||||||
|
|
||||||
/** iOS only */
|
|
||||||
isRecording(): Promise<boolean>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DetectionOptions {
|
interface DetectionOptions {
|
||||||
mode?: keyof FaceDetectionMode;
|
mode?: keyof FaceDetectionMode;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user