mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-30 19:54:16 -04:00
Display when subtitles are invalid on the web app
This commit is contained in:
parent
0f59798e73
commit
45b18eb8e6
@ -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>;
|
||||||
|
|
||||||
|
@ -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,20 +155,29 @@ 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),
|
{
|
||||||
width: percent(100),
|
paddingHorizontal: ts(2),
|
||||||
height: ts(5),
|
width: percent(100),
|
||||||
alignItems: "center",
|
height: ts(5),
|
||||||
flexDirection: "row",
|
alignItems: "center",
|
||||||
},
|
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}
|
||||||
|
@ -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),
|
{
|
||||||
flexGrow: 1,
|
paddingLeft: ts(icon || selected || left ? 0 : 2 + +!!icon),
|
||||||
})}
|
flexGrow: 1,
|
||||||
|
},
|
||||||
|
disabled && {
|
||||||
|
color: theme.overlay0,
|
||||||
|
},
|
||||||
|
])}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</P>
|
</P>
|
||||||
|
@ -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)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
@ -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 = () => {
|
||||||
|
@ -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()),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user