advance hook: useCameraDevices

This commit is contained in:
Marc Rousavy 2021-02-22 09:43:47 +01:00
parent a6a465881a
commit 1ccbbae9e0
4 changed files with 31 additions and 21 deletions

View File

@ -57,7 +57,8 @@ npx pod-install
```tsx ```tsx
function App() { function App() {
const device = useCameraDevice('wide-angle-camera') const devices = useCameraDevices('wide-angle-camera')
const device = devices.back
return ( return (
<Camera <Camera

View File

@ -1,9 +1,19 @@
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { CameraRuntimeError } from 'src/CameraError'; import type { CameraPosition } from 'src/CameraPosition';
import { sortDevices } from 'src/utils/FormatFilter'; import { sortDevices } from 'src/utils/FormatFilter';
import { Camera } from '../Camera'; import { Camera } from '../Camera';
import { CameraDevice, LogicalCameraDeviceType, parsePhysicalDeviceTypes, PhysicalCameraDeviceType } from '../CameraDevice'; import { CameraDevice, LogicalCameraDeviceType, parsePhysicalDeviceTypes, PhysicalCameraDeviceType } from '../CameraDevice';
type CameraDevices = {
[key in CameraPosition]: CameraDevice | undefined;
};
const DefaultCameraDevices: CameraDevices = {
back: undefined,
external: undefined,
front: undefined,
unspecified: undefined,
};
/** /**
* Gets the best available `CameraDevice`. Devices with more cameras are preferred. * Gets the best available `CameraDevice`. Devices with more cameras are preferred.
* *
@ -14,7 +24,7 @@ import { CameraDevice, LogicalCameraDeviceType, parsePhysicalDeviceTypes, Physic
* // ... * // ...
* return <Camera device={device} /> * return <Camera device={device} />
*/ */
export function useCameraDevice(): CameraDevice; export function useCameraDevices(): CameraDevices;
/** /**
* Gets a `CameraDevice` for the requested device type. * Gets a `CameraDevice` for the requested device type.
@ -26,32 +36,31 @@ export function useCameraDevice(): CameraDevice;
* // ... * // ...
* return <Camera device={device} /> * return <Camera device={device} />
*/ */
export function useCameraDevice(deviceType: PhysicalCameraDeviceType | LogicalCameraDeviceType): CameraDevice | undefined; export function useCameraDevices(deviceType: PhysicalCameraDeviceType | LogicalCameraDeviceType): CameraDevices;
export function useCameraDevice(deviceType?: PhysicalCameraDeviceType | LogicalCameraDeviceType): CameraDevice | undefined { export function useCameraDevices(deviceType?: PhysicalCameraDeviceType | LogicalCameraDeviceType): CameraDevices {
const [device, setDevice] = useState<CameraDevice>(); const [cameraDevices, setCameraDevices] = useState<CameraDevices>(DefaultCameraDevices);
useEffect(() => { useEffect(() => {
let isMounted = true; let isMounted = true;
const loadDevice = async (): Promise<void> => { const loadDevice = async (): Promise<void> => {
const devices = await Camera.getAvailableCameraDevices(); let devices = await Camera.getAvailableCameraDevices();
if (!isMounted) return; if (!isMounted) return;
let bestMatch: CameraDevice | undefined; devices = devices.sort(sortDevices);
if (deviceType == null) { if (deviceType != null) {
// use any device devices = devices.filter((d) => {
const sorted = devices.sort(sortDevices);
bestMatch = sorted[0];
} else {
// use specified device (type)
bestMatch = devices.find((d) => {
const parsedType = parsePhysicalDeviceTypes(d.devices); const parsedType = parsePhysicalDeviceTypes(d.devices);
return parsedType === deviceType; return parsedType === deviceType;
}); });
} }
if (bestMatch == null) throw new CameraRuntimeError('device/no-device', 'No Camera device was found!'); setCameraDevices({
setDevice(bestMatch); back: devices.find((d) => d.position === 'back'),
external: devices.find((d) => d.position === 'external'),
front: devices.find((d) => d.position === 'front'),
unspecified: devices.find((d) => d.position === 'unspecified'),
});
}; };
loadDevice(); loadDevice();
@ -60,5 +69,5 @@ export function useCameraDevice(deviceType?: PhysicalCameraDeviceType | LogicalC
}; };
}, [deviceType]); }, [deviceType]);
return device; return cameraDevices;
} }

View File

@ -10,6 +10,6 @@ export * from './Point';
export * from './Snapshot'; export * from './Snapshot';
export * from './TemporaryFile'; export * from './TemporaryFile';
export * from './VideoFile'; export * from './VideoFile';
export * from './hooks/useCameraDevice'; export * from './hooks/useCameraDevices';
export * from './hooks/useCameraFormat'; export * from './hooks/useCameraFormat';
export * from './utils/FormatFilter'; export * from './utils/FormatFilter';

View File

@ -91,8 +91,8 @@ export const sortFormatsByResolution = (left: CameraDeviceFormat, right: CameraD
let rightPoints = right.photoHeight * right.photoWidth; let rightPoints = right.photoHeight * right.photoWidth;
if (left.videoHeight != null && left.videoWidth != null && right.videoHeight != null && right.videoWidth != null) { if (left.videoHeight != null && left.videoWidth != null && right.videoHeight != null && right.videoWidth != null) {
leftPoints += left.videoWidth * left.videoHeight ?? 0; leftPoints += left.videoWidth * left.videoHeight;
rightPoints += right.videoWidth * right.videoHeight ?? 0; rightPoints += right.videoWidth * right.videoHeight;
} }
// "returns a negative value if left is better than one" // "returns a negative value if left is better than one"