Added Basic mode for WebUI & added new env var for selecting default preset.

This commit is contained in:
ArabCoders 2025-01-17 02:03:58 +03:00
parent bd065692fc
commit b1388eff6b
10 changed files with 78 additions and 34 deletions

2
.vscode/launch.json vendored
View file

@ -41,6 +41,8 @@
"YTP_LOG_LEVEL": "DEBUG",
"YTP_DEBUG": "true",
"YTP_YTDL_DEBUG": "false",
"YTP_BASIC_MODE": "true",
"YTP_DEFAULT_PRESET": "Best video and audio",
}
},
{

View file

@ -19,6 +19,7 @@ YTPTube started as a fork of [meTube](https://github.com/alexta69/metube), Since
* Queue multiple URLs separated by comma.
* Basic Authentication support.
* Support for curl_cffi, see [yt-dlp documentation](https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#impersonation)
* Support for both advanced and basic mode for WebUI.
### Tips
Your `yt-dlp` config should include the following options for optimal working conditions.
@ -94,6 +95,8 @@ Certain values can be set via environment variables, using the `-e` parameter on
* __YTP_UI_UPDATE_TITLE__: Whether to update the title of the page with the current stats. Defaults to `true`.
* __YTP_PIP_PACKAGES__: a space separated list of pip packages to install. Defaults to `""`, you can also use `{config_path}/pip.txt` to install the packages.
* __YTP_PIP_IGNORE_UPDATES__: Do not update the custom pip packages. Defaults to `false`.
* __YTP_BASIC_MODE__: Whether to run WebUI in basic mode. Defaults to `false`. In basic mode, A minimal UI will be shown, the majority of the features will be disabled.
* __YTP_DEFAULT_PRESET__: The default preset to use for the download. Defaults to `default`.
## Running behind a reverse proxy

View file

@ -69,10 +69,14 @@ class Config:
ytdlp_version: str = YTDLP_VERSION
started: int = 0
ignore_ui: bool = False
basic_mode: bool = False
presets: list = [
{"name": "default", "format": "default"},
]
default_preset: str = "default"
_manual_vars: tuple = (
"temp_path",
"config_path",
@ -108,6 +112,7 @@ class Config:
"ignore_ui",
"ui_update_title",
"pip_ignore_updates",
"basic_mode",
)
_frontend_vars: tuple = (
@ -122,6 +127,8 @@ class Config:
"remove_files",
"ui_update_title",
"max_workers",
"basic_mode",
"default_preset",
)
@staticmethod
@ -286,6 +293,9 @@ class Config:
if self.auth_password and self.auth_username:
LOG.warning(f"Basic authentication enabled with username '{self.auth_username}'.")
if self.basic_mode:
LOG.info("The frontend is running in basic mode.")
self.started = time.time()
def _getAttributes(self) -> dict:

View file

@ -203,7 +203,7 @@
</span>
</a>
</div>
<div class="column is-half-mobile" v-if="item.url">
<div class="column is-half-mobile" v-if="item.url && !config.app.basic_mode">
<button class="button is-info is-fullwidth" @click="emitter('getInfo', item.url)">
<span class="icon-text is-block">
<span class="icon"><i class="fa-solid fa-info" /></span>

View file

@ -12,7 +12,7 @@
</span>
</div>
</div>
<div class="column is-4-tablet is-12-mobile">
<div class="column is-4-tablet is-12-mobile" v-if="!config.app.basic_mode">
<div class="field has-addons">
<div class="control">
<a href="#" class="button is-static">Preset</a>
@ -28,7 +28,7 @@
</div>
</div>
</div>
<div class="column is-6-tablet is-12-mobile">
<div class="column is-6-tablet is-12-mobile" v-if="!config.app.basic_mode">
<div class="field has-addons" v-tooltip="'Folder relative to ' + config.app.download_path">
<div class="control">
<a href="#" class="button is-static">Save in</a>
@ -47,7 +47,20 @@
<span>Add</span>
</button>
</div>
<div class="column">
<div class="column has-text-right" v-if="config.app.basic_mode">
<div class="field">
<div class="control">
<button type="submit" class="button is-danger" @click="resetConfig" :disabled="!socket.isConnected"
v-tooltip="'This configuration are stored locally in your browser.'">
<span class="icon">
<i class="fa-solid fa-trash" />
</span>
<span>Reset Local Config</span>
</button>
</div>
</div>
</div>
<div class="column" v-if="!config.app.basic_mode">
<button type="submit" class="button is-info" @click="showAdvanced = !showAdvanced"
:class="{ 'is-loading': !socket.isConnected }" :disabled="!socket.isConnected">
<span class="icon"><i class="fa-solid fa-cog" /></span>
@ -55,7 +68,7 @@
</button>
</div>
</div>
<div class="columns is-multiline is-mobile" v-if="showAdvanced">
<div class="columns is-multiline is-mobile" v-if="showAdvanced && !config.app.basic_mode">
<div class="column is-12">
<div class="field">
<label class="label is-inline" for="output_format"
@ -139,11 +152,11 @@
import { useStorage } from '@vueuse/core'
const emitter = defineEmits(['getInfo'])
const config = useConfigStore();
const socket = useSocketStore();
const toast = useToast();
const config = useConfigStore()
const socket = useSocketStore()
const toast = useToast()
const selectedPreset = useStorage('selectedPreset', '')
const selectedPreset = useStorage('selectedPreset', config.app.default_preset)
const ytdlpConfig = useStorage('ytdlp_config', '')
const ytdlpCookies = useStorage('ytdlp_cookies', '')
const output_template = useStorage('output_template', null)
@ -153,36 +166,36 @@ const showAdvanced = useStorage('show_advanced', false)
const addInProgress = ref(false)
const addDownload = () => {
addInProgress.value = true;
addInProgress.value = true
url.value.split(',').forEach(url => {
if (!url.trim()) {
return;
return
}
socket.emit('add_url', {
url: url,
preset: selectedPreset.value,
preset: config.app.basic_mode ? config.app.default_preset : selectedPreset.value,
folder: downloadPath.value,
ytdlp_config: ytdlpConfig.value,
ytdlp_cookies: ytdlpCookies.value,
output_template: output_template.value,
});
});
})
})
}
const resetConfig = () => {
if (true !== confirm('Reset your local configuration?')) {
return;
return
}
selectedPreset.value = 'default';
ytdlpConfig.value = '';
ytdlpCookies.value = '';
output_template.value = null;
url.value = null;
downloadPath.value = null;
showAdvanced.value = false;
selectedPreset.value = config.app.default_preset.value
ytdlpConfig.value = ''
ytdlpCookies.value = ''
output_template.value = null
url.value = null
downloadPath.value = null
showAdvanced.value = false
toast.success('Local configuration has been reset.');
toast.success('Local configuration has been reset.')
}
const statusHandler = async data => {
@ -195,13 +208,13 @@ const statusHandler = async data => {
return
}
url.value = '';
url.value = ''
}
onMounted(() => {
socket.on('status', statusHandler)
if ('' === selectedPreset.value) {
selectedPreset.value = 'default'
selectedPreset.value = config.app.default_preset.value
}
})
onUnmounted(() => socket.off('status', statusHandler))

View file

@ -102,7 +102,7 @@
</span>
</button>
</div>
<div class="column is-half-mobile" v-if="item.url">
<div class="column is-half-mobile" v-if="item.url && !config.app.basic_mode">
<button class="button is-info is-fullwidth" @click="emitter('getInfo', item.url)">
<span class="icon-text is-block">
<span class="icon"><i class="fa-solid fa-info" /></span>

View file

@ -12,14 +12,14 @@
</div>
<div class="navbar-end is-flex">
<div class="navbar-item" v-if="socket.isConnected && config.app.has_cookies">
<div class="navbar-item" v-if="socket.isConnected && config.app.has_cookies && !config.app.basic_mode">
<button class="button is-dark" @click="checkCookies" v-tooltip="'Check youtube cookies status.'"
:disabled="isChecking">
<span class="icon has-text-info"><i class="fas fa-cookie"></i></span>
</button>
</div>
<div class="navbar-item" v-if="socket.isConnected">
<div class="navbar-item" v-if="socket.isConnected && !config.app.basic_mode">
<button class="button is-dark" @click="pauseDownload" v-if="false === config.paused"
v-tooltip="'Pause non-active downloads.'">
<span class="icon has-text-warning"><i class="fas fa-pause"></i></span>
@ -29,20 +29,20 @@
</button>
</div>
<div class="navbar-item">
<div class="navbar-item" v-if="!config.app.basic_mode">
<NuxtLink class="button is-dark has-tooltip-bottom" to="/console" v-tooltip.bottom="'Terminal'">
<span class="icon"><i class="fa-solid fa-terminal" /></span>
</NuxtLink>
</div>
<div class="navbar-item">
<div class="navbar-item" v-if="!config.app.basic_mode">
<button v-tooltip.bottom="'Toggle Add Form'" class="button is-dark has-tooltip-bottom"
@click="config.showForm = !config.showForm">
<span class="icon"><i class="fa-solid fa-plus" /></span>
</button>
</div>
<div class="navbar-item" v-if="config.tasks.length > 0" v-tooltip.bottom="'Tasks'">
<div class="navbar-item" v-if="!config.app.basic_mode && config.tasks.length > 0" v-tooltip.bottom="'Tasks'">
<NuxtLink class="button is-dark has-tooltip-bottom" to="/tasks">
<span class="icon"><i class="fa-solid fa-tasks" /></span>
</NuxtLink>
@ -67,7 +67,7 @@
</div>
</nav>
<NewDownload v-if="config.showForm" @getInfo="url => get_info = url" />
<NewDownload v-if="config.showForm || config.app.basic_mode" @getInfo="url => get_info = url" />
<NuxtPage @getInfo="url => get_info = url" />
<GetInfo v-if="get_info" :link="get_info" @closeModel="get_info = ''" />

View file

@ -65,7 +65,7 @@ const command = ref('')
const terminal_window = ref()
const command_input = ref()
const isLoading = ref(false)
const config = useConfigStore()
const socket = useSocketStore()
watch(() => isLoading.value, async value => {
@ -149,6 +149,13 @@ const writer = s => {
const loader = () => isLoading.value = false
watch(() => config.app.basic_mode, async () => {
if (!config.app.basic_mode) {
return
}
await navigateTo('/')
})
onMounted(async () => {
window.addEventListener('resize', reSizeTerminal);
focusInput()

View file

@ -64,4 +64,11 @@ div.table-container {
import moment from 'moment'
import { parseExpression } from 'cron-parser'
const config = useConfigStore()
watch(() => config.app.basic_mode, async () => {
if (!config.app.basic_mode) {
return
}
await navigateTo('/')
})
</script>

View file

@ -14,10 +14,12 @@ const CONFIG_KEYS = {
url_host: '',
url_prefix: '',
has_cookies: false,
basic_mode: true,
default_preset: 'default',
},
presets: [
{
'name': 'Default',
'name': 'default',
'format': 'default'
}
],