You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bazarr/frontend/src/pages/Movies/Details/table.tsx

201 lines
5.6 KiB

import { useMovieSubtitleModification } from "@/apis/hooks";
import { useShowOnlyDesired } from "@/apis/hooks/site";
import { Action, SimpleTable } from "@/components";
import Language from "@/components/bazarr/Language";
import SubtitleToolsMenu from "@/components/SubtitleToolsMenu";
import { task, TaskGroup } from "@/modules/task";
import { useTableStyles } from "@/styles";
import { filterSubtitleBy } from "@/utilities";
import { useProfileItemsToLanguages } from "@/utilities/languages";
import { faEllipsis, faSearch } from "@fortawesome/free-solid-svg-icons";
import { Badge, Text, TextProps } from "@mantine/core";
import { isString } from "lodash";
import { FunctionComponent, useMemo } from "react";
import { Column } from "react-table";
const missingText = "Missing Subtitles";
interface Props {
movie: Item.Movie | null;
disabled?: boolean;
profile?: Language.Profile;
}
function isSubtitleTrack(path: string | undefined | null) {
return !isString(path) || path.length === 0;
}
function isSubtitleMissing(path: string | undefined | null) {
return path === missingText;
}
const Table: FunctionComponent<Props> = ({ movie, profile, disabled }) => {
const onlyDesired = useShowOnlyDesired();
const profileItems = useProfileItemsToLanguages(profile);
const columns: Column<Subtitle>[] = useMemo<Column<Subtitle>[]>(
() => [
{
Header: "Subtitle Path",
accessor: "path",
Cell: ({ value }) => {
const { classes } = useTableStyles();
const props: TextProps = {
className: classes.primary,
};
if (isSubtitleTrack(value)) {
return <Text {...props}>Video File Subtitle Track</Text>;
} else if (isSubtitleMissing(value)) {
return (
<Text {...props} color="dimmed">
{value}
</Text>
);
} else {
return <Text {...props}>{value}</Text>;
}
},
},
{
Header: "Language",
accessor: "name",
Cell: ({ row }) => {
if (row.original.path === missingText) {
return (
<Badge color="primary">
<Language.Text value={row.original} long></Language.Text>
</Badge>
);
} else {
return (
<Badge color="secondary">
<Language.Text value={row.original} long></Language.Text>
</Badge>
);
}
},
},
{
accessor: "code2",
Cell: ({ row }) => {
const {
original: { code2, path, hi, forced },
} = row;
const { download, remove } = useMovieSubtitleModification();
const selections = useMemo(() => {
const list: FormType.ModifySubtitle[] = [];
if (path && !isSubtitleMissing(path) && movie !== null) {
list.push({
type: "movie",
path,
id: movie.radarrId,
language: code2,
});
}
return list;
}, [code2, path]);
if (movie === null) {
return null;
}
const { radarrId } = movie;
if (isSubtitleMissing(path)) {
return (
<Action
label="Search Subtitle"
icon={faSearch}
disabled={disabled}
onClick={() => {
task.create(
movie.title,
TaskGroup.SearchSubtitle,
download.mutateAsync,
{
radarrId,
form: {
language: code2,
forced,
hi,
},
}
);
}}
></Action>
);
}
return (
<SubtitleToolsMenu
selections={selections}
onAction={(action) => {
if (action === "delete" && path) {
task.create(
movie.title,
TaskGroup.DeleteSubtitle,
remove.mutateAsync,
{
radarrId,
form: {
language: code2,
forced,
hi,
path,
},
}
);
} else if (action === "search") {
throw new Error(
"This shouldn't happen, please report the bug"
);
}
}}
>
<Action
label="Subtitle Actions"
disabled={isSubtitleTrack(path)}
color="dark"
icon={faEllipsis}
></Action>
</SubtitleToolsMenu>
);
},
},
],
[movie, disabled]
);
const data: Subtitle[] = useMemo(() => {
const missing =
movie?.missing_subtitles.map((item) => ({
...item,
path: missingText,
})) ?? [];
let rawSubtitles = movie?.subtitles ?? [];
if (onlyDesired) {
rawSubtitles = filterSubtitleBy(rawSubtitles, profileItems);
}
return [...rawSubtitles, ...missing];
}, [movie, onlyDesired, profileItems]);
return (
<SimpleTable
columns={columns}
data={data}
tableStyles={{ emptyText: "No subtitles found for this movie" }}
></SimpleTable>
);
};
export default Table;