mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Use a better display name for audios
This commit is contained in:
parent
4be4fa2c4f
commit
0d4b9fe488
@ -20,6 +20,17 @@
|
||||
|
||||
import { z } from "zod";
|
||||
import { imageFn } from "../traits";
|
||||
import i18next from "i18next";
|
||||
|
||||
const getDisplayName = (sub: Track) => {
|
||||
const languageNames = new Intl.DisplayNames([i18next.language ?? "en"], { type: "language" });
|
||||
const lng = sub.language ? languageNames.of(sub.language) : undefined;
|
||||
|
||||
if (lng && sub.title && sub.title !== lng) return `${lng} - ${sub.title}`;
|
||||
if (lng) return lng;
|
||||
if (sub.title) return sub.title;
|
||||
return `Unknwon (${sub.index})`;
|
||||
};
|
||||
|
||||
/**
|
||||
* A audio or subtitle track.
|
||||
@ -50,14 +61,23 @@ export const TrackP = z.object({
|
||||
*/
|
||||
isForced: z.boolean(),
|
||||
});
|
||||
export type Audio = z.infer<typeof TrackP>;
|
||||
export type Track = z.infer<typeof TrackP>;
|
||||
|
||||
export const AudioP = TrackP.transform((x) => ({
|
||||
...x,
|
||||
displayName: getDisplayName(x),
|
||||
}));
|
||||
export type Audio = z.infer<typeof AudioP>;
|
||||
|
||||
export const SubtitleP = TrackP.extend({
|
||||
/*
|
||||
* The url of this track (only if this is a subtitle)..
|
||||
*/
|
||||
link: z.string().transform(imageFn).nullable(),
|
||||
});
|
||||
}).transform((x) => ({
|
||||
...x,
|
||||
displayName: getDisplayName(x),
|
||||
}));
|
||||
export type Subtitle = z.infer<typeof SubtitleP>;
|
||||
|
||||
export const ChapterP = z.object({
|
||||
@ -97,7 +117,7 @@ export const WatchInfoP = z.object({
|
||||
/**
|
||||
* The list of audio tracks.
|
||||
*/
|
||||
audios: z.array(TrackP),
|
||||
audios: z.array(AudioP),
|
||||
/**
|
||||
* The list of subtitles tracks.
|
||||
*/
|
||||
|
@ -33,7 +33,7 @@ import {
|
||||
tooltip,
|
||||
ts,
|
||||
} from "@kyoo/primitives";
|
||||
import { Chapter, KyooImage, Subtitle } from "@kyoo/models";
|
||||
import { Chapter, KyooImage, Subtitle, Audio } from "@kyoo/models";
|
||||
import { useAtomValue, useSetAtom, useAtom } from "jotai";
|
||||
import { ImageStyle, Platform, Pressable, View, ViewProps } from "react-native";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@ -52,6 +52,7 @@ export const Hover = ({
|
||||
poster,
|
||||
chapters,
|
||||
subtitles,
|
||||
audios,
|
||||
fonts,
|
||||
previousSlug,
|
||||
nextSlug,
|
||||
@ -68,6 +69,7 @@ export const Hover = ({
|
||||
poster?: KyooImage | null;
|
||||
chapters?: Chapter[];
|
||||
subtitles?: Subtitle[];
|
||||
audios?: Audio[];
|
||||
fonts?: string[];
|
||||
previousSlug?: string | null;
|
||||
nextSlug?: string | null;
|
||||
@ -123,6 +125,7 @@ export const Hover = ({
|
||||
<LeftButtons previousSlug={previousSlug} nextSlug={nextSlug} />
|
||||
<RightButtons
|
||||
subtitles={subtitles}
|
||||
audios={audios}
|
||||
fonts={fonts}
|
||||
onMenuOpen={onMenuOpen}
|
||||
onMenuClose={onMenuClose}
|
||||
|
@ -18,7 +18,7 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Subtitle } from "@kyoo/models";
|
||||
import { Audio, Subtitle } from "@kyoo/models";
|
||||
import { IconButton, tooltip, Menu, ts } from "@kyoo/primitives";
|
||||
import { useAtom } from "jotai";
|
||||
import { Platform, View } from "react-native";
|
||||
@ -33,23 +33,15 @@ import { fullscreenAtom, subtitleAtom } from "../state";
|
||||
import { AudiosMenu, QualitiesMenu } from "../video";
|
||||
import i18next from "i18next";
|
||||
|
||||
export const getDisplayName = (sub: Subtitle) => {
|
||||
const languageNames = new Intl.DisplayNames([i18next.language ?? "en"], { type: "language" });
|
||||
const lng = sub.language ? languageNames.of(sub.language) : undefined;
|
||||
|
||||
if (lng && sub.title) return `${lng} - ${sub.title}`;
|
||||
if (lng) return lng;
|
||||
if (sub.title) return sub.title;
|
||||
return `Unknwon (${sub.index})`;
|
||||
};
|
||||
|
||||
export const RightButtons = ({
|
||||
audios,
|
||||
subtitles,
|
||||
fonts,
|
||||
onMenuOpen,
|
||||
onMenuClose,
|
||||
...props
|
||||
}: {
|
||||
audios?: Audio[];
|
||||
subtitles?: Subtitle[];
|
||||
fonts?: string[];
|
||||
onMenuOpen: () => void;
|
||||
@ -81,7 +73,7 @@ export const RightButtons = ({
|
||||
{subtitles.map((x) => (
|
||||
<Menu.Item
|
||||
key={x.index}
|
||||
label={x.link ? getDisplayName(x) : `${getDisplayName(x)} (${x.codec})`}
|
||||
label={x.link ? x.displayName : `${x.displayName} (${x.codec})`}
|
||||
selected={selectedSubtitle === x}
|
||||
disabled={!x.link}
|
||||
onSelect={() => setSubtitle(x)}
|
||||
@ -94,6 +86,7 @@ export const RightButtons = ({
|
||||
icon={MusicNote}
|
||||
onMenuOpen={onMenuOpen}
|
||||
onMenuClose={onMenuClose}
|
||||
audios={audios}
|
||||
{...tooltip(t("player.audios"), true)}
|
||||
{...spacing}
|
||||
/>
|
||||
|
@ -77,6 +77,7 @@ const mapData = (
|
||||
href: data ? (data.type === "movie" ? `/movie/${data.slug}` : `/show/${data.show!.slug}`) : "#",
|
||||
poster: data.type === "movie" ? data.poster : data.show!.poster,
|
||||
subtitles: info.subtitles,
|
||||
audios: info.audios,
|
||||
chapters: info.chapters,
|
||||
fonts: info.fonts,
|
||||
previousSlug,
|
||||
|
@ -34,7 +34,7 @@ declare module "react-native-video" {
|
||||
|
||||
export * from "react-native-video";
|
||||
|
||||
import { Subtitle, getToken } from "@kyoo/models";
|
||||
import { Audio, Subtitle, getToken } from "@kyoo/models";
|
||||
import { IconButton, Menu } from "@kyoo/primitives";
|
||||
import { ComponentProps, forwardRef, useEffect, useRef } from "react";
|
||||
import { atom, useAtom, useAtomValue, useSetAtom } from "jotai";
|
||||
@ -119,7 +119,7 @@ const Video = forwardRef<NativeVideo, VideoProps>(function Video(
|
||||
export default Video;
|
||||
|
||||
type CustomMenu = ComponentProps<typeof Menu<ComponentProps<typeof IconButton>>>;
|
||||
export const AudiosMenu = (props: CustomMenu) => {
|
||||
export const AudiosMenu = ({ audios, ...props }: CustomMenu & { audios?: Audio[] }) => {
|
||||
const info = useAtomValue(infoAtom);
|
||||
const [audio, setAudio] = useAtom(audioAtom);
|
||||
|
||||
@ -130,7 +130,7 @@ export const AudiosMenu = (props: CustomMenu) => {
|
||||
{info.audioTracks.map((x) => (
|
||||
<Menu.Item
|
||||
key={x.index}
|
||||
label={x.title}
|
||||
label={audios?.[x.index].displayName ?? x.title}
|
||||
selected={audio === x.index}
|
||||
onSelect={() => setAudio(x.index)}
|
||||
/>
|
||||
|
@ -18,7 +18,7 @@
|
||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { getToken, Subtitle } from "@kyoo/models";
|
||||
import { getToken, Subtitle, Audio } from "@kyoo/models";
|
||||
import {
|
||||
forwardRef,
|
||||
RefObject,
|
||||
@ -38,7 +38,6 @@ import Hls, { Level, LoadPolicy } from "hls.js";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Menu } from "@kyoo/primitives";
|
||||
import toVttBlob from "srt-webvtt";
|
||||
import { getDisplayName } from "./components/right-buttons";
|
||||
|
||||
let hls: Hls | null = null;
|
||||
|
||||
@ -256,7 +255,7 @@ const useSubtitle = (
|
||||
const addSubtitle = async () => {
|
||||
const track: HTMLTrackElement = htmlTrack ?? document.createElement("track");
|
||||
track.kind = "subtitles";
|
||||
track.label = getDisplayName(value);
|
||||
track.label = value.displayName;
|
||||
if (value.language) track.srclang = value.language;
|
||||
track.src = value.codec === "subrip" ? await toWebVtt(value.link!) : value.link!;
|
||||
track.className = "subtitle_container";
|
||||
@ -300,14 +299,18 @@ const toWebVtt = async (srtUrl: string) => {
|
||||
return await toVttBlob(srt);
|
||||
};
|
||||
|
||||
export const AudiosMenu = (props: ComponentProps<typeof Menu>) => {
|
||||
export const AudiosMenu = ({
|
||||
audios,
|
||||
...props
|
||||
}: ComponentProps<typeof Menu> & { audios?: Audio[] }) => {
|
||||
if (!hls || hls.audioTracks.length < 2) return null;
|
||||
console.log(audios);
|
||||
return (
|
||||
<Menu {...props}>
|
||||
{hls.audioTracks.map((x, i) => (
|
||||
<Menu.Item
|
||||
key={i.toString()}
|
||||
label={x.name}
|
||||
label={audios?.[i].displayName ?? x.name}
|
||||
selected={hls!.audioTrack === i}
|
||||
onSelect={() => (hls!.audioTrack = i)}
|
||||
/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user