diff --git a/src/components/Dashboard/TRC/RightClickMenu.vue b/src/components/Dashboard/TRC/RightClickMenu.vue index d5b0fb41..2d58ba47 100644 --- a/src/components/Dashboard/TRC/RightClickMenu.vue +++ b/src/components/Dashboard/TRC/RightClickMenu.vue @@ -3,6 +3,7 @@ import RightClickMenuEntry from '@/components/Dashboard/TRC/RightClickMenuEntry. import ConfirmDeleteDialog from '@/components/Dialogs/ConfirmDeleteDialog.vue' import MoveTorrentDialog from '@/components/Dialogs/MoveTorrentDialog.vue' import RenameTorrentDialog from '@/components/Dialogs/RenameTorrentDialog.vue' +import SpeedLimitDialog from '@/components/Dialogs/SpeedLimitDialog.vue' import { useDashboardStore } from '@/stores/dashboard' import { useDialogStore } from '@/stores/dialog' import { useMaindataStore } from '@/stores/maindata' @@ -93,6 +94,18 @@ async function copyValue(valueToCopy: string) { await navigator.clipboard.writeText(valueToCopy) } +function setDownloadLimit() { + dialogStore.createDialog(SpeedLimitDialog, { hash: hash.value, mode: 'download' }) +} + +function setUploadLimit() { + dialogStore.createDialog(SpeedLimitDialog, { hash: hash.value, mode: 'upload' }) +} + +function setShareLimit() { + //TODO: dialogStore.createDialog(ShareLimitDialog, { hash: hash.value }) +} + async function exportTorrents() { hashes.value.forEach(hash => { maindataStore.exportTorrent(hash).then(blob => { @@ -208,23 +221,18 @@ const menuData = computed<TRCMenuEntry[]>(() => [ { text: t('dashboard.right_click.speed_limit.download'), icon: 'mdi-download', - action: () => { - /* TODO */ - } + action: setDownloadLimit }, { text: t('dashboard.right_click.speed_limit.upload'), icon: 'mdi-upload', - action: () => { - /* TODO */ - } + action: setUploadLimit }, { text: t('dashboard.right_click.speed_limit.share'), icon: 'mdi-account-group', - action: () => { - /* TODO */ - } + hidden: true, + action: setShareLimit } ] }, diff --git a/src/components/Dialogs/SpeedLimitDialog.vue b/src/components/Dialogs/SpeedLimitDialog.vue new file mode 100644 index 00000000..3385cc15 --- /dev/null +++ b/src/components/Dialogs/SpeedLimitDialog.vue @@ -0,0 +1,78 @@ +<script setup lang="ts"> +import { useDialog } from '@/composables' +import { useMaindataStore } from '@/stores/maindata.ts' +import { onBeforeMount, ref } from 'vue' + +const props = defineProps<{ + guid: string + hash: string + mode: 'download' | 'upload' +}>() + +const { isOpened } = useDialog(props.guid) +const maindataStore = useMaindataStore() + +const isFormValid = ref(false) +const value = ref(0) + +function close() { + isOpened.value = false +} + +async function submit() { + const formattedValue = Math.max(0, value.value) * 1000 + switch (props.mode) { + case 'download': + await maindataStore.setDownloadLimit(formattedValue, [props.hash]) + break + case 'upload': + await maindataStore.setUploadLimit(formattedValue, [props.hash]) + break + } + close() +} + +onBeforeMount(async () => { + const torrent = maindataStore.getTorrentByHash(props.hash) + if (!torrent) { + return close() + } + + switch (props.mode) { + case 'download': + value.value = Math.max(0, Math.round(torrent.dl_limit / 1000)) + break + case 'upload': + value.value = Math.max(0, Math.round(torrent.up_limit / 1000)) + break + } +}) +</script> + +<template> + <v-dialog v-model="isOpened"> + <v-card :title="$t(`dialogs.speed_limit.${mode}`)"> + <v-card-text> + <v-form v-model="isFormValid" @submit.prevent @keydown.enter.prevent="submit"> + <v-text-field v-model="value" + type="number" + autofocus + clearable + :label="$t('dialogs.speed_limit.label')" + prepend-inner-icon="mdi-speedometer" + suffix="kB/s" + @keydown.enter.prevent="submit" /> + </v-form> + </v-card-text> + <v-card-actions> + <v-spacer /> + <v-btn color="error" @click="close">{{ $t('common.cancel') }}</v-btn> + <v-btn color="accent" :disabled="!isFormValid" @click="submit">{{ $t('common.save') }}</v-btn> + </v-card-actions> + </v-card> + </v-dialog> +</template> + +<style scoped> + +</style> \ No newline at end of file diff --git a/src/locales/en.json b/src/locales/en.json index f7b4ded9..5f271998 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -545,6 +545,11 @@ "url": "Engine URL", "actions": "Actions" } + }, + "speed_limit": { + "download": "Set Download Speed Limit", + "upload": "Set Upload Speed Limit", + "label": "Speed Limit" } }, "settings": { diff --git a/src/services/qbit.ts b/src/services/qbit.ts index 8fdab8e6..44bf97a7 100644 --- a/src/services/qbit.ts +++ b/src/services/qbit.ts @@ -338,10 +338,11 @@ export class QBitApi { return this.execute('/transfer/setUploadLimit', data) } - async setShareLimit(hashes: string[], ratioLimit: number, seedingTimeLimit: number): Promise<void> { + async setShareLimit(hashes: string[], ratioLimit: number, seedingTimeLimit: number, inactiveSeedingTimeLimit: number): Promise<void> { return this.torrentAction('setShareLimits', hashes, { ratioLimit, - seedingTimeLimit + seedingTimeLimit, + inactiveSeedingTimeLimit }) } diff --git a/src/stores/maindata.ts b/src/stores/maindata.ts index d2ac3a6c..2a637f2b 100644 --- a/src/stores/maindata.ts +++ b/src/stores/maindata.ts @@ -303,6 +303,14 @@ export const useMaindataStore = defineStore('maindata', () => { return await qbit.exportTorrent(hash) } + async function setDownloadLimit(limit: number, hashes: string[]) { + return await qbit.setDownloadLimit(hashes, limit) + } + + async function setUploadLimit(limit: number, hashes: string[]) { + return await qbit.setUploadLimit(hashes, limit) + } + return { categories, isUpdatingMaindata, @@ -354,7 +362,9 @@ export const useMaindataStore = defineStore('maindata', () => { addTorrentPeers, banPeers, setTorrentFilePriority, - exportTorrent + exportTorrent, + setDownloadLimit, + setUploadLimit } }, { persist: {