ESLint autofix
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import React, { useCallback, useMemo, useRef } from "react";
|
||||
import { Platform, StyleSheet, View, ViewProps } from "react-native";
|
||||
import React, { useCallback, useMemo, useRef } from 'react';
|
||||
import { Platform, StyleSheet, View, ViewProps } from 'react-native';
|
||||
import {
|
||||
PanGestureHandler,
|
||||
PanGestureHandlerGestureEvent,
|
||||
State,
|
||||
TapGestureHandler,
|
||||
TapGestureHandlerStateChangeEvent,
|
||||
} from "react-native-gesture-handler";
|
||||
} from 'react-native-gesture-handler';
|
||||
import Reanimated, {
|
||||
cancelAnimation,
|
||||
Easing,
|
||||
@@ -18,28 +18,25 @@ import Reanimated, {
|
||||
useAnimatedGestureHandler,
|
||||
useSharedValue,
|
||||
withRepeat,
|
||||
} from "react-native-reanimated";
|
||||
import type { Camera, PhotoFile, TakePhotoOptions, TakeSnapshotOptions, VideoFile } from "react-native-vision-camera";
|
||||
import { CAPTURE_BUTTON_SIZE, SCREEN_HEIGHT, SCREEN_WIDTH, USE_SNAPSHOT_ON_ANDROID } from "./../Constants";
|
||||
} from 'react-native-reanimated';
|
||||
import type { Camera, PhotoFile, TakePhotoOptions, TakeSnapshotOptions, VideoFile } from 'react-native-vision-camera';
|
||||
import { CAPTURE_BUTTON_SIZE, SCREEN_HEIGHT, SCREEN_WIDTH, USE_SNAPSHOT_ON_ANDROID } from './../Constants';
|
||||
|
||||
const PAN_GESTURE_HANDLER_FAIL_X = [-SCREEN_WIDTH, SCREEN_WIDTH];
|
||||
const PAN_GESTURE_HANDLER_ACTIVE_Y = [-2, 2];
|
||||
|
||||
const IS_ANDROID = Platform.OS === "android";
|
||||
const IS_ANDROID = Platform.OS === 'android';
|
||||
|
||||
const START_RECORDING_DELAY = 200;
|
||||
const BORDER_WIDTH = CAPTURE_BUTTON_SIZE * 0.1;
|
||||
|
||||
interface Props extends ViewProps {
|
||||
camera: React.RefObject<Camera>;
|
||||
onMediaCaptured: (
|
||||
media: PhotoFile | VideoFile,
|
||||
type: "photo" | "video"
|
||||
) => void;
|
||||
onMediaCaptured: (media: PhotoFile | VideoFile, type: 'photo' | 'video') => void;
|
||||
|
||||
cameraZoom: Reanimated.SharedValue<number>;
|
||||
|
||||
flash: "off" | "on" | "auto";
|
||||
flash: 'off' | 'on' | 'auto';
|
||||
|
||||
enabled: boolean;
|
||||
|
||||
@@ -61,36 +58,29 @@ const _CaptureButton: React.FC<Props> = ({
|
||||
const recordingProgress = useSharedValue(0);
|
||||
const takePhotoOptions = useMemo<TakePhotoOptions & TakeSnapshotOptions>(
|
||||
() => ({
|
||||
photoCodec: "jpeg",
|
||||
qualityPrioritization: "speed",
|
||||
photoCodec: 'jpeg',
|
||||
qualityPrioritization: 'speed',
|
||||
flash: flash,
|
||||
quality: 90,
|
||||
skipMetadata: true,
|
||||
}),
|
||||
[flash]
|
||||
[flash],
|
||||
);
|
||||
const isPressingButton = useSharedValue(false);
|
||||
|
||||
//#region Camera Capture
|
||||
const takePhoto = useCallback(async () => {
|
||||
try {
|
||||
if (camera.current == null) throw new Error("Camera ref is null!");
|
||||
if (camera.current == null) throw new Error('Camera ref is null!');
|
||||
|
||||
// If we're on Android and flash is disabled, we can use the "snapshot" method.
|
||||
// this will take a snapshot of the current SurfaceView, which results in faster image
|
||||
// capture rate at the cost of greatly reduced quality.
|
||||
const photoMethod =
|
||||
USE_SNAPSHOT_ON_ANDROID &&
|
||||
IS_ANDROID &&
|
||||
takePhotoOptions.flash === "off"
|
||||
? "snapshot"
|
||||
: "photo";
|
||||
const photoMethod = USE_SNAPSHOT_ON_ANDROID && IS_ANDROID && takePhotoOptions.flash === 'off' ? 'snapshot' : 'photo';
|
||||
console.log(`Taking ${photoMethod}...`);
|
||||
const photo =
|
||||
photoMethod === "snapshot"
|
||||
? await camera.current.takeSnapshot(takePhotoOptions)
|
||||
: await camera.current.takePhoto(takePhotoOptions);
|
||||
onMediaCaptured(photo, "photo");
|
||||
photoMethod === 'snapshot' ? await camera.current.takeSnapshot(takePhotoOptions) : await camera.current.takePhoto(takePhotoOptions);
|
||||
onMediaCaptured(photo, 'photo');
|
||||
} catch (e) {
|
||||
console.error('Failed to take photo!', e);
|
||||
}
|
||||
@@ -99,24 +89,24 @@ const _CaptureButton: React.FC<Props> = ({
|
||||
const onStoppedRecording = useCallback(() => {
|
||||
isRecording.current = false;
|
||||
cancelAnimation(recordingProgress);
|
||||
console.log(`stopped recording video!`);
|
||||
console.log('stopped recording video!');
|
||||
}, [recordingProgress]);
|
||||
const stopRecording = useCallback(async () => {
|
||||
try {
|
||||
if (camera.current == null) throw new Error("Camera ref is null!");
|
||||
if (camera.current == null) throw new Error('Camera ref is null!');
|
||||
|
||||
console.log("calling stopRecording()...");
|
||||
console.log('calling stopRecording()...');
|
||||
await camera.current.stopRecording();
|
||||
console.log("called stopRecording()!");
|
||||
console.log('called stopRecording()!');
|
||||
} catch (e) {
|
||||
console.error(`failed to stop recording!`, e);
|
||||
console.error('failed to stop recording!', e);
|
||||
}
|
||||
}, [camera]);
|
||||
const startRecording = useCallback(() => {
|
||||
try {
|
||||
if (camera.current == null) throw new Error("Camera ref is null!");
|
||||
if (camera.current == null) throw new Error('Camera ref is null!');
|
||||
|
||||
console.log(`calling startRecording()...`);
|
||||
console.log('calling startRecording()...');
|
||||
camera.current.startRecording({
|
||||
flash: flash,
|
||||
onRecordingError: (error) => {
|
||||
@@ -125,24 +115,17 @@ const _CaptureButton: React.FC<Props> = ({
|
||||
},
|
||||
onRecordingFinished: (video) => {
|
||||
console.log(`Recording successfully finished! ${video.path}`);
|
||||
onMediaCaptured(video, "video");
|
||||
onMediaCaptured(video, 'video');
|
||||
onStoppedRecording();
|
||||
},
|
||||
});
|
||||
// TODO: wait until startRecording returns to actually find out if the recording has successfully started
|
||||
console.log(`called startRecording()!`);
|
||||
console.log('called startRecording()!');
|
||||
isRecording.current = true;
|
||||
} catch (e) {
|
||||
console.error(`failed to start recording!`, e, "camera");
|
||||
console.error('failed to start recording!', e, 'camera');
|
||||
}
|
||||
}, [
|
||||
camera,
|
||||
flash,
|
||||
onMediaCaptured,
|
||||
onStoppedRecording,
|
||||
recordingProgress,
|
||||
stopRecording,
|
||||
]);
|
||||
}, [camera, flash, onMediaCaptured, onStoppedRecording, recordingProgress, stopRecording]);
|
||||
//#endregion
|
||||
|
||||
//#region Tap handler
|
||||
@@ -180,8 +163,7 @@ const _CaptureButton: React.FC<Props> = ({
|
||||
case State.CANCELLED: {
|
||||
// exit "recording mode"
|
||||
try {
|
||||
if (pressDownDate.current == null)
|
||||
throw new Error("PressDownDate ref .current was null!");
|
||||
if (pressDownDate.current == null) throw new Error('PressDownDate ref .current was null!');
|
||||
const now = new Date();
|
||||
const diff = now.getTime() - pressDownDate.current.getTime();
|
||||
pressDownDate.current = undefined;
|
||||
@@ -204,46 +186,26 @@ const _CaptureButton: React.FC<Props> = ({
|
||||
break;
|
||||
}
|
||||
},
|
||||
[
|
||||
isPressingButton,
|
||||
recordingProgress,
|
||||
setIsPressingButton,
|
||||
startRecording,
|
||||
stopRecording,
|
||||
takePhoto,
|
||||
]
|
||||
[isPressingButton, recordingProgress, setIsPressingButton, startRecording, stopRecording, takePhoto],
|
||||
);
|
||||
//#endregion
|
||||
//#region Pan handler
|
||||
const panHandler = useRef<PanGestureHandler>();
|
||||
const onPanGestureEvent = useAnimatedGestureHandler<
|
||||
PanGestureHandlerGestureEvent,
|
||||
{ offsetY?: number; startY?: number }
|
||||
>({
|
||||
const onPanGestureEvent = useAnimatedGestureHandler<PanGestureHandlerGestureEvent, { offsetY?: number; startY?: number }>({
|
||||
onStart: (event, context) => {
|
||||
context.startY = event.absoluteY;
|
||||
const yForFullZoom = context.startY * 0.7;
|
||||
const offsetYForFullZoom = context.startY - yForFullZoom;
|
||||
|
||||
// extrapolate [0 ... 1] zoom -> [0 ... Y_FOR_FULL_ZOOM] finger position
|
||||
context.offsetY = interpolate(
|
||||
Math.sqrt(cameraZoom.value),
|
||||
[0, 1],
|
||||
[0, offsetYForFullZoom],
|
||||
Extrapolate.CLAMP
|
||||
);
|
||||
context.offsetY = interpolate(Math.sqrt(cameraZoom.value), [0, 1], [0, offsetYForFullZoom], Extrapolate.CLAMP);
|
||||
},
|
||||
onActive: (event, context) => {
|
||||
const offset = context.offsetY ?? 0;
|
||||
const startY = context.startY ?? SCREEN_HEIGHT;
|
||||
const yForFullZoom = startY * 0.7;
|
||||
|
||||
const zoom = interpolate(
|
||||
event.absoluteY - offset,
|
||||
[yForFullZoom, startY],
|
||||
[1, 0],
|
||||
Extrapolate.CLAMP
|
||||
);
|
||||
const zoom = interpolate(event.absoluteY - offset, [yForFullZoom, startY], [1, 0], Extrapolate.CLAMP);
|
||||
cameraZoom.value = zoom ** 2;
|
||||
},
|
||||
});
|
||||
@@ -261,44 +223,45 @@ const _CaptureButton: React.FC<Props> = ({
|
||||
},
|
||||
],
|
||||
}),
|
||||
[isPressingButton]
|
||||
[isPressingButton],
|
||||
);
|
||||
const buttonStyle = useAnimatedStyle(
|
||||
() => {
|
||||
let scale: number;
|
||||
if (enabled) {
|
||||
if (isPressingButton.value) {
|
||||
scale = withRepeat(withSpring(1, {
|
||||
const buttonStyle = useAnimatedStyle(() => {
|
||||
let scale: number;
|
||||
if (enabled) {
|
||||
if (isPressingButton.value) {
|
||||
scale = withRepeat(
|
||||
withSpring(1, {
|
||||
stiffness: 100,
|
||||
damping: 1000,
|
||||
}), -1, true);
|
||||
} else {
|
||||
scale = withSpring(0.9, {
|
||||
stiffness: 500,
|
||||
damping: 300,
|
||||
});
|
||||
}
|
||||
}),
|
||||
-1,
|
||||
true,
|
||||
);
|
||||
} else {
|
||||
scale = withSpring(0.6, {
|
||||
scale = withSpring(0.9, {
|
||||
stiffness: 500,
|
||||
damping: 300,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
scale = withSpring(0.6, {
|
||||
stiffness: 500,
|
||||
damping: 300,
|
||||
});
|
||||
}
|
||||
|
||||
return ({
|
||||
opacity: withTiming(enabled ? 1 : 0.3, {
|
||||
duration: 100,
|
||||
easing: Easing.linear,
|
||||
}),
|
||||
transform: [
|
||||
{
|
||||
scale: scale
|
||||
},
|
||||
],
|
||||
})
|
||||
},
|
||||
[enabled, isPressingButton]
|
||||
);
|
||||
return {
|
||||
opacity: withTiming(enabled ? 1 : 0.3, {
|
||||
duration: 100,
|
||||
easing: Easing.linear,
|
||||
}),
|
||||
transform: [
|
||||
{
|
||||
scale: scale,
|
||||
},
|
||||
],
|
||||
};
|
||||
}, [enabled, isPressingButton]);
|
||||
|
||||
return (
|
||||
<TapGestureHandler
|
||||
@@ -333,17 +296,17 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
},
|
||||
shadow: {
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
width: CAPTURE_BUTTON_SIZE,
|
||||
height: CAPTURE_BUTTON_SIZE,
|
||||
borderRadius: CAPTURE_BUTTON_SIZE / 2,
|
||||
backgroundColor: "#e34077",
|
||||
backgroundColor: '#e34077',
|
||||
},
|
||||
button: {
|
||||
width: CAPTURE_BUTTON_SIZE,
|
||||
height: CAPTURE_BUTTON_SIZE,
|
||||
borderRadius: CAPTURE_BUTTON_SIZE / 2,
|
||||
borderWidth: BORDER_WIDTH,
|
||||
borderColor: "white",
|
||||
borderColor: 'white',
|
||||
},
|
||||
});
|
||||
|
@@ -1,11 +1,5 @@
|
||||
import React, { useCallback } from "react";
|
||||
import {
|
||||
PressableProps,
|
||||
Pressable,
|
||||
PressableStateCallbackType,
|
||||
StyleProp,
|
||||
ViewStyle,
|
||||
} from "react-native";
|
||||
import React, { useCallback } from 'react';
|
||||
import { PressableProps, Pressable, PressableStateCallbackType, StyleProp, ViewStyle } from 'react-native';
|
||||
|
||||
export interface PressableOpacityProps extends PressableProps {
|
||||
/**
|
||||
@@ -22,9 +16,7 @@ export interface PressableOpacityProps extends PressableProps {
|
||||
activeOpacity?: number;
|
||||
}
|
||||
|
||||
export type StyleType = (
|
||||
state: PressableStateCallbackType
|
||||
) => StyleProp<ViewStyle>;
|
||||
export type StyleType = (state: PressableStateCallbackType) => StyleProp<ViewStyle>;
|
||||
|
||||
/**
|
||||
* A Pressable component that lowers opacity when in pressed state. Uses the JS Pressability API.
|
||||
@@ -45,12 +37,9 @@ export const PressableOpacity = ({
|
||||
else return 1;
|
||||
}
|
||||
},
|
||||
[activeOpacity, disabled, disabledOpacity]
|
||||
);
|
||||
const _style = useCallback<StyleType>(
|
||||
({ pressed }) => [style as ViewStyle, { opacity: getOpacity(pressed) }],
|
||||
[getOpacity, style]
|
||||
[activeOpacity, disabled, disabledOpacity],
|
||||
);
|
||||
const _style = useCallback<StyleType>(({ pressed }) => [style as ViewStyle, { opacity: getOpacity(pressed) }], [getOpacity, style]);
|
||||
|
||||
return <Pressable style={_style} disabled={disabled} {...passThroughProps} />;
|
||||
};
|
||||
|
@@ -1,14 +1,11 @@
|
||||
import { BlurView, BlurViewProperties } from "@react-native-community/blur";
|
||||
import React from "react";
|
||||
import { Platform, StyleSheet } from "react-native";
|
||||
import StaticSafeAreaInsets from "react-native-static-safe-area-insets";
|
||||
import { BlurView, BlurViewProperties } from '@react-native-community/blur';
|
||||
import React from 'react';
|
||||
import { Platform, StyleSheet } from 'react-native';
|
||||
import StaticSafeAreaInsets from 'react-native-static-safe-area-insets';
|
||||
|
||||
const FALLBACK_COLOR = "rgba(140, 140, 140, 0.3)";
|
||||
const FALLBACK_COLOR = 'rgba(140, 140, 140, 0.3)';
|
||||
|
||||
const StatusBarBlurBackgroundImpl = ({
|
||||
style,
|
||||
...props
|
||||
}: BlurViewProperties) => {
|
||||
const StatusBarBlurBackgroundImpl = ({ style, ...props }: BlurViewProperties) => {
|
||||
if (Platform.OS !== 'ios') return null;
|
||||
|
||||
return (
|
||||
@@ -26,7 +23,7 @@ export const StatusBarBlurBackground = React.memo(StatusBarBlurBackgroundImpl);
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
statusBarBackground: {
|
||||
position: "absolute",
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
|
Reference in New Issue
Block a user