mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 23:59:08 +00:00
feat: MPV player for both Android and iOS with added HW decoding PiP (with subtitles) (#1332)
Co-authored-by: Alex Kim <alexkim@Alexs-MacBook-Pro.local> Co-authored-by: Alex <111128610+Alexk2309@users.noreply.github.com> Co-authored-by: Simon-Eklundh <simon.eklundh@proton.me>
This commit is contained in:
committed by
GitHub
parent
df2f44e086
commit
f1575ca48b
@@ -7,19 +7,14 @@ import { useRouter } from "expo-router";
|
||||
import { type FC, useCallback, useState } from "react";
|
||||
import { Platform, TouchableOpacity, View } from "react-native";
|
||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||
import { PlaybackSpeedSelector } from "@/components/PlaybackSpeedSelector";
|
||||
import { useHaptic } from "@/hooks/useHaptic";
|
||||
import { useOrientation } from "@/hooks/useOrientation";
|
||||
import { OrientationLock } from "@/packages/expo-screen-orientation";
|
||||
import { useSettings, VideoPlayerIOS } from "@/utils/atoms/settings";
|
||||
import { useSettings } from "@/utils/atoms/settings";
|
||||
import { ICON_SIZES } from "./constants";
|
||||
import DropdownView from "./dropdown/DropdownView";
|
||||
import { PlaybackSpeedScope } from "./utils/playback-speed-settings";
|
||||
import {
|
||||
type AspectRatio,
|
||||
AspectRatioSelector,
|
||||
} from "./VideoScalingModeSelector";
|
||||
import { type ScaleFactor, VlcZoomControl } from "./VlcZoomControl";
|
||||
import { type AspectRatio } from "./VideoScalingModeSelector";
|
||||
import { ZoomToggle } from "./ZoomToggle";
|
||||
|
||||
interface HeaderControlsProps {
|
||||
@@ -33,13 +28,7 @@ interface HeaderControlsProps {
|
||||
goToNextItem: (options: { isAutoPlay?: boolean }) => void;
|
||||
previousItem?: BaseItemDto | null;
|
||||
nextItem?: BaseItemDto | null;
|
||||
useVlcPlayer?: boolean;
|
||||
// VLC-specific props
|
||||
aspectRatio?: AspectRatio;
|
||||
setVideoAspectRatio?: (aspectRatio: string | null) => Promise<void>;
|
||||
scaleFactor?: ScaleFactor;
|
||||
setVideoScaleFactor?: (scaleFactor: number) => Promise<void>;
|
||||
// KSPlayer-specific props
|
||||
isZoomedToFill?: boolean;
|
||||
onZoomToggle?: () => void;
|
||||
// Playback speed props
|
||||
@@ -58,11 +47,7 @@ export const HeaderControls: FC<HeaderControlsProps> = ({
|
||||
goToNextItem,
|
||||
previousItem,
|
||||
nextItem,
|
||||
useVlcPlayer = false,
|
||||
aspectRatio = "default",
|
||||
setVideoAspectRatio,
|
||||
scaleFactor = 0,
|
||||
setVideoScaleFactor,
|
||||
aspectRatio: _aspectRatio = "default",
|
||||
isZoomedToFill = false,
|
||||
onZoomToggle,
|
||||
playbackSpeed = 1.0,
|
||||
@@ -109,9 +94,10 @@ export const HeaderControls: FC<HeaderControlsProps> = ({
|
||||
style={[
|
||||
{
|
||||
position: "absolute",
|
||||
top: settings?.safeAreaInControlsEnabled ? insets.top : 0,
|
||||
left: settings?.safeAreaInControlsEnabled ? insets.left : 0,
|
||||
right: settings?.safeAreaInControlsEnabled ? insets.right : 0,
|
||||
top: (settings?.safeAreaInControlsEnabled ?? true) ? insets.top : 0,
|
||||
left: (settings?.safeAreaInControlsEnabled ?? true) ? insets.left : 0,
|
||||
right:
|
||||
(settings?.safeAreaInControlsEnabled ?? true) ? insets.right : 0,
|
||||
},
|
||||
]}
|
||||
pointerEvents={showControls ? "auto" : "none"}
|
||||
@@ -120,7 +106,10 @@ export const HeaderControls: FC<HeaderControlsProps> = ({
|
||||
<View className='mr-auto p-2' pointerEvents='box-none'>
|
||||
{!Platform.isTV && (!offline || !mediaSource?.TranscodingUrl) && (
|
||||
<View pointerEvents='auto'>
|
||||
<DropdownView />
|
||||
<DropdownView
|
||||
playbackSpeed={playbackSpeed}
|
||||
setPlaybackSpeed={setPlaybackSpeed}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
@@ -142,20 +131,18 @@ export const HeaderControls: FC<HeaderControlsProps> = ({
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{!Platform.isTV &&
|
||||
startPictureInPicture &&
|
||||
settings?.videoPlayerIOS !== VideoPlayerIOS.VLC && (
|
||||
<TouchableOpacity
|
||||
onPress={startPictureInPicture}
|
||||
className='aspect-square flex flex-col rounded-xl items-center justify-center p-2'
|
||||
>
|
||||
<MaterialIcons
|
||||
name='picture-in-picture'
|
||||
size={ICON_SIZES.HEADER}
|
||||
color='white'
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{!Platform.isTV && startPictureInPicture && (
|
||||
<TouchableOpacity
|
||||
onPress={startPictureInPicture}
|
||||
className='aspect-square flex flex-col rounded-xl items-center justify-center p-2'
|
||||
>
|
||||
<MaterialIcons
|
||||
name='picture-in-picture'
|
||||
size={ICON_SIZES.HEADER}
|
||||
color='white'
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{item?.Type === "Episode" && (
|
||||
<TouchableOpacity
|
||||
onPress={switchOnEpisodeMode}
|
||||
@@ -188,47 +175,12 @@ export const HeaderControls: FC<HeaderControlsProps> = ({
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
{/* Playback Speed Control */}
|
||||
{!Platform.isTV && setPlaybackSpeed && (
|
||||
<PlaybackSpeedSelector
|
||||
selected={playbackSpeed}
|
||||
onChange={setPlaybackSpeed}
|
||||
item={item}
|
||||
/>
|
||||
)}
|
||||
{/* VLC-specific controls: Aspect Ratio and Scale/Zoom */}
|
||||
{useVlcPlayer && (
|
||||
<AspectRatioSelector
|
||||
currentRatio={aspectRatio}
|
||||
onRatioChange={async (newRatio) => {
|
||||
if (setVideoAspectRatio) {
|
||||
const aspectRatioString =
|
||||
newRatio === "default" ? null : newRatio;
|
||||
await setVideoAspectRatio(aspectRatioString);
|
||||
}
|
||||
}}
|
||||
disabled={!setVideoAspectRatio}
|
||||
/>
|
||||
)}
|
||||
{useVlcPlayer && (
|
||||
<VlcZoomControl
|
||||
currentScale={scaleFactor}
|
||||
onScaleChange={async (newScale) => {
|
||||
if (setVideoScaleFactor) {
|
||||
await setVideoScaleFactor(newScale);
|
||||
}
|
||||
}}
|
||||
disabled={!setVideoScaleFactor}
|
||||
/>
|
||||
)}
|
||||
{/* KSPlayer-specific control: Zoom to Fill */}
|
||||
{!useVlcPlayer && (
|
||||
<ZoomToggle
|
||||
isZoomedToFill={isZoomedToFill}
|
||||
onToggle={onZoomToggle ?? (() => {})}
|
||||
disabled={!onZoomToggle}
|
||||
/>
|
||||
)}
|
||||
{/* MPV Zoom Toggle */}
|
||||
<ZoomToggle
|
||||
isZoomedToFill={isZoomedToFill}
|
||||
onToggle={onZoomToggle ?? (() => {})}
|
||||
disabled={!onZoomToggle}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
onPress={onClose}
|
||||
className='aspect-square flex flex-col rounded-xl items-center justify-center p-2'
|
||||
|
||||
Reference in New Issue
Block a user