diff --git a/front/bun.lock b/front/bun.lock index f2729624..db4d0a99 100644 --- a/front/bun.lock +++ b/front/bun.lock @@ -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=="], diff --git a/front/public/translations/en.json b/front/public/translations/en.json index ccf3f101..0551af65 100644 --- a/front/public/translations/en.json +++ b/front/public/translations/en.json @@ -198,6 +198,7 @@ "volume": "Volume", "quality": "Quality", "audios": "Audio", + "videos": "Video", "subtitles": "Subtitles", "subtitle-none": "None", "fullscreen": "Fullscreen", diff --git a/front/src/ui/player/controls/bottom-controls.tsx b/front/src/ui/player/controls/bottom-controls.tsx index 5d263cbd..f53b21a4 100644 --- a/front/src/ui/player/controls/bottom-controls.tsx +++ b/front/src/ui/player/controls/bottom-controls.tsx @@ -165,8 +165,8 @@ const ControlButtons = ({ - - + + {Platform.OS === "web" && } diff --git a/front/src/ui/player/controls/tracks-menu.tsx b/front/src/ui/player/controls/tracks-menu.tsx index dc38a7ae..aa1e4224 100644 --- a/front/src/ui/player/controls/tracks-menu.tsx +++ b/front/src/ui/player/controls/tracks-menu.tsx @@ -51,13 +51,12 @@ export const AudioMenu = ({ }: { player: VideoPlayer } & Partial) => { 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 ( ) => { +export const VideoMenu = ({ + player, + ...props +}: { + player: VideoPlayer; +} & Partial) => { const { t } = useTranslation(); + const getDisplayName = useDisplayName(); + + const rerender = useForceRerender(); + useEvent(player, "onVideoTrackChange", rerender); + + const tracks = player.getAvailableVideoTracks(); + if (tracks.length <= 1) return null; return ( ) => { icon={VideoSettings} {...tooltip(t("player.audios"), true)} {...props} - > + > + {tracks.map((x) => ( + player.selectAudioTrack(x)} + /> + ))} + ); }; @@ -95,9 +115,19 @@ export const PlayModeContext = createContext< ["direct" | "hls", (val: "direct" | "hls") => void] >(null!); -export const QualityMenu = (props: Partial) => { +export const QualityMenu = ({ + player, + ...props +}: { player: VideoPlayer } & Partial) => { 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 ( ) => { selected={playMode === "direct"} onSelect={() => setPlayMode("direct")} /> - {/* = 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) => ( */} - {/* { */} - {/* setPlayMode(PlayMode.Hls); */} - {/* hls!.currentLevel = i; */} - {/* }} */} - {/* /> */} - {/* )) */} - {/* .reverse()} */} + { + setPlayMode("hls"); + player.selectQuality(null); + }} + /> + {lvls + .map((x) => ( + { + setPlayMode("hls"); + player.selectQuality(x); + }} + /> + )) + .reverse()} ); };