mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2024-11-28 13:08:53 +03:00
perf: Add download path management (#1359)
This commit is contained in:
parent
fdad814b1f
commit
988ecaaa03
5 changed files with 81 additions and 24 deletions
|
@ -52,8 +52,12 @@ function deleteTorrents() {
|
||||||
dialogStore.createDialog(ConfirmDeleteDialog, { hashes: [...dashboardStore.selectedTorrents] })
|
dialogStore.createDialog(ConfirmDeleteDialog, { hashes: [...dashboardStore.selectedTorrents] })
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveTorrents() {
|
function setDownloadPath() {
|
||||||
dialogStore.createDialog(MoveTorrentDialog, { hashes: [...dashboardStore.selectedTorrents] })
|
dialogStore.createDialog(MoveTorrentDialog, { hashes: [...dashboardStore.selectedTorrents], mode: 'dl' })
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSavePath() {
|
||||||
|
dialogStore.createDialog(MoveTorrentDialog, { hashes: [...dashboardStore.selectedTorrents], mode: 'save' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function renameTorrents() {
|
function renameTorrents() {
|
||||||
|
@ -126,9 +130,14 @@ const menuData = computed<TRCMenuEntry[]>(() => [
|
||||||
icon: 'mdi-head-cog',
|
icon: 'mdi-head-cog',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: t('dashboard.right_click.advanced.change_location'),
|
text: t('dashboard.right_click.advanced.download_path'),
|
||||||
icon: 'mdi-folder',
|
icon: 'mdi-tray-arrow-down',
|
||||||
action: moveTorrents
|
action: setDownloadPath
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: t('dashboard.right_click.advanced.save_path'),
|
||||||
|
icon: 'mdi-content-save',
|
||||||
|
action: setSavePath
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: t('dashboard.right_click.advanced.rename'),
|
text: t('dashboard.right_click.advanced.rename'),
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useDialog } from '@/composables'
|
import { useDialog } from '@/composables'
|
||||||
import { useTorrentStore } from '@/stores'
|
import { useMaindataStore, useTorrentStore } from '@/stores'
|
||||||
import { computed, onBeforeMount, reactive, ref } from 'vue'
|
import { computed, onBeforeMount, reactive, ref } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { VForm } from 'vuetify/components'
|
import { VForm } from 'vuetify/components'
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
guid: string
|
guid: string
|
||||||
hashes: string[]
|
hashes: string[],
|
||||||
|
mode: 'dl' | 'save'
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { isOpened } = useDialog(props.guid)
|
const { isOpened } = useDialog(props.guid)
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const maindataStore = useMaindataStore()
|
||||||
const torrentStore = useTorrentStore()
|
const torrentStore = useTorrentStore()
|
||||||
|
|
||||||
const form = ref<VForm>()
|
const form = ref<VForm>()
|
||||||
|
@ -20,16 +22,24 @@ const formData = reactive({
|
||||||
newPath: ''
|
newPath: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
const rules = [(v: string) => !!v || t('dialogs.moveTorrent.required'), (v: string) => v !== oldPath.value || t('dialogs.moveTorrent.samePath')]
|
const rules = [(v: string) => !!v || t('dialogs.moveTorrent.required')]
|
||||||
|
|
||||||
const torrents = computed(() => props.hashes.map(torrentStore.getTorrentByHash))
|
const torrents = computed(() => props.hashes.map(torrentStore.getTorrentByHash))
|
||||||
const oldPath = computed(() => torrents.value[0]?.savePath)
|
const oldPath = computed(() => {
|
||||||
|
switch (props.mode) {
|
||||||
|
case 'dl':
|
||||||
|
return torrents.value[0]?.download_path
|
||||||
|
case 'save':
|
||||||
|
return torrents.value[0]?.savePath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
async function submit() {
|
async function submit() {
|
||||||
await form.value?.validate()
|
await form.value?.validate()
|
||||||
if (!isFormValid.value) return
|
if (!isFormValid.value) return
|
||||||
|
|
||||||
await torrentStore.moveTorrents(props.hashes, formData.newPath)
|
await maindataStore.toggleAutoTmm(props.hashes, false)
|
||||||
|
await torrentStore.moveTorrents(props.mode, props.hashes, formData.newPath)
|
||||||
|
|
||||||
close()
|
close()
|
||||||
}
|
}
|
||||||
|
@ -39,14 +49,14 @@ const close = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
formData.newPath = torrents.value[0]?.savePath || ''
|
formData.newPath = oldPath.value || ''
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-dialog v-model="isOpened">
|
<v-dialog v-model="isOpened">
|
||||||
<v-card>
|
<v-card>
|
||||||
<v-card-title>{{ $t('dialogs.moveTorrent.title') }}</v-card-title>
|
<v-card-title>{{ $t(`dialogs.moveTorrent.${mode}.title`) }}</v-card-title>
|
||||||
<v-card-text>
|
<v-card-text>
|
||||||
<v-form v-model="isFormValid" ref="form" @submit.prevent>
|
<v-form v-model="isFormValid" ref="form" @submit.prevent>
|
||||||
<v-text-field v-if="oldPath" :model-value="oldPath" disabled :label="$t('dialogs.moveTorrent.oldPath')" />
|
<v-text-field v-if="oldPath" :model-value="oldPath" disabled :label="$t('dialogs.moveTorrent.oldPath')" />
|
||||||
|
|
|
@ -126,8 +126,8 @@ async function copyHash() {
|
||||||
await navigator.clipboard.writeText(props.torrent.hash)
|
await navigator.clipboard.writeText(props.torrent.hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
function openMoveTorrentDialog() {
|
function openMoveTorrentDialog(mode: 'dl' | 'save') {
|
||||||
dialogStore.createDialog(MoveTorrentDialog, { hashes: [props.torrent.hash] })
|
dialogStore.createDialog(MoveTorrentDialog, { hashes: [props.torrent.hash], mode })
|
||||||
}
|
}
|
||||||
|
|
||||||
function openMoveTorrentFileDialog() {
|
function openMoveTorrentFileDialog() {
|
||||||
|
@ -169,9 +169,15 @@ watch(
|
||||||
function handleKeyboardShortcuts(e: KeyboardEvent) {
|
function handleKeyboardShortcuts(e: KeyboardEvent) {
|
||||||
if (dialogStore.hasActiveDialog) return false
|
if (dialogStore.hasActiveDialog) return false
|
||||||
|
|
||||||
|
if (e.key === 'd') {
|
||||||
|
e.preventDefault()
|
||||||
|
openMoveTorrentDialog('dl')
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
if (e.key === 's') {
|
if (e.key === 's') {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
openMoveTorrentDialog()
|
openMoveTorrentDialog('save')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +216,7 @@ onUnmounted(() => {
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="12" md="6">
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="4" md="4">
|
<v-col cols="4">
|
||||||
<v-progress-circular :color="torrentStateColor" :indeterminate="isFetchingMetadata" :size="100"
|
<v-progress-circular :color="torrentStateColor" :indeterminate="isFetchingMetadata" :size="100"
|
||||||
:model-value="torrent?.progress * 100 ?? 0" :width="15">
|
:model-value="torrent?.progress * 100 ?? 0" :width="15">
|
||||||
<template v-slot>
|
<template v-slot>
|
||||||
|
@ -220,7 +226,7 @@ onUnmounted(() => {
|
||||||
</template>
|
</template>
|
||||||
</v-progress-circular>
|
</v-progress-circular>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="8" md="8" class="d-flex flex-column align-center justify-center">
|
<v-col cols="8" class="d-flex flex-column align-center justify-center">
|
||||||
<div v-if="isFetchingMetadata">
|
<div v-if="isFetchingMetadata">
|
||||||
<span>{{ $t('torrentDetail.overview.waitingForMetadata') }}</span>
|
<span>{{ $t('torrentDetail.overview.waitingForMetadata') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -259,9 +265,9 @@ onUnmounted(() => {
|
||||||
|
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="6">
|
<v-col cols="6">
|
||||||
<div>{{ $t('torrent.properties.save_path') }}:</div>
|
<div>{{ $t('torrent.properties.download_path') }}:</div>
|
||||||
<div>{{ torrent.savePath }}</div>
|
<div>{{ torrent.download_path }}</div>
|
||||||
<v-btn icon="mdi-pencil" color="accent" size="x-small" @click="openMoveTorrentDialog" />
|
<v-btn icon="mdi-pencil" color="accent" size="x-small" @click="openMoveTorrentDialog('dl')" />
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="6">
|
<v-col cols="6">
|
||||||
<div>{{ $t('torrentDetail.overview.fileCount') }}:</div>
|
<div>{{ $t('torrentDetail.overview.fileCount') }}:</div>
|
||||||
|
@ -271,7 +277,20 @@ onUnmounted(() => {
|
||||||
@click="openMoveTorrentFileDialog" />
|
@click="openMoveTorrentFileDialog" />
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="6">
|
||||||
|
<div>{{ $t('torrent.properties.save_path') }}:</div>
|
||||||
|
<div>{{ torrent.savePath }}</div>
|
||||||
|
<v-btn icon="mdi-pencil" color="accent" size="x-small" @click="openMoveTorrentDialog('save')" />
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="6">
|
||||||
|
<div>{{ $t('torrent.properties.content_path') }}:</div>
|
||||||
|
<div>{{ torrent.content_path }}</div>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
</v-col>
|
</v-col>
|
||||||
|
|
||||||
<v-col cols="12" md="6">
|
<v-col cols="12" md="6">
|
||||||
<v-row>
|
<v-row>
|
||||||
<v-col cols="6">
|
<v-col cols="6">
|
||||||
|
|
|
@ -354,8 +354,22 @@ export class QBitApi {
|
||||||
return this.torrentAction('recheck', hashes)
|
return this.torrentAction('recheck', hashes)
|
||||||
}
|
}
|
||||||
|
|
||||||
async setTorrentLocation(hashes: string[], location: string): Promise<void> {
|
async setTorrentDownloadPath(hashes: string[], path: string): Promise<void> {
|
||||||
return this.torrentAction('setLocation', hashes, { location })
|
const params = {
|
||||||
|
id: hashes.length ? hashes.join('|') : 'all',
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.execute(`/torrents/setDownloadPath`, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
async setTorrentSavePath(hashes: string[], path: string): Promise<void> {
|
||||||
|
const params = {
|
||||||
|
id: hashes.length ? hashes.join('|') : 'all',
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.execute(`/torrents/setSavePath`, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
async addTorrentTrackers(hash: string, trackers: string): Promise<void> {
|
async addTorrentTrackers(hash: string, trackers: string): Promise<void> {
|
||||||
|
|
|
@ -95,8 +95,13 @@ export const useTorrentStore = defineStore('torrents', () => {
|
||||||
await qbit.deleteTorrents(hashes, deleteWithFiles)
|
await qbit.deleteTorrents(hashes, deleteWithFiles)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function moveTorrents(hashes: string[], newPath: string) {
|
async function moveTorrents(mode: 'dl' | 'save', hashes: string[], newPath: string) {
|
||||||
await qbit.setTorrentLocation(hashes, newPath)
|
switch (mode) {
|
||||||
|
case 'dl':
|
||||||
|
return await qbit.setTorrentDownloadPath(hashes, newPath)
|
||||||
|
case 'save':
|
||||||
|
return await qbit.setTorrentSavePath(hashes, newPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function addTorrents(torrents: File[], urls: string, payload: AddTorrentPayload) {
|
async function addTorrents(torrents: File[], urls: string, payload: AddTorrentPayload) {
|
||||||
|
|
Loading…
Reference in a new issue