import React, { useEffect, useState } from "react"; import { Button, Form, InputGroup } from "react-bootstrap"; import * as GQL from "src/core/generated-graphql"; import { StashService } from "src/core/StashService"; import { useToast } from "src/hooks"; import { Icon, LoadingIndicator } from "src/components/Shared"; import { FolderSelect } from "src/components/Shared/FolderSelect/FolderSelect"; export const SettingsConfigurationPanel: React.FC = () => { const Toast = useToast(); // Editing config state const [stashes, setStashes] = useState([]); const [databasePath, setDatabasePath] = useState( undefined ); const [generatedPath, setGeneratedPath] = useState( undefined ); const [maxTranscodeSize, setMaxTranscodeSize] = useState< GQL.StreamingResolutionEnum | undefined >(undefined); const [maxStreamingTranscodeSize, setMaxStreamingTranscodeSize] = useState< GQL.StreamingResolutionEnum | undefined >(undefined); const [username, setUsername] = useState(undefined); const [password, setPassword] = useState(undefined); const [logFile, setLogFile] = useState(); const [logOut, setLogOut] = useState(true); const [logLevel, setLogLevel] = useState("Info"); const [logAccess, setLogAccess] = useState(true); const [excludes, setExcludes] = useState([]); const [scraperUserAgent, setScraperUserAgent] = useState( undefined ); const { data, error, loading } = StashService.useConfiguration(); const [updateGeneralConfig] = StashService.useConfigureGeneral({ stashes, databasePath, generatedPath, maxTranscodeSize, maxStreamingTranscodeSize, username, password, logFile, logOut, logLevel, logAccess, excludes, scraperUserAgent, }); useEffect(() => { if (!data?.configuration || error) return; const conf = data.configuration; if (conf.general) { setStashes(conf.general.stashes ?? []); setDatabasePath(conf.general.databasePath); setGeneratedPath(conf.general.generatedPath); setMaxTranscodeSize(conf.general.maxTranscodeSize ?? undefined); setMaxStreamingTranscodeSize( conf.general.maxStreamingTranscodeSize ?? undefined ); setUsername(conf.general.username); setPassword(conf.general.password); setLogFile(conf.general.logFile ?? undefined); setLogOut(conf.general.logOut); setLogLevel(conf.general.logLevel); setLogAccess(conf.general.logAccess); setExcludes(conf.general.excludes); setScraperUserAgent(conf.general.scraperUserAgent ?? undefined); } }, [data, error]); function onStashesChanged(directories: string[]) { setStashes(directories); } function excludeRegexChanged(idx: number, value: string) { const newExcludes = excludes.map((regex, i) => { const ret = idx !== i ? regex : value; return ret; }); setExcludes(newExcludes); } function excludeRemoveRegex(idx: number) { const newExcludes = excludes.filter((_regex, i) => i !== idx); setExcludes(newExcludes); } function excludeAddRegex() { const demo = "sample\\.mp4$"; const newExcludes = excludes.concat(demo); setExcludes(newExcludes); } async function onSave() { try { const result = await updateGeneralConfig(); // eslint-disable-next-line no-console console.log(result); Toast.success({ content: "Updated config" }); } catch (e) { Toast.error(e); } } const transcodeQualities = [ GQL.StreamingResolutionEnum.Low, GQL.StreamingResolutionEnum.Standard, GQL.StreamingResolutionEnum.StandardHd, GQL.StreamingResolutionEnum.FullHd, GQL.StreamingResolutionEnum.FourK, GQL.StreamingResolutionEnum.Original, ].map(resolutionToString); function resolutionToString(r: GQL.StreamingResolutionEnum | undefined) { switch (r) { case GQL.StreamingResolutionEnum.Low: return "240p"; case GQL.StreamingResolutionEnum.Standard: return "480p"; case GQL.StreamingResolutionEnum.StandardHd: return "720p"; case GQL.StreamingResolutionEnum.FullHd: return "1080p"; case GQL.StreamingResolutionEnum.FourK: return "4k"; case GQL.StreamingResolutionEnum.Original: return "Original"; } return "Original"; } function translateQuality(quality: string) { switch (quality) { case "240p": return GQL.StreamingResolutionEnum.Low; case "480p": return GQL.StreamingResolutionEnum.Standard; case "720p": return GQL.StreamingResolutionEnum.StandardHd; case "1080p": return GQL.StreamingResolutionEnum.FullHd; case "4k": return GQL.StreamingResolutionEnum.FourK; case "Original": return GQL.StreamingResolutionEnum.Original; } return GQL.StreamingResolutionEnum.Original; } if (error) return

{error.message}

; if (!data?.configuration || loading) return ; return ( <>

Library

Stashes
Directory locations to your content
Database Path
) => setDatabasePath(e.currentTarget.value) } /> File location for the SQLite database (requires restart)
Generated Path
) => setGeneratedPath(e.currentTarget.value) } /> Directory location for the generated files (scene markers, scene previews, sprites, etc)
Excluded Patterns
{excludes && excludes.map((regexp, i) => ( ) => excludeRegexChanged(i, e.currentTarget.value) } /> ))} Regexps of files/paths to exclude from Scan and add to Clean

Video

Maximum transcode size
) => setMaxTranscodeSize(translateQuality(event.currentTarget.value)) } value={resolutionToString(maxTranscodeSize)} > {transcodeQualities.map((q) => ( ))} Maximum size for generated transcodes
Maximum streaming transcode size
) => setMaxStreamingTranscodeSize( translateQuality(event.currentTarget.value) ) } value={resolutionToString(maxStreamingTranscodeSize)} > {transcodeQualities.map((q) => ( ))} Maximum size for transcoded streams

Scraping
) => setScraperUserAgent(e.currentTarget.value) } /> User-Agent string used during scrape http requests

Authentication

Username
) => setUsername(e.currentTarget.value) } /> Username to access Stash. Leave blank to disable user authentication
Password
) => setPassword(e.currentTarget.value) } /> Password to access Stash. Leave blank to disable user authentication

Logging

Log file
) => setLogFile(e.currentTarget.value) } /> Path to the file to output logging to. Blank to disable file logging. Requires restart.
setLogOut(!logOut)} /> Logs to the terminal in addition to a file. Always true if file logging is disabled. Requires restart.
Log Level
) => setLogLevel(event.currentTarget.value) } value={logLevel} > {["Debug", "Info", "Warning", "Error"].map((o) => ( ))}
setLogAccess(!logAccess)} /> Logs http access to the terminal. Requires restart.
); };