mirror of
https://github.com/streamyfin/streamyfin.git
synced 2025-08-20 18:37:18 +02:00
fix: revert fade in controls
This commit is contained in:
@@ -24,13 +24,11 @@ import {
|
||||
View,
|
||||
} from "react-native";
|
||||
import { Slider } from "react-native-awesome-slider";
|
||||
import Animated, {
|
||||
import {
|
||||
runOnJS,
|
||||
type SharedValue,
|
||||
useAnimatedReaction,
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withTiming,
|
||||
} from "react-native-reanimated";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { Text } from "@/components/common/Text";
|
||||
@@ -163,45 +161,11 @@ export const Controls: FC<Props> = ({
|
||||
const min = useSharedValue(0);
|
||||
const max = useSharedValue(item.RunTimeTicks || 0);
|
||||
|
||||
// Animated opacity for smooth transitions
|
||||
const controlsOpacity = useSharedValue(showControls ? 1 : 0);
|
||||
|
||||
// Animated scale for slider
|
||||
const sliderScale = useSharedValue(1);
|
||||
|
||||
const wasPlayingRef = useRef(false);
|
||||
const lastProgressRef = useRef<number>(0);
|
||||
|
||||
const lightHapticFeedback = useHaptic("light");
|
||||
|
||||
// Animate controls opacity when showControls changes
|
||||
useEffect(() => {
|
||||
controlsOpacity.value = withTiming(showControls ? 1 : 0, {
|
||||
duration: 300,
|
||||
});
|
||||
}, [showControls, controlsOpacity]);
|
||||
|
||||
// Animated styles for controls
|
||||
const animatedControlsStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
opacity: controlsOpacity.value,
|
||||
};
|
||||
});
|
||||
|
||||
// Animated style for black overlay (75% opacity when visible)
|
||||
const animatedOverlayStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
opacity: controlsOpacity.value * 0.75,
|
||||
};
|
||||
});
|
||||
|
||||
// Animated style for slider scale
|
||||
const animatedSliderStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
transform: [{ scaleY: sliderScale.value }],
|
||||
};
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
prefetchAllTrickplayImages();
|
||||
}, []);
|
||||
@@ -552,31 +516,19 @@ export const Controls: FC<Props> = ({
|
||||
if (!showControls) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale up the slider immediately on touch
|
||||
sliderScale.value = withTiming(1.4, { duration: 300 });
|
||||
}, [showControls]);
|
||||
|
||||
const handleTouchEnd = useCallback(() => {
|
||||
if (!showControls) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale down the slider on touch end (only if not sliding, to avoid conflict with onSlidingComplete)
|
||||
if (!isSliding) {
|
||||
sliderScale.value = withTiming(1.0, { duration: 300 });
|
||||
}
|
||||
}, [showControls, isSliding]);
|
||||
|
||||
const handleSliderComplete = useCallback(
|
||||
async (value: number) => {
|
||||
setIsSliding(false);
|
||||
isSeeking.value = false;
|
||||
progress.value = value;
|
||||
setIsSliding(false);
|
||||
|
||||
// Scale down the slider
|
||||
sliderScale.value = withTiming(1.0, { duration: 200 });
|
||||
|
||||
seek(Math.max(0, Math.floor(isVlc ? value : ticksToSeconds(value))));
|
||||
if (wasPlayingRef.current) {
|
||||
play();
|
||||
@@ -791,10 +743,10 @@ export const Controls: FC<Props> = ({
|
||||
<VideoTouchOverlay
|
||||
screenWidth={screenWidth}
|
||||
screenHeight={screenHeight}
|
||||
showControls={showControls}
|
||||
onToggleControls={toggleControls}
|
||||
animatedStyle={animatedOverlayStyle}
|
||||
/>
|
||||
<Animated.View
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
position: "absolute",
|
||||
@@ -803,8 +755,8 @@ export const Controls: FC<Props> = ({
|
||||
width: settings?.safeAreaInControlsEnabled
|
||||
? screenWidth - insets.left - insets.right
|
||||
: screenWidth,
|
||||
opacity: showControls ? 1 : 0,
|
||||
},
|
||||
animatedControlsStyle,
|
||||
]}
|
||||
pointerEvents={showControls ? "auto" : "none"}
|
||||
className={"flex flex-row w-full pt-2"}
|
||||
@@ -883,11 +835,9 @@ export const Controls: FC<Props> = ({
|
||||
<Ionicons name='close' size={24} color='white' />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</Animated.View>
|
||||
|
||||
<Animated.View
|
||||
style={[
|
||||
{
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "50%", // Center vertically
|
||||
left: settings?.safeAreaInControlsEnabled ? insets.left : 0,
|
||||
@@ -896,26 +846,22 @@ export const Controls: FC<Props> = ({
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
transform: [{ translateY: -22.5 }], // Adjust for the button's height (half of 45)
|
||||
paddingHorizontal: 17,
|
||||
},
|
||||
animatedControlsStyle,
|
||||
]}
|
||||
paddingHorizontal: "28%", // Add some padding to the left and right
|
||||
}}
|
||||
pointerEvents={showControls ? "box-none" : "none"}
|
||||
>
|
||||
{/* Brightness Control */}
|
||||
<View
|
||||
style={{
|
||||
width: 50,
|
||||
height: 50,
|
||||
position: "absolute",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
transform: [{ rotate: "270deg" }],
|
||||
transform: [{ rotate: "270deg" }], // Rotate the slider to make it vertical
|
||||
left: 0,
|
||||
bottom: 30,
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<BrightnessSlider />
|
||||
</View>
|
||||
|
||||
{/* Skip Backward */}
|
||||
{!Platform.isTV && (
|
||||
<TouchableOpacity onPress={handleSkipBackward}>
|
||||
<View
|
||||
@@ -923,6 +869,7 @@ export const Controls: FC<Props> = ({
|
||||
position: "relative",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<Ionicons
|
||||
@@ -948,8 +895,9 @@ export const Controls: FC<Props> = ({
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
{/* Play/Pause Button */}
|
||||
<View style={{ alignItems: "center" }}>
|
||||
<View
|
||||
style={Platform.isTV ? { flex: 1, alignItems: "center" } : {}}
|
||||
>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
togglePlay();
|
||||
@@ -960,6 +908,9 @@ export const Controls: FC<Props> = ({
|
||||
name={isPlaying ? "pause" : "play"}
|
||||
size={50}
|
||||
color='white'
|
||||
style={{
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Loader size={"large"} />
|
||||
@@ -967,7 +918,6 @@ export const Controls: FC<Props> = ({
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Skip Forward */}
|
||||
{!Platform.isTV && (
|
||||
<TouchableOpacity onPress={handleSkipForward}>
|
||||
<View
|
||||
@@ -975,6 +925,7 @@ export const Controls: FC<Props> = ({
|
||||
position: "relative",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<Ionicons name='refresh-outline' size={50} color='white' />
|
||||
@@ -992,23 +943,21 @@ export const Controls: FC<Props> = ({
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
|
||||
{/* Volume/Audio Control */}
|
||||
<View
|
||||
style={{
|
||||
width: 50,
|
||||
height: 50,
|
||||
position: "absolute",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
transform: [{ rotate: "270deg" }],
|
||||
transform: [{ rotate: "270deg" }], // Rotate the slider to make it vertical
|
||||
bottom: 30,
|
||||
right: 0,
|
||||
opacity: showAudioSlider || showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<AudioSlider setVisibility={setShowAudioSlider} />
|
||||
</View>
|
||||
</Animated.View>
|
||||
</View>
|
||||
|
||||
<Animated.View
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
position: "absolute",
|
||||
@@ -1018,7 +967,6 @@ export const Controls: FC<Props> = ({
|
||||
? Math.max(insets.bottom - 17, 0)
|
||||
: 0,
|
||||
},
|
||||
animatedControlsStyle,
|
||||
]}
|
||||
className={"flex flex-col px-2"}
|
||||
onTouchStart={handleControlsInteraction}
|
||||
@@ -1034,6 +982,7 @@ export const Controls: FC<Props> = ({
|
||||
style={{
|
||||
flexDirection: "column",
|
||||
alignSelf: "flex-end", // Shrink height based on content
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
pointerEvents={showControls ? "box-none" : "none"}
|
||||
>
|
||||
@@ -1082,6 +1031,9 @@ export const Controls: FC<Props> = ({
|
||||
</View>
|
||||
<View
|
||||
className={"flex flex-col-reverse rounded-lg items-center my-2"}
|
||||
style={{
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
pointerEvents={showControls ? "box-none" : "none"}
|
||||
>
|
||||
<View className={"flex flex-col w-full shrink"}>
|
||||
@@ -1094,7 +1046,6 @@ export const Controls: FC<Props> = ({
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
>
|
||||
<Animated.View style={animatedSliderStyle}>
|
||||
<Slider
|
||||
theme={{
|
||||
maximumTrackTintColor: "rgba(255,255,255,0.2)",
|
||||
@@ -1113,8 +1064,7 @@ export const Controls: FC<Props> = ({
|
||||
borderRadius: 100,
|
||||
}}
|
||||
renderBubble={() =>
|
||||
(isSliding || showRemoteBubble) &&
|
||||
memoizedRenderBubble()
|
||||
(isSliding || showRemoteBubble) && memoizedRenderBubble()
|
||||
}
|
||||
sliderHeight={10}
|
||||
thumbWidth={0}
|
||||
@@ -1122,7 +1072,6 @@ export const Controls: FC<Props> = ({
|
||||
minimumValue={min}
|
||||
maximumValue={max}
|
||||
/>
|
||||
</Animated.View>
|
||||
</View>
|
||||
<View className='flex flex-row items-center justify-between mt-2'>
|
||||
<Text className='text-[12px] text-neutral-400'>
|
||||
@@ -1152,7 +1101,7 @@ export const Controls: FC<Props> = ({
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</Animated.View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
{settings.maxAutoPlayEpisodeCount.value !== -1 && (
|
||||
|
||||
@@ -1,32 +1,28 @@
|
||||
import { Pressable } from "react-native";
|
||||
import Animated, { type AnimatedStyle } from "react-native-reanimated";
|
||||
import { useTapDetection } from "./useTapDetection";
|
||||
|
||||
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
||||
|
||||
interface Props {
|
||||
screenWidth: number;
|
||||
screenHeight: number;
|
||||
showControls: boolean;
|
||||
onToggleControls: () => void;
|
||||
animatedStyle: AnimatedStyle;
|
||||
}
|
||||
|
||||
export const VideoTouchOverlay = ({
|
||||
screenWidth,
|
||||
screenHeight,
|
||||
showControls,
|
||||
onToggleControls,
|
||||
animatedStyle,
|
||||
}: Props) => {
|
||||
const { handleTouchStart, handleTouchEnd } = useTapDetection({
|
||||
onValidTap: onToggleControls,
|
||||
});
|
||||
|
||||
return (
|
||||
<AnimatedPressable
|
||||
<Pressable
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
style={[
|
||||
{
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: screenWidth,
|
||||
height: screenHeight,
|
||||
@@ -35,9 +31,8 @@ export const VideoTouchOverlay = ({
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
animatedStyle,
|
||||
]}
|
||||
opacity: showControls ? 0.75 : 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user