Merge pull request #380 from arabcoders/dev
Refactor: update basic mode watch logic to check config loading state
This commit is contained in:
commit
d2ce9940e8
14 changed files with 80 additions and 30 deletions
|
|
@ -107,6 +107,7 @@ class Download:
|
|||
self.temp_dir = info.temp_dir
|
||||
self.template = info.template
|
||||
self.template_chapter = info.template_chapter
|
||||
self.download_info_expires = int(config.download_info_expires)
|
||||
self.preset = info.preset
|
||||
self.info = info
|
||||
self.id = info._id
|
||||
|
|
@ -226,7 +227,15 @@ class Download:
|
|||
self.logger.error(err_msg)
|
||||
raise ValueError(err_msg) from e
|
||||
|
||||
if not self.info_dict:
|
||||
# Safe-guard incase downloading take too long and the info expires.
|
||||
if self.info_dict and isinstance(self.info_dict, dict) and self.download_info_expires > 0:
|
||||
_ts: int | None = self.info_dict.get("timestamp")
|
||||
_ts = datetime.fromtimestamp(_ts, tz=UTC) if _ts else None
|
||||
if not _ts or (datetime.now(tz=UTC) - _ts).total_seconds() > self.download_info_expires:
|
||||
self.info_dict = None
|
||||
self.logger.warning(f"Info for '{self.info.url}' has expired, re-extracting info.")
|
||||
|
||||
if not self.info_dict or not isinstance(self.info_dict, dict):
|
||||
self.logger.info(f"Extracting info for '{self.info.url}'.")
|
||||
self.logs = []
|
||||
ie_params = params.copy()
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ class Config:
|
|||
download_path_depth: int = 2
|
||||
"""How many subdirectories to show in auto complete."""
|
||||
|
||||
download_info_expires: int = 10800
|
||||
"""How long (in seconds) the download info is valid before it needs to be re-extracted."""
|
||||
|
||||
temp_path: str = "/tmp"
|
||||
"""The path to the temporary directory."""
|
||||
|
||||
|
|
@ -226,6 +229,7 @@ class Config:
|
|||
"debugpy_port",
|
||||
"playlist_items_concurrency",
|
||||
"download_path_depth",
|
||||
"download_info_expires",
|
||||
)
|
||||
"The variables that are integers."
|
||||
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<div class="column" v-if="!config.app.basic_mode">
|
||||
<Dropdown icons="fa-solid fa-cogs" label="Actions">
|
||||
<template v-if="'finished' === item.status && item.filename">
|
||||
<NuxtLink @click="playVideo(item)" class="dropdown-item">
|
||||
|
|
|
|||
|
|
@ -88,7 +88,16 @@ const setDropdownItemRef = (el: Element | ComponentPublicInstance | null, idx: n
|
|||
dropdownItemRefs.value[idx] = el instanceof HTMLElement ? el : null
|
||||
}
|
||||
|
||||
watch(filteredOptions, () => dropdownItemRefs.value = Array(filteredOptions.value.length).fill(null))
|
||||
watch(filteredOptions, () => {
|
||||
highlightedIndex.value = filteredOptions.value.length ? 0 : -1
|
||||
dropdownItemRefs.value = Array(filteredOptions.value.length).fill(null)
|
||||
nextTick(() => {
|
||||
const dropdown = document.querySelector('.dropdown-content')
|
||||
if (dropdown) {
|
||||
dropdown.scrollTop = 0
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const handleKeydown = (e: KeyboardEvent) => {
|
||||
if (!filteredOptions.value.length) {
|
||||
|
|
|
|||
|
|
@ -121,7 +121,8 @@
|
|||
<span class="icon"><i class="fa-solid fa-terminal" /></span>
|
||||
<span>Command options for yt-dlp</span>
|
||||
</label>
|
||||
<TextareaAutocomplete id="cli_options" v-model="form.cli" :options="ytDlpOpt" />
|
||||
<TextareaAutocomplete id="cli_options" v-model="form.cli" :options="ytDlpOpt"
|
||||
:disabled="!socket.isConnected || addInProgress" />
|
||||
<span class="help is-bold">
|
||||
<span class="icon"><i class="fa-solid fa-info" /></span>
|
||||
<span>
|
||||
|
|
|
|||
|
|
@ -77,10 +77,22 @@ const appendFlag = (flag: string) => {
|
|||
}
|
||||
|
||||
const onInput = () => {
|
||||
showList.value = true
|
||||
highlightedIndex.value = filteredOptions.value.length ? 0 : -1
|
||||
const lastWord = localValue.value.split(/\s+/).pop() || ''
|
||||
showList.value = lastWord.length > 0
|
||||
highlightedIndex.value = (showList.value && filteredOptions.value.length && lastWord.length > 0) ? 0 : -1
|
||||
}
|
||||
|
||||
// Reset scroll position when filtered options change
|
||||
watch(filteredOptions, () => {
|
||||
highlightedIndex.value = filteredOptions.value.length > 0 && showList.value ? 0 : -1
|
||||
nextTick(() => {
|
||||
const dropdown = document.querySelector('.dropdown-content')
|
||||
if (dropdown) {
|
||||
dropdown.scrollTop = 0
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const hideList = () => setTimeout(() => { showList.value = false; highlightedIndex.value = -1 }, 100)
|
||||
|
||||
const onKeydown = (e: KeyboardEvent) => {
|
||||
|
|
@ -119,9 +131,11 @@ const onKeydown = (e: KeyboardEvent) => {
|
|||
if (el) el.scrollIntoView({ block: 'nearest' })
|
||||
})
|
||||
} else if (e.key === 'Enter' || e.key === 'Tab') {
|
||||
const lastWord = localValue.value.split(/\s+/).pop() || ''
|
||||
const selected = highlightedIndex.value >= 0 && highlightedIndex.value < filteredOptions.value.length ?
|
||||
filteredOptions.value[highlightedIndex.value] : undefined
|
||||
if (selected) {
|
||||
// Only autocomplete if there's a partial word being typed
|
||||
if (selected && lastWord.trim().length > 0) {
|
||||
e.preventDefault()
|
||||
appendFlag(selected.value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,15 @@
|
|||
<div>
|
||||
<Settings v-if="show_settings" :isLoading="loadingImage" @reload_bg="() => loadImage(true)" />
|
||||
<NuxtLoadingIndicator />
|
||||
<NuxtPage />
|
||||
<NuxtPage v-if="config.is_loaded" />
|
||||
<Message v-else class="has-background-info-90 has-text-dark mt-5" title="Loading Configuration"
|
||||
icon="fas fa-spinner fa-spin">
|
||||
<p>Loading application configuration. This usually takes less than a second.</p>
|
||||
<p v-if="!socket.isConnected" class="mt-2">
|
||||
If this is taking too long, please check that the backend server is running and that the WebSocket
|
||||
connection is functional.
|
||||
</p>
|
||||
</Message>
|
||||
</div>
|
||||
|
||||
<div class="columns mt-3 is-mobile">
|
||||
|
|
|
|||
|
|
@ -221,6 +221,14 @@ const table_container = ref<boolean>(false)
|
|||
const search = ref<string>('')
|
||||
const show_filter = ref<boolean>(false)
|
||||
|
||||
watch(() => config.app.basic_mode, async v => {
|
||||
if (!config.isLoaded() || !v) {
|
||||
return
|
||||
}
|
||||
await navigateTo('/')
|
||||
},{ immediate: true })
|
||||
|
||||
|
||||
const filteredItems = computed<FileItem[]>(() => {
|
||||
if (!search.value) {
|
||||
return sortedItems(items.value)
|
||||
|
|
|
|||
|
|
@ -131,12 +131,12 @@ const initialLoad = ref(true)
|
|||
const addInProgress = ref(false)
|
||||
const remove_keys = ['in_progress', 'raw']
|
||||
|
||||
watch(() => config.app.basic_mode, async () => {
|
||||
if (!config.app.basic_mode) {
|
||||
watch(() => config.app.basic_mode, async v => {
|
||||
if (!config.isLoaded() || !v) {
|
||||
return
|
||||
}
|
||||
await navigateTo("/")
|
||||
})
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => socket.isConnected, async () => {
|
||||
if (socket.isConnected && initialLoad.value) {
|
||||
|
|
|
|||
|
|
@ -82,11 +82,11 @@ watch(() => isLoading.value, async value => {
|
|||
}, { immediate: true })
|
||||
|
||||
watch(() => config.app.basic_mode, async () => {
|
||||
if (!config.app.basic_mode) {
|
||||
if (!config.isLoaded() || !config.app.basic_mode) {
|
||||
return
|
||||
}
|
||||
await navigateTo('/')
|
||||
})
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => config.app.console_enabled, async () => {
|
||||
if (config.app.console_enabled) {
|
||||
|
|
|
|||
|
|
@ -156,11 +156,11 @@ watch(toggleFilter, () => {
|
|||
});
|
||||
|
||||
watch(() => config.app.basic_mode, async v => {
|
||||
if (!v) {
|
||||
if (!config.isLoaded() || !v) {
|
||||
return
|
||||
}
|
||||
await navigateTo('/')
|
||||
})
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => config.app.file_logging, async v => {
|
||||
if (v) {
|
||||
|
|
|
|||
|
|
@ -223,12 +223,12 @@ const isLoading = ref(false)
|
|||
const initialLoad = ref(true)
|
||||
const addInProgress = ref(false)
|
||||
|
||||
watch(() => config.app.basic_mode, async () => {
|
||||
if (!config.app.basic_mode) {
|
||||
watch(() => config.app.basic_mode, async v => {
|
||||
if (!config.isLoaded() || !v) {
|
||||
return
|
||||
}
|
||||
await navigateTo('/')
|
||||
})
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => socket.isConnected, async () => {
|
||||
if (socket.isConnected && initialLoad.value) {
|
||||
|
|
|
|||
|
|
@ -226,15 +226,12 @@ const remove_keys = ['raw', 'toggle_description']
|
|||
|
||||
const presetsNoDefault = computed(() => presets.value.filter((t) => !t.default))
|
||||
|
||||
watch(
|
||||
() => config.app.basic_mode,
|
||||
async () => {
|
||||
if (!config.app.basic_mode) {
|
||||
return
|
||||
}
|
||||
await navigateTo('/')
|
||||
},
|
||||
)
|
||||
watch(() => config.app.basic_mode, async v => {
|
||||
if (!config.isLoaded() || !v) {
|
||||
return
|
||||
}
|
||||
await navigateTo('/')
|
||||
}, { immediate: true })
|
||||
|
||||
watch(() => socket.isConnected, async () => {
|
||||
if (socket.isConnected && initialLoad.value) {
|
||||
|
|
|
|||
|
|
@ -423,12 +423,12 @@ watch(masterSelectAll, value => {
|
|||
}
|
||||
})
|
||||
|
||||
watch(() => config.app.basic_mode, async () => {
|
||||
if (!config.app.basic_mode) {
|
||||
watch(() => config.app.basic_mode, async v => {
|
||||
if (!config.isLoaded() || !v) {
|
||||
return
|
||||
}
|
||||
await navigateTo('/')
|
||||
})
|
||||
},{ immediate: true })
|
||||
|
||||
watch(() => socket.isConnected, async () => {
|
||||
if (socket.isConnected && initialLoad.value) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue