mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-06-02 12:08:37 +01:00
refactor(casting): extract useCastDismissGesture hook
This commit is contained in:
69
hooks/useCastDismissGesture.ts
Normal file
69
hooks/useCastDismissGesture.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import type { Router } from "expo-router";
|
||||
import { useCallback } from "react";
|
||||
import { Gesture } from "react-native-gesture-handler";
|
||||
import {
|
||||
runOnJS,
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withSpring,
|
||||
} from "react-native-reanimated";
|
||||
|
||||
interface UseCastDismissGestureParams {
|
||||
router: Router;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swipe-down-to-dismiss gesture cluster for the casting player modal.
|
||||
* Owns the `translateY`/`context` shared values, the pan gesture, the animated
|
||||
* style, and the `dismissModal` callback (also invoked by the header button).
|
||||
*/
|
||||
export function useCastDismissGesture({ router }: UseCastDismissGestureParams) {
|
||||
// Swipe down to dismiss gesture
|
||||
const translateY = useSharedValue(0);
|
||||
const context = useSharedValue({ y: 0 });
|
||||
|
||||
const dismissModal = useCallback(() => {
|
||||
// Navigate immediately without animation to prevent crashes
|
||||
if (router.canGoBack()) {
|
||||
router.back();
|
||||
} else {
|
||||
router.replace("/(auth)/(tabs)/(home)/");
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
const panGesture = Gesture.Pan()
|
||||
.onStart(() => {
|
||||
context.value = { y: translateY.value };
|
||||
})
|
||||
.onUpdate((event) => {
|
||||
// Only allow downward swipes from top of screen
|
||||
if (event.translationY > 0) {
|
||||
translateY.value = context.value.y + event.translationY;
|
||||
}
|
||||
})
|
||||
.onEnd((event) => {
|
||||
// Dismiss if swiped down more than 150px or fast swipe
|
||||
if (event.translationY > 150 || event.velocityY > 600) {
|
||||
// Animate down and dismiss
|
||||
translateY.value = withSpring(
|
||||
1000,
|
||||
{
|
||||
damping: 20,
|
||||
stiffness: 90,
|
||||
},
|
||||
() => {
|
||||
runOnJS(dismissModal)();
|
||||
},
|
||||
);
|
||||
} else {
|
||||
// Spring back to position
|
||||
translateY.value = withSpring(0);
|
||||
}
|
||||
});
|
||||
|
||||
const animatedStyle = useAnimatedStyle(() => ({
|
||||
transform: [{ translateY: translateY.value }],
|
||||
}));
|
||||
|
||||
return { panGesture, animatedStyle, dismissModal };
|
||||
}
|
||||
Reference in New Issue
Block a user