Squash format-filter

This commit is contained in:
Marc Rousavy
2021-02-20 23:20:28 +01:00
parent 99a640238e
commit 04fd5bb069
10 changed files with 203 additions and 223 deletions

View File

@@ -1,21 +1,64 @@
import { useEffect, useState } from 'react';
import { CameraRuntimeError } from 'src/CameraError';
import { sortDevices } from 'src/utils/FormatFilter';
import { Camera } from '../Camera';
import { CameraDevice, LogicalCameraDeviceType, parsePhysicalDeviceTypes, PhysicalCameraDeviceType } from '../CameraDevice';
export const useCameraDevice = (deviceType: PhysicalCameraDeviceType | LogicalCameraDeviceType): CameraDevice | undefined => {
/**
* Gets the best available `CameraDevice`. Devices with more cameras are preferred.
*
* @returns A `CameraDevice` for the requested device type.
* @throws `CameraRuntimeError` if no device was found.
* @example
* const device = useCameraDevice('wide-angle-camera')
* // ...
* return <Camera device={device} />
*/
export function useCameraDevice(): CameraDevice;
/**
* Gets a `CameraDevice` for the requested device type.
*
* @returns A `CameraDevice` for the requested device type, or `undefined` if no matching device was found
*
* @example
* const device = useCameraDevice('wide-angle-camera')
* // ...
* return <Camera device={device} />
*/
export function useCameraDevice(deviceType: PhysicalCameraDeviceType | LogicalCameraDeviceType): CameraDevice | undefined;
export function useCameraDevice(deviceType?: PhysicalCameraDeviceType | LogicalCameraDeviceType): CameraDevice | undefined {
const [device, setDevice] = useState<CameraDevice>();
useEffect(() => {
let isMounted = true;
const loadDevice = async (): Promise<void> => {
const devices = await Camera.getAvailableCameraDevices();
const bestMatch = devices.find((d) => {
const parsedType = parsePhysicalDeviceTypes(d.devices);
return parsedType === deviceType;
});
setDevice(bestMatch);
if (!isMounted) return;
if (deviceType == null) {
// use any device
const sorted = devices.sort(sortDevices);
const bestMatch = sorted[0];
if (bestMatch == null) throw new CameraRuntimeError('device/no-device', 'No Camera device was found!');
setDevice(bestMatch);
} else {
// use specified device (type)
const bestMatch = devices.find((d) => {
const parsedType = parsePhysicalDeviceTypes(d.devices);
return parsedType === deviceType;
});
setDevice(bestMatch);
}
};
loadDevice();
return () => {
isMounted = false;
};
}, [deviceType]);
return device;
};
}

View File

@@ -0,0 +1,24 @@
import { useMemo } from 'react';
import type { CameraDevice, CameraDeviceFormat } from 'src/CameraDevice';
import { filterFormatsByAspectRatio, sortFormatsByResolution } from 'src/utils/FormatFilter';
import type { Size } from 'src/utils/FormatFilter';
/**
* Returns the best format for the given camera device.
*
* This function tries to choose a format with the highest possible photo-capture resolution and best matching aspect ratio.
*
* @param device The Camera Device
* @param cameraViewSize The Camera View's size. This can be an approximation and **must be memoized**! Default: `SCREEN_SIZE`
*
* @returns The best matching format for the given camera device, or `undefined` if the camera device is `undefined`.
*/
export function useCameraFormat(device?: CameraDevice, cameraViewSize?: Size): CameraDeviceFormat | undefined {
const formats = useMemo(() => {
if (device?.formats == null) return [];
const filtered = filterFormatsByAspectRatio(device.formats, cameraViewSize);
return filtered.sort(sortFormatsByResolution);
}, [device?.formats, cameraViewSize]);
return formats[0];
}