This commit is contained in:
morpheus65535 2024-02-27 20:01:33 -05:00
parent 512d97672d
commit 55da60ad2d
111 changed files with 348 additions and 351 deletions

View File

@ -3,7 +3,7 @@
import { readFile } from "fs/promises";
import { get } from "lodash";
import YAML from "yaml";
import { parse } from "yaml";
class ConfigReader {
config: object;
@ -15,7 +15,7 @@ class ConfigReader {
async open(path: string) {
try {
const rawConfig = await readFile(path, "utf8");
this.config = YAML.parse(rawConfig);
this.config = parse(rawConfig);
} catch (err) {
// We don't want to catch the error here, handle it on getValue method
}
@ -53,7 +53,7 @@ export default async function overrideEnv(env: Record<string, string>) {
process.env["VITE_API_KEY"] = apiKey;
} catch (err) {
throw new Error(
`No API key found, please run the backend first, (error: ${err.message})`
`No API key found, please run the backend first, (error: ${err.message})`,
);
}
}
@ -71,7 +71,7 @@ export default async function overrideEnv(env: Record<string, string>) {
process.env["VITE_PROXY_URL"] = url;
} catch (err) {
throw new Error(
`No proxy url found, please run the backend first, (error: ${err.message})`
`No proxy url found, please run the backend first, (error: ${err.message})`,
);
}
}

View File

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<title>Bazarr</title>

View File

@ -84,7 +84,7 @@ function useIsActive(parent: string, route: RouteObject) {
const paths = useMemo(
() => [root, ...(children?.map((v) => pathJoin(root, v.path ?? "")) ?? [])],
[root, children]
[root, children],
);
const selection = useSelection().selection;
@ -92,7 +92,7 @@ function useIsActive(parent: string, route: RouteObject) {
() =>
selection?.includes(root) ||
paths.some((path) => matchPath(path, pathname)),
[pathname, paths, root, selection]
[pathname, paths, root, selection],
);
}
@ -338,7 +338,7 @@ const NavbarItem: FunctionComponent<NavbarItemProps> = ({
clsx(classes.anchor, {
[classes.active]: isActive,
[classes.hover]: hovered,
})
}),
)
}
>

View File

@ -40,8 +40,8 @@ const App: FunctionComponent = () => {
showNotification(
notification.info(
"Update available",
"A new version of Bazarr is ready, restart is required"
)
"A new version of Bazarr is ready, restart is required",
),
);
}
}, []);

View File

@ -309,7 +309,7 @@ function useRoutes(): CustomRouteObject[] {
data?.announcements,
radarr,
sonarr,
]
],
);
}
@ -321,7 +321,7 @@ export const Router: FunctionComponent = () => {
// TODO: Move this outside the function component scope
const router = useMemo(
() => createBrowserRouter(routes, { basename: Environment.baseUrl }),
[routes]
[routes],
);
return (

View File

@ -19,7 +19,7 @@ const cacheEpisodes = (client: QueryClient, episodes: Item.Episode[]) => {
QueryKeys.Episodes,
item.sonarrEpisodeId,
],
item
item,
);
});
};
@ -33,7 +33,7 @@ export function useEpisodesByIds(ids: number[]) {
onSuccess: (data) => {
cacheEpisodes(client, data);
},
}
},
);
}
@ -46,20 +46,20 @@ export function useEpisodesBySeriesId(id: number) {
onSuccess: (data) => {
cacheEpisodes(client, data);
},
}
},
);
}
export function useEpisodeWantedPagination() {
return usePaginationQuery([QueryKeys.Series, QueryKeys.Wanted], (param) =>
api.episodes.wanted(param)
api.episodes.wanted(param),
);
}
export function useEpisodeBlacklist() {
return useQuery(
[QueryKeys.Series, QueryKeys.Episodes, QueryKeys.Blacklist],
() => api.episodes.blacklist()
() => api.episodes.blacklist(),
);
}
@ -84,7 +84,7 @@ export function useEpisodeAddBlacklist() {
]);
client.invalidateQueries([QueryKeys.Series, seriesId]);
},
}
},
);
}
@ -102,7 +102,7 @@ export function useEpisodeDeleteBlacklist() {
QueryKeys.Blacklist,
]);
},
}
},
);
}
@ -110,7 +110,7 @@ export function useEpisodeHistoryPagination() {
return usePaginationQuery(
[QueryKeys.Series, QueryKeys.Episodes, QueryKeys.History],
(param) => api.episodes.history(param),
false
false,
);
}
@ -121,6 +121,6 @@ export function useEpisodeHistory(episodeId?: number) {
if (episodeId) {
return api.episodes.historyBy(episodeId);
}
}
},
);
}

View File

@ -6,7 +6,7 @@ export function useHistoryStats(
time: History.TimeFrameOptions,
action: History.ActionOptions | null,
provider: System.Provider | null,
language: Language.Info | null
language: Language.Info | null,
) {
return useQuery(
[QueryKeys.System, QueryKeys.History, { time, action, provider, language }],
@ -15,7 +15,7 @@ export function useHistoryStats(
time,
action ?? undefined,
provider?.name,
language?.code2
)
language?.code2,
),
);
}

View File

@ -8,7 +8,7 @@ export function useLanguages(history?: boolean) {
() => api.system.languages(history),
{
staleTime: Infinity,
}
},
);
}
@ -18,6 +18,6 @@ export function useLanguageProfiles() {
() => api.system.languagesProfileList(),
{
staleTime: Infinity,
}
},
);
}

View File

@ -39,13 +39,13 @@ export function useMovies() {
onSuccess: (data) => {
cacheMovies(client, data);
},
}
},
);
}
export function useMoviesPagination() {
return usePaginationQuery([QueryKeys.Movies], (param) =>
api.movies.moviesBy(param)
api.movies.moviesBy(param),
);
}
@ -62,7 +62,7 @@ export function useMovieModification() {
// TODO: query less
client.invalidateQueries([QueryKeys.Movies]);
},
}
},
);
}
@ -75,19 +75,19 @@ export function useMovieAction() {
onSuccess: () => {
client.invalidateQueries([QueryKeys.Movies]);
},
}
},
);
}
export function useMovieWantedPagination() {
return usePaginationQuery([QueryKeys.Movies, QueryKeys.Wanted], (param) =>
api.movies.wanted(param)
api.movies.wanted(param),
);
}
export function useMovieBlacklist() {
return useQuery([QueryKeys.Movies, QueryKeys.Blacklist], () =>
api.movies.blacklist()
api.movies.blacklist(),
);
}
@ -104,7 +104,7 @@ export function useMovieAddBlacklist() {
client.invalidateQueries([QueryKeys.Movies, QueryKeys.Blacklist]);
client.invalidateQueries([QueryKeys.Movies, id]);
},
}
},
);
}
@ -118,7 +118,7 @@ export function useMovieDeleteBlacklist() {
onSuccess: (_, param) => {
client.invalidateQueries([QueryKeys.Movies, QueryKeys.Blacklist]);
},
}
},
);
}
@ -126,7 +126,7 @@ export function useMovieHistoryPagination() {
return usePaginationQuery(
[QueryKeys.Movies, QueryKeys.History],
(param) => api.movies.history(param),
false
false,
);
}

View File

@ -5,7 +5,7 @@ import api from "../raw";
export function useSystemProviders(history?: boolean) {
return useQuery(
[QueryKeys.System, QueryKeys.Providers, history ?? false],
() => api.providers.providers(history)
() => api.providers.providers(history),
);
}
@ -19,7 +19,7 @@ export function useMoviesProvider(radarrId?: number) {
},
{
staleTime: 0,
}
},
);
}
@ -33,7 +33,7 @@ export function useEpisodesProvider(episodeId?: number) {
},
{
staleTime: 0,
}
},
);
}
@ -46,7 +46,7 @@ export function useResetProvider() {
onSuccess: () => {
client.invalidateQueries([QueryKeys.System, QueryKeys.Providers]);
},
}
},
);
}
@ -68,13 +68,13 @@ export function useDownloadEpisodeSubtitles() {
api.providers.downloadEpisodeSubtitle(
param.seriesId,
param.episodeId,
param.form
param.form,
),
{
onSuccess: (_, param) => {
client.invalidateQueries([QueryKeys.Series, param.seriesId]);
},
}
},
);
}
@ -94,6 +94,6 @@ export function useDownloadMovieSubtitles() {
onSuccess: (_, param) => {
client.invalidateQueries([QueryKeys.Movies, param.radarrId]);
},
}
},
);
}

View File

@ -39,13 +39,13 @@ export function useSeries() {
onSuccess: (data) => {
cacheSeries(client, data);
},
}
},
);
}
export function useSeriesPagination() {
return usePaginationQuery([QueryKeys.Series], (param) =>
api.series.seriesBy(param)
api.series.seriesBy(param),
);
}
@ -61,7 +61,7 @@ export function useSeriesModification() {
});
client.invalidateQueries([QueryKeys.Series]);
},
}
},
);
}
@ -74,6 +74,6 @@ export function useSeriesAction() {
onSuccess: () => {
client.invalidateQueries([QueryKeys.Series]);
},
}
},
);
}

View File

@ -23,7 +23,7 @@ export function useSubtitleAction() {
client.invalidateQueries([QueryKeys.Movies, id]);
}
},
}
},
);
}
@ -42,13 +42,13 @@ export function useEpisodeSubtitleModification() {
api.episodes.downloadSubtitles(
param.seriesId,
param.episodeId,
param.form
param.form,
),
{
onSuccess: (_, param) => {
client.invalidateQueries([QueryKeys.Series, param.seriesId]);
},
}
},
);
const remove = useMutation(
@ -59,7 +59,7 @@ export function useEpisodeSubtitleModification() {
onSuccess: (_, param) => {
client.invalidateQueries([QueryKeys.Series, param.seriesId]);
},
}
},
);
const upload = useMutation(
@ -70,7 +70,7 @@ export function useEpisodeSubtitleModification() {
onSuccess: (_, { seriesId }) => {
client.invalidateQueries([QueryKeys.Series, seriesId]);
},
}
},
);
return { download, remove, upload };
@ -92,7 +92,7 @@ export function useMovieSubtitleModification() {
onSuccess: (_, param) => {
client.invalidateQueries([QueryKeys.Movies, param.radarrId]);
},
}
},
);
const remove = useMutation(
@ -103,7 +103,7 @@ export function useMovieSubtitleModification() {
onSuccess: (_, param) => {
client.invalidateQueries([QueryKeys.Movies, param.radarrId]);
},
}
},
);
const upload = useMutation(
@ -114,7 +114,7 @@ export function useMovieSubtitleModification() {
onSuccess: (_, { radarrId }) => {
client.invalidateQueries([QueryKeys.Movies, radarrId]);
},
}
},
);
return { download, remove, upload };
@ -122,30 +122,30 @@ export function useMovieSubtitleModification() {
export function useSubtitleInfos(names: string[]) {
return useQuery([QueryKeys.Subtitles, QueryKeys.Infos, names], () =>
api.subtitles.info(names)
api.subtitles.info(names),
);
}
export function useRefTracksByEpisodeId(
subtitlesPath: string,
sonarrEpisodeId: number,
isEpisode: boolean
isEpisode: boolean,
) {
return useQuery(
[QueryKeys.Episodes, sonarrEpisodeId, QueryKeys.Subtitles, subtitlesPath],
() => api.subtitles.getRefTracksByEpisodeId(subtitlesPath, sonarrEpisodeId),
{ enabled: isEpisode }
{ enabled: isEpisode },
);
}
export function useRefTracksByMovieId(
subtitlesPath: string,
radarrMovieId: number,
isMovie: boolean
isMovie: boolean,
) {
return useQuery(
[QueryKeys.Movies, radarrMovieId, QueryKeys.Subtitles, subtitlesPath],
() => api.subtitles.getRefTracksByMovieId(subtitlesPath, radarrMovieId),
{ enabled: isMovie }
{ enabled: isMovie },
);
}

View File

@ -13,14 +13,14 @@ export function useBadges() {
refetchOnWindowFocus: "always",
refetchInterval: 1000 * 60,
staleTime: 1000 * 10,
}
},
);
}
export function useFileSystem(
type: "bazarr" | "sonarr" | "radarr",
path: string,
enabled: boolean
enabled: boolean,
) {
return useQuery(
[QueryKeys.FileSystem, type, path],
@ -35,7 +35,7 @@ export function useFileSystem(
},
{
enabled,
}
},
);
}
@ -45,7 +45,7 @@ export function useSystemSettings() {
() => api.system.settings(),
{
staleTime: Infinity,
}
},
);
}
@ -63,7 +63,7 @@ export function useSettingsMutation() {
client.invalidateQueries([QueryKeys.Wanted]);
client.invalidateQueries([QueryKeys.Badges]);
},
}
},
);
}
@ -73,7 +73,7 @@ export function useServerSearch(query: string, enabled: boolean) {
() => api.system.search(query),
{
enabled,
}
},
);
}
@ -94,7 +94,7 @@ export function useDeleteLogs() {
onSuccess: () => {
client.invalidateQueries([QueryKeys.System, QueryKeys.Logs]);
},
}
},
);
}
@ -106,7 +106,7 @@ export function useSystemAnnouncements() {
refetchOnWindowFocus: "always",
refetchInterval: 1000 * 60,
staleTime: 1000 * 10,
}
},
);
}
@ -123,7 +123,7 @@ export function useSystemAnnouncementsAddDismiss() {
client.invalidateQueries([QueryKeys.System, QueryKeys.Announcements]);
client.invalidateQueries([QueryKeys.System, QueryKeys.Badges]);
},
}
},
);
}
@ -135,7 +135,7 @@ export function useSystemTasks() {
refetchOnWindowFocus: "always",
refetchInterval: 1000 * 60,
staleTime: 1000 * 10,
}
},
);
}
@ -149,7 +149,7 @@ export function useRunTask() {
client.invalidateQueries([QueryKeys.System, QueryKeys.Tasks]);
client.invalidateQueries([QueryKeys.System, QueryKeys.Backups]);
},
}
},
);
}
@ -166,7 +166,7 @@ export function useCreateBackups() {
onSuccess: () => {
client.invalidateQueries([QueryKeys.System, QueryKeys.Backups]);
},
}
},
);
}
@ -179,7 +179,7 @@ export function useRestoreBackups() {
onSuccess: () => {
client.invalidateQueries([QueryKeys.System, QueryKeys.Backups]);
},
}
},
);
}
@ -192,7 +192,7 @@ export function useDeleteBackups() {
onSuccess: () => {
client.invalidateQueries([QueryKeys.System, QueryKeys.Backups]);
},
}
},
);
}
@ -218,7 +218,7 @@ export function useSystem() {
setAuthenticated(false);
client.clear();
},
}
},
);
const { mutate: login, isLoading: isLoggingIn } = useMutation(
@ -230,7 +230,7 @@ export function useSystem() {
// TODO: Hard-coded value
window.location.replace(Environment.baseUrl);
},
}
},
);
const { mutate: shutdown, isLoading: isShuttingDown } = useMutation(
@ -240,7 +240,7 @@ export function useSystem() {
onSuccess: () => {
client.clear();
},
}
},
);
const { mutate: restart, isLoading: isRestarting } = useMutation(
@ -250,7 +250,7 @@ export function useSystem() {
onSuccess: () => {
client.clear();
},
}
},
);
return useMemo(
@ -270,6 +270,6 @@ export function useSystem() {
logout,
restart,
shutdown,
]
],
);
}

View File

@ -26,11 +26,11 @@ export type UsePaginationQueryResult<T extends object> = UseQueryResult<
export function usePaginationQuery<
TObject extends object = object,
TQueryKey extends QueryKey = QueryKey
TQueryKey extends QueryKey = QueryKey,
>(
queryKey: TQueryKey,
queryFn: RangeQuery<TObject>,
cacheIndividual = true
cacheIndividual = true,
): UsePaginationQueryResult<TObject> {
const client = useQueryClient();
@ -59,7 +59,7 @@ export function usePaginationQuery<
});
}
},
}
},
);
const { data } = results;
@ -73,7 +73,7 @@ export function usePaginationQuery<
setIndex(idx);
}
},
[pageCount]
[pageCount],
);
const [isPageLoading, setIsPageLoading] = useState(false);

View File

@ -64,7 +64,7 @@ class BazarrClient {
(error: AxiosError) => {
const message = GetErrorMessage(
error.response?.data,
"You have disconnected from the server"
"You have disconnected from the server",
);
const backendError: BackendError = {
@ -76,7 +76,7 @@ class BazarrClient {
this.handleError(backendError);
return Promise.reject(error);
}
},
);
}

View File

@ -22,7 +22,7 @@ class EpisodeApi extends BaseApi {
async wanted(params: Parameter.Range) {
const response = await this.get<DataWrapperWithTotal<Wanted.Episode>>(
"/wanted",
params
params,
);
return response;
}
@ -30,7 +30,7 @@ class EpisodeApi extends BaseApi {
async wantedBy(episodeid: number[]) {
const response = await this.get<DataWrapperWithTotal<Wanted.Episode>>(
"/wanted",
{ episodeid }
{ episodeid },
);
return response;
}
@ -38,7 +38,7 @@ class EpisodeApi extends BaseApi {
async history(params: Parameter.Range) {
const response = await this.get<DataWrapperWithTotal<History.Episode>>(
"/history",
params
params,
);
return response;
}
@ -46,7 +46,7 @@ class EpisodeApi extends BaseApi {
async historyBy(episodeid: number) {
const response = await this.get<DataWrapperWithTotal<History.Episode>>(
"/history",
{ episodeid }
{ episodeid },
);
return response.data;
}
@ -54,7 +54,7 @@ class EpisodeApi extends BaseApi {
async downloadSubtitles(
seriesid: number,
episodeid: number,
form: FormType.Subtitle
form: FormType.Subtitle,
) {
await this.patch("/subtitles", form, { seriesid, episodeid });
}
@ -62,7 +62,7 @@ class EpisodeApi extends BaseApi {
async uploadSubtitles(
seriesid: number,
episodeid: number,
form: FormType.UploadSubtitle
form: FormType.UploadSubtitle,
) {
await this.post("/subtitles", form, { seriesid, episodeid });
}
@ -70,22 +70,21 @@ class EpisodeApi extends BaseApi {
async deleteSubtitles(
seriesid: number,
episodeid: number,
form: FormType.DeleteSubtitle
form: FormType.DeleteSubtitle,
) {
await this.delete("/subtitles", form, { seriesid, episodeid });
}
async blacklist() {
const response = await this.get<DataWrapper<Blacklist.Episode[]>>(
"/blacklist"
);
const response =
await this.get<DataWrapper<Blacklist.Episode[]>>("/blacklist");
return response.data;
}
async addBlacklist(
seriesid: number,
episodeid: number,
form: FormType.AddBlacklist
form: FormType.AddBlacklist,
) {
await this.post("/blacklist", form, { seriesid, episodeid });
}

View File

@ -9,7 +9,7 @@ class HistoryApi extends BaseApi {
timeFrame?: History.TimeFrameOptions,
action?: History.ActionOptions,
provider?: string,
language?: Language.CodeType
language?: Language.CodeType,
) {
const response = await this.get<History.Stat>("/stats", {
timeFrame,

View File

@ -6,9 +6,8 @@ class MovieApi extends BaseApi {
}
async blacklist() {
const response = await this.get<DataWrapper<Blacklist.Movie[]>>(
"/blacklist"
);
const response =
await this.get<DataWrapper<Blacklist.Movie[]>>("/blacklist");
return response.data;
}
@ -30,7 +29,7 @@ class MovieApi extends BaseApi {
async moviesBy(params: Parameter.Range) {
const response = await this.get<DataWrapperWithTotal<Item.Movie>>(
"",
params
params,
);
return response;
}
@ -42,7 +41,7 @@ class MovieApi extends BaseApi {
async wanted(params: Parameter.Range) {
const response = await this.get<DataWrapperWithTotal<Wanted.Movie>>(
"/wanted",
params
params,
);
return response;
}
@ -52,7 +51,7 @@ class MovieApi extends BaseApi {
"/wanted",
{
radarrid,
}
},
);
return response;
}
@ -60,7 +59,7 @@ class MovieApi extends BaseApi {
async history(params: Parameter.Range) {
const response = await this.get<DataWrapperWithTotal<History.Movie>>(
"/history",
params
params,
);
return response;
}
@ -68,7 +67,7 @@ class MovieApi extends BaseApi {
async historyBy(radarrid: number) {
const response = await this.get<DataWrapperWithTotal<History.Movie>>(
"/history",
{ radarrid }
{ radarrid },
);
return response.data;
}

View File

@ -19,7 +19,7 @@ class ProviderApi extends BaseApi {
async movies(id: number) {
const response = await this.get<DataWrapper<SearchResultType[]>>(
"/movies",
{ radarrid: id }
{ radarrid: id },
);
return response.data;
}
@ -33,7 +33,7 @@ class ProviderApi extends BaseApi {
"/episodes",
{
episodeid,
}
},
);
return response.data;
}
@ -41,7 +41,7 @@ class ProviderApi extends BaseApi {
async downloadEpisodeSubtitle(
seriesid: number,
episodeid: number,
form: FormType.ManualDownload
form: FormType.ManualDownload,
) {
await this.post("/episodes", form, { seriesid, episodeid });
}

View File

@ -15,7 +15,7 @@ class SeriesApi extends BaseApi {
async seriesBy(params: Parameter.Range) {
const response = await this.get<DataWrapperWithTotal<Item.Series>>(
"",
params
params,
);
return response;
}

View File

@ -7,7 +7,7 @@ class SubtitlesApi extends BaseApi {
async getRefTracksByEpisodeId(
subtitlesPath: string,
sonarrEpisodeId: number
sonarrEpisodeId: number,
) {
const response = await this.get<DataWrapper<Item.RefTracks>>("", {
subtitlesPath,
@ -18,7 +18,7 @@ class SubtitlesApi extends BaseApi {
async getRefTracksByMovieId(
subtitlesPath: string,
radarrMovieId?: number | undefined
radarrMovieId?: number | undefined,
) {
const response = await this.get<DataWrapper<Item.RefTracks>>("", {
subtitlesPath,

View File

@ -88,9 +88,8 @@ class SystemApi extends BaseApi {
}
async announcements() {
const response = await this.get<DataWrapper<System.Announcements[]>>(
"/announcements"
);
const response =
await this.get<DataWrapper<System.Announcements[]>>("/announcements");
return response.data;
}

View File

@ -15,7 +15,7 @@ class RequestUtils {
try {
const result = await client.axios.get<UrlTestResponse>(
`../test/${protocol}/${url}api/system/status`,
{ params }
{ params },
);
const { data } = result;
if (data.status && data.version) {
@ -26,7 +26,7 @@ class RequestUtils {
} catch (e) {
const result = await client.axios.get<UrlTestResponse>(
`../test/${protocol}/${url}api/v3/system/status`,
{ params }
{ params },
);
return result.data;
}

View File

@ -37,7 +37,7 @@ function useSearch(query: string) {
link,
};
}) ?? [],
[data]
[data],
);
}
@ -69,7 +69,7 @@ const ResultComponent = forwardRef<HTMLDivElement, ResultCompProps>(
{value}
</Anchor>
);
}
},
);
const Search: FunctionComponent = () => {

View File

@ -100,7 +100,7 @@ export function useTools() {
modal: TranslationModal,
},
],
[]
[],
);
}
@ -131,7 +131,7 @@ const SubtitleToolsMenu: FunctionComponent<Props> = ({
task.create(s.path, name, mutateAsync, { action, form });
});
},
[mutateAsync, selections]
[mutateAsync, selections],
);
const tools = useTools();

View File

@ -53,7 +53,7 @@ describe("Language text", () => {
it("should show long text with Forced", () => {
rawRender(
<Language.Text value={testLanguageWithForced} long></Language.Text>
<Language.Text value={testLanguageWithForced} long></Language.Text>,
);
const expectedText = `${testLanguageWithHi.name} Forced`;

View File

@ -14,7 +14,7 @@ const LanguageProfileName: FunctionComponent<Props> = ({
const name = useMemo(
() => data?.find((v) => v.profileId === index)?.name ?? empty,
[data, empty, index]
[data, empty, index],
);
return <>{name}</>;

View File

@ -25,7 +25,7 @@ const LanguageSelector: FunctionComponent<LanguageSelectorProps> = ({
const options = useSelectorOptions(
filteredData ?? [],
(value) => value.name,
(value) => value.code3
(value) => value.code3,
);
return <Selector {...options} searchable {...selector}></Selector>;

View File

@ -96,7 +96,7 @@ const ColorToolForm: FunctionComponent<Props> = ({ selections, onSubmit }) => {
validate: {
color: FormUtils.validation(
(value) => colorOptions.find((op) => op.value === value) !== undefined,
"Must select a color"
"Must select a color",
),
},
});
@ -110,7 +110,7 @@ const ColorToolForm: FunctionComponent<Props> = ({ selections, onSubmit }) => {
task.create(s.path, TaskName, mutateAsync, {
action,
form: s,
})
}),
);
onSubmit?.();

View File

@ -29,11 +29,11 @@ const FrameRateForm: FunctionComponent<Props> = ({ selections, onSubmit }) => {
validate: {
from: FormUtils.validation(
(value) => value > 0,
"The From value must be larger than 0"
"The From value must be larger than 0",
),
to: FormUtils.validation(
(value) => value > 0,
"The To value must be larger than 0"
"The To value must be larger than 0",
),
},
});
@ -47,7 +47,7 @@ const FrameRateForm: FunctionComponent<Props> = ({ selections, onSubmit }) => {
task.create(s.path, TaskName, mutateAsync, {
action,
form: s,
})
}),
);
onSubmit?.();

View File

@ -27,12 +27,12 @@ const ItemEditForm: FunctionComponent<Props> = ({
const profileOptions = useSelectorOptions(
data ?? [],
(v) => v.name ?? "Unknown",
(v) => v.profileId.toString() ?? "-1"
(v) => v.profileId.toString() ?? "-1",
);
const profile = useMemo(
() => data?.find((v) => v.profileId === item?.profileId) ?? null,
[data, item?.profileId]
[data, item?.profileId],
);
const form = useForm({
@ -44,7 +44,7 @@ const ItemEditForm: FunctionComponent<Props> = ({
const options = useSelectorOptions(
item?.audio_language ?? [],
(v) => v.name,
(v) => v.code2
(v) => v.code2,
);
const isOverlayVisible = isLoading || isFetching || item === null;

View File

@ -47,7 +47,7 @@ type SubtitleValidateResult = {
const validator = (
movie: Item.Movie,
file: SubtitleFile
file: SubtitleFile,
): SubtitleValidateResult => {
if (file.language === null) {
return {
@ -57,7 +57,7 @@ const validator = (
} else {
const { subtitles } = movie;
const existing = subtitles.find(
(v) => v.code2 === file.language?.code2 && isString(v.path)
(v) => v.code2 === file.language?.code2 && isString(v.path),
);
if (existing !== undefined) {
return {
@ -91,12 +91,12 @@ const MovieUploadForm: FunctionComponent<Props> = ({
const languageOptions = useSelectorOptions(
languages,
(v) => v.name,
(v) => v.code2
(v) => v.code2,
);
const defaultLanguage = useMemo(
() => (languages.length > 0 ? languages[0] : null),
[languages]
[languages],
);
const form = useForm({
@ -120,7 +120,7 @@ const MovieUploadForm: FunctionComponent<Props> = ({
(v) =>
v.language === null ||
v.validateResult === undefined ||
v.validateResult.state === "error"
v.validateResult.state === "error",
) === undefined
);
}, "Some files cannot be uploaded, please check"),
@ -254,7 +254,7 @@ const MovieUploadForm: FunctionComponent<Props> = ({
},
},
],
[action, languageOptions]
[action, languageOptions],
);
const { upload } = useMovieSubtitleModification();
@ -294,7 +294,7 @@ export const MovieUploadModal = withModal(
{
title: "Upload Subtitles",
size: "xl",
}
},
);
export default MovieUploadForm;

View File

@ -69,11 +69,11 @@ const ProfileEditForm: FunctionComponent<Props> = ({
validate: {
name: FormUtils.validation(
(value) => value.length > 0,
"Must have a name"
"Must have a name",
),
items: FormUtils.validation(
(value) => value.length > 0,
"Must contain at lease 1 language"
"Must contain at lease 1 language",
),
},
});
@ -83,7 +83,7 @@ const ProfileEditForm: FunctionComponent<Props> = ({
const itemCutoffOptions = useSelectorOptions(
form.values.items,
(v) => v.language,
(v) => String(v.id)
(v) => String(v.id),
);
const cutoffOptions = useMemo(
@ -91,24 +91,24 @@ const ProfileEditForm: FunctionComponent<Props> = ({
...itemCutoffOptions,
options: [...itemCutoffOptions.options, ...defaultCutoffOptions],
}),
[itemCutoffOptions]
[itemCutoffOptions],
);
const selectedCutoff = useMemo(
() =>
cutoffOptions.options.find((v) => v.value.id === form.values.cutoff)
?.value ?? null,
[cutoffOptions, form.values.cutoff]
[cutoffOptions, form.values.cutoff],
);
const mustContainOptions = useSelectorOptions(
form.values.mustContain,
(v) => v
(v) => v,
);
const mustNotContainOptions = useSelectorOptions(
form.values.mustNotContain,
(v) => v
(v) => v,
);
const action = useArrayAction<Language.ProfileItem>((fn) => {
@ -120,7 +120,7 @@ const ProfileEditForm: FunctionComponent<Props> = ({
1 +
form.values.items.reduce<number>(
(val, item) => Math.max(item.id, val),
0
0,
);
if (languages.length > 0) {
@ -154,7 +154,7 @@ const ProfileEditForm: FunctionComponent<Props> = ({
() =>
languageOptions.options.find((l) => l.value.code2 === code)
?.value ?? null,
[code]
[code],
);
const { classes } = useTableStyles();
@ -238,7 +238,7 @@ const ProfileEditForm: FunctionComponent<Props> = ({
},
},
],
[action, languageOptions]
[action, languageOptions],
);
return (
@ -332,5 +332,5 @@ export const ProfileEditModal = withModal(
{
title: "Edit Languages Profile",
size: "xl",
}
},
);

View File

@ -64,7 +64,7 @@ const validator = (file: SubtitleFile): SubtitleValidateResult => {
} else {
const { subtitles } = file.episode;
const existing = subtitles.find(
(v) => v.code2 === file.language?.code2 && isString(v.path)
(v) => v.code2 === file.language?.code2 && isString(v.path),
);
if (existing !== undefined) {
return {
@ -95,7 +95,7 @@ const SeriesUploadForm: FunctionComponent<Props> = ({
const episodeOptions = useSelectorOptions(
episodes.data ?? [],
(v) => `(${v.season}x${v.episode}) ${v.title}`,
(v) => v.sonarrEpisodeId.toString()
(v) => v.sonarrEpisodeId.toString(),
);
const profile = useLanguageProfileBy(series.profileId);
@ -103,12 +103,12 @@ const SeriesUploadForm: FunctionComponent<Props> = ({
const languageOptions = useSelectorOptions(
languages,
(v) => v.name,
(v) => v.code2
(v) => v.code2,
);
const defaultLanguage = useMemo(
() => (languages.length > 0 ? languages[0] : null),
[languages]
[languages],
);
const form = useForm({
@ -134,9 +134,9 @@ const SeriesUploadForm: FunctionComponent<Props> = ({
v.language === null ||
v.episode === null ||
v.validateResult === undefined ||
v.validateResult.state === "error"
v.validateResult.state === "error",
) === undefined,
"Some files cannot be uploaded, please check"
"Some files cannot be uploaded, please check",
),
},
});
@ -162,7 +162,7 @@ const SeriesUploadForm: FunctionComponent<Props> = ({
if (info) {
item.episode =
episodes.data?.find(
(v) => v.season === info.season && v.episode === info.episode
(v) => v.season === info.season && v.episode === info.episode,
) ?? item.episode;
}
return item;
@ -320,7 +320,7 @@ const SeriesUploadForm: FunctionComponent<Props> = ({
},
},
],
[action, episodeOptions, languageOptions]
[action, episodeOptions, languageOptions],
);
const { upload } = useEpisodeSubtitleModification();
@ -335,7 +335,7 @@ const SeriesUploadForm: FunctionComponent<Props> = ({
if (language === null || episode === null) {
throw new Error(
"Invalid language or episode. This shouldn't happen, please report this bug."
"Invalid language or episode. This shouldn't happen, please report this bug.",
);
}
@ -370,7 +370,7 @@ const SeriesUploadForm: FunctionComponent<Props> = ({
export const SeriesUploadModal = withModal(
SeriesUploadForm,
"upload-series-subtitles",
{ title: "Upload Subtitles", size: "xl" }
{ title: "Upload Subtitles", size: "xl" },
);
export default SeriesUploadForm;

View File

@ -21,18 +21,18 @@ const TaskName = "Syncing Subtitle";
function useReferencedSubtitles(
mediaType: "episode" | "movie",
mediaId: number,
subtitlesPath: string
subtitlesPath: string,
) {
// We cannot call hooks conditionally, we rely on useQuery "enabled" option to do only the required API call
const episodeData = useRefTracksByEpisodeId(
subtitlesPath,
mediaId,
mediaType === "episode"
mediaType === "episode",
);
const movieData = useRefTracksByMovieId(
subtitlesPath,
mediaId,
mediaType === "movie"
mediaType === "movie",
);
const mediaData = mediaType === "episode" ? episodeData : movieData;
@ -108,7 +108,7 @@ const SyncSubtitleForm: FunctionComponent<Props> = ({
const subtitles: SelectorOption<string>[] = useReferencedSubtitles(
mediaType,
mediaId,
subtitlesPath
subtitlesPath,
);
const form = useForm<FormValues>({

View File

@ -37,7 +37,7 @@ const TimeOffsetForm: FunctionComponent<Props> = ({ selections, onSubmit }) => {
sec: FormUtils.validation((v) => v >= 0, "Second must be larger than 0"),
ms: FormUtils.validation(
(v) => v >= 0,
"Millisecond must be larger than 0"
"Millisecond must be larger than 0",
),
},
});
@ -62,7 +62,7 @@ const TimeOffsetForm: FunctionComponent<Props> = ({ selections, onSubmit }) => {
task.create(s.path, TaskName, mutateAsync, {
action,
form: s,
})
}),
);
onSubmit?.();

View File

@ -146,13 +146,13 @@ const TranslationForm: FunctionComponent<Props> = ({
const available = useMemo(
() => languages.filter((v) => v.code2 in translations),
[languages]
[languages],
);
const options = useSelectorOptions(
available,
(v) => v.name,
(v) => v.code2
(v) => v.code2,
);
return (
@ -166,7 +166,7 @@ const TranslationForm: FunctionComponent<Props> = ({
...s,
language: language.code2,
},
})
}),
);
onSubmit?.();

View File

@ -28,7 +28,7 @@ describe("Action button", () => {
it("should call on-click event when clicked", async () => {
const onClickFn = vitest.fn();
rawRender(
<Action icon={testIcon} label={testLabel} onClick={onClickFn}></Action>
<Action icon={testIcon} label={testLabel} onClick={onClickFn}></Action>,
);
await userEvent.click(screen.getByRole("button", { name: testLabel }));

View File

@ -27,7 +27,7 @@ const Action = forwardRef<HTMLButtonElement, ActionProps>(
</ActionIcon>
</Tooltip>
);
}
},
);
export default Action;

View File

@ -30,7 +30,7 @@ describe("ChipInput", () => {
});
rawRender(
<ChipInput value={existedValues} onChange={mockedFn}></ChipInput>
<ChipInput value={existedValues} onChange={mockedFn}></ChipInput>,
);
const element = screen.getByRole("searchbox");

View File

@ -53,7 +53,7 @@ export const FileBrowser: FunctionComponent<FileBrowserProps> = ({
item: v,
})) ?? []),
],
[tree]
[tree],
);
const parent = useMemo(() => {

View File

@ -19,7 +19,7 @@ describe("Selector", () => {
describe("options", () => {
it("should work with the SelectorOption", () => {
rawRender(
<Selector name={selectorName} options={testOptions}></Selector>
<Selector name={selectorName} options={testOptions}></Selector>,
);
// TODO: selectorName
@ -28,7 +28,7 @@ describe("Selector", () => {
it("should display when clicked", async () => {
rawRender(
<Selector name={selectorName} options={testOptions}></Selector>
<Selector name={selectorName} options={testOptions}></Selector>,
);
const element = screen.getByRole("searchbox");
@ -49,7 +49,7 @@ describe("Selector", () => {
name={selectorName}
options={testOptions}
defaultValue={option.value}
></Selector>
></Selector>,
);
expect(screen.getByDisplayValue(option.label)).toBeDefined();
@ -62,7 +62,7 @@ describe("Selector", () => {
name={selectorName}
options={testOptions}
value={option.value}
></Selector>
></Selector>,
);
expect(screen.getByDisplayValue(option.label)).toBeDefined();
@ -80,7 +80,7 @@ describe("Selector", () => {
name={selectorName}
options={testOptions}
onChange={mockedFn}
></Selector>
></Selector>,
);
const element = screen.getByRole("searchbox");
@ -121,7 +121,7 @@ describe("Selector", () => {
options={objectOptions}
onChange={mockedFn}
getkey={(v) => v.name}
></Selector>
></Selector>,
);
const element = screen.getByRole("searchbox");
@ -142,7 +142,7 @@ describe("Selector", () => {
name={selectorName}
options={testOptions}
placeholder={placeholder}
></Selector>
></Selector>,
);
expect(screen.getByPlaceholderText(placeholder)).toBeDefined();

View File

@ -29,7 +29,7 @@ function DefaultKeyBuilder<T>(value: T) {
} else {
LOG("error", "Unknown value type", value);
throw new Error(
`Invalid type (${typeof value}) in the SelectorOption, please provide a label builder`
`Invalid type (${typeof value}) in the SelectorOption, please provide a label builder`,
);
}
}
@ -64,7 +64,7 @@ export function Selector<T>({
payload: value,
...option,
})),
[keyRef, options]
[keyRef, options],
);
const wrappedValue = useMemo(() => {
@ -88,7 +88,7 @@ export function Selector<T>({
const payload = data.find((v) => v.value === value)?.payload ?? null;
onChange?.(payload);
},
[data, onChange]
[data, onChange],
);
return (
@ -137,16 +137,16 @@ export function MultiSelector<T>({
payload: value,
...option,
})),
[options]
[options],
);
const wrappedValue = useMemo(
() => value && value.map(labelRef.current),
[value]
[value],
);
const wrappedDefaultValue = useMemo(
() => defaultValue && defaultValue.map(labelRef.current),
[defaultValue]
[defaultValue],
);
const wrappedOnChange = useCallback(
@ -162,7 +162,7 @@ export function MultiSelector<T>({
}
onChange?.(payloads);
},
[data, onChange]
[data, onChange],
);
return (

View File

@ -123,7 +123,7 @@ const MovieHistoryView: FunctionComponent<MovieHistoryViewProps> = ({
},
},
],
[]
[],
);
return (
@ -263,7 +263,7 @@ const EpisodeHistoryView: FunctionComponent<EpisodeHistoryViewProps> = ({
},
},
],
[]
[],
);
return (
@ -280,5 +280,5 @@ const EpisodeHistoryView: FunctionComponent<EpisodeHistoryViewProps> = ({
export const EpisodeHistoryModal = withModal(
EpisodeHistoryView,
"episode-history",
{ size: "xl" }
{ size: "xl" },
);

View File

@ -32,7 +32,7 @@ type SupportType = Item.Movie | Item.Episode;
interface Props<T extends SupportType> {
download: (item: T, result: SearchResultType) => Promise<void>;
query: (
id?: number
id?: number,
) => UseQueryResult<SearchResultType[] | undefined, unknown>;
item: T;
}
@ -111,7 +111,7 @@ function ManualSearchView<T extends SupportType>(props: Props<T>) {
const items = useMemo(
() => value.slice(1).map((v, idx) => <Text key={idx}>{v}</Text>),
[value]
[value],
);
if (value.length === 0) {
@ -176,7 +176,7 @@ function ManualSearchView<T extends SupportType>(props: Props<T>) {
TaskGroup.DownloadSubtitle,
download,
item,
result
result,
);
}}
></Action>
@ -184,7 +184,7 @@ function ManualSearchView<T extends SupportType>(props: Props<T>) {
},
},
],
[download, item]
[download, item],
);
const bSceneNameAvailable =
@ -228,10 +228,10 @@ function ManualSearchView<T extends SupportType>(props: Props<T>) {
export const MovieSearchModal = withModal<Props<Item.Movie>>(
ManualSearchView,
"movie-manual-search",
{ title: "Search Subtitles", size: "calc(100vw - 4rem)" }
{ title: "Search Subtitles", size: "calc(100vw - 4rem)" },
);
export const EpisodeSearchModal = withModal<Props<Item.Episode>>(
ManualSearchView,
"episode-manual-search",
{ title: "Search Subtitles", size: "calc(100vw - 4rem)" }
{ title: "Search Subtitles", size: "calc(100vw - 4rem)" },
);

View File

@ -67,7 +67,7 @@ const SubtitleToolView: FunctionComponent<SubtitleToolViewProps> = ({
},
},
],
[]
[],
);
const data = useMemo<TableColumnType[]>(
@ -91,7 +91,7 @@ const SubtitleToolView: FunctionComponent<SubtitleToolViewProps> = ({
}
});
}),
[payload]
[payload],
);
const plugins = [useRowSelect, useCustomSelection];

View File

@ -33,7 +33,7 @@ const useStyles = createStyles((theme) => {
});
function DefaultHeaderRenderer<T extends object>(
headers: HeaderGroup<T>[]
headers: HeaderGroup<T>[],
): JSX.Element[] {
return headers.map((col) => (
<th style={{ whiteSpace: "nowrap" }} {...col.getHeaderProps()}>
@ -71,7 +71,7 @@ export default function BaseTable<T extends object>(props: BaseTableProps<T>) {
const colCount = useMemo(() => {
return headerGroups.reduce(
(prev, curr) => (curr.headers.length > prev ? curr.headers.length : prev),
0
0,
);
}, [headerGroups]);

View File

@ -60,7 +60,7 @@ function renderRow<T extends object>(row: Row<T>) {
}
function renderHeaders<T extends object>(
headers: HeaderGroup<T>[]
headers: HeaderGroup<T>[],
): JSX.Element[] {
return headers
.filter((col) => !col.isGrouped)

View File

@ -20,7 +20,7 @@ export default function PageTable<T extends object>(props: Props<T>) {
options,
useDefaultSettings,
...tablePlugins,
...(plugins ?? [])
...(plugins ?? []),
);
// use page size as specified in UI settings

View File

@ -9,7 +9,7 @@ export type SimpleTableProps<T extends object> = TableOptions<T> & {
};
export default function SimpleTable<T extends object>(
props: SimpleTableProps<T>
props: SimpleTableProps<T>,
) {
const { plugins, instanceRef, tableStyles, ...options } = props;

View File

@ -71,7 +71,7 @@ function useInstance<T extends object>(instance: TableInstance<T>) {
useEffect(() => {
// Performance
let items = Object.keys(selectedRowIds).flatMap(
(v) => rows.find((n) => n.id === v)?.original ?? []
(v) => rows.find((n) => n.id === v)?.original ?? [],
);
if (canSelect) {
@ -84,7 +84,7 @@ function useInstance<T extends object>(instance: TableInstance<T>) {
function visibleColumns<T extends object>(
columns: ColumnInstance<T>[],
meta: MetaBase<T>
meta: MetaBase<T>,
): Column<T>[] {
const { instance } = meta;
const checkbox: Column<T> = {

View File

@ -38,7 +38,7 @@ type ToolboxMutateButtonProps<R, T extends () => Promise<R>> = {
} & Omit<ToolboxButtonProps, "onClick" | "loading">;
export function ToolboxMutateButton<R, T extends () => Promise<R>>(
props: PropsWithChildren<ToolboxMutateButtonProps<R, T>>
props: PropsWithChildren<ToolboxMutateButtonProps<R, T>>,
): JSX.Element {
const { promise, onSuccess, ...button } = props;

View File

@ -14,6 +14,6 @@ if (container === null) {
<AllProviders>
<Router />
</AllProviders>
</StrictMode>
</StrictMode>,
);
}

View File

@ -21,7 +21,7 @@ const ModalsProvider: FunctionComponent<PropsWithChildren> = ({ children }) => {
prev[curr.modalKey] = curr;
return prev;
}, {}),
[]
[],
);
return (

View File

@ -17,7 +17,7 @@ export const ModalIdContext = createContext<string | null>(null);
export default function withModal<T extends {}>(
Content: FunctionComponent<T>,
key: string,
defaultSettings?: ModalSettings
defaultSettings?: ModalSettings,
) {
const Comp: ModalComponent<T> = (props) => {
const { id, innerProps } = props;

View File

@ -15,7 +15,7 @@ export function useModals() {
<ARGS extends {}>(
modal: ModalComponent<ARGS>,
props: ARGS,
settings?: ModalSettings
settings?: ModalSettings,
) => {
openMantineContextModal(modal.modalKey, {
...modal.settings,
@ -23,14 +23,14 @@ export function useModals() {
innerProps: props,
});
},
[openMantineContextModal]
[openMantineContextModal],
);
const closeContextModal = useCallback(
(modal: ModalComponent) => {
rest.closeModal(modal.modalKey);
},
[rest]
[rest],
);
const id = useContext(ModalIdContext);
@ -44,6 +44,6 @@ export function useModals() {
// TODO: Performance
return useMemo(
() => ({ openContextModal, closeContextModal, closeSelf, ...rest }),
[closeContextModal, closeSelf, openContextModal, rest]
[closeContextModal, closeSelf, openContextModal, rest],
);
}

View File

@ -32,7 +32,7 @@ declare namespace SocketIO {
type ReducerGroup<
E extends EventType,
U extends PayloadType | undefined,
D = U
D = U,
> = ValueOf<{
[P in E]: {
key: P;

View File

@ -59,7 +59,7 @@ class TaskDispatcher {
group,
task.description,
index,
tasks.length
tasks.length,
);
updateNotification(notifyInProgress);
@ -120,8 +120,8 @@ class TaskDispatcher {
item.header,
item.name,
item.value,
item.count
)
item.count,
),
);
} else if (item.value > 1 && this.progress[item.id] === undefined) {
showNotification(notification.progress.pending(item.id, item.header));
@ -134,7 +134,7 @@ class TaskDispatcher {
public removeProgress(ids: string[]) {
setTimeout(
() => ids.forEach(hideNotification),
notification.PROGRESS_TIMEOUT
notification.PROGRESS_TIMEOUT,
);
}
}

View File

@ -32,7 +32,7 @@ export const notification = {
progress: {
pending: (
id: string,
header: string
header: string,
): NotificationProps & { id: string } => {
return {
id,
@ -47,7 +47,7 @@ export const notification = {
header: string,
body: string,
current: number,
total: number
total: number,
): NotificationProps & { id: string } => {
return {
id,

View File

@ -84,7 +84,7 @@ const Table: FunctionComponent<Props> = ({ blacklist }) => {
},
},
],
[]
[],
);
return (
<PageTable

View File

@ -91,7 +91,7 @@ const Table: FunctionComponent<Props> = ({ blacklist }) => {
},
},
],
[]
[],
);
return (
<PageTable

View File

@ -81,7 +81,7 @@ export const Subtitle: FunctionComponent<Props> = ({
hi: subtitle.hi,
forced: subtitle.forced,
},
}
},
);
} else if (action === "delete" && subtitle.path) {
task.create(
@ -97,7 +97,7 @@ export const Subtitle: FunctionComponent<Props> = ({
forced: subtitle.forced,
path: subtitle.path,
},
}
},
);
}
}}

View File

@ -72,7 +72,7 @@ const SeriesEpisodesView: FunctionComponent = () => {
text: series?.seriesType ?? "",
},
],
[series]
[series],
);
const modals = useModals();
@ -92,12 +92,12 @@ const SeriesEpisodesView: FunctionComponent = () => {
showNotification(
notification.warn(
"Cannot Upload Files",
"series or language profile is not ready"
)
"series or language profile is not ready",
),
);
}
},
[modals, profile, series]
[modals, profile, series],
);
useDocumentTitle(`${series?.title ?? "Unknown Series"} - Bazarr (Series)`);
@ -202,7 +202,7 @@ const SeriesEpisodesView: FunctionComponent = () => {
item: series,
mutation,
},
{ title: series.title }
{ title: series.title },
);
}
}}

View File

@ -73,7 +73,7 @@ const Table: FunctionComponent<Props> = ({
},
});
},
[mutateAsync]
[mutateAsync],
);
const columns: Column<Item.Episode>[] = useMemo<Column<Item.Episode>[]>(
@ -194,7 +194,7 @@ const Table: FunctionComponent<Props> = ({
},
{
title: `History - ${row.original.title}`,
}
},
);
}}
icon={faHistory}
@ -204,16 +204,16 @@ const Table: FunctionComponent<Props> = ({
},
},
],
[onlyDesired, profileItems, disabled, download]
[onlyDesired, profileItems, disabled, download],
);
const maxSeason = useMemo(
() =>
episodes?.reduce<number>(
(prev, curr) => Math.max(prev, curr.season),
0
0,
) ?? 0,
[episodes]
[episodes],
);
const instance = useRef<TableInstance<Item.Episode> | null>(null);

View File

@ -144,7 +144,7 @@ const MoviesHistoryView: FunctionComponent = () => {
},
},
],
[]
[],
);
const query = useMovieHistoryPagination();

View File

@ -167,7 +167,7 @@ const SeriesHistoryView: FunctionComponent = () => {
},
},
],
[]
[],
);
const query = useEpisodeHistoryPagination();

View File

@ -50,7 +50,7 @@ const HistoryStats: FunctionComponent = () => {
const languageOptions = useSelectorOptions(
historyLanguages ?? [],
(value) => value.name
(value) => value.name,
);
const [timeFrame, setTimeFrame] = useState<History.TimeFrameOptions>("month");

View File

@ -78,7 +78,7 @@ const MovieDetailView: FunctionComponent = () => {
},
});
},
[downloadAsync]
[downloadAsync],
);
const onDrop = useCallback(
@ -92,12 +92,12 @@ const MovieDetailView: FunctionComponent = () => {
showNotification(
notification.warn(
"Cannot Upload Files",
"movie or language profile is not ready"
)
"movie or language profile is not ready",
),
);
}
},
[modals, movie, profile]
[modals, movie, profile],
);
const hasTask = useIsMovieActionRunning();
@ -187,7 +187,7 @@ const MovieDetailView: FunctionComponent = () => {
item: movie,
mutation,
},
{ title: movie.title }
{ title: movie.title },
);
}
}}

View File

@ -126,7 +126,7 @@ const Table: FunctionComponent<Props> = ({ movie, profile, disabled }) => {
forced,
hi,
},
}
},
);
}}
></Action>
@ -150,11 +150,11 @@ const Table: FunctionComponent<Props> = ({ movie, profile, disabled }) => {
hi,
path,
},
}
},
);
} else if (action === "search") {
throw new Error(
"This shouldn't happen, please report the bug"
"This shouldn't happen, please report the bug",
);
}
}}
@ -170,7 +170,7 @@ const Table: FunctionComponent<Props> = ({ movie, profile, disabled }) => {
},
},
],
[movie, disabled]
[movie, disabled],
);
const data: Subtitle[] = useMemo(() => {

View File

@ -32,7 +32,7 @@ const MovieMassEditor: FunctionComponent = () => {
},
},
],
[]
[],
);
useDocumentTitle("Movies - Bazarr (Mass Editor)");

View File

@ -99,7 +99,7 @@ const MovieView: FunctionComponent = () => {
},
{
title: row.original.title,
}
},
)
}
icon={faWrench}
@ -108,7 +108,7 @@ const MovieView: FunctionComponent = () => {
},
},
],
[]
[],
);
useDocumentTitle("Movies - Bazarr");

View File

@ -32,7 +32,7 @@ const SeriesMassEditor: FunctionComponent = () => {
},
},
],
[]
[],
);
useDocumentTitle("Series - Bazarr (Mass Editor)");

View File

@ -106,7 +106,7 @@ const SeriesView: FunctionComponent = () => {
},
{
title: original.title,
}
},
)
}
icon={faWrench}
@ -115,7 +115,7 @@ const SeriesView: FunctionComponent = () => {
},
},
],
[mutation]
[mutation],
);
useDocumentTitle("Series - Bazarr");

View File

@ -35,7 +35,7 @@ export const LanguageSelector: FunctionComponent<
searchable
onChange={(val) => {
setValue(val, settingKey, (value: Language.Info[]) =>
value.map((v) => v.code2)
value.map((v) => v.code2),
);
}}
></MultiSelector>
@ -53,7 +53,7 @@ export const ProfileSelector: FunctionComponent<
profiles.map((v) => {
return { label: v.name, value: v.profileId };
}),
[profiles]
[profiles],
);
return (

View File

@ -15,7 +15,7 @@ describe("Equals Parser", () => {
function testParsedResult(
text: string,
expected: LanguageEqualImmediateData
expected: LanguageEqualImmediateData,
) {
const result = decodeEqualData(text);
@ -26,7 +26,7 @@ describe("Equals Parser", () => {
expect(
result,
`${text} does not match with the expected equal data`
`${text} does not match with the expected equal data`,
).toStrictEqual(expected);
}
@ -187,7 +187,7 @@ describe("Equals Parser", () => {
expect(
encoded,
`Encoded result '${encoded}' is not matched to '${expected}'`
`Encoded result '${encoded}' is not matched to '${expected}'`,
).toEqual(expected);
}

View File

@ -28,7 +28,7 @@ export type LanguageEqualImmediateData =
export type LanguageEqualData = LanguageEqualGenericData<Language.Server>;
function decodeEqualTarget(
text: string
text: string,
): GenericEqualTarget<Language.CodeType> | undefined {
const [code, decoration] = text.split("@");
@ -47,7 +47,7 @@ function decodeEqualTarget(
}
export function decodeEqualData(
text: string
text: string,
): LanguageEqualImmediateData | undefined {
const [first, second] = text.split(":");
@ -97,10 +97,10 @@ export function useLatestLanguageEquals(): LanguageEqualData[] {
}
const source = data?.find(
(value) => value.code3 === parsed.source.content
(value) => value.code3 === parsed.source.content,
);
const target = data?.find(
(value) => value.code3 === parsed.target.content
(value) => value.code3 === parsed.target.content,
);
if (source === undefined || target === undefined) {
@ -113,7 +113,7 @@ export function useLatestLanguageEquals(): LanguageEqualData[] {
};
})
.filter((v): v is LanguageEqualData => v !== undefined) ?? [],
[data, latest]
[data, latest],
);
}
@ -134,7 +134,7 @@ const EqualsTable: FunctionComponent<EqualsTableProps> = () => {
LOG("info", "updating language equals data", values);
setValue(encodedValues, languageEqualsKey);
},
[setValue]
[setValue],
);
const add = useCallback(() => {
@ -178,7 +178,7 @@ const EqualsTable: FunctionComponent<EqualsTableProps> = () => {
newValue[index] = { ...value };
setEquals(newValue);
},
[equals, setEquals]
[equals, setEquals],
);
const remove = useCallback(
@ -193,7 +193,7 @@ const EqualsTable: FunctionComponent<EqualsTableProps> = () => {
setEquals(newValue);
},
[equals, setEquals]
[equals, setEquals],
);
const columns = useMemo<Column<LanguageEqualData>[]>(
@ -349,7 +349,7 @@ const EqualsTable: FunctionComponent<EqualsTableProps> = () => {
},
},
],
[remove, update]
[remove, update],
);
return (

View File

@ -23,7 +23,7 @@ const Table: FunctionComponent = () => {
() =>
1 +
profiles.reduce<number>((val, prof) => Math.max(prof.profileId, val), 0),
[profiles]
[profiles],
);
const { setValue } = useFormActions();
@ -34,7 +34,7 @@ const Table: FunctionComponent = () => {
(list: Language.Profile[]) => {
setValue(list, languageProfileKey, (value) => JSON.stringify(value));
},
[setValue]
[setValue],
);
const updateProfile = useCallback(
@ -49,7 +49,7 @@ const Table: FunctionComponent = () => {
}
submitProfiles(list);
},
[profiles, submitProfiles]
[profiles, submitProfiles],
);
const action = useArrayAction<Language.Profile>((fn) => {
@ -152,7 +152,7 @@ const Table: FunctionComponent = () => {
},
],
// TODO: Optimize this
[action, languages, modals, updateProfile]
[action, languages, modals, updateProfile],
);
const canAdd = languages.length !== 0;

View File

@ -37,7 +37,7 @@ const NotificationForm: FunctionComponent<Props> = ({
}) => {
const availableSelections = useMemo(
() => selections.filter((v) => !v.enabled || v.name === payload?.name),
[payload?.name, selections]
[payload?.name, selections],
);
const options = useSelectorOptions(availableSelections, (v) => v.name);
@ -51,11 +51,11 @@ const NotificationForm: FunctionComponent<Props> = ({
validate: {
selection: FormUtils.validation(
isObject,
"Please select a notification provider"
"Please select a notification provider",
),
url: FormUtils.validation(
(value) => value.trim().length !== 0,
"URL must not be empty"
"URL must not be empty",
),
},
});
@ -123,20 +123,20 @@ export const NotificationView: FunctionComponent = () => {
{
onLoaded: (settings) => settings.notifications.providers,
onSubmit: (value) => value.map((v) => JSON.stringify(v)),
}
},
);
const update = useUpdateArray<Settings.NotificationInfo>(
notificationsKey,
notifications ?? [],
"name"
"name",
);
const updateWrapper = useCallback(
(info: Settings.NotificationInfo) => {
update(info, notificationHook);
},
[update]
[update],
);
const modals = useModals();

View File

@ -63,7 +63,7 @@ export const ProviderView: FunctionComponent = () => {
});
}
},
[modals, providers, settings, staged, update]
[modals, providers, settings, staged, update],
);
const cards = useMemo(() => {
@ -171,7 +171,7 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({
modals.closeAll();
}
},
[info, enabledProviders, modals]
[info, enabledProviders, modals],
);
const canSave = info !== null;
@ -192,14 +192,14 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({
ProviderList.filter(
(v) =>
enabledProviders?.find((p) => p === v.key && p !== info?.key) ===
undefined
undefined,
),
[info?.key, enabledProviders]
[info?.key, enabledProviders],
);
const options = useSelectorOptions(
availableOptions,
(v) => v.name ?? capitalize(v.key)
(v) => v.name ?? capitalize(v.key),
);
const inputs = useMemo(() => {
@ -223,7 +223,7 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({
key={BuildKey(itemKey, key)}
label={label}
settingKey={`settings-${itemKey}-${key}`}
></Text>
></Text>,
);
return;
case "password":
@ -232,7 +232,7 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({
key={BuildKey(itemKey, key)}
label={label}
settingKey={`settings-${itemKey}-${key}`}
></Password>
></Password>,
);
return;
case "switch":
@ -242,7 +242,7 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({
inline
label={label}
settingKey={`settings-${itemKey}-${key}`}
></Check>
></Check>,
);
return;
case "select":
@ -252,7 +252,7 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({
label={label}
settingKey={`settings-${itemKey}-${key}`}
options={options}
></GlobalSelector>
></GlobalSelector>,
);
return;
case "chips":
@ -261,7 +261,7 @@ const ProviderTool: FunctionComponent<ProviderToolProps> = ({
key={key}
label={label}
settingKey={`settings-${itemKey}-${key}`}
></Chips>
></Chips>,
);
return;
default:

View File

@ -160,7 +160,7 @@ export const providerOptions: SelectorOption<string>[] = ProviderList.map(
(v) => ({
label: v.key,
value: v.key,
})
}),
);
export const syncMaxOffsetSecondsOptions: SelectorOption<number>[] = [

View File

@ -8,7 +8,7 @@ describe("Settings layout", () => {
render(
<Layout name="Test Settings">
<Text>Value</Text>
</Layout>
</Layout>,
);
});
@ -16,7 +16,7 @@ describe("Settings layout", () => {
render(
<Layout name="Test Settings">
<Text>Value</Text>
</Layout>
</Layout>,
);
expect(screen.getByRole("button", { name: "Save" })).toBeDisabled();

View File

@ -47,7 +47,7 @@ const Layout: FunctionComponent<Props> = (props) => {
mutate(settingsToSubmit);
}
},
[mutate]
[mutate],
);
const totalStagedCount = useMemo(() => {
@ -56,7 +56,7 @@ const Layout: FunctionComponent<Props> = (props) => {
usePrompt(
totalStagedCount > 0,
`You have ${totalStagedCount} unsaved changes, are you sure you want to leave?`
`You have ${totalStagedCount} unsaved changes, are you sure you want to leave?`,
);
useDocumentTitle(`${name} - Bazarr (Settings)`);

View File

@ -54,7 +54,7 @@ const LayoutModal: FunctionComponent<Props> = (props) => {
}, 500);
}
},
[mutate, callbackModal]
[mutate, callbackModal],
);
const totalStagedCount = useMemo(() => {

View File

@ -17,7 +17,7 @@ describe("Settings section", () => {
rawRender(
<Section header="Section Header">
<Text>{text}</Text>
</Section>
</Section>,
);
expect(screen.getByText(header)).toBeDefined();
@ -29,7 +29,7 @@ describe("Settings section", () => {
rawRender(
<Section header="Section Header" hidden>
<Text>{text}</Text>
</Section>
</Section>,
);
expect(screen.getByText(header)).not.toBeVisible();

View File

@ -17,7 +17,7 @@ const FormSupport: FunctionComponent<PropsWithChildren> = ({ children }) => {
const formRender = (
ui: ReactElement,
options?: Omit<RenderOptions, "wrapper">
options?: Omit<RenderOptions, "wrapper">,
) => rawRender(ui, { wrapper: FormSupport, ...options });
describe("Settings form", () => {

View File

@ -115,7 +115,7 @@ export type MultiSelectorProps<T extends string | number> = BaseInput<T[]> &
GlobalMultiSelectorProps<T>;
export function MultiSelector<T extends string | number>(
props: MultiSelectorProps<T>
props: MultiSelectorProps<T>,
) {
const { value, update, rest } = useBaseInput(props);
@ -187,7 +187,7 @@ export const Action: FunctionComponent<
interface FileProps extends BaseInput<string> {}
export const File: FunctionComponent<Override<FileProps, FileBrowserProps>> = (
props
props,
) => {
const { value, update, rest } = useBaseInput(props);

View File

@ -56,10 +56,10 @@ export const PathMappingTable: FunctionComponent<TableProps> = ({ type }) => {
(newItems: PathMappingItem[]) => {
setValue(
newItems.map((v) => [v.from, v.to]),
key
key,
);
},
[key, setValue]
[key, setValue],
);
const addRow = useCallback(() => {
@ -71,7 +71,7 @@ export const PathMappingTable: FunctionComponent<TableProps> = ({ type }) => {
const data = useMemo<PathMappingItem[]>(
() => items?.map((v) => ({ from: v[0], to: v[1] })) ?? [],
[items]
[items],
);
const action = useArrayAction<PathMappingItem>((fn) => {
@ -130,7 +130,7 @@ export const PathMappingTable: FunctionComponent<TableProps> = ({ type }) => {
},
},
],
[action, type]
[action, type],
);
if (enabled) {

View File

@ -3,7 +3,7 @@ import type { UseFormReturnType } from "@mantine/form";
import { createContext, useCallback, useContext, useRef } from "react";
export const FormContext = createContext<UseFormReturnType<FormValues> | null>(
null
null,
);
export function useFormValues() {
@ -44,7 +44,7 @@ export function useFormActions() {
if (hook) {
LOG(
"info",
`Adding submit hook ${key}, will be executed before submitting`
`Adding submit hook ${key}, will be executed before submitting`,
);
hooks[key] = hook;
}
@ -72,7 +72,7 @@ export type FormValues = {
export function runHooks(
hooks: FormValues["hooks"],
settings: FormValues["settings"]
settings: FormValues["settings"],
) {
for (const key in settings) {
if (key in hooks) {

View File

@ -36,7 +36,7 @@ export function useBaseInput<T, V>(props: T & BaseInput<V>) {
setValue(moddedValue, settingKey, settingOptions?.onSubmit);
},
[settingOptions, setValue, settingKey]
[settingOptions, setValue, settingKey],
);
return { value, update, rest };
@ -44,7 +44,7 @@ export function useBaseInput<T, V>(props: T & BaseInput<V>) {
export function useSettingValue<T>(
key: string,
options?: SettingValueOptions<T>
options?: SettingValueOptions<T>,
): Readonly<Nullable<T>> {
const settings = useSettings();
@ -85,7 +85,7 @@ export function useSettingValue<T>(
export function useUpdateArray<T>(
key: string,
current: Readonly<T[]>,
compare: keyof T
compare: keyof T,
) {
const { setValue } = useFormActions();
const stagedValue = useStagedValues();
@ -106,6 +106,6 @@ export function useUpdateArray<T>(
const newArray = uniqBy([v, ...staged], compareRef.current);
setValue(newArray, key, hook);
},
[staged, setValue, key]
[staged, setValue, key],
);
}

View File

@ -62,7 +62,7 @@ const Table: FunctionComponent<Props> = ({ announcements }) => {
},
},
],
[]
[],
);
return (

View File

@ -100,7 +100,7 @@ const Table: FunctionComponent<Props> = ({ backups }) => {
},
},
],
[]
[],
);
return <PageTable columns={columns} data={backups}></PageTable>;

View File

@ -14,7 +14,7 @@ const SystemLogModal: FunctionComponent<Props> = ({ stack }) => {
{v}
</Text>
)),
[stack]
[stack],
);
return <Code block>{result}</Code>;

View File

@ -70,7 +70,7 @@ const Table: FunctionComponent<Props> = ({ logs }) => {
},
},
],
[]
[],
);
return (

View File

@ -22,7 +22,7 @@ const Table: FunctionComponent<Props> = (props) => {
accessor: "retry",
},
],
[]
[],
);
return <SimpleTable columns={columns} data={props.providers}></SimpleTable>;

View File

@ -42,7 +42,7 @@ const ReleaseCard: FunctionComponent<ReleaseInfo> = ({
}) => {
const infos = useMemo(
() => body.map((v) => v.replace(/(\s\[.*?\])\(.*?\)/, "")),
[body]
[body],
);
return (
<Card shadow="md" p="lg">

View File

@ -86,7 +86,7 @@ const SystemStatusView: FunctionComponent = () => {
if (startTime) {
const duration = moment.duration(
moment().utc().unix() - startTime,
"seconds"
"seconds",
),
days = duration.days(),
hours = duration.hours().toString().padStart(2, "0"),

View File

@ -28,7 +28,7 @@ const Table: FunctionComponent<Props> = ({ health }) => {
},
},
],
[]
[],
);
return (

View File

@ -52,7 +52,7 @@ const Table: FunctionComponent<Props> = ({ tasks }) => {
},
},
],
[]
[],
);
return (

View File

@ -58,7 +58,7 @@ const WantedMoviesView: FunctionComponent = () => {
hi: item.hi,
forced: item.forced,
},
}
},
);
}}
>
@ -70,7 +70,7 @@ const WantedMoviesView: FunctionComponent = () => {
},
},
],
[]
[],
);
const { mutateAsync } = useMovieAction();

View File

@ -74,7 +74,7 @@ const WantedSeriesView: FunctionComponent = () => {
hi: item.hi,
forced: item.forced,
},
}
},
);
}}
>
@ -86,7 +86,7 @@ const WantedSeriesView: FunctionComponent = () => {
},
},
],
[]
[],
);
const { mutateAsync } = useSeriesAction();

Some files were not shown because too many files have changed in this diff Show More