mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2025-04-01 14:24:12 +03:00
496 lines
16 KiB
Vue
496 lines
16 KiB
Vue
<template>
|
|
<v-list v-if="torrent" class="noselect">
|
|
<v-list-item link @click="resume">
|
|
<v-icon>{{ mdiPlay }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.resume') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item link @click="forceResume">
|
|
<v-icon>{{ mdiFastForward }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.forceResume') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item link @click="pause">
|
|
<v-icon>{{ mdiPause }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('pause') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
|
|
<v-divider />
|
|
<v-list-item link @click="removeTorrent">
|
|
<v-icon color="red">
|
|
{{ mdiDelete }}
|
|
</v-icon>
|
|
<v-list-item-title class="ml-2 red--text list-item__title">
|
|
{{ $t('delete') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-divider />
|
|
<v-menu :open-on-hover="!touchmode" top offset-x :transition="isRightside ? 'slide-x-reverse-transition' : 'slide-x-transition'" :left="isRightside">
|
|
<template #activator="{ on }">
|
|
<v-list-item link v-on="on">
|
|
<v-icon>{{ mdiHeadCog }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.advanced') | titleCase }}
|
|
</v-list-item-title>
|
|
<v-list-item-action>
|
|
<v-icon>{{ mdiChevronRight }}</v-icon>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item link @click="location">
|
|
<v-icon>{{ mdiFolder }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.changeLocation') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item v-if="!multiple" link @click="rename">
|
|
<v-icon>{{ mdiRenameBox }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.rename') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item link @click="recheck">
|
|
<v-icon>{{ mdiPlaylistCheck }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.forceRecheck') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item link @click="reannounce">
|
|
<v-icon>{{ mdiBullhorn }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.forceReannounce') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item v-if="!multiple" link @click="toggleSeq">
|
|
<v-icon>
|
|
{{ torrent.seq_dl ? mdiCheckboxMarked : mdiCheckboxBlankOutline }}
|
|
</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.sequentialDownload') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item v-if="!multiple" link @click="toggleFL">
|
|
<v-icon>
|
|
{{ torrent.f_l_piece_prio ? mdiCheckboxMarked : mdiCheckboxBlankOutline }}
|
|
</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.firstLastPriority') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item v-if="!multiple" link @click="toggleAutoTMM">
|
|
<v-icon>
|
|
{{ torrent.auto_tmm ? mdiCheckboxMarked : mdiCheckboxBlankOutline }}
|
|
</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.advanced.automaticTorrentManagement') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
<v-menu :open-on-hover="!touchmode" top offset-x :transition="isRightside ? 'slide-x-reverse-transition' : 'slide-x-transition'" :left="isRightside">
|
|
<template #activator="{ on }">
|
|
<v-list-item link v-on="on">
|
|
<v-icon>{{ mdiPriorityHigh }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.prio.prio') | titleCase }}
|
|
</v-list-item-title>
|
|
<v-list-item-action>
|
|
<v-icon>{{ mdiChevronRight }}</v-icon>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item v-for="(item, index) in priority_options" :key="index" link @click="setPriority(item.action)">
|
|
<v-icon>{{ item.icon }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.prio.' + item.name) | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
<v-menu
|
|
v-if="availableTags.length > 0"
|
|
:open-on-hover="!touchmode"
|
|
top
|
|
offset-x
|
|
:transition="isRightside ? 'slide-x-reverse-transition' : 'slide-x-transition'"
|
|
:left="isRightside"
|
|
>
|
|
<template #activator="{ on }">
|
|
<v-list-item link v-on="on">
|
|
<v-icon>{{ mdiTag }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.tags') | titleCase }}
|
|
</v-list-item-title>
|
|
<v-list-item-action>
|
|
<v-icon>{{ mdiChevronRight }}</v-icon>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item v-for="(tag, index) in availableTags" :key="index" link @click="setTag(tag)">
|
|
<v-icon>
|
|
{{ torrent.tags !== null && torrent.tags.includes(tag) ? mdiCheckboxMarked : mdiCheckboxBlankOutline }}
|
|
</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ tag }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
<v-list-item v-else>
|
|
<v-icon>{{ mdiTagOff }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.notags') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-menu
|
|
v-if="availableCategories.length > 1"
|
|
:open-on-hover="!touchmode"
|
|
top
|
|
offset-x
|
|
:transition="isRightside ? 'slide-x-reverse-transition' : 'slide-x-transition'"
|
|
:left="isRightside"
|
|
>
|
|
<template #activator="{ on }">
|
|
<v-list-item link v-on="on">
|
|
<v-icon>{{ mdiLabel }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.category') | titleCase }}
|
|
</v-list-item-title>
|
|
<v-list-item-action>
|
|
<v-icon>{{ mdiChevronRight }}</v-icon>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item v-for="(item, index) in availableCategories" :key="index" link @click="setCategory(item.value)">
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ item.name }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
<v-list-item v-else>
|
|
<v-icon>{{ mdiLabelOff }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.nocategory') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-menu v-if="!multiple" :open-on-hover="!touchmode" top offset-x :transition="isRightside ? 'slide-x-reverse-transition' : 'slide-x-transition'" :left="isRightside">
|
|
<template #activator="{ on }">
|
|
<v-list-item link v-on="on">
|
|
<v-icon>{{ mdiSpeedometerSlow }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.limit') | titleCase }}
|
|
</v-list-item-title>
|
|
<v-list-item-action>
|
|
<v-icon>{{ mdiChevronRight }}</v-icon>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item @click="setLimit('download')">
|
|
<v-icon>{{ mdiChevronDown }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('download') }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="setLimit('upload')">
|
|
<v-icon>{{ mdiChevronUp }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('upload') }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="setShareLimit()">
|
|
<v-icon>{{ mdiAccountGroup }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('share') }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
<v-menu v-if="!multiple" :open-on-hover="!touchmode" top offset-x :transition="isRightside ? 'slide-x-reverse-transition' : 'slide-x-transition'" :left="isRightside">
|
|
<template #activator="{ on }">
|
|
<v-list-item link v-on="on">
|
|
<v-icon>{{ mdiContentCopy }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.copy') | titleCase }}
|
|
</v-list-item-title>
|
|
<v-list-item-action>
|
|
<v-icon>{{ mdiChevronRight }}</v-icon>
|
|
</v-list-item-action>
|
|
</v-list-item>
|
|
</template>
|
|
<v-list>
|
|
<v-list-item @click="copyToClipBoard(torrent.name)">
|
|
<v-icon>{{ mdiContentCopy }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('name') }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="copyToClipBoard(torrent.hash)">
|
|
<v-icon>{{ mdiContentCopy }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('hash') }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-list-item @click="copyToClipBoard(torrent.magnet)">
|
|
<v-icon>{{ mdiMagnet }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('magnet') }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</v-menu>
|
|
<v-list-item link @click="exportTorrents">
|
|
<v-icon>{{ multiple ? mdiDownloadMultiple : mdiDownload }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $tc('rightClick.export', multiple ? 2 : 1) | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
<v-divider v-if="!multiple" />
|
|
<v-list-item v-if="!multiple" link @click="showInfo">
|
|
<v-icon>{{ mdiInformation }}</v-icon>
|
|
<v-list-item-title class="ml-2 list-item__title">
|
|
{{ $t('rightClick.info') | titleCase }}
|
|
</v-list-item-title>
|
|
</v-list-item>
|
|
</v-list>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters, mapState } from 'vuex'
|
|
import qbit from '@/services/qbit'
|
|
import { General, TorrentSelect } from '@/mixins'
|
|
import {
|
|
mdiAccountGroup,
|
|
mdiArrowDown,
|
|
mdiArrowUp,
|
|
mdiBullhorn,
|
|
mdiCheckboxBlankOutline,
|
|
mdiCheckboxMarked,
|
|
mdiChevronDown,
|
|
mdiChevronRight,
|
|
mdiChevronUp,
|
|
mdiContentCopy,
|
|
mdiDelete,
|
|
mdiFastForward,
|
|
mdiFolder,
|
|
mdiHeadCog,
|
|
mdiInformation,
|
|
mdiLabel,
|
|
mdiLabelOff,
|
|
mdiMagnet,
|
|
mdiPause,
|
|
mdiPlay,
|
|
mdiPlaylistCheck,
|
|
mdiPriorityHigh,
|
|
mdiPriorityLow,
|
|
mdiRenameBox,
|
|
mdiSelect,
|
|
mdiSpeedometerSlow,
|
|
mdiTag,
|
|
mdiTagOff,
|
|
mdiDownload,
|
|
mdiDownloadMultiple
|
|
} from '@mdi/js'
|
|
|
|
export default {
|
|
name: 'TorrentRightClickMenu',
|
|
mixins: [General, TorrentSelect],
|
|
props: {
|
|
hash: String,
|
|
touchmode: Boolean,
|
|
x: Number
|
|
},
|
|
data() {
|
|
return {
|
|
isRightside: true,
|
|
priority_options: [
|
|
{ name: 'top', icon: mdiPriorityHigh, action: 'topPrio' },
|
|
{ name: 'increase', icon: mdiArrowUp, action: 'increasePrio' },
|
|
{ name: 'decrease', icon: mdiArrowDown, action: 'decreasePrio' },
|
|
{ name: 'bottom', icon: mdiPriorityLow, action: 'bottomPrio' }
|
|
],
|
|
mdiDelete,
|
|
mdiPlay,
|
|
mdiPause,
|
|
mdiSelect,
|
|
mdiFastForward,
|
|
mdiFolder,
|
|
mdiRenameBox,
|
|
mdiInformation,
|
|
mdiMagnet,
|
|
mdiAccountGroup,
|
|
mdiPlaylistCheck,
|
|
mdiPriorityHigh,
|
|
mdiBullhorn,
|
|
mdiChevronRight,
|
|
mdiLabel,
|
|
mdiLabelOff,
|
|
mdiTag,
|
|
mdiTagOff,
|
|
mdiHeadCog,
|
|
mdiCheckboxMarked,
|
|
mdiCheckboxBlankOutline,
|
|
mdiSpeedometerSlow,
|
|
mdiChevronUp,
|
|
mdiChevronDown,
|
|
mdiContentCopy,
|
|
mdiDownload,
|
|
mdiDownloadMultiple
|
|
}
|
|
},
|
|
computed: {
|
|
...mapGetters(['getCategories', 'getAvailableTags', 'getTorrent']),
|
|
...mapState(['selected_torrents']),
|
|
availableCategories() {
|
|
const categories = [{ name: 'None', value: '' }]
|
|
categories.push(
|
|
...this.getCategories().map(c => {
|
|
return { name: c.name, value: c.name }
|
|
})
|
|
)
|
|
|
|
return categories
|
|
},
|
|
availableTags() {
|
|
return this.getAvailableTags()
|
|
},
|
|
hashes() {
|
|
if (this.multiple) return this.selected_torrents
|
|
|
|
return [this.torrent.hash]
|
|
},
|
|
multiple() {
|
|
return this.selected_torrents.length > 1
|
|
},
|
|
torrent() {
|
|
return this.getTorrent(this.hash)
|
|
}
|
|
},
|
|
watch: {
|
|
x() {
|
|
this.detectRightside()
|
|
}
|
|
},
|
|
mounted() {
|
|
this.detectRightside()
|
|
},
|
|
methods: {
|
|
detectRightside() {
|
|
this.isRightside = document.documentElement.clientWidth < this.x + 380
|
|
},
|
|
resume() {
|
|
qbit.resumeTorrents(this.hashes)
|
|
},
|
|
pause() {
|
|
qbit.pauseTorrents(this.hashes)
|
|
},
|
|
location() {
|
|
this.createModal('ChangeLocationModal', { hashes: this.multiple ? this.selected_torrents : [this.torrent.hash] })
|
|
},
|
|
rename() {
|
|
this.createModal('RenameModal', { hash: this.torrent.hash })
|
|
},
|
|
reannounce() {
|
|
qbit.reannounceTorrents(this.hashes)
|
|
},
|
|
removeTorrent() {
|
|
this.$store.state.selected_torrents = this.hashes
|
|
|
|
return this.createModal('ConfirmDeleteModal')
|
|
},
|
|
recheck() {
|
|
qbit.recheckTorrents(this.hashes)
|
|
},
|
|
showInfo() {
|
|
this.$router.push({ name: 'torrentDetail', params: { hash: this.torrent.hash } })
|
|
},
|
|
setPriority(priority) {
|
|
qbit.setTorrentPriority(this.hashes, priority)
|
|
},
|
|
setLimit(mode) {
|
|
this.createModal('SpeedLimitModal', { hash: this.torrent.hash, mode })
|
|
},
|
|
setShareLimit() {
|
|
this.createModal('ShareLimitModal', { hash: this.torrent.hash })
|
|
},
|
|
forceResume() {
|
|
qbit.forceStartTorrents(this.hashes)
|
|
},
|
|
setCategory(cat) {
|
|
qbit.setCategory(this.hashes, cat)
|
|
},
|
|
setTag(tag) {
|
|
if (this.torrent.tags && this.torrent.tags.includes(tag)) this.removeTag(tag)
|
|
else this.addTag(tag)
|
|
},
|
|
addTag(tag) {
|
|
qbit.addTorrentTag(this.hashes, [tag])
|
|
},
|
|
removeTag(tag) {
|
|
qbit.removeTorrentTag(this.hashes, [tag])
|
|
},
|
|
toggleSeq() {
|
|
qbit.toggleSequentialDownload(this.hashes)
|
|
},
|
|
toggleFL() {
|
|
qbit.toggleFirstLastPiecePriority(this.hashes)
|
|
},
|
|
toggleAutoTMM() {
|
|
qbit.setAutoTMM(this.hashes, !this.torrent.auto_tmm)
|
|
},
|
|
copyToClipBoard(text) {
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
navigator.clipboard.writeText(text)
|
|
} else {
|
|
const textArea = document.createElement('textarea')
|
|
textArea.value = text
|
|
textArea.style.position = 'fixed'
|
|
textArea.style.opacity = '0'
|
|
document.body.appendChild(textArea)
|
|
textArea.select()
|
|
if (!document.execCommand('copy')) {
|
|
this.$toast.error(this.$t('toast.copyNotSupported').toString())
|
|
return
|
|
}
|
|
document.body.removeChild(textArea)
|
|
}
|
|
this.$toast.success(this.$t('toast.copySuccess').toString())
|
|
},
|
|
async exportTorrents() {
|
|
this.hashes.forEach(hash => {
|
|
qbit.exportTorrent(hash).then(blob => {
|
|
const url = window.URL.createObjectURL(blob)
|
|
const link = document.createElement('a')
|
|
link.href = url
|
|
link.style.opacity = '0'
|
|
link.setAttribute('download', `${hash}.torrent`)
|
|
document.body.appendChild(link)
|
|
link.click()
|
|
document.body.removeChild(link)
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style scoped lang="scss">
|
|
.list-item {
|
|
&__title {
|
|
font-size: 1em;
|
|
}
|
|
}
|
|
|
|
.v-menu__content {
|
|
max-height: 720px;
|
|
overflow-y: auto !important;
|
|
}
|
|
</style>
|