mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2026-06-03 05:18:50 -04:00
* WIP: fetchPlaceName mock to workaround issue on Android phones without Play Services * Update vision-camera.js * Fixes an error while rendering this mock
177 lines
5.2 KiB
JavaScript
177 lines
5.2 KiB
JavaScript
import {
|
|
copyAssetsFileIOS,
|
|
copyFile,
|
|
ExternalDirectoryPath,
|
|
TemporaryDirectoryPath,
|
|
} from "@dr.pogodin/react-native-fs";
|
|
import { CameraRoll } from "@react-native-camera-roll/camera-roll";
|
|
import React from "react";
|
|
import { Platform, View } from "react-native";
|
|
|
|
const mockFrame = {
|
|
isValid: true,
|
|
width: 1920,
|
|
height: 1080,
|
|
bytesPerRow: 1920,
|
|
planesCount: 1,
|
|
isMirrored: false,
|
|
timestamp: 0,
|
|
orientation: "portrait",
|
|
pixelFormat: "yuv",
|
|
// Returns a fake ArrayBuffer
|
|
toArrayBuffer: () => new ArrayBuffer( 1920 * 1080 ),
|
|
toString: () => "Frame",
|
|
getNativeBuffer: () => ( {
|
|
// Returns a fake pointer
|
|
pointer: 0,
|
|
delete: () => null,
|
|
} ),
|
|
incrementRefCount: () => null,
|
|
decrementRefCount: () => null,
|
|
};
|
|
|
|
const style = { flex: 1, backgroundColor: "red" };
|
|
export class mockCamera extends React.PureComponent {
|
|
static async getAvailableCameraDevices() {
|
|
return [
|
|
{
|
|
position: "back",
|
|
},
|
|
];
|
|
}
|
|
|
|
/*
|
|
Every time the component updates we are running the frame processor that is a prop
|
|
to the camera component. We are running the frame processor with a mocked frame that
|
|
does not include any kind of image data at all.
|
|
Running it only on component update means it only is called a few times and not
|
|
every second (or so - depending on fps). This is enough to satisfy the e2e test
|
|
though because the mocked prediction needs to appear only once to be found by the
|
|
test matcher. I tried running it with a timer every second but since it never idles
|
|
the test never finishes.
|
|
*/
|
|
componentDidUpdate() {
|
|
const { frameProcessor, isActive } = this.props;
|
|
if ( isActive === false || !frameProcessor ) {
|
|
return;
|
|
}
|
|
frameProcessor.frameProcessor( mockFrame );
|
|
}
|
|
|
|
// eslint-disable-next-line class-methods-use-this, react/no-unused-class-component-methods
|
|
async takePhoto() {
|
|
if ( Platform.OS === "android" ) {
|
|
/*
|
|
On Android, copyAssetsFileIOS is not available. Instead, copy the test
|
|
image that was pushed to the app's external files directory by
|
|
iNatE2eBeforeAll (via `adb push e2e/animal.jpg`).
|
|
ExternalDirectoryPath = /sdcard/Android/data/<package>/files/
|
|
which is accessible by the app without extra permissions.
|
|
*/
|
|
const sourcePath = `${ExternalDirectoryPath}/e2e_test.jpg`;
|
|
const destPath = `${TemporaryDirectoryPath}/temp.jpg`;
|
|
try {
|
|
await copyFile( sourcePath, destPath );
|
|
return {
|
|
path: destPath,
|
|
metadata: { Orientation: 1 },
|
|
};
|
|
} catch ( err ) {
|
|
console.log( "Error copying test photo on Android:", err );
|
|
return null;
|
|
}
|
|
}
|
|
|
|
return CameraRoll.getPhotos( {
|
|
first: 20,
|
|
assetType: "Photos",
|
|
} )
|
|
.then( async r => {
|
|
/*
|
|
Basically, here, we are reading the newest twenty photos from the simulators gallery
|
|
and return the oldest one of those. Copy it to a new path and treat it as a new photo.
|
|
*/
|
|
const testPhoto = r.edges[r.edges.length - 1].node.image;
|
|
let oldUri = testPhoto.uri;
|
|
if ( testPhoto.uri.includes( "ph://" ) ) {
|
|
let id = testPhoto.uri.replace( "ph://", "" );
|
|
id = id.substring( 0, id.indexOf( "/" ) );
|
|
oldUri = `assets-library://asset/asset.jpg?id=${id}&ext=jpg`;
|
|
console.log( `Converted file uri to ${oldUri}` );
|
|
}
|
|
const encodedUri = encodeURI( oldUri );
|
|
const destPath = `${TemporaryDirectoryPath}/temp.jpg`;
|
|
const newPath = await copyAssetsFileIOS(
|
|
encodedUri,
|
|
destPath,
|
|
0,
|
|
0,
|
|
);
|
|
const photo = { uri: newPath, predictions: [] };
|
|
if ( typeof photo !== "object" ) {
|
|
console.log( "photo is not an object", typeof photo );
|
|
return null;
|
|
}
|
|
return {
|
|
...testPhoto,
|
|
path: newPath,
|
|
metadata: {
|
|
Orientation: testPhoto.orientation,
|
|
},
|
|
};
|
|
} )
|
|
.catch( err => {
|
|
console.log( "Error getting photos", err );
|
|
return null;
|
|
} );
|
|
}
|
|
|
|
render() {
|
|
return <View style={style} collapsable={false} />;
|
|
}
|
|
}
|
|
|
|
export const mockSortDevices = ( _left, _right ) => 1;
|
|
|
|
const device = {
|
|
physicalDevices: ["wide-angle-camera"],
|
|
hasFlash: true,
|
|
hasTorch: true,
|
|
id: "1",
|
|
isMultiCam: true,
|
|
maxZoom: 12.931958198547363,
|
|
minZoom: 1,
|
|
name: "front (1)",
|
|
neutralZoom: 1,
|
|
position: "front",
|
|
supportsDepthCapture: false,
|
|
supportsFocus: true,
|
|
supportsLowLightBoost: false,
|
|
supportsParallelVideoProcessing: true,
|
|
supportsRawCapture: true,
|
|
};
|
|
|
|
export const mockUseCameraDevice = _deviceType => device;
|
|
export const mockUseCameraDevices = () => [device];
|
|
|
|
export const mockUseCameraFormat = _device => {
|
|
const format = {
|
|
autoFocusSystem: "contrast-detection",
|
|
fieldOfView: 83.97117848314457,
|
|
maxFps: 60,
|
|
maxISO: 11377,
|
|
minFps: 15,
|
|
minISO: 44,
|
|
photoHeight: 3024,
|
|
photoWidth: 4032,
|
|
pixelFormats: ["yuv", "native"],
|
|
supportsDepthCapture: false,
|
|
supportsPhotoHdr: false,
|
|
supportsVideoHdr: false,
|
|
videoHeight: 2160,
|
|
videoStabilizationModes: ["off", "cinematic", "cinematic-extended"],
|
|
videoWidth: 3840,
|
|
};
|
|
return format;
|
|
};
|