minor changes to newDownload form

This commit is contained in:
arabcoders 2025-04-04 22:53:21 +03:00
parent 93e830f029
commit 260901cfa9
6 changed files with 128 additions and 61 deletions

View file

@ -18,7 +18,7 @@ from .AsyncPool import AsyncPool
from .config import Config
from .DataStore import DataStore
from .Download import Download
from .Events import EventBus, Events
from .Events import EventBus, Events, info
from .ItemDTO import Item, ItemDTO
from .Presets import Presets
from .Singleton import Singleton
@ -307,6 +307,14 @@ class DownloadQueue(metaclass=Singleton):
dlInfo.info.status = "not_live"
itemDownload = self.done.put(dlInfo)
NotifyEvent = Events.COMPLETED
log_message = f"{dl.title or dl.id or dl._id}: stream is not live yet."
if dlInfo.info.live_in:
log_message += f" Will start in {dlInfo.info.live_in}."
await self._notify.emit(
Events.LOG_INFO,
data=info(msg=log_message, data=itemDownload.info.serialize()),
)
elif self.config.allow_manifestless is False and is_manifestless is True:
dlInfo.info.status = "error"
dlInfo.info.error = "Video is in post-live manifestless mode."

View file

@ -309,3 +309,7 @@ hr {
.is-auto {
unicode-bidi: embed;
}
.is-justify-self-end {
justify-self: end;
}

View file

@ -153,7 +153,7 @@
</div>
<div class="control" v-if="item.status != 'finished' || !item.filename">
<button class="button is-warning is-fullwidth is-small" v-tooltip="'Re-queue video'"
@click="reQueueItem(item)">
@click="(event) => reQueueItem(item, event)">
<span class="icon"><i class="fa-solid fa-rotate-right" /></span>
</button>
</div>
@ -283,7 +283,7 @@
</div>
<div class="columns is-mobile is-multiline">
<div class="column is-half-mobile" v-if="item.status != 'finished' || !item.filename">
<a class="button is-warning is-fullwidth" @click="reQueueItem(item)">
<a class="button is-warning is-fullwidth" @click="(event) => reQueueItem(item, event)">
<span class="icon-text is-block">
<span class="icon"><i class="fa-solid fa-rotate-right" /></span>
<span>Re-queue</span>
@ -371,13 +371,13 @@
import moment from 'moment'
import { useStorage } from '@vueuse/core'
import { makeDownload, formatBytes } from '~/utils/index'
import toast from '~/plugins/toast'
import { isEmbedable, getEmbedable } from '~/utils/embedable'
const emitter = defineEmits(['getInfo'])
const emitter = defineEmits(['getInfo', 'add_new'])
const config = useConfigStore()
const stateStore = useStateStore()
const socket = useSocketStore()
const toast = useToast()
const selectedElms = ref([])
const masterSelectAll = ref(false)
@ -624,9 +624,7 @@ const removeItem = item => {
})
}
const reQueueItem = item => {
socket.emit('item_delete', { id: item._id, remove_file: false })
const reQueueItem = (item, event = null) => {
let extras = {}
if (item.extras) {
@ -637,7 +635,7 @@ const reQueueItem = item => {
})
}
socket.emit('add_url', {
const item_req = {
url: item.url,
preset: item.preset,
folder: item.folder,
@ -645,7 +643,17 @@ const reQueueItem = item => {
template: item.template,
cli: item?.cli,
extras: extras
})
};
socket.emit('item_delete', { id: item._id, remove_file: false })
if (event && (event?.altKey && true === event?.altKey)) {
toast.info('Removed the item from history, and added it to the new download form.')
emitter('add_new', item_req)
return
}
socket.emit('add_url', item_req)
}
const pImg = e => e.target.naturalHeight > e.target.naturalWidth ? e.target.classList.add('image-portrait') : null

View file

@ -11,7 +11,7 @@
</label>
<div class="control">
<input type="text" class="input" id="url" placeholder="Video or playlist link"
:disabled="!socket.isConnected || addInProgress" v-model="url">
:disabled="!socket.isConnected || addInProgress" v-model="form.url">
</div>
<span class="help">
<span class="icon"><i class="fa-solid fa-info" /></span>
@ -29,7 +29,7 @@
<div class="control is-expanded">
<div class="select is-fullwidth">
<select id="preset" class="is-fullwidth"
:disabled="!socket.isConnected || addInProgress || hasFormatInConfig" v-model="selectedPreset"
:disabled="!socket.isConnected || addInProgress || hasFormatInConfig" v-model="form.preset"
v-tooltip.bottom="hasFormatInConfig ? 'Presets are disabled. Format key is present in the Command arguments for yt-dlp.' : ''">
<optgroup label="Custom presets" v-if="config?.presets.filter(p => !p?.default).length > 0">
<option v-for="item in filter_presets(false)" :key="item.name" :value="item.name">
@ -55,7 +55,7 @@
</a>
</div>
<div class="control is-expanded">
<input type="text" class="input is-fullwidth" id="path" v-model="downloadPath" placeholder="Default"
<input type="text" class="input is-fullwidth" id="path" v-model="form.folder" placeholder="Default"
:disabled="!socket.isConnected || addInProgress" list="folders">
</div>
</div>
@ -63,7 +63,7 @@
<div class="column">
<button type="submit" class="button is-primary"
:class="{ 'is-loading': !socket.isConnected || addInProgress }"
:disabled="!socket.isConnected || addInProgress || !url">
:disabled="!socket.isConnected || addInProgress || !form?.url">
<span class="icon"><i class="fa-solid fa-plus" /></span>
<span>Add</span>
</button>
@ -85,7 +85,7 @@
Output Template
</label>
<div class="control">
<input type="text" class="input" v-model="output_template" id="output_format"
<input type="text" class="input" v-model="form.template" id="output_format"
:disabled="!socket.isConnected || addInProgress"
placeholder="Uses default output template naming if empty.">
</div>
@ -104,7 +104,7 @@
Command arguments for yt-dlp
</label>
<div class="control">
<textarea class="textarea is-pre" v-model="ytdlp_cli" id="cli_options"
<textarea class="textarea is-pre" v-model="form.cli" id="cli_options"
:disabled="!socket.isConnected || addInProgress"
placeholder="command options to use, e.g. --no-embed-metadata --no-embed-thumbnail" />
</div>
@ -127,7 +127,7 @@
Cookies
</label>
<div class="control">
<textarea class="textarea is-pre" id="ytdlpCookies" v-model="ytdlpCookies"
<textarea class="textarea is-pre" id="ytdlpCookies" v-model="form.cookies"
:disabled="!socket.isConnected || addInProgress" />
</div>
<span class="help">
@ -140,21 +140,20 @@
</div>
</div>
<div class="column is-6-tablet is-4-mobile has-text-left">
<button type="button" class="button is-info" @click="emitter('getInfo', url)"
:class="{ 'is-loading': !socket.isConnected }" :disabled="!socket.isConnected || addInProgress || !url">
<button type="button" class="button is-info" @click="emitter('getInfo', form.url)"
:class="{ 'is-loading': !socket.isConnected }"
:disabled="!socket.isConnected || addInProgress || !form?.url">
<span class="icon"><i class="fa-solid fa-info" /></span>
<span>Information</span>
</button>
</div>
<div class="column is-6-tablet is-6-mobile has-text-right">
<div class="field">
<div class="field is-grouped is-justify-self-end">
<div class="control">
<button type="button" 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 Configuration</span>
<button type="button" class="button is-danger" @click="resetConfig"
:disabled="!socket.isConnected || form?.id" v-tooltip="'Reset local settings'">
<span class="icon"><i class="fa-solid fa-rotate-left" /></span>
<span>Reset</span>
</button>
</div>
</div>
@ -172,24 +171,35 @@
<script setup>
import { useStorage } from '@vueuse/core'
const emitter = defineEmits(['getInfo'])
const props = defineProps({
item: {
type: Object,
required: false,
default: () => { },
},
})
const emitter = defineEmits(['getInfo', 'clear_form'])
const config = useConfigStore()
const socket = useSocketStore()
const toast = useToast()
const selectedPreset = useStorage('selectedPreset', config.app.default_preset)
const ytdlpCookies = useStorage('ytdlp_cookies', '')
const ytdlp_cli = useStorage('ytdlp_cli', '')
const output_template = useStorage('output_template', null)
const downloadPath = useStorage('downloadPath', null)
const url = useStorage('downloadUrl', null)
const showAdvanced = useStorage('show_advanced', false)
const addInProgress = ref(false)
const form = useStorage('local_config', {
id: null,
url: '',
preset: config.app.default_preset,
cookies: '',
cli: '',
template: '',
folder: '',
})
const addDownload = async () => {
// -- send request to convert cli options to JSON
if (ytdlp_cli.value && '' !== ytdlp_cli.value) {
const options = await convertOptions(ytdlp_cli.value)
if (form.value?.cli && '' !== form.value.cli) {
const options = await convertOptions(form.value.cli)
if (null === options) {
return
}
@ -197,17 +207,17 @@ const addDownload = async () => {
addInProgress.value = true
url.value.split(',').forEach(url => {
form.value.url.split(',').forEach(url => {
if (!url.trim()) {
return
}
socket.emit('add_url', {
url: url,
preset: config.app.basic_mode ? config.app.default_preset : selectedPreset.value,
folder: config.app.basic_mode ? null : downloadPath.value,
cookies: config.app.basic_mode ? '' : ytdlpCookies.value,
template: config.app.basic_mode ? null : output_template.value,
cli: config.app.basic_mode ? null : ytdlp_cli.value,
preset: config.app.basic_mode ? config.app.default_preset : form.value.preset,
folder: config.app.basic_mode ? null : form.value.folder,
template: config.app.basic_mode ? null : form.value.template,
cookies: config.app.basic_mode ? '' : form.value.cookies,
cli: config.app.basic_mode ? null : form.value.cli,
})
})
}
@ -217,12 +227,16 @@ const resetConfig = () => {
return
}
selectedPreset.value = config.app.default_preset
ytdlpCookies.value = ''
ytdlp_cli.value = ''
output_template.value = null
url.value = null
downloadPath.value = null
form.value = {
id: null,
url: '',
preset: config.app.default_preset,
cookies: '',
cli: '',
template: '',
folder: '',
}
showAdvanced.value = false
toast.success('Local configuration has been reset.')
@ -238,7 +252,7 @@ const statusHandler = async stream => {
return
}
url.value = ''
form.value.url = ''
}
const unlockDownload = async stream => {
@ -246,7 +260,7 @@ const unlockDownload = async stream => {
if (!json?.data) {
return
}
if ("unlock" in json.data && json.data.unlock === true) {
if ("unlock" in json.data && true === json.data.unlock) {
addInProgress.value = false
}
}
@ -256,11 +270,11 @@ const convertOptions = async args => {
const response = await convertCliOptions(args)
if (response.output_template) {
output_template.value = response.output_template
form.value.template = response.output_template
}
if (response.download_path) {
downloadPath.value = response.download_path
form.value.folder = response.download_path
}
return response.opts
@ -271,11 +285,24 @@ const convertOptions = async args => {
return null;
}
onMounted(() => {
onMounted(async () => {
socket.on('status', statusHandler)
socket.on('error', unlockDownload)
if ('' === selectedPreset.value) {
selectedPreset.value = config.app.default_preset.value
await nextTick()
if ('' === form.value?.preset) {
form.value.preset = config.app.default_preset
}
if (props?.item) {
Object.keys(props.item).forEach(key => {
console.log(key, form.value[key], props.item[key])
if (key in form.value) {
form.value[key] = props.item[key]
}
})
emitter('clear_form');
}
})
@ -285,11 +312,11 @@ onUnmounted(() => {
})
const hasFormatInConfig = computed(() => {
if (!ytdlp_cli.value) {
if (!form?.value?.value) {
return false
}
return /(?<!\S)(-f|--format)(=|\s)(\S+)/.test(ytdlp_cli.value)
return /(?<!\S)(-f|--format)(=|\s)(\S+)/.test(form.value.cli)
})
const filter_presets = (flag = true) => config.presets.filter(item => item.default === flag)

View file

@ -43,11 +43,13 @@
</template>
<script setup>
defineProps({
const props = defineProps({
error: {
type: Object,
required: true
}
})
const showStacks = ref(false)
onMounted(() => console.error(props.error))
</script>

View file

@ -49,7 +49,7 @@
</p>
<p class="control" v-if="!config.app.basic_mode">
<button v-tooltip.bottom="'Toggle Add Form'" class="button is-primary has-tooltip-bottom"
<button v-tooltip.bottom="'Toggle new download form'" class="button is-primary has-tooltip-bottom"
@click="config.showForm = !config.showForm">
<span class="icon"><i class="fa-solid fa-plus" /></span>
</button>
@ -73,9 +73,10 @@
</div>
</div>
<NewDownload v-if="config.showForm || config.app.basic_mode" @getInfo="url => get_info = url" />
<NewDownload v-if="config.showForm || config.app.basic_mode" @getInfo="url => get_info = url" :item="item_form"
@clear_form="item_form = {}" />
<Queue @getInfo="url => get_info = url" />
<History @getInfo="url => get_info = url" />
<History @getInfo="url => get_info = url" @add_new="item => toNewDownload(item)" />
<GetInfo v-if="get_info" :link="get_info" @closeModel="get_info = ''" />
</div>
</template>
@ -94,6 +95,7 @@ const get_info = ref('')
const bg_enable = useStorage('random_bg', true)
const bg_opacity = useStorage('random_bg_opacity', 0.85)
const display_style = useStorage('display_style', 'cards')
const item_form = ref({})
onMounted(() => {
if (!config.app.ui_update_title) {
@ -159,4 +161,20 @@ watch(get_info, v => {
})
const changeDisplay = () => display_style.value = display_style.value === 'cards' ? 'list' : 'cards'
const toNewDownload = async (item) => {
if (!item) {
return
}
if (config.showForm) {
config.showForm = false
await nextTick()
}
item_form.value = item
await nextTick()
config.showForm = true
}
</script>