added rpc polling time selector
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { selector } from 'recoil'
|
import { atom, selector } from 'recoil'
|
||||||
import { RPCClient } from '../lib/rpcClient'
|
import { RPCClient } from '../lib/rpcClient'
|
||||||
import { rpcHTTPEndpoint, rpcWebSocketEndpoint } from './settings'
|
import { rpcHTTPEndpoint, rpcWebSocketEndpoint } from './settings'
|
||||||
|
|
||||||
@@ -12,3 +12,12 @@ export const rpcClientState = selector({
|
|||||||
),
|
),
|
||||||
dangerouslyAllowMutability: true,
|
dangerouslyAllowMutability: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const rpcPollingTimeState = atom({
|
||||||
|
key: 'rpcPollingTimeState',
|
||||||
|
default: Number(localStorage.getItem('rpc-polling-time')) || 1000,
|
||||||
|
effects: [
|
||||||
|
({ onSet }) =>
|
||||||
|
onSet(a => localStorage.setItem('rpc-polling-time', a.toString()))
|
||||||
|
]
|
||||||
|
})
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
|
import DownloadIcon from '@mui/icons-material/Download'
|
||||||
import SettingsEthernet from '@mui/icons-material/SettingsEthernet'
|
import SettingsEthernet from '@mui/icons-material/SettingsEthernet'
|
||||||
import { AppBar, Chip, Divider, Toolbar } from '@mui/material'
|
import { AppBar, Chip, Divider, Toolbar } from '@mui/material'
|
||||||
import { Suspense } from 'react'
|
import { Suspense } from 'react'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { settingsState } from '../atoms/settings'
|
import { settingsState } from '../atoms/settings'
|
||||||
import { connectedState } from '../atoms/status'
|
import { connectedState } from '../atoms/status'
|
||||||
|
import { totalDownloadSpeedState } from '../atoms/ui'
|
||||||
import { useI18n } from '../hooks/useI18n'
|
import { useI18n } from '../hooks/useI18n'
|
||||||
|
import { formatSpeedMiB } from '../utils'
|
||||||
import FreeSpaceIndicator from './FreeSpaceIndicator'
|
import FreeSpaceIndicator from './FreeSpaceIndicator'
|
||||||
import VersionIndicator from './VersionIndicator'
|
import VersionIndicator from './VersionIndicator'
|
||||||
import DownloadIcon from '@mui/icons-material/Download'
|
|
||||||
import { totalDownloadSpeedState } from '../atoms/ui'
|
|
||||||
import { formatSpeedMiB } from '../utils'
|
|
||||||
|
|
||||||
const Footer: React.FC = () => {
|
const Footer: React.FC = () => {
|
||||||
const settings = useRecoilValue(settingsState)
|
const settings = useRecoilValue(settingsState)
|
||||||
@@ -35,7 +35,7 @@ const Footer: React.FC = () => {
|
|||||||
display: 'flex', gap: 1, justifyContent: 'space-between'
|
display: 'flex', gap: 1, justifyContent: 'space-between'
|
||||||
}}>
|
}}>
|
||||||
<div style={{ display: 'flex', gap: 4, alignItems: 'center' }}>
|
<div style={{ display: 'flex', gap: 4, alignItems: 'center' }}>
|
||||||
<Chip label="RPC v3.0.8" variant="outlined" size="small" />
|
<Chip label="RPC v3.0.9" variant="outlined" size="small" />
|
||||||
<VersionIndicator />
|
<VersionIndicator />
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', gap: 4, 'alignItems': 'center' }}>
|
<div style={{ display: 'flex', gap: 4, 'alignItems': 'center' }}>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom'
|
|||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { take, timer } from 'rxjs'
|
import { take, timer } from 'rxjs'
|
||||||
import { downloadsState } from '../atoms/downloads'
|
import { downloadsState } from '../atoms/downloads'
|
||||||
|
import { rpcPollingTimeState } from '../atoms/rpc'
|
||||||
import { serverAddressAndPortState } from '../atoms/settings'
|
import { serverAddressAndPortState } from '../atoms/settings'
|
||||||
import { connectedState } from '../atoms/status'
|
import { connectedState } from '../atoms/status'
|
||||||
import { useSubscription } from '../hooks/observable'
|
import { useSubscription } from '../hooks/observable'
|
||||||
@@ -19,6 +20,7 @@ const SocketSubscriber: React.FC<Props> = () => {
|
|||||||
const [, setDownloads] = useRecoilState(downloadsState)
|
const [, setDownloads] = useRecoilState(downloadsState)
|
||||||
|
|
||||||
const serverAddressAndPort = useRecoilValue(serverAddressAndPortState)
|
const serverAddressAndPort = useRecoilValue(serverAddressAndPortState)
|
||||||
|
const rpcPollingTime = useRecoilValue(rpcPollingTimeState)
|
||||||
|
|
||||||
const { i18n } = useI18n()
|
const { i18n } = useI18n()
|
||||||
const { client } = useRPC()
|
const { client } = useRPC()
|
||||||
@@ -70,11 +72,10 @@ const SocketSubscriber: React.FC<Props> = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
const sub = timer(0, 1000).subscribe(() => client.running())
|
const sub = timer(0, rpcPollingTime).subscribe(() => client.running())
|
||||||
|
|
||||||
return () => sub.unsubscribe()
|
return () => sub.unsubscribe()
|
||||||
}
|
}
|
||||||
}, [connected, client])
|
}, [connected, client, rpcPollingTime])
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
Container,
|
Container,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
FormGroup,
|
|
||||||
Grid,
|
Grid,
|
||||||
InputAdornment,
|
InputAdornment,
|
||||||
InputLabel,
|
InputLabel,
|
||||||
@@ -12,6 +11,7 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Select,
|
Select,
|
||||||
SelectChangeEvent,
|
SelectChangeEvent,
|
||||||
|
Slider,
|
||||||
Stack,
|
Stack,
|
||||||
Switch,
|
Switch,
|
||||||
TextField,
|
TextField,
|
||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
map,
|
map,
|
||||||
takeWhile
|
takeWhile
|
||||||
} from 'rxjs'
|
} from 'rxjs'
|
||||||
|
import { rpcPollingTimeState } from '../atoms/rpc'
|
||||||
import {
|
import {
|
||||||
Language,
|
Language,
|
||||||
Theme,
|
Theme,
|
||||||
@@ -55,15 +56,20 @@ import { validateDomain, validateIP } from '../utils'
|
|||||||
export default function Settings() {
|
export default function Settings() {
|
||||||
const [reverseProxy, setReverseProxy] = useRecoilState(servedFromReverseProxyState)
|
const [reverseProxy, setReverseProxy] = useRecoilState(servedFromReverseProxyState)
|
||||||
const [baseURL, setBaseURL] = useRecoilState(servedFromReverseProxySubDirState)
|
const [baseURL, setBaseURL] = useRecoilState(servedFromReverseProxySubDirState)
|
||||||
|
|
||||||
const [formatSelection, setFormatSelection] = useRecoilState(formatSelectionState)
|
const [formatSelection, setFormatSelection] = useRecoilState(formatSelectionState)
|
||||||
const [pathOverriding, setPathOverriding] = useRecoilState(pathOverridingState)
|
const [pathOverriding, setPathOverriding] = useRecoilState(pathOverridingState)
|
||||||
const [fileRenaming, setFileRenaming] = useRecoilState(fileRenamingState)
|
const [fileRenaming, setFileRenaming] = useRecoilState(fileRenamingState)
|
||||||
const [enableArgs, setEnableArgs] = useRecoilState(enableCustomArgsState)
|
const [enableArgs, setEnableArgs] = useRecoilState(enableCustomArgsState)
|
||||||
|
|
||||||
const [serverAddr, setServerAddr] = useRecoilState(serverAddressState)
|
const [serverAddr, setServerAddr] = useRecoilState(serverAddressState)
|
||||||
const [serverPort, setServerPort] = useRecoilState(serverPortState)
|
const [serverPort, setServerPort] = useRecoilState(serverPortState)
|
||||||
|
const [cliArgs, setCliArgs] = useRecoilState(latestCliArgumentsState)
|
||||||
|
|
||||||
|
const [pollingTime, setPollingTime] = useRecoilState(rpcPollingTimeState)
|
||||||
const [language, setLanguage] = useRecoilState(languageState)
|
const [language, setLanguage] = useRecoilState(languageState)
|
||||||
const [appTitle, setApptitle] = useRecoilState(appTitleState)
|
const [appTitle, setApptitle] = useRecoilState(appTitleState)
|
||||||
const [cliArgs, setCliArgs] = useRecoilState(latestCliArgumentsState)
|
|
||||||
const [theme, setTheme] = useRecoilState(themeState)
|
const [theme, setTheme] = useRecoilState(themeState)
|
||||||
|
|
||||||
const [invalidIP, setInvalidIP] = useState(false)
|
const [invalidIP, setInvalidIP] = useState(false)
|
||||||
@@ -148,216 +154,238 @@ export default function Settings() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="xl" sx={{ mt: 4, mb: 8 }}>
|
<Container maxWidth="xl" sx={{ mt: 4, mb: 8 }}>
|
||||||
<Grid container spacing={3}>
|
<Paper
|
||||||
<Grid item xs={12} md={12} lg={12}>
|
sx={{
|
||||||
<Paper
|
p: 2.5,
|
||||||
sx={{
|
display: 'flex',
|
||||||
p: 2.5,
|
flexDirection: 'column',
|
||||||
display: 'flex',
|
minHeight: 240,
|
||||||
flexDirection: 'column',
|
}}
|
||||||
minHeight: 240,
|
>
|
||||||
}}
|
<Typography pb={2} variant="h6" color="primary">
|
||||||
>
|
{i18n.t('settingsAnchor')}
|
||||||
<Typography pb={2} variant="h6" color="primary">
|
</Typography>
|
||||||
{i18n.t('settingsAnchor')}
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12} md={11}>
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label={i18n.t('serverAddressTitle')}
|
||||||
|
defaultValue={serverAddr}
|
||||||
|
error={invalidIP}
|
||||||
|
onChange={(e) => serverAddr$.next(e.currentTarget.value)}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">ws://</InputAdornment>,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={1}>
|
||||||
|
<TextField
|
||||||
|
disabled={reverseProxy}
|
||||||
|
fullWidth
|
||||||
|
label={i18n.t('serverPortTitle')}
|
||||||
|
defaultValue={serverPort}
|
||||||
|
onChange={(e) => serverPort$.next(e.currentTarget.value)}
|
||||||
|
error={isNaN(Number(serverPort)) || Number(serverPort) > 65535}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={12}>
|
||||||
|
<TextField
|
||||||
|
disabled={reverseProxy}
|
||||||
|
fullWidth
|
||||||
|
label={i18n.t('appTitle')}
|
||||||
|
defaultValue={appTitle}
|
||||||
|
onChange={(e) => setApptitle(e.currentTarget.value)}
|
||||||
|
error={appTitle === ''}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={12}>
|
||||||
|
<Typography>
|
||||||
|
{i18n.t('rpcPollingTimeTitle')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<FormGroup>
|
<Typography variant='caption' sx={{ mb: 0.5 }}>
|
||||||
<Grid container spacing={2}>
|
{i18n.t('rpcPollingTimeDescription')}
|
||||||
<Grid item xs={12} md={11}>
|
</Typography>
|
||||||
<TextField
|
<Slider
|
||||||
fullWidth
|
aria-label="rpc polling time"
|
||||||
label={i18n.t('serverAddressTitle')}
|
defaultValue={pollingTime}
|
||||||
defaultValue={serverAddr}
|
max={2000}
|
||||||
error={invalidIP}
|
getAriaValueText={(v: number) => `${v} ms`}
|
||||||
onChange={(e) => serverAddr$.next(e.currentTarget.value)}
|
step={null}
|
||||||
InputProps={{
|
valueLabelDisplay="off"
|
||||||
startAdornment: <InputAdornment position="start">ws://</InputAdornment>,
|
marks={[
|
||||||
}}
|
{ value: 100, label: '100 ms' },
|
||||||
/>
|
{ value: 250, label: '250 ms' },
|
||||||
</Grid>
|
{ value: 500, label: '500 ms' },
|
||||||
<Grid item xs={12} md={1}>
|
{ value: 750, label: '750 ms' },
|
||||||
<TextField
|
{ value: 1000, label: '1000 ms' },
|
||||||
disabled={reverseProxy}
|
{ value: 2000, label: '2000 ms' },
|
||||||
fullWidth
|
]}
|
||||||
label={i18n.t('serverPortTitle')}
|
onChange={(_, value) => typeof value === 'number'
|
||||||
defaultValue={serverPort}
|
? setPollingTime(value)
|
||||||
onChange={(e) => serverPort$.next(e.currentTarget.value)}
|
: setPollingTime(1000)
|
||||||
error={isNaN(Number(serverPort)) || Number(serverPort) > 65535}
|
}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} md={12}>
|
<Grid item xs={12}>
|
||||||
<TextField
|
<Typography variant="h6" color="primary" sx={{ mb: 0.5 }}>
|
||||||
disabled={reverseProxy}
|
Reverse Proxy
|
||||||
fullWidth
|
</Typography>
|
||||||
label={i18n.t('appTitle')}
|
<FormControlLabel
|
||||||
defaultValue={appTitle}
|
control={
|
||||||
onChange={(e) => setApptitle(e.currentTarget.value)}
|
<Checkbox
|
||||||
error={appTitle === ''}
|
defaultChecked={reverseProxy}
|
||||||
/>
|
onChange={() => setReverseProxy(state => !state)}
|
||||||
</Grid>
|
/>
|
||||||
<Grid item xs={12}>
|
}
|
||||||
<Typography variant="h6" color="primary" sx={{ mb: 0.5 }}>
|
label={i18n.t('servedFromReverseProxyCheckbox')}
|
||||||
Reverse Proxy
|
sx={{ mb: 1 }}
|
||||||
</Typography>
|
/>
|
||||||
<FormControlLabel
|
<TextField
|
||||||
control={
|
fullWidth
|
||||||
<Checkbox
|
label={i18n.t('urlBase')}
|
||||||
defaultChecked={reverseProxy}
|
defaultValue={baseURL}
|
||||||
onChange={() => setReverseProxy(state => !state)}
|
onChange={(e) => {
|
||||||
/>
|
let value = e.currentTarget.value
|
||||||
}
|
if (value.startsWith('/')) {
|
||||||
label={i18n.t('servedFromReverseProxyCheckbox')}
|
value = value.substring(1)
|
||||||
sx={{ mb: 1 }}
|
|
||||||
/>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label={i18n.t('urlBase')}
|
|
||||||
defaultValue={baseURL}
|
|
||||||
onChange={(e) => {
|
|
||||||
let value = e.currentTarget.value
|
|
||||||
if (value.startsWith('/')) {
|
|
||||||
value = value.substring(1)
|
|
||||||
}
|
|
||||||
if (value.endsWith('/')) {
|
|
||||||
value = value.substring(0, value.length - 1)
|
|
||||||
}
|
|
||||||
baseURL$.next(value)
|
|
||||||
}}
|
|
||||||
sx={{ mb: 2 }}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Typography variant="h6" color="primary" sx={{ mt: 0.5, mb: 2 }}>
|
|
||||||
Appaerance
|
|
||||||
</Typography>
|
|
||||||
<Grid container spacing={2}>
|
|
||||||
<Grid item xs={12} md={6}>
|
|
||||||
<FormControl fullWidth>
|
|
||||||
<InputLabel>{i18n.t('languageSelect')}</InputLabel>
|
|
||||||
<Select
|
|
||||||
defaultValue={language}
|
|
||||||
label={i18n.t('languageSelect')}
|
|
||||||
onChange={handleLanguageChange}
|
|
||||||
>
|
|
||||||
{languages.toSorted((a, b) => a.localeCompare(b)).map(l => (
|
|
||||||
<MenuItem value={l} key={l}>
|
|
||||||
{capitalize(l)}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</Grid>
|
|
||||||
<Grid item xs={12} md={6}>
|
|
||||||
<FormControl fullWidth>
|
|
||||||
<InputLabel>{i18n.t('themeSelect')}</InputLabel>
|
|
||||||
<Select
|
|
||||||
defaultValue={theme}
|
|
||||||
label={i18n.t('themeSelect')}
|
|
||||||
onChange={handleThemeChange}
|
|
||||||
>
|
|
||||||
<MenuItem value="light">Light</MenuItem>
|
|
||||||
<MenuItem value="dark">Dark</MenuItem>
|
|
||||||
<MenuItem value="system">System</MenuItem>
|
|
||||||
</Select>
|
|
||||||
</FormControl>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Typography variant="h6" color="primary" sx={{ mt: 2, mb: 0.5 }}>
|
|
||||||
General download settings
|
|
||||||
</Typography>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
defaultChecked={argsBuilder.noMTime}
|
|
||||||
onChange={() => setCliArgs(argsBuilder.toggleNoMTime().toString())}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
label={i18n.t('noMTimeCheckbox')}
|
if (value.endsWith('/')) {
|
||||||
|
value = value.substring(0, value.length - 1)
|
||||||
/>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
defaultChecked={argsBuilder.extractAudio}
|
|
||||||
onChange={() => setCliArgs(argsBuilder.toggleExtractAudio().toString())}
|
|
||||||
disabled={formatSelection}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
label={i18n.t('extractAudioCheckbox')}
|
baseURL$.next(value)
|
||||||
/>
|
}}
|
||||||
<FormControlLabel
|
sx={{ mb: 2 }}
|
||||||
control={
|
/>
|
||||||
<Switch
|
</Grid>
|
||||||
defaultChecked={formatSelection}
|
|
||||||
onChange={() => {
|
|
||||||
setCliArgs(argsBuilder.disableExtractAudio().toString())
|
|
||||||
setFormatSelection(!formatSelection)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n.t('formatSelectionEnabler')}
|
|
||||||
/>
|
|
||||||
<Grid>
|
|
||||||
<Typography variant="h6" color="primary" sx={{ mt: 2, mb: 0.5 }}>
|
|
||||||
{i18n.t('overridesAnchor')}
|
|
||||||
</Typography>
|
|
||||||
<Stack direction="column">
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
defaultChecked={!!pathOverriding}
|
|
||||||
onChange={() => {
|
|
||||||
setPathOverriding(state => !state)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n.t('pathOverrideOption')}
|
|
||||||
/>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
defaultChecked={fileRenaming}
|
|
||||||
onChange={() => {
|
|
||||||
setFileRenaming(state => !state)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n.t('filenameOverrideOption')}
|
|
||||||
/>
|
|
||||||
<FormControlLabel
|
|
||||||
control={
|
|
||||||
<Switch
|
|
||||||
defaultChecked={enableArgs}
|
|
||||||
onChange={() => {
|
|
||||||
setEnableArgs(state => !state)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={i18n.t('customArgs')}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
<Grid sx={{ mr: 1, mt: 2 }}>
|
|
||||||
<Typography variant="h6" color="primary" sx={{ mb: 2 }}>
|
|
||||||
Cookies
|
|
||||||
</Typography>
|
|
||||||
<CookiesTextField />
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<Stack direction="row">
|
|
||||||
<Button
|
|
||||||
sx={{ mr: 1, mt: 3 }}
|
|
||||||
variant="contained"
|
|
||||||
onClick={() => updateBinary()}
|
|
||||||
>
|
|
||||||
{i18n.t('updateBinButton')}
|
|
||||||
</Button>
|
|
||||||
</Stack>
|
|
||||||
</Grid>
|
|
||||||
</FormGroup>
|
|
||||||
</Paper>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
<Typography variant="h6" color="primary" sx={{ mt: 0.5, mb: 2 }}>
|
||||||
|
Appaerance
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>{i18n.t('languageSelect')}</InputLabel>
|
||||||
|
<Select
|
||||||
|
defaultValue={language}
|
||||||
|
label={i18n.t('languageSelect')}
|
||||||
|
onChange={handleLanguageChange}
|
||||||
|
>
|
||||||
|
{languages.toSorted((a, b) => a.localeCompare(b)).map(l => (
|
||||||
|
<MenuItem value={l} key={l}>
|
||||||
|
{capitalize(l)}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} md={6}>
|
||||||
|
<FormControl fullWidth>
|
||||||
|
<InputLabel>{i18n.t('themeSelect')}</InputLabel>
|
||||||
|
<Select
|
||||||
|
defaultValue={theme}
|
||||||
|
label={i18n.t('themeSelect')}
|
||||||
|
onChange={handleThemeChange}
|
||||||
|
>
|
||||||
|
<MenuItem value="light">Light</MenuItem>
|
||||||
|
<MenuItem value="dark">Dark</MenuItem>
|
||||||
|
<MenuItem value="system">System</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Typography variant="h6" color="primary" sx={{ mt: 2, mb: 0.5 }}>
|
||||||
|
General download settings
|
||||||
|
</Typography>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
defaultChecked={argsBuilder.noMTime}
|
||||||
|
onChange={() => setCliArgs(argsBuilder.toggleNoMTime().toString())}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n.t('noMTimeCheckbox')}
|
||||||
|
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
defaultChecked={argsBuilder.extractAudio}
|
||||||
|
onChange={() => setCliArgs(argsBuilder.toggleExtractAudio().toString())}
|
||||||
|
disabled={formatSelection}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n.t('extractAudioCheckbox')}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
defaultChecked={formatSelection}
|
||||||
|
onChange={() => {
|
||||||
|
setCliArgs(argsBuilder.disableExtractAudio().toString())
|
||||||
|
setFormatSelection(!formatSelection)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n.t('formatSelectionEnabler')}
|
||||||
|
/>
|
||||||
|
<Grid>
|
||||||
|
<Typography variant="h6" color="primary" sx={{ mt: 2, mb: 0.5 }}>
|
||||||
|
{i18n.t('overridesAnchor')}
|
||||||
|
</Typography>
|
||||||
|
<Stack direction="column">
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
defaultChecked={!!pathOverriding}
|
||||||
|
onChange={() => {
|
||||||
|
setPathOverriding(state => !state)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n.t('pathOverrideOption')}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
defaultChecked={fileRenaming}
|
||||||
|
onChange={() => {
|
||||||
|
setFileRenaming(state => !state)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n.t('filenameOverrideOption')}
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
defaultChecked={enableArgs}
|
||||||
|
onChange={() => {
|
||||||
|
setEnableArgs(state => !state)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={i18n.t('customArgs')}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
<Grid sx={{ mr: 1, mt: 2 }}>
|
||||||
|
<Typography variant="h6" color="primary" sx={{ mb: 2 }}>
|
||||||
|
Cookies
|
||||||
|
</Typography>
|
||||||
|
<CookiesTextField />
|
||||||
|
</Grid>
|
||||||
|
<Grid>
|
||||||
|
<Stack direction="row">
|
||||||
|
<Button
|
||||||
|
sx={{ mr: 1, mt: 3 }}
|
||||||
|
variant="contained"
|
||||||
|
onClick={() => updateBinary()}
|
||||||
|
>
|
||||||
|
{i18n.t('updateBinButton')}
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Grid>
|
||||||
|
</Paper>
|
||||||
</Container>
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user