Display when subtitles are invalid on the web app

This commit is contained in:
Zoe Roux 2023-08-01 18:28:34 +09:00
parent 0f59798e73
commit 45b18eb8e6
6 changed files with 41 additions and 24 deletions

View File

@ -58,7 +58,7 @@ export const SubtitleP = TrackP.extend({
/* /*
* The url of this track (only if this is a subtitle).. * The url of this track (only if this is a subtitle)..
*/ */
link: z.string().transform(imageFn), link: z.string().transform(imageFn).nullable(),
}); });
export type Subtitle = z.infer<typeof SubtitleP>; export type Subtitle = z.infer<typeof SubtitleP>;

View File

@ -126,11 +126,13 @@ const MenuItem = ({
onSelect, onSelect,
href, href,
icon, icon,
disabled,
...props ...props
}: { }: {
label: string; label: string;
selected?: boolean; selected?: boolean;
left?: ReactElement; left?: ReactElement;
disabled?: boolean;
icon?: ComponentType<SvgProps>; icon?: ComponentType<SvgProps>;
} & ({ onSelect: () => void; href?: undefined } | { href: string; onSelect?: undefined })) => { } & ({ onSelect: () => void; href?: undefined } | { href: string; onSelect?: undefined })) => {
const { css, theme } = useYoshiki(); const { css, theme } = useYoshiki();
@ -153,7 +155,9 @@ const MenuItem = ({
onSelect?.call(null); onSelect?.call(null);
if (href) router.push(href); if (href) router.push(href);
}} }}
disabled={disabled}
{...css( {...css(
[
{ {
paddingHorizontal: ts(2), paddingHorizontal: ts(2),
width: percent(100), width: percent(100),
@ -161,12 +165,19 @@ const MenuItem = ({
alignItems: "center", alignItems: "center",
flexDirection: "row", flexDirection: "row",
}, },
disabled && {},
],
props as any, props as any,
)} )}
> >
{left && left} {left && left}
{!left && icn && icn} {!left && icn && icn}
<P {...css({ paddingLeft: ts(2) + +!(icon || selected || left) * px(24), flexGrow: 1 })}> <P
{...css([
{ paddingLeft: ts(2) + +!(icon || selected || left) * px(24), flexGrow: 1 },
disabled && { color: theme.overlay0 },
])}
>
{label} {label}
</P> </P>
{left && icn && icn} {left && icn && icn}

View File

@ -123,11 +123,13 @@ const MenuItem = ({
selected, selected,
onSelect, onSelect,
href, href,
disabled,
...props ...props
}: { }: {
label: string; label: string;
icon?: ComponentType<SvgProps>; icon?: ComponentType<SvgProps>;
left?: ReactElement; left?: ReactElement;
disabled?: boolean;
selected?: boolean; selected?: boolean;
} & ({ onSelect: () => void; href?: undefined } | { href: string; onSelect?: undefined })) => { } & ({ onSelect: () => void; href?: undefined } | { href: string; onSelect?: undefined })) => {
const { css: nCss } = useNativeYoshiki(); const { css: nCss } = useNativeYoshiki();
@ -152,6 +154,7 @@ const MenuItem = ({
<Item <Item
onSelect={onSelect} onSelect={onSelect}
href={href} href={href}
disabled={disabled}
{...css( {...css(
{ {
display: "flex", display: "flex",
@ -167,10 +170,15 @@ const MenuItem = ({
{!left && icn && icn} {!left && icn && icn}
{ {
<P <P
{...nCss({ {...nCss([
paddingLeft: ts((icon || selected || left) ? 0 : 2 + +!!icon), {
paddingLeft: ts(icon || selected || left ? 0 : 2 + +!!icon),
flexGrow: 1, flexGrow: 1,
})} },
disabled && {
color: theme.overlay0,
},
])}
> >
{label} {label}
</P> </P>

View File

@ -83,8 +83,9 @@ export const RightButtons = ({
{subtitles.map((x) => ( {subtitles.map((x) => (
<Menu.Item <Menu.Item
key={x.index} key={x.index}
label={getDisplayName(x)} label={x.link ? getDisplayName(x) : `${getDisplayName(x)} (${x.codec})`}
selected={selectedSubtitle === x} selected={selectedSubtitle === x}
disabled={!x.link}
onSelect={() => setSubtitle(x)} onSelect={() => setSubtitle(x)}
/> />
))} ))}

View File

@ -18,7 +18,7 @@
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>. * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { getToken, queryFn, Subtitle } from "@kyoo/models"; import { getToken, Subtitle } from "@kyoo/models";
import { import {
forwardRef, forwardRef,
RefObject, RefObject,
@ -222,7 +222,7 @@ const useSubtitle = (
subOcto = null; subOcto = null;
}; };
if (!value) { if (!value || !value.link) {
removeHtmlSubtitle(); removeHtmlSubtitle();
removeOctoSub(); removeOctoSub();
} else if (value.codec === "vtt" || value.codec === "subrip") { } else if (value.codec === "vtt" || value.codec === "subrip") {
@ -233,7 +233,7 @@ const useSubtitle = (
track.kind = "subtitles"; track.kind = "subtitles";
track.label = getDisplayName(value); track.label = getDisplayName(value);
if (value.language) track.srclang = value.language; if (value.language) track.srclang = value.language;
track.src = value.codec === "subrip" ? await toWebVtt(value.link) : value.link; track.src = value.codec === "subrip" ? await toWebVtt(value.link!) : value.link!;
track.className = "subtitle_container"; track.className = "subtitle_container";
track.default = true; track.default = true;
track.onload = () => { track.onload = () => {

View File

@ -4,7 +4,6 @@ use sha1::{Digest, Sha1};
use std::{ use std::{
collections::HashMap, collections::HashMap,
fs, io, fs, io,
iter::Map,
path::PathBuf, path::PathBuf,
process::Stdio, process::Stdio,
str::{self, FromStr}, str::{self, FromStr},
@ -84,7 +83,7 @@ pub struct Subtitle {
/// Is this stream tagged as forced? (useful only for subtitles) /// Is this stream tagged as forced? (useful only for subtitles)
pub is_forced: bool, pub is_forced: bool,
/// The link to access this subtitle. /// The link to access this subtitle.
pub link: String, pub link: Option<String>,
} }
#[derive(Serialize, ToSchema)] #[derive(Serialize, ToSchema)]
@ -124,7 +123,8 @@ async fn extract(path: String, sha: &String, subs: &Vec<Subtitle>) {
} }
pub async fn identify(path: String) -> Result<MediaInfo, std::io::Error> { pub async fn identify(path: String) -> Result<MediaInfo, std::io::Error> {
let extension_table: HashMap<&str, &str> = HashMap::from([("subrip", "srt"), ("ass", "ass")]); let extension_table: HashMap<&str, &str> =
HashMap::from([("subrip", "srt"), ("ass", "ass"), ("vtt", "vtt")]);
let mediainfo = Command::new("mediainfo") let mediainfo = Command::new("mediainfo")
.arg("--Output=JSON") .arg("--Output=JSON")
@ -157,10 +157,7 @@ pub async fn identify(path: String) -> Result<MediaInfo, std::io::Error> {
} }
let extension = extension_table.get(codec.as_str()).map(|x| x.to_string()); let extension = extension_table.get(codec.as_str()).map(|x| x.to_string());
Subtitle { Subtitle {
link: format!( link: extension.as_ref().map(|ext| format!("/video/{sha}/subtitle/{index}.{ext}")),
"/video/{sha}/subtitle/{index}.{ext}",
ext = extension.clone().unwrap_or(codec.clone())
),
index, index,
title: a["Title"].as_str().map(|x| x.to_string()), title: a["Title"].as_str().map(|x| x.to_string()),
language: a["Language"].as_str().map(|x| x.to_string()), language: a["Language"].as_str().map(|x| x.to_string()),