mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-07-08 05:22:57 +01:00
Reworked controls to have pause, and skip not in the slider anymore
This commit is contained in:
3
app.json
3
app.json
@@ -41,7 +41,8 @@
|
|||||||
"package": "com.fredrikburmester.streamyfin",
|
"package": "com.fredrikburmester.streamyfin",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"android.permission.FOREGROUND_SERVICE",
|
"android.permission.FOREGROUND_SERVICE",
|
||||||
"android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"
|
"android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK",
|
||||||
|
"android.permission.WRITE_SETTINGS"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|||||||
@@ -455,21 +455,6 @@ export default function page() {
|
|||||||
writeToLog("ERROR", "Video Error", e.nativeEvent);
|
writeToLog("ERROR", "Video Error", e.nativeEvent);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
opacity: isBuffering ? 1 : 0,
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
}}
|
|
||||||
pointerEvents="none"
|
|
||||||
>
|
|
||||||
<Loader />
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
{videoRef.current && (
|
{videoRef.current && (
|
||||||
<Controls
|
<Controls
|
||||||
|
|||||||
@@ -467,20 +467,6 @@ const Player = () => {
|
|||||||
selectedTextTrack={selectedTextTrack}
|
selectedTextTrack={selectedTextTrack}
|
||||||
selectedAudioTrack={selectedAudioTrack}
|
selectedAudioTrack={selectedAudioTrack}
|
||||||
/>
|
/>
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
opacity: isBuffering ? 1 : 0,
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
}}
|
|
||||||
pointerEvents="none"
|
|
||||||
>
|
|
||||||
<Loader />
|
|
||||||
</View>
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Text>No video source...</Text>
|
<Text>No video source...</Text>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import {
|
|||||||
Pressable,
|
Pressable,
|
||||||
TouchableOpacity,
|
TouchableOpacity,
|
||||||
View,
|
View,
|
||||||
|
StyleSheet,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import { Slider } from "react-native-awesome-slider";
|
import { Slider } from "react-native-awesome-slider";
|
||||||
import {
|
import {
|
||||||
@@ -50,6 +51,7 @@ import { VideoProvider } from "./contexts/VideoContext";
|
|||||||
import * as Haptics from "expo-haptics";
|
import * as Haptics from "expo-haptics";
|
||||||
import DropdownViewDirect from "./dropdown/DropdownViewDirect";
|
import DropdownViewDirect from "./dropdown/DropdownViewDirect";
|
||||||
import DropdownViewTranscoding from "./dropdown/DropdownViewTranscoding";
|
import DropdownViewTranscoding from "./dropdown/DropdownViewTranscoding";
|
||||||
|
import * as Brightness from "expo-brightness";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
item: BaseItemDto;
|
item: BaseItemDto;
|
||||||
@@ -134,6 +136,22 @@ export const Controls: React.FC<Props> = ({
|
|||||||
isVlc
|
isVlc
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [brightness, setBrightness] = useState(useSharedValue(0.5));
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const getBrightness = async () => {
|
||||||
|
const currentBrightness = await Brightness.getBrightnessAsync();
|
||||||
|
setBrightness(useSharedValue(currentBrightness));
|
||||||
|
};
|
||||||
|
|
||||||
|
getBrightness();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleBrightnessChange = async (value) => {
|
||||||
|
setBrightness(value);
|
||||||
|
await Brightness.setBrightnessAsync(value);
|
||||||
|
};
|
||||||
|
|
||||||
const { showSkipCreditButton, skipCredit } = useCreditSkipper(
|
const { showSkipCreditButton, skipCredit } = useCreditSkipper(
|
||||||
offline ? undefined : item.Id,
|
offline ? undefined : item.Id,
|
||||||
currentTime,
|
currentTime,
|
||||||
@@ -352,7 +370,7 @@ export const Controls: React.FC<Props> = ({
|
|||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
bottom: 97,
|
bottom: 110,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
className={`z-10 p-4
|
className={`z-10 p-4
|
||||||
@@ -370,7 +388,7 @@ export const Controls: React.FC<Props> = ({
|
|||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
bottom: 94,
|
bottom: 110,
|
||||||
height: 70,
|
height: 70,
|
||||||
}}
|
}}
|
||||||
pointerEvents={showSkipCreditButton ? "auto" : "none"}
|
pointerEvents={showSkipCreditButton ? "auto" : "none"}
|
||||||
@@ -409,6 +427,24 @@ export const Controls: React.FC<Props> = ({
|
|||||||
pointerEvents={showControls ? "auto" : "none"}
|
pointerEvents={showControls ? "auto" : "none"}
|
||||||
className={`flex flex-row items-center space-x-2 z-10 p-4 `}
|
className={`flex flex-row items-center space-x-2 z-10 p-4 `}
|
||||||
>
|
>
|
||||||
|
{previousItem && (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={goToPreviousItem}
|
||||||
|
className="aspect-square flex flex-col bg-neutral-800/90 rounded-xl items-center justify-center p-2"
|
||||||
|
>
|
||||||
|
<Ionicons name="play-skip-back" size={24} color="white" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{nextItem && (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={goToNextItem}
|
||||||
|
className="aspect-square flex flex-col bg-neutral-800/90 rounded-xl items-center justify-center p-2"
|
||||||
|
>
|
||||||
|
<Ionicons name="play-skip-forward" size={24} color="white" />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)}
|
||||||
|
|
||||||
{Platform.OS !== "ios" && (
|
{Platform.OS !== "ios" && (
|
||||||
<TouchableOpacity
|
<TouchableOpacity
|
||||||
onPress={toggleIgnoreSafeAreas}
|
onPress={toggleIgnoreSafeAreas}
|
||||||
@@ -432,6 +468,91 @@ export const Controls: React.FC<Props> = ({
|
|||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%", // Center vertically
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
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"}
|
||||||
|
>
|
||||||
|
<TouchableOpacity onPress={handleSkipBackward}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
position: "relative",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name="refresh-outline"
|
||||||
|
size={50}
|
||||||
|
color="white"
|
||||||
|
style={{
|
||||||
|
transform: [{ scaleY: -1 }, { rotate: "180deg" }],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
color: "white",
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
bottom: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings?.rewindSkipTime}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
{!isBuffering ? (
|
||||||
|
<TouchableOpacity
|
||||||
|
onPress={() => {
|
||||||
|
togglePlay(progress.value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons
|
||||||
|
name={isPlaying ? "pause" : "play"}
|
||||||
|
size={50}
|
||||||
|
color="white"
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
) : (
|
||||||
|
<Loader />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<TouchableOpacity onPress={handleSkipForward}>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
position: "relative",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Ionicons name="refresh-outline" size={50} color="white" />
|
||||||
|
<Text
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
color: "white",
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: "bold",
|
||||||
|
bottom: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings?.forwardSkipTime}
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
@@ -458,50 +579,8 @@ export const Controls: React.FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
<View
|
<View
|
||||||
className={`flex flex-col-reverse py-4 px-4 rounded-2xl items-center bg-neutral-800`}
|
className={`flex flex-col-reverse py-4 pb-2 px-4 rounded-2xl items-center bg-neutral-800`}
|
||||||
>
|
>
|
||||||
<View className="flex flex-row items-center space-x-4">
|
|
||||||
<TouchableOpacity
|
|
||||||
style={{
|
|
||||||
opacity: !previousItem ? 0.5 : 1,
|
|
||||||
}}
|
|
||||||
onPress={goToPreviousItem}
|
|
||||||
>
|
|
||||||
<Ionicons name="play-skip-back" size={24} color="white" />
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity onPress={handleSkipBackward}>
|
|
||||||
<Ionicons
|
|
||||||
name="refresh-outline"
|
|
||||||
size={26}
|
|
||||||
color="white"
|
|
||||||
style={{
|
|
||||||
transform: [{ scaleY: -1 }, { rotate: "180deg" }],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={() => {
|
|
||||||
togglePlay(progress.value);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Ionicons
|
|
||||||
name={isPlaying ? "pause" : "play"}
|
|
||||||
size={30}
|
|
||||||
color="white"
|
|
||||||
/>
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity onPress={handleSkipForward}>
|
|
||||||
<Ionicons name="refresh-outline" size={26} color="white" />
|
|
||||||
</TouchableOpacity>
|
|
||||||
<TouchableOpacity
|
|
||||||
style={{
|
|
||||||
opacity: !nextItem ? 0.5 : 1,
|
|
||||||
}}
|
|
||||||
onPress={goToNextItem}
|
|
||||||
>
|
|
||||||
<Ionicons name="play-skip-forward" size={24} color="white" />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
<View className={`flex flex-col w-full shrink`}>
|
<View className={`flex flex-col w-full shrink`}>
|
||||||
<Slider
|
<Slider
|
||||||
theme={{
|
theme={{
|
||||||
@@ -509,9 +588,22 @@ export const Controls: React.FC<Props> = ({
|
|||||||
minimumTrackTintColor: "#fff",
|
minimumTrackTintColor: "#fff",
|
||||||
cacheTrackTintColor: "rgba(255,255,255,0.3)",
|
cacheTrackTintColor: "rgba(255,255,255,0.3)",
|
||||||
bubbleBackgroundColor: "#fff",
|
bubbleBackgroundColor: "#fff",
|
||||||
bubbleTextColor: "#000",
|
bubbleTextColor: "#666",
|
||||||
heartbeatColor: "#999",
|
heartbeatColor: "#999",
|
||||||
}}
|
}}
|
||||||
|
renderThumb={() => (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: 18,
|
||||||
|
height: 18,
|
||||||
|
left: -2,
|
||||||
|
borderRadius: 10,
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
></View>
|
||||||
|
)}
|
||||||
cache={cacheProgress}
|
cache={cacheProgress}
|
||||||
onSlidingStart={handleSliderStart}
|
onSlidingStart={handleSliderStart}
|
||||||
onSlidingComplete={handleSliderComplete}
|
onSlidingComplete={handleSliderComplete}
|
||||||
@@ -524,47 +616,53 @@ export const Controls: React.FC<Props> = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { x, y, url } = trickPlayUrl;
|
const { x, y, url } = trickPlayUrl;
|
||||||
|
|
||||||
const tileWidth = 150;
|
const tileWidth = 150;
|
||||||
const tileHeight = 150 / trickplayInfo.aspectRatio!;
|
const tileHeight = 150 / trickplayInfo.aspectRatio!;
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
bottom: 0,
|
left: -57,
|
||||||
left: 0,
|
bottom: 15,
|
||||||
width: tileWidth,
|
paddingTop: 30,
|
||||||
height: tileHeight,
|
paddingBottom: 5,
|
||||||
marginLeft: -tileWidth / 4,
|
width: tileWidth * 1.5, // Adjust the width of the outer container if needed
|
||||||
marginTop: -tileHeight / 4 - 60,
|
backgroundColor: "rgba(0, 0, 0, 0.6)", // Outer box background color (optional)
|
||||||
zIndex: 10,
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
className=" bg-neutral-800 overflow-hidden"
|
|
||||||
>
|
>
|
||||||
<Image
|
<View
|
||||||
cachePolicy={"memory-disk"}
|
|
||||||
style={{
|
style={{
|
||||||
width: 150 * trickplayInfo?.data.TileWidth!,
|
width: tileWidth,
|
||||||
height:
|
height: tileHeight,
|
||||||
(150 / trickplayInfo.aspectRatio!) *
|
alignSelf: "center",
|
||||||
trickplayInfo?.data.TileHeight!,
|
transform: [{ scale: 1.4 }],
|
||||||
transform: [
|
borderRadius: 5, // Optional border radius
|
||||||
{ translateX: -x * tileWidth },
|
|
||||||
{ translateY: -y * tileHeight },
|
|
||||||
],
|
|
||||||
}}
|
}}
|
||||||
source={{ uri: url }}
|
className=" bg-neutral-800 overflow-hidden"
|
||||||
contentFit="cover"
|
>
|
||||||
/>
|
<Image
|
||||||
|
cachePolicy={"memory-disk"}
|
||||||
|
style={{
|
||||||
|
width: 150 * trickplayInfo?.data.TileWidth!,
|
||||||
|
height:
|
||||||
|
(150 / trickplayInfo.aspectRatio!) *
|
||||||
|
trickplayInfo?.data.TileHeight!,
|
||||||
|
transform: [
|
||||||
|
{ translateX: -x * tileWidth },
|
||||||
|
{ translateY: -y * tileHeight },
|
||||||
|
],
|
||||||
|
resizeMode: "cover",
|
||||||
|
}}
|
||||||
|
source={{ uri: url }}
|
||||||
|
contentFit="cover"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
marginTop: 30,
|
||||||
bottom: 5,
|
fontSize: 16,
|
||||||
left: 5,
|
|
||||||
color: "white",
|
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
||||||
padding: 5,
|
|
||||||
borderRadius: 5,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${time.hours > 0 ? `${time.hours}:` : ""}${
|
{`${time.hours > 0 ? `${time.hours}:` : ""}${
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
"expo-asset": "~10.0.10",
|
"expo-asset": "~10.0.10",
|
||||||
"expo-background-fetch": "~12.0.1",
|
"expo-background-fetch": "~12.0.1",
|
||||||
"expo-blur": "~13.0.2",
|
"expo-blur": "~13.0.2",
|
||||||
|
"expo-brightness": "~12.0.1",
|
||||||
"expo-build-properties": "~0.12.5",
|
"expo-build-properties": "~0.12.5",
|
||||||
"expo-constants": "~16.0.2",
|
"expo-constants": "~16.0.2",
|
||||||
"expo-dev-client": "~4.0.29",
|
"expo-dev-client": "~4.0.29",
|
||||||
|
|||||||
Reference in New Issue
Block a user