forked from Ninjalama/streamyfin_mirror
Added feature to show audio slider when changing audio through device
This commit is contained in:
@@ -1,15 +1,21 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
import { View, StyleSheet } from "react-native";
|
||||
import { useSharedValue } from "react-native-reanimated";
|
||||
import { Slider } from "react-native-awesome-slider";
|
||||
import { VolumeManager } from "react-native-volume-manager";
|
||||
import { Ionicons } from "@expo/vector-icons";
|
||||
|
||||
const AudioSlider = () => {
|
||||
interface AudioSliderProps {
|
||||
setVisibility: (show: boolean) => void;
|
||||
}
|
||||
|
||||
const AudioSlider: React.FC<AudioSliderProps> = ({ setVisibility }) => {
|
||||
const volume = useSharedValue<number>(50); // Explicitly type as number
|
||||
const min = useSharedValue<number>(0); // Explicitly type as number
|
||||
const max = useSharedValue<number>(100); // Explicitly type as number
|
||||
|
||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null); // Use a ref to store the timeout ID
|
||||
|
||||
useEffect(() => {
|
||||
const fetchInitialVolume = async () => {
|
||||
try {
|
||||
@@ -33,7 +39,7 @@ const AudioSlider = () => {
|
||||
|
||||
const handleValueChange = async (value: number) => {
|
||||
volume.value = value;
|
||||
console.log("volume", value);
|
||||
console.log("volume through slider", value);
|
||||
await VolumeManager.setVolume(value / 100);
|
||||
|
||||
// Re-call showNativeVolumeUI to ensure the setting is applied on iOS
|
||||
@@ -42,14 +48,28 @@ const AudioSlider = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const volumeListener = VolumeManager.addVolumeListener((result) => {
|
||||
console.log("Volume changed:", result.volume);
|
||||
console.log("Volume through device", result.volume);
|
||||
volume.value = result.volume * 100;
|
||||
setVisibility(true);
|
||||
|
||||
// Clear any existing timeout
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
|
||||
// Set a new timeout to hide the visibility after 2 seconds
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
setVisibility(false);
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
return () => {
|
||||
volumeListener.remove();
|
||||
if (timeoutRef.current) {
|
||||
clearTimeout(timeoutRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}, [volume]);
|
||||
|
||||
return (
|
||||
<View style={styles.sliderContainer}>
|
||||
|
||||
@@ -253,7 +253,14 @@ export const Controls: React.FC<Props> = ({
|
||||
useEffect(() => {
|
||||
prefetchAllTrickplayImages();
|
||||
}, []);
|
||||
const toggleControls = () => setShowControls(!showControls);
|
||||
const toggleControls = () => {
|
||||
if (showControls) {
|
||||
setShowAudioSlider(false);
|
||||
setShowControls(false);
|
||||
} else {
|
||||
setShowControls(true);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSliderStart = useCallback(() => {
|
||||
if (showControls === false) return;
|
||||
@@ -438,6 +445,9 @@ export const Controls: React.FC<Props> = ({
|
||||
router.replace(`player/transcoding-player?${queryParams}`);
|
||||
};
|
||||
|
||||
// Used when user changes audio through audio button on device.
|
||||
const [showAudioSlider, setShowAudioSlider] = useState(false);
|
||||
|
||||
return (
|
||||
<ControlProvider
|
||||
item={item}
|
||||
@@ -546,7 +556,6 @@ export const Controls: React.FC<Props> = ({
|
||||
alignItems: "center",
|
||||
transform: [{ translateY: -22.5 }], // Adjust for the button's height (half of 45)
|
||||
paddingHorizontal: "28%", // Add some padding to the left and right
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
pointerEvents={showControls ? "box-none" : "none"}
|
||||
>
|
||||
@@ -557,6 +566,7 @@ export const Controls: React.FC<Props> = ({
|
||||
transform: [{ rotate: "270deg" }], // Rotate the slider to make it vertical
|
||||
left: 0,
|
||||
bottom: 30,
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<BrightnessSlider />
|
||||
@@ -567,6 +577,7 @@ export const Controls: React.FC<Props> = ({
|
||||
position: "relative",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<Ionicons
|
||||
@@ -601,6 +612,9 @@ export const Controls: React.FC<Props> = ({
|
||||
name={isPlaying ? "pause" : "play"}
|
||||
size={50}
|
||||
color="white"
|
||||
style={{
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Loader size={"large"} />
|
||||
@@ -613,6 +627,7 @@ export const Controls: React.FC<Props> = ({
|
||||
position: "relative",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
opacity: showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<Ionicons name="refresh-outline" size={50} color="white" />
|
||||
@@ -637,9 +652,10 @@ export const Controls: React.FC<Props> = ({
|
||||
transform: [{ rotate: "270deg" }], // Rotate the slider to make it vertical
|
||||
bottom: 30,
|
||||
right: 0,
|
||||
opacity: showAudioSlider || showControls ? 1 : 0,
|
||||
}}
|
||||
>
|
||||
<AudioSlider />
|
||||
<AudioSlider setVisibility={setShowAudioSlider} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { TrackInfo } from '@/modules/vlc-player';
|
||||
import { BaseItemDto, MediaSourceInfo } from '@jellyfin/sdk/lib/generated-client';
|
||||
import React, { createContext, useContext, useState, ReactNode } from 'react';
|
||||
import { TrackInfo } from "@/modules/vlc-player";
|
||||
import {
|
||||
BaseItemDto,
|
||||
MediaSourceInfo,
|
||||
} from "@jellyfin/sdk/lib/generated-client";
|
||||
import React, { createContext, useContext, useState, ReactNode } from "react";
|
||||
|
||||
interface ControlContextProps {
|
||||
item: BaseItemDto;
|
||||
@@ -8,7 +11,9 @@ interface ControlContextProps {
|
||||
isVideoLoaded: boolean | undefined;
|
||||
}
|
||||
|
||||
const ControlContext = createContext<ControlContextProps | undefined>(undefined);
|
||||
const ControlContext = createContext<ControlContextProps | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
interface ControlProviderProps {
|
||||
children: ReactNode;
|
||||
@@ -17,7 +22,12 @@ interface ControlProviderProps {
|
||||
isVideoLoaded: boolean | undefined;
|
||||
}
|
||||
|
||||
export const ControlProvider: React.FC<ControlProviderProps> = ({ children, item, mediaSource, isVideoLoaded }) => {
|
||||
export const ControlProvider: React.FC<ControlProviderProps> = ({
|
||||
children,
|
||||
item,
|
||||
mediaSource,
|
||||
isVideoLoaded,
|
||||
}) => {
|
||||
return (
|
||||
<ControlContext.Provider value={{ item, mediaSource, isVideoLoaded }}>
|
||||
{children}
|
||||
@@ -28,7 +38,7 @@ export const ControlProvider: React.FC<ControlProviderProps> = ({ children, item
|
||||
export const useControlContext = () => {
|
||||
const context = useContext(ControlContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useControlContext must be used within a ControlProvider');
|
||||
throw new Error("useControlContext must be used within a ControlProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user