Use a better display name for audios

This commit is contained in:
Zoe Roux 2023-10-11 19:18:34 +02:00
parent 4be4fa2c4f
commit 0d4b9fe488
6 changed files with 44 additions and 24 deletions

View File

@ -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.
*/

View File

@ -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}

View File

@ -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}
/>

View File

@ -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,

View File

@ -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)}
/>

View File

@ -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)}
/>