perf: Add download path management (#1359)

This commit is contained in:
Rémi Marseault 2023-11-26 16:39:06 +01:00 committed by GitHub
parent fdad814b1f
commit 988ecaaa03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 81 additions and 24 deletions

View file

@ -52,8 +52,12 @@ function deleteTorrents() {
dialogStore.createDialog(ConfirmDeleteDialog, { hashes: [...dashboardStore.selectedTorrents] })
}
function moveTorrents() {
dialogStore.createDialog(MoveTorrentDialog, { hashes: [...dashboardStore.selectedTorrents] })
function setDownloadPath() {
dialogStore.createDialog(MoveTorrentDialog, { hashes: [...dashboardStore.selectedTorrents], mode: 'dl' })
}
function setSavePath() {
dialogStore.createDialog(MoveTorrentDialog, { hashes: [...dashboardStore.selectedTorrents], mode: 'save' })
}
function renameTorrents() {
@ -126,9 +130,14 @@ const menuData = computed<TRCMenuEntry[]>(() => [
icon: 'mdi-head-cog',
children: [
{
text: t('dashboard.right_click.advanced.change_location'),
icon: 'mdi-folder',
action: moveTorrents
text: t('dashboard.right_click.advanced.download_path'),
icon: 'mdi-tray-arrow-down',
action: setDownloadPath
},
{
text: t('dashboard.right_click.advanced.save_path'),
icon: 'mdi-content-save',
action: setSavePath
},
{
text: t('dashboard.right_click.advanced.rename'),

View file

@ -1,17 +1,19 @@
<script setup lang="ts">
import { useDialog } from '@/composables'
import { useTorrentStore } from '@/stores'
import { useMaindataStore, useTorrentStore } from '@/stores'
import { computed, onBeforeMount, reactive, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { VForm } from 'vuetify/components'
const props = defineProps<{
guid: string
hashes: string[]
hashes: string[],
mode: 'dl' | 'save'
}>()
const { isOpened } = useDialog(props.guid)
const { t } = useI18n()
const maindataStore = useMaindataStore()
const torrentStore = useTorrentStore()
const form = ref<VForm>()
@ -20,16 +22,24 @@ const formData = reactive({
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 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() {
await form.value?.validate()
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()
}
@ -39,14 +49,14 @@ const close = () => {
}
onBeforeMount(() => {
formData.newPath = torrents.value[0]?.savePath || ''
formData.newPath = oldPath.value || ''
})
</script>
<template>
<v-dialog v-model="isOpened">
<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-form v-model="isFormValid" ref="form" @submit.prevent>
<v-text-field v-if="oldPath" :model-value="oldPath" disabled :label="$t('dialogs.moveTorrent.oldPath')" />

View file

@ -126,8 +126,8 @@ async function copyHash() {
await navigator.clipboard.writeText(props.torrent.hash)
}
function openMoveTorrentDialog() {
dialogStore.createDialog(MoveTorrentDialog, { hashes: [props.torrent.hash] })
function openMoveTorrentDialog(mode: 'dl' | 'save') {
dialogStore.createDialog(MoveTorrentDialog, { hashes: [props.torrent.hash], mode })
}
function openMoveTorrentFileDialog() {
@ -169,9 +169,15 @@ watch(
function handleKeyboardShortcuts(e: KeyboardEvent) {
if (dialogStore.hasActiveDialog) return false
if (e.key === 'd') {
e.preventDefault()
openMoveTorrentDialog('dl')
return true
}
if (e.key === 's') {
e.preventDefault()
openMoveTorrentDialog()
openMoveTorrentDialog('save')
return true
}
@ -210,7 +216,7 @@ onUnmounted(() => {
<v-row>
<v-col cols="12" md="6">
<v-row>
<v-col cols="4" md="4">
<v-col cols="4">
<v-progress-circular :color="torrentStateColor" :indeterminate="isFetchingMetadata" :size="100"
:model-value="torrent?.progress * 100 ?? 0" :width="15">
<template v-slot>
@ -220,7 +226,7 @@ onUnmounted(() => {
</template>
</v-progress-circular>
</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">
<span>{{ $t('torrentDetail.overview.waitingForMetadata') }}</span>
</div>
@ -259,9 +265,9 @@ onUnmounted(() => {
<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" />
<div>{{ $t('torrent.properties.download_path') }}:</div>
<div>{{ torrent.download_path }}</div>
<v-btn icon="mdi-pencil" color="accent" size="x-small" @click="openMoveTorrentDialog('dl')" />
</v-col>
<v-col cols="6">
<div>{{ $t('torrentDetail.overview.fileCount') }}:</div>
@ -271,7 +277,20 @@ onUnmounted(() => {
@click="openMoveTorrentFileDialog" />
</v-col>
</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 cols="12" md="6">
<v-row>
<v-col cols="6">

View file

@ -354,8 +354,22 @@ export class QBitApi {
return this.torrentAction('recheck', hashes)
}
async setTorrentLocation(hashes: string[], location: string): Promise<void> {
return this.torrentAction('setLocation', hashes, { location })
async setTorrentDownloadPath(hashes: string[], path: string): Promise<void> {
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> {

View file

@ -95,8 +95,13 @@ export const useTorrentStore = defineStore('torrents', () => {
await qbit.deleteTorrents(hashes, deleteWithFiles)
}
async function moveTorrents(hashes: string[], newPath: string) {
await qbit.setTorrentLocation(hashes, newPath)
async function moveTorrents(mode: 'dl' | 'save', hashes: string[], newPath: string) {
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) {