diff --git a/frontend/src/pages/Settings/Providers/components.tsx b/frontend/src/pages/Settings/Providers/components.tsx index 601aef1f0..8fc6575ea 100644 --- a/frontend/src/pages/Settings/Providers/components.tsx +++ b/frontend/src/pages/Settings/Providers/components.tsx @@ -1,6 +1,7 @@ import { Selector } from "@/components"; import { useModals, withModal } from "@/modules/modals"; -import { BuildKey, isReactText, useSelectorOptions } from "@/utilities"; +import { BuildKey, useSelectorOptions } from "@/utilities"; +import { ASSERT } from "@/utilities/console"; import { Button, Divider, @@ -10,7 +11,7 @@ import { Text as MantineText, } from "@mantine/core"; import { useForm } from "@mantine/hooks"; -import { capitalize, isBoolean } from "lodash"; +import { capitalize } from "lodash"; import { forwardRef, FunctionComponent, @@ -22,6 +23,7 @@ import { import { Card, Check, + Chips, Message, Password, Text, @@ -192,34 +194,30 @@ const ProviderTool: FunctionComponent = ({ (v) => v.name ?? capitalize(v.key) ); - const modification = useMemo(() => { - if (info === null) { - return null; - } - - const defaultKey = info.defaultKey; - const override = info.keyNameOverride ?? {}; - if (defaultKey === undefined) { + const inputs = useMemo(() => { + if (info === null || info.inputs === undefined) { return null; } const itemKey = info.key; const elements: JSX.Element[] = []; - const checks: JSX.Element[] = []; - for (const key in defaultKey) { - const value = defaultKey[key]; - let label = key; + info.inputs?.forEach((value) => { + const key = value.key; + const label = value.name ?? capitalize(value.key); - if (label in override) { - label = override[label]; - } else { - label = capitalize(key); - } - - if (isReactText(value)) { - if (key === "password") { + switch (value.type) { + case "text": + elements.push( + + ); + return; + case "password": elements.push( = ({ settingKey={`settings-${itemKey}-${key}`} > ); - } else { + return; + case "switch": elements.push( - + > ); - } - } else if (isBoolean(value)) { - checks.push( - - ); + return; + case "chips": + elements.push( + + ); + return; + default: + ASSERT(false, "Implement your new input here"); } - } + }); - return ( - - {elements} - - - ); + return {elements}; }, [info]); return ( @@ -271,7 +268,7 @@ const ProviderTool: FunctionComponent = ({ onChange={onSelect} > {info?.description} - {modification} + {inputs} diff --git a/frontend/src/pages/Settings/Providers/list.ts b/frontend/src/pages/Settings/Providers/list.ts index 90ba0c1ea..fe5d9b9cf 100644 --- a/frontend/src/pages/Settings/Providers/list.ts +++ b/frontend/src/pages/Settings/Providers/list.ts @@ -1,56 +1,79 @@ import { ReactText } from "react"; -type AvailableType = ReactText | boolean; +type Input = { + type: N; + key: string; + defaultValue?: T; + name?: string; + description?: string; +}; + +type AvailableInput = + | Input + | Input + | Input + | Input; + export interface ProviderInfo { key: string; name?: string; description?: string; message?: string; - defaultKey?: { - [key: string]: AvailableType; - }; - keyNameOverride?: { - [key: string]: string; - }; + inputs?: AvailableInput[]; } export const ProviderList: Readonly = [ { key: "addic7ed", description: "Requires Anti-Captcha Provider or cookies", - defaultKey: { - username: "", - password: "", - cookies: "", - user_agent: "", - vip: false, - }, - keyNameOverride: { - vip: "VIP", - cookies: - "Cookies, e.g., PHPSESSID=abc; wikisubtitlesuser=xyz; wikisubtitlespass=efg", - user_agent: - "User-Agent, e.g., Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + { + type: "text", + key: "cookies", + name: "Cookies, e.g., PHPSESSID=abc; wikisubtitlesuser=xyz; wikisubtitlespass=efg", + }, + { + type: "text", + key: "user_agent", + name: "User-Agent, e.g., Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0", + }, + { + type: "switch", + key: "vip", + name: "VIP", + }, + ], }, { key: "argenteam", description: "LATAM Spanish Subtitles Provider" }, { key: "assrt", description: "Chinese Subtitles Provider", - defaultKey: { - token: "", - }, + inputs: [ + { + type: "text", + key: "token", + }, + ], }, { key: "betaseries", name: "BetaSeries", description: "French / English Provider for TV Shows Only", - defaultKey: { - token: "", - }, - keyNameOverride: { - token: "API KEY", - }, + inputs: [ + { + type: "text", + key: "token", + name: "API KEY", + }, + ], }, { key: "bsplayer", @@ -62,24 +85,38 @@ export const ProviderList: Readonly = [ key: "embeddedsubtitles", name: "Embedded Subtitles", description: "Embedded Subtitles from your Media Files", - defaultKey: { - include_srt: true, - include_ass: true, - hi_fallback: false, - mergerfs_mode: false, - timeout: 600, - }, + inputs: [ + { + type: "switch", + key: "include_srt", + name: "Include SRT", + defaultValue: true, + }, + { + type: "switch", + key: "include_ass", + name: "Include ASS (will be converted to SRT)", + defaultValue: true, + }, + { + type: "switch", + key: "hi_fallback", + name: "Use HI subtitles as a fallback (don't enable it if you have a HI language profile)", + }, + { + type: "switch", + key: "mergerfs_mode", + name: "[EXPERIMENTAL] Ignore cloud video files from rclone/mergerfs", + }, + { + type: "text", + key: "timeout", + defaultValue: 600, + name: "Extraction timeout in seconds", + }, + ], message: "Warning for cloud users: this provider needs to read the entire file in order to extract subtitles.", - keyNameOverride: { - include_srt: "Include SRT", - include_ass: "Include ASS (will be converted to SRT)", - hi_fallback: - "Use HI subtitles as a fallback (don't enable it if you have a HI language profile)", - mergerfs_mode: - "[EXPERIMENTAL] Ignore cloud video files from rclone/mergerfs", - timeout: "Extraction timeout in seconds", - }, }, { key: "gestdown", @@ -101,39 +138,53 @@ export const ProviderList: Readonly = [ key: "legendasdivx", name: "LegendasDivx", description: "Brazilian / Portuguese Subtitles Provider", - defaultKey: { - username: "", - password: "", - skip_wrong_fps: false, - }, - keyNameOverride: { - skip_wrong_fps: "Skip Wrong FPS", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + { type: "switch", key: "skip_wrong_fps", name: "Skip Wrong FPS" }, + ], }, { key: "ktuvit", name: "Ktuvit", description: "Hebrew Subtitles Provider", - defaultKey: { - email: "", - hashed_password: "", - }, - keyNameOverride: { - hashed_password: "Hashed Password", - }, + inputs: [ + { + type: "text", + key: "email", + }, + { + type: "text", + key: "hashed_password", + name: "Hashed Password", + }, + ], }, { key: "legendastv", name: "LegendasTV", description: "Brazilian / Portuguese Subtitles Provider", - defaultKey: { - username: "", - password: "", - featured_only: false, - }, - keyNameOverride: { - featured_only: "Only Download Featured", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + { + type: "switch", + key: "featured_only", + name: "Only Download Featured", + }, + ], }, { key: "napiprojekt", description: "Polish Subtitles Provider" }, { @@ -141,50 +192,77 @@ export const ProviderList: Readonly = [ description: "Polish Subtitles Provider", message: "The provided credentials must have API access. Leave empty to use the defaults.", - defaultKey: { - username: "", - password: "", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + ], }, { key: "nekur", description: "Latvian Subtitles Provider" }, { key: "opensubtitles", name: "OpenSubtitles.org", - defaultKey: { - username: "", - password: "", - vip: false, - ssl: false, - skip_wrong_fps: false, - }, - keyNameOverride: { - vip: "VIP", - ssl: "Use SSL", - skip_wrong_fps: "Skip Wrong FPS", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + { + type: "switch", + key: "vip", + name: "VIP", + }, + { + type: "switch", + key: "ssl", + name: "Use SSL", + }, + { + type: "switch", + key: "skip_wrong_fps", + name: "Skip Wrong FPS", + }, + ], }, { key: "opensubtitlescom", name: "OpenSubtitles.com", - defaultKey: { - username: "", - password: "", - use_hash: false, - }, - keyNameOverride: { - use_hash: "Use Hash", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + { + type: "switch", + key: "use_hash", + name: "Use Hash", + }, + ], }, { key: "podnapisi", name: "Podnapisi", - defaultKey: { - verify_ssl: true, - }, - keyNameOverride: { - verify_ssl: - "Verify SSL certificate (disabling introduce a MitM attack risk)", - }, + inputs: [ + { + type: "switch", + key: "verify_ssl", + name: "Verify SSL certificate (disabling introduce a MitM attack risk)", + defaultValue: true, + }, + ], }, { key: "regielive", @@ -220,10 +298,16 @@ export const ProviderList: Readonly = [ }, { key: "subscene", - defaultKey: { - username: "", - password: "", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + ], }, { key: "subscenter" }, { @@ -251,10 +335,16 @@ export const ProviderList: Readonly = [ { key: "supersubtitles" }, { key: "titlovi", - defaultKey: { - username: "", - password: "", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + ], }, { key: "titrari", @@ -272,14 +362,21 @@ export const ProviderList: Readonly = [ key: "titulky", name: "Titulky.com", description: "CZ/SK Subtitles Provider. Available only with VIP", - defaultKey: { - username: "", - password: "", - approved_only: false, - }, - keyNameOverride: { - approved_only: "Skip unapproved subtitles", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + { + type: "switch", + key: "approved_only", + name: "Skip unapproved subtitles", + }, + ], }, { key: "tvsubtitles", name: "TVSubtitles" }, { key: "wizdom", description: "Wizdom.xyz Subtitles Provider." }, @@ -287,10 +384,16 @@ export const ProviderList: Readonly = [ key: "xsubs", name: "XSubs", description: "Greek Subtitles Provider", - defaultKey: { - username: "", - password: "", - }, + inputs: [ + { + type: "text", + key: "username", + }, + { + type: "password", + key: "password", + }, + ], }, { key: "yavkanet", diff --git a/frontend/src/utilities/console.ts b/frontend/src/utilities/console.ts index d6c0820e2..658cfa981 100644 --- a/frontend/src/utilities/console.ts +++ b/frontend/src/utilities/console.ts @@ -22,3 +22,5 @@ export function ENSURE(condition: boolean, msg: string, ...payload: any[]) { LOG("error", msg, payload); } } + +export const ASSERT = console.assert;