Add video & quality selector

This commit is contained in:
Zoe Roux 2025-10-20 01:42:42 +02:00
parent c5f237771c
commit 70ff2285d5
No known key found for this signature in database
4 changed files with 69 additions and 38 deletions

View File

@ -1265,7 +1265,7 @@
"react-native-svg-transformer": ["react-native-svg-transformer@1.5.1", "", { "dependencies": { "@svgr/core": "^8.1.0", "@svgr/plugin-jsx": "^8.1.0", "@svgr/plugin-svgo": "^8.1.0", "path-dirname": "^1.0.2" }, "peerDependencies": { "react-native": ">=0.59.0", "react-native-svg": ">=12.0.0" } }, "sha512-dFvBNR8A9VPum9KCfh+LE49YiJEF8zUSnEFciKQroR/bEOhlPoZA0SuQ0qNk7m2iZl2w59FYjdRe0pMHWMDl0Q=="],
"react-native-video": ["react-native-video@github:zoriya/react-native-video#3f30e52", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": ">=0.27.2" } }, "zoriya-react-native-video-3f30e52"],
"react-native-video": ["react-native-video@github:zoriya/react-native-video#8287a84", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": ">=0.27.2" } }, "zoriya-react-native-video-8287a84"],
"react-native-web": ["react-native-web@0.21.2", "", { "dependencies": { "@babel/runtime": "^7.18.6", "@react-native/normalize-colors": "^0.74.1", "fbjs": "^3.0.4", "inline-style-prefixer": "^7.0.1", "memoize-one": "^6.0.0", "nullthrows": "^1.1.1", "postcss-value-parser": "^4.2.0", "styleq": "^0.1.3" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-SO2t9/17zM4iEnFvlu2DA9jqNbzNhoUP+AItkoCOyFmDMOhUnBBznBDCYN92fGdfAkfQlWzPoez6+zLxFNsZEg=="],

View File

@ -198,6 +198,7 @@
"volume": "Volume",
"quality": "Quality",
"audios": "Audio",
"videos": "Video",
"subtitles": "Subtitles",
"subtitle-none": "None",
"fullscreen": "Fullscreen",

View File

@ -165,8 +165,8 @@ const ControlButtons = ({
<View {...css({ flexDirection: "row" })}>
<SubtitleMenu {...menuProps} />
<AudioMenu player={player} {...menuProps} />
<VideoMenu {...menuProps} />
<QualityMenu {...menuProps} />
<VideoMenu player={player} {...menuProps} />
<QualityMenu player={player} {...menuProps} />
{Platform.OS === "web" && <FullscreenButton {...spacing} />}
</View>
</View>

View File

@ -51,13 +51,12 @@ export const AudioMenu = ({
}: { player: VideoPlayer } & Partial<MenuProps>) => {
const { t } = useTranslation();
const getDisplayName = useDisplayName();
const rerender = useForceRerender();
const rerender = useForceRerender();
useEvent(player, "onAudioTrackChange", rerender);
const tracks = player.getAvailableAudioTracks();
if (tracks.length === 0) return null;
if (tracks.length <= 1) return null;
return (
<Menu
@ -78,8 +77,20 @@ export const AudioMenu = ({
);
};
export const VideoMenu = (props: Partial<MenuProps>) => {
export const VideoMenu = ({
player,
...props
}: {
player: VideoPlayer;
} & Partial<MenuProps>) => {
const { t } = useTranslation();
const getDisplayName = useDisplayName();
const rerender = useForceRerender();
useEvent(player, "onVideoTrackChange", rerender);
const tracks = player.getAvailableVideoTracks();
if (tracks.length <= 1) return null;
return (
<Menu
@ -87,7 +98,16 @@ export const VideoMenu = (props: Partial<MenuProps>) => {
icon={VideoSettings}
{...tooltip(t("player.audios"), true)}
{...props}
></Menu>
>
{tracks.map((x) => (
<Menu.Item
key={x.id}
label={getDisplayName({ title: x.label, language: x.language })}
selected={x.selected}
onSelect={() => player.selectAudioTrack(x)}
/>
))}
</Menu>
);
};
@ -95,9 +115,19 @@ export const PlayModeContext = createContext<
["direct" | "hls", (val: "direct" | "hls") => void]
>(null!);
export const QualityMenu = (props: Partial<MenuProps>) => {
export const QualityMenu = ({
player,
...props
}: { player: VideoPlayer } & Partial<MenuProps>) => {
const { t } = useTranslation();
const [playMode, setPlayMode] = useContext(PlayModeContext);
const rerender = useForceRerender();
useEvent(player, "onQualityChange", rerender);
const lvls = player.getAvailableQualities();
const current = player.currentQuality;
const auto = player.autoQualityEnabled;
return (
<Menu
@ -111,35 +141,35 @@ export const QualityMenu = (props: Partial<MenuProps>) => {
selected={playMode === "direct"}
onSelect={() => setPlayMode("direct")}
/>
{/* <Menu.Item */}
{/* label={ */}
{/* hls?.autoLevelEnabled && hls.currentLevel >= 0 */}
{/* ? `${t("player.auto")} (${levelName(hls.levels[hls.currentLevel], true)})` */}
{/* : t("player.auto") */}
{/* } */}
{/* selected={hls?.autoLevelEnabled && mode === PlayMode.Hls} */}
{/* onSelect={() => { */}
{/* setPlayMode(PlayMode.Hls); */}
{/* if (hls) hls.currentLevel = -1; */}
{/* }} */}
{/* /> */}
{/* {hls?.levels */}
{/* .map((x, i) => ( */}
{/* <Menu.Item */}
{/* key={i.toString()} */}
{/* label={levelName(x)} */}
{/* selected={ */}
{/* mode === PlayMode.Hls && */}
{/* hls!.currentLevel === i && */}
{/* !hls?.autoLevelEnabled */}
{/* } */}
{/* onSelect={() => { */}
{/* setPlayMode(PlayMode.Hls); */}
{/* hls!.currentLevel = i; */}
{/* }} */}
{/* /> */}
{/* )) */}
{/* .reverse()} */}
<Menu.Item
label={
auto && current
? `${t("player.auto")} (${current.id.includes("original") ? t("player.transmux") : `${current.height}p`})`
: t("player.auto")
}
selected={auto && playMode === "hls"}
onSelect={() => {
setPlayMode("hls");
player.selectQuality(null);
}}
/>
{lvls
.map((x) => (
<Menu.Item
key={x.id}
label={
x.id.includes("original")
? `${t("player.transmux")} (${x.height}p)`
: `${x.height}p`
}
selected={x.selected && !auto}
onSelect={() => {
setPlayMode("hls");
player.selectQuality(x);
}}
/>
))
.reverse()}
</Menu>
);
};