ytptube/frontend/src/components/Form-Add.vue
2023-12-29 15:39:13 +03:00

251 lines
9.2 KiB
Vue

<template>
<main class="columns mt-2">
<div class="column">
<div class="box">
<div class="columns is-multiline">
<div class="column is-12">
<div class="control has-icons-left">
<input type="url" class="input" id="url" placeholder="Video or playlist link"
:disabled="!config.isConnected || addInProgress" v-model="url">
<span class="icon is-small is-left">
<font-awesome-icon icon="fa-solid fa-link" />
</span>
</div>
</div>
<div class="column is-3">
<div class="field has-addons">
<div class="control">
<a href="#" class="button is-static">Format</a>
</div>
<div class="control is-expanded">
<div class="select is-fullwidth">
<select id="format" class="is-fullwidth" :disabled="!config.isConnected" v-model="selectedFormat"
@change="updateQualities">
<option v-for="item in downloadFormats" :key="item.id" :value="item.id">
{{ item.text }}
</option>
</select>
</div>
</div>
</div>
</div>
<div class="column is-3">
<div class="field has-addons">
<div class="control">
<a href="#" class="button is-static">Quality</a>
</div>
<div class="control is-expanded">
<div class="select is-fullwidth">
<select id="quality" class="is-fullwidth" v-model="selectedQuality" :disabled="!config.isConnected">
<option v-for="item in qualities" :key="item.id" :value="item.id">{{ item.text }}</option>
</select>
</div>
</div>
</div>
</div>
<div class="column is-4">
<div class="field has-addons" :data-tooltip="'Download path relative to ' + config.app.download_path">
<div class="control">
<a href="#" class="button is-static">Download Path</a>
</div>
<div class="control is-expanded">
<input type="text" class="input is-fullwidth" id="path" v-model="downloadPath" placeholder="Default"
:disabled="!config.isConnected">
</div>
</div>
</div>
<div class="column">
<button type="submit" class="button is-primary" @click="addDownload"
:class="{ 'is-loading': !config.isConnected || addInProgress }"
:disabled="!config.isConnected || addInProgress || !url">
<span class="icon">
<font-awesome-icon icon="fa-solid fa-plus" />
</span>
<span>Add Link</span>
</button>
</div>
<div class="column">
<button type="submit" class="button is-info" @click="showAdvanced = !showAdvanced"
data-tooltip="Show advanced options" :class="{ 'is-loading': !config.isConnected }"
:disabled="!config.isConnected">
<span class="icon">
<font-awesome-icon icon="fa-solid fa-cog" />
</span>
</button>
</div>
</div>
<div class="columns is-multiline" v-if="showAdvanced">
<div class="column is-12">
<div class="field">
<label class="label is-inline" for="output_format"
:data-tooltip="'Default Format: ' + config.app.output_template">
Output Format
</label>
<div class="control">
<input type="text" class="input" v-model="output_template" id="output_format"
placeholder="Uses default format if non is given.">
</div>
<span class="subtitle is-6 has-text-info">
All format options can be found at <a class="has-text-danger" target="_blank" referrerpolicy="no-referrer"
href="https://github.com/yt-dlp/yt-dlp#output-template">this page</a>.
</span>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label is-inline" for="ytdlpConfig"
data-tooltip="Extends current global yt-dlp config. (JSON)">
JSON yt-dlp config
</label>
<div class="control">
<textarea class="textarea" id="ytdlpConfig" v-model="ytdlpConfig"
:disabled="!config.isConnected"></textarea>
</div>
<span class="subtitle is-6 has-text-info">
Some config fields are ignored like cookiefile, path, and output_format etc.
Available option can be found at <a class="has-text-danger" target="_blank" referrerpolicy="no-referrer"
href="https://github.com/yt-dlp/yt-dlp/blob/a0b19d319a6ce8b7059318fa17a34b144fde1785/yt_dlp/YoutubeDL.py#L194">this
page</a>.
</span>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label is-inline" for="ytdlpCookies" data-tooltip="JSON exported cookies for downloading.">
yt-dlp Cookies
</label>
<div class="control">
<textarea class="textarea" id="ytdlpCookies" v-model="ytdlpCookies"
:disabled="!config.isConnected"></textarea>
</div>
<span class="subtitle is-6 has-text-info">
Use something like <a class="has-text-danger" href="https://github.com/jrie/flagCookies">flagCookies</a>
to extract cookies as JSON string.
</span>
</div>
</div>
<div class="column is-12 has-text-right">
<div class="field">
<div class="control">
<button type="submit" class="button is-danger" @click="resetConfig" :disabled="!config.isConnected"
data-tooltip="This configuration are stored locally in your browser.">
<span class="icon">
<font-awesome-icon icon="fa-solid fa-trash" />
</span>
<span>Reset Local Configuration</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</template>
<script setup>
import { defineEmits, defineProps, onMounted, ref } from 'vue'
import { downloadFormats } from '../formats.js'
import { useStorage, useEventBus } from '@vueuse/core'
const bus = useEventBus('item_added', 'task_edit','show_form');
const emits = defineEmits(['addItem']);
const selectedFormat = useStorage('selectedFormat', 'any')
const selectedQuality = useStorage('selectedQuality', '')
const ytdlpConfig = useStorage('ytdlp_config', '')
const ytdlpCookies = useStorage('ytdlp_cookies', '')
const output_template = useStorage('output_template', null)
const downloadPath = useStorage('downloadPath', null)
const url = useStorage('downloadUrl', null)
const showAdvanced = useStorage('show_advanced', false)
const qualities = ref([])
const addInProgress = ref(false)
const updateQualities = () => {
for (const key in downloadFormats) {
const item = downloadFormats[key];
if (item.id === selectedFormat.value) {
qualities.value = item.qualities;
break;
}
}
selectedQuality.value = qualities.value[0].id;
}
defineProps({
config: {
type: Object,
required: true
}
});
onMounted(() => {
updateQualities();
})
const addDownload = () => {
addInProgress.value = true;
emits('addItem', {
url: url.value,
format: selectedFormat.value,
quality: selectedQuality.value,
folder: downloadPath.value,
ytdlp_config: ytdlpConfig.value,
ytdlp_cookies: ytdlpCookies.value,
output_template: output_template.value,
});
}
const resetConfig = () => {
if (!confirm('Are you sure you want to reset the local configuration? this will NOT delete any downloads or server configuration.')) {
return;
}
selectedFormat.value = 'any';
selectedQuality.value = '';
ytdlpConfig.value = '';
ytdlpCookies.value = '';
output_template.value = null;
url.value = '';
downloadPath.value = '';
}
bus.on((event, data) => {
const allowedEvents = ['item_added', 'task_edit'];
if (!allowedEvents.includes(event)) {
return;
}
if (event === 'item_added') {
if (data?.status === 'ok') {
url.value = '';
}
url.value = data.url;
addInProgress.value = false;
}
if ('task_edit' === event) {
console.log(data);
selectedFormat.value = data.format;
selectedQuality.value = data.quality;
if (typeof data.ytdlp_config === 'object') {
data.ytdlp_config = JSON.stringify(data.ytdlp_config);
}
if (typeof data.ytdlp_cookies === 'object') {
data.ytdlp_cookies = JSON.stringify(data.ytdlp_cookies);
}
ytdlpConfig.value = data.ytdlp_config;
ytdlpCookies.value = data.ytdlp_cookies;
output_template.value = data.output_template;
downloadPath.value = data.folder;
url.value = data.url;
showAdvanced.value = true;
bus.emit('show_form');
}
});
</script>