@@ -34,7 +34,8 @@ languages:
|
|||||||
clipboardAction: Copied URL to clipboard
|
clipboardAction: Copied URL to clipboard
|
||||||
playlistCheckbox: Download playlist (it will take time, after submitting you may close this window)
|
playlistCheckbox: Download playlist (it will take time, after submitting you may close this window)
|
||||||
restartAppMessage: Needs a page reload to take effect
|
restartAppMessage: Needs a page reload to take effect
|
||||||
servedFromReverseProxyCheckbox: Is behind a reverse proxy subfolder
|
servedFromReverseProxyCheckbox: Is behind a reverse proxy
|
||||||
|
urlBase: URL base, for reverse proxy support (subdir), defaults to empty
|
||||||
newDownloadButton: New download
|
newDownloadButton: New download
|
||||||
homeButtonLabel: Home
|
homeButtonLabel: Home
|
||||||
archiveButtonLabel: Archive
|
archiveButtonLabel: Archive
|
||||||
|
|||||||
@@ -135,6 +135,15 @@ export const servedFromReverseProxyState = atom({
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const servedFromReverseProxySubDirState = atom<string>({
|
||||||
|
key: 'servedFromReverseProxyState',
|
||||||
|
default: localStorage.getItem('reverseProxySubDir') ?? '',
|
||||||
|
effects: [
|
||||||
|
({ onSet }) =>
|
||||||
|
onSet(a => localStorage.setItem('reverseProxySubDir', a.toString()))
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
export const appTitleState = atom({
|
export const appTitleState = atom({
|
||||||
key: 'appTitleState',
|
key: 'appTitleState',
|
||||||
default: localStorage.getItem('appTitle') ?? 'yt-dlp Web UI',
|
default: localStorage.getItem('appTitle') ?? 'yt-dlp Web UI',
|
||||||
@@ -147,7 +156,9 @@ export const appTitleState = atom({
|
|||||||
export const serverAddressAndPortState = selector({
|
export const serverAddressAndPortState = selector({
|
||||||
key: 'serverAddressAndPortState',
|
key: 'serverAddressAndPortState',
|
||||||
get: ({ get }) => get(servedFromReverseProxyState)
|
get: ({ get }) => get(servedFromReverseProxyState)
|
||||||
? `${get(serverAddressState)}`
|
? get(servedFromReverseProxySubDirState) ?
|
||||||
|
`${get(serverAddressState)}/${get(servedFromReverseProxySubDirState)}/`
|
||||||
|
: `${get(serverAddressState)}`
|
||||||
: `${get(serverAddressState)}:${get(serverPortState)}`
|
: `${get(serverAddressState)}:${get(serverPortState)}`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import {
|
|||||||
latestCliArgumentsState,
|
latestCliArgumentsState,
|
||||||
pathOverridingState,
|
pathOverridingState,
|
||||||
servedFromReverseProxyState,
|
servedFromReverseProxyState,
|
||||||
|
servedFromReverseProxySubDirState,
|
||||||
serverAddressState,
|
serverAddressState,
|
||||||
serverPortState,
|
serverPortState,
|
||||||
themeState
|
themeState
|
||||||
@@ -53,6 +54,7 @@ import { validateDomain, validateIP } from '../utils'
|
|||||||
// NEED ABSOLUTELY TO BE SPLIT IN MULTIPLE COMPONENTS
|
// NEED ABSOLUTELY TO BE SPLIT IN MULTIPLE COMPONENTS
|
||||||
export default function Settings() {
|
export default function Settings() {
|
||||||
const [reverseProxy, setReverseProxy] = useRecoilState(servedFromReverseProxyState)
|
const [reverseProxy, setReverseProxy] = useRecoilState(servedFromReverseProxyState)
|
||||||
|
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)
|
||||||
@@ -73,9 +75,20 @@ export default function Settings() {
|
|||||||
|
|
||||||
const argsBuilder = useMemo(() => new CliArguments().fromString(cliArgs), [])
|
const argsBuilder = useMemo(() => new CliArguments().fromString(cliArgs), [])
|
||||||
|
|
||||||
|
const baseURL$ = useMemo(() => new Subject<string>(), [])
|
||||||
const serverAddr$ = useMemo(() => new Subject<string>(), [])
|
const serverAddr$ = useMemo(() => new Subject<string>(), [])
|
||||||
const serverPort$ = useMemo(() => new Subject<string>(), [])
|
const serverPort$ = useMemo(() => new Subject<string>(), [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = baseURL$
|
||||||
|
.pipe(debounceTime(500))
|
||||||
|
.subscribe(baseURL => {
|
||||||
|
setBaseURL(baseURL)
|
||||||
|
pushMessage(i18n.t('restartAppMessage'), 'info')
|
||||||
|
})
|
||||||
|
return () => sub.unsubscribe()
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sub = serverAddr$
|
const sub = serverAddr$
|
||||||
.pipe(
|
.pipe(
|
||||||
@@ -145,7 +158,7 @@ export default function Settings() {
|
|||||||
minHeight: 240,
|
minHeight: 240,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography pb={3} variant="h5" color="primary">
|
<Typography pb={2} variant="h6" color="primary">
|
||||||
{i18n.t('settingsAnchor')}
|
{i18n.t('settingsAnchor')}
|
||||||
</Typography>
|
</Typography>
|
||||||
<FormGroup>
|
<FormGroup>
|
||||||
@@ -183,6 +196,9 @@ export default function Settings() {
|
|||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
|
<Typography variant="h6" color="primary" sx={{ mb: 0.5 }}>
|
||||||
|
Reverse Proxy
|
||||||
|
</Typography>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={
|
control={
|
||||||
<Checkbox
|
<Checkbox
|
||||||
@@ -191,10 +207,29 @@ export default function Settings() {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={i18n.t('servedFromReverseProxyCheckbox')}
|
label={i18n.t('servedFromReverseProxyCheckbox')}
|
||||||
|
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 }}
|
sx={{ mb: 2 }}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Typography variant="h6" color="primary" sx={{ mt: 0.5, mb: 2 }}>
|
||||||
|
Appaerance
|
||||||
|
</Typography>
|
||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={12} md={6}>
|
<Grid item xs={12} md={6}>
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
@@ -227,6 +262,9 @@ export default function Settings() {
|
|||||||
</FormControl>
|
</FormControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Typography variant="h6" color="primary" sx={{ mt: 2, mb: 0.5 }}>
|
||||||
|
General download settings
|
||||||
|
</Typography>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={
|
control={
|
||||||
<Switch
|
<Switch
|
||||||
@@ -235,7 +273,7 @@ export default function Settings() {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
label={i18n.t('noMTimeCheckbox')}
|
label={i18n.t('noMTimeCheckbox')}
|
||||||
sx={{ mt: 3 }}
|
|
||||||
/>
|
/>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={
|
control={
|
||||||
@@ -299,7 +337,7 @@ export default function Settings() {
|
|||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid sx={{ mr: 1, mt: 3 }}>
|
<Grid sx={{ mr: 1, mt: 2 }}>
|
||||||
<Typography variant="h6" color="primary" sx={{ mb: 2 }}>
|
<Typography variant="h6" color="primary" sx={{ mb: 2 }}>
|
||||||
Cookies
|
Cookies
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
Reference in New Issue
Block a user