From f2fe68c31a5d3d3586987a4f4ab655d85b641e32 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Fri, 22 Mar 2024 19:55:36 +0100 Subject: [PATCH] improve volume and brightness gestures --- apps/expo/src/components/player/Header.tsx | 8 +- .../src/components/player/VideoPlayer.tsx | 111 ++++++++++-------- .../src/components/player/VideoSlider.tsx | 16 --- apps/expo/src/hooks/player/useBrightness.ts | 10 +- apps/expo/src/hooks/player/useVolume.ts | 7 +- 5 files changed, 70 insertions(+), 82 deletions(-) diff --git a/apps/expo/src/components/player/Header.tsx b/apps/expo/src/components/player/Header.tsx index 621ec5b..bcc8746 100644 --- a/apps/expo/src/components/player/Header.tsx +++ b/apps/expo/src/components/player/Header.tsx @@ -38,14 +38,14 @@ export const Header = () => { : ""} { const { brightness, showBrightnessOverlay, - currentBrightness, setShowBrightnessOverlay, handleBrightnessChange, } = useBrightness(); - const { showVolumeOverlay, setShowVolumeOverlay, volume, currentVolume } = - useVolume(); + const { volume, showVolumeOverlay, setShowVolumeOverlay } = useVolume(); + const { currentSpeed } = usePlaybackSpeed(); const { synchronizePlayback } = useAudioTrack(); const { dismissFullscreenPlayer } = usePlayer(); @@ -41,8 +48,8 @@ export const VideoPlayer = () => { const [isLoading, setIsLoading] = useState(true); const [resizeMode, setResizeMode] = useState(ResizeMode.CONTAIN); const [hasStartedPlaying, setHasStartedPlaying] = useState(false); - const isGestureInSliderVicinity = useSharedValue(false); const router = useRouter(); + const scale = useSharedValue(1); const state = usePlayerStore((state) => state.interface.state); @@ -65,10 +72,6 @@ export const VideoPlayer = () => { }); }, []); - const checkGestureInSliderVicinity = (x: number, y: number) => { - isGestureInSliderVicinity.value = isPointInSliderVicinity(x, y); - }; - const updateResizeMode = (newMode: ResizeMode) => { setResizeMode(newMode); void Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); @@ -84,7 +87,7 @@ export const VideoPlayer = () => { }); const doubleTapGesture = Gesture.Tap() - .enabled(gestureControlsEnabled) + .enabled(gestureControlsEnabled && isIdle) .numberOfTaps(2) .onEnd(() => { runOnJS(toggleAudio)(); @@ -94,12 +97,8 @@ export const VideoPlayer = () => { const screenHalfWidth = Dimensions.get("window").width / 2; const panGesture = Gesture.Pan() - .enabled(gestureControlsEnabled) + .enabled(gestureControlsEnabled && isIdle) .onStart((event) => { - runOnJS(checkGestureInSliderVicinity)(event.x, event.y); - if (isGestureInSliderVicinity.value) { - return; - } if (event.x > screenHalfWidth) { runOnJS(setShowVolumeOverlay)(true); } else { @@ -108,9 +107,6 @@ export const VideoPlayer = () => { }) .onUpdate((event) => { const divisor = 5000; - const panIsInHeaderOrFooter = event.y < 100 || event.y > 400; - if (panIsInHeaderOrFooter) return; - const directionMultiplier = event.velocityY < 0 ? 1 : -1; const change = directionMultiplier * Math.abs(event.velocityY / divisor); @@ -271,9 +267,9 @@ export const VideoPlayer = () => { )} - {showVolumeOverlay && } + {showVolumeOverlay && } {showBrightnessOverlay && ( - + )} @@ -281,36 +277,57 @@ export const VideoPlayer = () => { ); }; -function BrightnessOverlay(props: { brightness: number }) { - return ( - - - Brightness: {Math.round(props.brightness * 100)}% - - - ); -} +function GestureOverlay(props: { + value: SharedValue; + type: "brightness" | "volume"; +}) { + const theme = useTheme(); -function VolumeOverlay(props: { volume: number }) { + const animatedStyle = useAnimatedStyle(() => { + return { + height: `${props.value.value * 100}%`, + borderTopLeftRadius: props.value.value >= 0.98 ? 44 : 0, + borderTopRightRadius: props.value.value >= 0.98 ? 44 : 0, + }; + }); return ( - Volume: {Math.round(props.volume * 100)}% + + + + ); } diff --git a/apps/expo/src/components/player/VideoSlider.tsx b/apps/expo/src/components/player/VideoSlider.tsx index 83794d4..590919f 100644 --- a/apps/expo/src/components/player/VideoSlider.tsx +++ b/apps/expo/src/components/player/VideoSlider.tsx @@ -29,22 +29,6 @@ interface VideoSliderProps { onSlidingComplete?: (value: number) => void; } -const SLIDER_VICINITY = { - x: 20, - y: 200, - width: Dimensions.get("window").width - 40, - height: 20, -}; - -export const isPointInSliderVicinity = (x: number, y: number) => { - return ( - x >= SLIDER_VICINITY.x && - x <= SLIDER_VICINITY.x + SLIDER_VICINITY.width && - y >= SLIDER_VICINITY.y && - y <= SLIDER_VICINITY.y + SLIDER_VICINITY.height - ); -}; - const VideoSlider = ({ onSlidingComplete }: VideoSliderProps) => { const theme = useTheme(); const tapRef = useRef(null); diff --git a/apps/expo/src/hooks/player/useBrightness.ts b/apps/expo/src/hooks/player/useBrightness.ts index 7d2ae23..38981e6 100644 --- a/apps/expo/src/hooks/player/useBrightness.ts +++ b/apps/expo/src/hooks/player/useBrightness.ts @@ -1,19 +1,12 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import { useSharedValue } from "react-native-reanimated"; import * as Brightness from "expo-brightness"; -import { useDebounceValue } from "tamagui"; export const useBrightness = () => { const [showBrightnessOverlay, setShowBrightnessOverlay] = useState(false); const brightness = useSharedValue(0.5); - const currentBrightness = useDebounceValue(brightness.value, 20); - const memoizedBrightness = useMemo( - () => currentBrightness, - [currentBrightness], - ); - useEffect(() => { async function init() { try { @@ -42,7 +35,6 @@ export const useBrightness = () => { showBrightnessOverlay, setShowBrightnessOverlay, brightness, - currentBrightness: memoizedBrightness, handleBrightnessChange, } as const; }; diff --git a/apps/expo/src/hooks/player/useVolume.ts b/apps/expo/src/hooks/player/useVolume.ts index 4ca8628..d522e4e 100644 --- a/apps/expo/src/hooks/player/useVolume.ts +++ b/apps/expo/src/hooks/player/useVolume.ts @@ -1,19 +1,14 @@ -import { useMemo, useState } from "react"; +import { useState } from "react"; import { useSharedValue } from "react-native-reanimated"; -import { useDebounceValue } from "tamagui"; export const useVolume = () => { const [showVolumeOverlay, setShowVolumeOverlay] = useState(false); const volume = useSharedValue(1); - const currentVolume = useDebounceValue(volume.value, 20); - const memoizedVolume = useMemo(() => currentVolume, [currentVolume]); - return { showVolumeOverlay, setShowVolumeOverlay, volume, - currentVolume: memoizedVolume, } as const; };