mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2024-10-23 03:06:43 +03:00
0.4.1 (#53)
This commit is contained in:
parent
ae6a2048eb
commit
dde4c08f2b
19 changed files with 454 additions and 377 deletions
|
@ -1 +1 @@
|
||||||
node_modules
|
node_modules/*
|
|
@ -12,7 +12,7 @@ module.exports = {
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||||
indent: ['error', 4],
|
indent: ['warn', 4],
|
||||||
semi: ['error', 'never'],
|
semi: ['error', 'never'],
|
||||||
quotes: ['error', 'single'],
|
quotes: ['error', 'single'],
|
||||||
'comma-dangle': ['error', 'never'],
|
'comma-dangle': ['error', 'never'],
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "vuetorrent",
|
"name": "vuetorrent",
|
||||||
"version": "0.4.0",
|
"version": "0.4.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
|
|
|
@ -8,8 +8,8 @@ build_and_copy(){
|
||||||
cd ../vuetorrent-release
|
cd ../vuetorrent-release
|
||||||
git checkout latest-release
|
git checkout latest-release
|
||||||
git pull
|
git pull
|
||||||
sudo rm -r public
|
sudo rm -r public || true
|
||||||
cp -r ../vuetorrent/vuetorrent/* ./
|
cp -r ../VueTorrent/vuetorrent/* ./
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
<v-row no-gutters>
|
<v-row no-gutters>
|
||||||
<v-col ref="fileZone">
|
<v-col ref="fileZone">
|
||||||
<v-file-input
|
<v-file-input
|
||||||
v-if="!url"
|
|
||||||
v-model="files"
|
v-model="files"
|
||||||
color="deep-purple accent-4"
|
color="deep-purple accent-4"
|
||||||
counter
|
counter
|
||||||
|
@ -44,8 +43,7 @@
|
||||||
>
|
>
|
||||||
</template>
|
</template>
|
||||||
</v-file-input>
|
</v-file-input>
|
||||||
<v-text-field
|
<v-textarea
|
||||||
v-if="files.length == 0"
|
|
||||||
label="URL"
|
label="URL"
|
||||||
prepend-icon="mdi-link"
|
prepend-icon="mdi-link"
|
||||||
:rows="
|
:rows="
|
||||||
|
@ -53,7 +51,10 @@
|
||||||
"
|
"
|
||||||
required
|
required
|
||||||
:autofocus="!phoneLayout"
|
:autofocus="!phoneLayout"
|
||||||
v-model="url"
|
v-model="urls"
|
||||||
|
auto-grow
|
||||||
|
clearable
|
||||||
|
hint="One link per line"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
@ -130,17 +131,17 @@ export default {
|
||||||
'Not a valid magnet link'
|
'Not a valid magnet link'
|
||||||
],
|
],
|
||||||
loading: false,
|
loading: false,
|
||||||
url: null,
|
urls: null,
|
||||||
valid: false
|
valid: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
submit() {
|
submit() {
|
||||||
if (this.files.length || this.url) {
|
if (this.files.length || this.urls) {
|
||||||
let torrents = []
|
let torrents = []
|
||||||
let params = { urls: null, autoTMM: this.autoTMM }
|
let params = { urls: null, autoTMM: this.autoTMM }
|
||||||
if (this.files.length) torrents.push(...this.files)
|
if (this.files.length) torrents.push(...this.files)
|
||||||
if (this.url) params.urls = this.url
|
if (this.urls) params.urls = this.urls
|
||||||
if (this.category) params.category = this.category
|
if (this.category) params.category = this.category
|
||||||
if (!this.autoTMM) params.savepath = this.directory
|
if (!this.autoTMM) params.savepath = this.directory
|
||||||
if (this.skip_checking) params.skip_checking = this.skip_checking
|
if (this.skip_checking) params.skip_checking = this.skip_checking
|
||||||
|
|
71
src/components/Modals/ConfirmDeleteModal.vue
Normal file
71
src/components/Modals/ConfirmDeleteModal.vue
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<template>
|
||||||
|
<v-dialog v-model="dialog" scrollable max-width="500px">
|
||||||
|
<v-card>
|
||||||
|
<v-container :class="`pa-0 project done`">
|
||||||
|
<v-card-title class="justify-center">
|
||||||
|
<h2>Confirm Removal</h2>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-list flat>
|
||||||
|
<v-list-item
|
||||||
|
v-for="t in torrents"
|
||||||
|
:key="t.hash"
|
||||||
|
>
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title class="truncate" v-text="t.name"></v-list-item-title>
|
||||||
|
</v-list-item-content>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-card-text>
|
||||||
|
<v-card-actions class="justify-center pb-5">
|
||||||
|
<v-btn text class="error white--text mt-3"
|
||||||
|
@click="close()"
|
||||||
|
>Cancel</v-btn
|
||||||
|
>
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
class="green_accent white--text mt-3"
|
||||||
|
@click="deleteWithoutFiles()"
|
||||||
|
>Delete</v-btn
|
||||||
|
>
|
||||||
|
<v-btn
|
||||||
|
text
|
||||||
|
class="green_accent white--text mt-3"
|
||||||
|
@click="deleteWithFiles()"
|
||||||
|
>Delete with files</v-btn
|
||||||
|
>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-container>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapState, mapGetters } from 'vuex'
|
||||||
|
import { Modal } from '@/mixins'
|
||||||
|
import qbit from '@/services/qbit'
|
||||||
|
export default {
|
||||||
|
name: 'ConfirmDeleteModal',
|
||||||
|
mixins: [Modal],
|
||||||
|
methods: {
|
||||||
|
close() {
|
||||||
|
this.$store.commit('DELETE_MODAL', this.guid)
|
||||||
|
},
|
||||||
|
deleteWithoutFiles() {
|
||||||
|
qbit.deleteTorrents(this.selected_torrents, false)
|
||||||
|
this.close()
|
||||||
|
},
|
||||||
|
deleteWithFiles() {
|
||||||
|
qbit.deleteTorrents(this.selected_torrents, true)
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState(['selected_torrents']),
|
||||||
|
...mapGetters(['getTorrents']),
|
||||||
|
torrents(){
|
||||||
|
return this.getTorrents().filter(t => this.selected_torrents.includes(t.hash))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
80
src/components/Modals/RenameModal.vue
Normal file
80
src/components/Modals/RenameModal.vue
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
<template>
|
||||||
|
<v-dialog
|
||||||
|
v-model="dialog"
|
||||||
|
scrollable
|
||||||
|
:width="dialogWidth"
|
||||||
|
:fullscreen="phoneLayout"
|
||||||
|
>
|
||||||
|
<v-card style="overflow: hidden !important">
|
||||||
|
<v-container :style="{ height: phoneLayout ? '100vh' : '' }">
|
||||||
|
<v-card-title class="pb-0 justify-center">
|
||||||
|
<h2>Rename Torrent</h2>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<div>
|
||||||
|
<v-container>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-text-field
|
||||||
|
label="Torrent Name"
|
||||||
|
prepend-icon="insert_drive_file"
|
||||||
|
v-model="name"
|
||||||
|
/>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-container>
|
||||||
|
</div>
|
||||||
|
</v-card-text>
|
||||||
|
<div>
|
||||||
|
<v-card-actions class="justify-center">
|
||||||
|
<v-btn color="success" @click="rename">Save</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</div>
|
||||||
|
</v-container>
|
||||||
|
<v-fab-transition v-if="phoneLayout">
|
||||||
|
<v-btn @click="close" color="red" dark absolute bottom right>
|
||||||
|
<v-icon>close</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
</v-fab-transition>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import { Modal, FullScreenModal } from '@/mixins'
|
||||||
|
import qbit from '@/services/qbit'
|
||||||
|
export default {
|
||||||
|
name: 'RenameModal',
|
||||||
|
mixins: [Modal, FullScreenModal],
|
||||||
|
props: {
|
||||||
|
hash: String
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
name: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getTorrent']),
|
||||||
|
dialogWidth() {
|
||||||
|
return this.phoneLayout ? '100%' : '750px'
|
||||||
|
},
|
||||||
|
torrent() {
|
||||||
|
return this.getTorrent(this.hash)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
rename() {
|
||||||
|
qbit.setTorrentName(this.hash, this.name)
|
||||||
|
this.close()
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.$store.commit('DELETE_MODAL', this.guid)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.name = this.torrent.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -46,10 +46,10 @@ export default {
|
||||||
mixins: [Modal],
|
mixins: [Modal],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
sortProperty: { value: 'added_on', name: 'Default' },
|
sortProperty: { value: 'added_on', name: 'Added On' },
|
||||||
reverse: true,
|
reverse: true,
|
||||||
options: [
|
options: [
|
||||||
{ value: 'added_on', name: 'Default' },
|
{ value: 'added_on', name: 'Added On' },
|
||||||
{ value: 'availability', name: 'Availability' },
|
{ value: 'availability', name: 'Availability' },
|
||||||
{ value: 'category', name: 'Category' },
|
{ value: 'category', name: 'Category' },
|
||||||
{ value: 'completed', name: 'Completed' },
|
{ value: 'completed', name: 'Completed' },
|
||||||
|
|
|
@ -92,8 +92,9 @@ export default {
|
||||||
qbit.resumeTorrents(this.selected_torrents)
|
qbit.resumeTorrents(this.selected_torrents)
|
||||||
},
|
},
|
||||||
removeTorrents() {
|
removeTorrents() {
|
||||||
qbit.deleteTorrents(this.selected_torrents, false)
|
if(!this.selected_torrents.length) return
|
||||||
this.$store.commit('RESET_SELECTED')
|
|
||||||
|
return this.createModal('ConfirmDeleteModal')
|
||||||
},
|
},
|
||||||
addModal(name) {
|
addModal(name) {
|
||||||
this.createModal(name)
|
this.createModal(name)
|
||||||
|
|
|
@ -1,143 +1,183 @@
|
||||||
<template>
|
<template>
|
||||||
<v-card
|
<v-card
|
||||||
ripple
|
ripple
|
||||||
flat
|
flat
|
||||||
class="pointer torrent noselect"
|
class="pointer torrent noselect"
|
||||||
:class="{ torrent_selected: containsTorrent(torrent.hash) }"
|
:class="{ torrent_selected: isAlreadySelected(torrent.hash) }"
|
||||||
@click.native="selectTorrent(torrent.hash)"
|
@click.native.exact.prevent="
|
||||||
@dblclick.prevent="showInfo(torrent.hash)"
|
$vuetify.breakpoint.smAndDown ?
|
||||||
>
|
selectTorrent(torrent.hash) :
|
||||||
<v-layout row wrap :class="style">
|
showInfo(torrent.hash)"
|
||||||
<v-flex xs12 class="mb-4">
|
@dblclick.prevent="showInfo(torrent.hash)"
|
||||||
<div class="caption grey--text">Torrent title</div>
|
@click.ctrl.exact.prevent="selectTorrent(torrent.hash)"
|
||||||
<div class="truncate">{{ torrent.name }}</div>
|
>
|
||||||
</v-flex>
|
<v-tooltip top>
|
||||||
<v-flex xs6 sm1 md1>
|
<template v-slot:activator="{ on }">
|
||||||
<div class="caption grey--text">Size</div>
|
<v-layout v-on="denseDashboard && on" row wrap :class="style">
|
||||||
<div>
|
<v-flex xs12 :class="denseDashboard ? 'sm3' : ''">
|
||||||
{{ torrent.size | getDataValue }}
|
<div class="caption grey--text">Torrent title</div>
|
||||||
<span class="caption grey--text">{{
|
<div class="truncate">{{ torrent.name }}</div>
|
||||||
torrent.size | getDataUnit
|
</v-flex>
|
||||||
}}</span>
|
<v-flex xs6 sm1 md1 class="mr-2">
|
||||||
</div>
|
<div class="caption grey--text">Size</div>
|
||||||
</v-flex>
|
<div>
|
||||||
<v-flex xs12 sm1 md1 class="mr-4">
|
{{ torrent.size | getDataValue }}
|
||||||
<div class="caption grey--text">Done</div>
|
<span class="caption grey--text">{{
|
||||||
<v-progress-linear
|
torrent.size | getDataUnit
|
||||||
v-model="torrent.progress"
|
}}</span>
|
||||||
height="20"
|
</div>
|
||||||
:style="phoneLayout ? '' : 'width: 80%;'"
|
</v-flex>
|
||||||
:color="`torrent-${state}-color`" >
|
<v-flex xs12 sm1 md1 class="mr-4">
|
||||||
|
<div class="caption grey--text">Done</div>
|
||||||
|
<v-progress-linear
|
||||||
|
v-model="torrent.progress"
|
||||||
|
height="20"
|
||||||
|
:style="phoneLayout ? '' : 'width: 80%;'"
|
||||||
|
:color="`torrent-${state}-color`" >
|
||||||
<span
|
<span
|
||||||
class="caption"
|
class="caption"
|
||||||
>
|
>
|
||||||
{{ torrent.progress }}%
|
{{ torrent.progress }}%
|
||||||
</span>
|
</span>
|
||||||
</v-progress-linear>
|
</v-progress-linear>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
<v-flex xs6 sm1 md1>
|
<v-flex xs6 sm1 md1 class="mr-2" v-if="torrent.progress !== 100" >
|
||||||
<div class="caption grey--text">Ratio</div>
|
<div class="caption grey--text">Download</div>
|
||||||
<div>
|
<div>
|
||||||
{{ torrent.ratio }}
|
{{ torrent.dlspeed | getDataValue }}
|
||||||
</div>
|
<span class="caption grey--text">{{
|
||||||
</v-flex>
|
torrent.dlspeed | getDataUnit
|
||||||
<v-flex xs6 sm1 md1>
|
}}</span>
|
||||||
<div class="caption grey--text">ETA</div>
|
</div>
|
||||||
<div>
|
</v-flex>
|
||||||
{{ torrent.eta }}
|
<v-flex xs6 sm1 md1 class="mr-2" v-else >
|
||||||
</div>
|
<div class="caption grey--text">Ratio</div>
|
||||||
</v-flex>
|
<div>{{ torrent.ratio }}</div>
|
||||||
<v-flex xs6 sm1 md1>
|
</v-flex>
|
||||||
<div class="caption grey--text">Download</div>
|
<v-flex xs5 sm1 md1 class="mr-2">
|
||||||
<div>
|
<div class="caption grey--text">Upload</div>
|
||||||
{{ torrent.dlspeed | getDataValue }}
|
<div>
|
||||||
<span class="caption grey--text">{{
|
{{ torrent.upspeed | getDataValue }}
|
||||||
torrent.dlspeed | getDataUnit
|
<span class="caption grey--text">{{
|
||||||
}}</span>
|
torrent.upspeed | getDataUnit
|
||||||
</div>
|
}}</span>
|
||||||
</v-flex>
|
</div>
|
||||||
<v-flex xs6 sm1 md1>
|
</v-flex>
|
||||||
<div class="caption grey--text">Upload</div>
|
<v-flex xs6 sm1 md1 class="mr-2">
|
||||||
<div>
|
<div class="caption grey--text">ETA</div>
|
||||||
{{ torrent.upspeed | getDataValue }}
|
<div>
|
||||||
<span class="caption grey--text">{{
|
{{ torrent.eta }}
|
||||||
torrent.upspeed | getDataUnit
|
</div>
|
||||||
}}</span>
|
</v-flex>
|
||||||
</div>
|
<v-flex xs5 sm1 md1 class="mr-2">
|
||||||
</v-flex>
|
<div class="caption grey--text">Peers</div>
|
||||||
<v-flex xs6 sm1 md1>
|
<div>
|
||||||
<div class="caption grey--text">Peers</div>
|
{{ torrent.num_leechs }}
|
||||||
<div>
|
<span class="grey--text caption"
|
||||||
{{ torrent.num_leechs }}
|
>/{{ torrent.available_peers }}</span
|
||||||
<span class="grey--text caption"
|
>
|
||||||
>/{{ torrent.available_peers }}</span
|
</div>
|
||||||
>
|
</v-flex>
|
||||||
</div>
|
<v-flex xs6 sm1 md1 class="mr-2">
|
||||||
</v-flex>
|
<div class="caption grey--text">Seeds</div>
|
||||||
<v-flex xs6 sm1 md1>
|
<div>
|
||||||
<div class="caption grey--text">Seeds</div>
|
{{ torrent.num_seeds }}
|
||||||
<div>
|
<span class="grey--text caption"
|
||||||
{{ torrent.num_seeds }}
|
>/{{ torrent.available_seeds }}</span
|
||||||
<span class="grey--text caption"
|
>
|
||||||
>/{{ torrent.available_seeds }}</span
|
</div>
|
||||||
>
|
</v-flex>
|
||||||
</div>
|
<v-flex xs5 sm1>
|
||||||
</v-flex>
|
|
||||||
<v-flex xs6 sm1 md1 :class="phoneLayout ? '' : 'mr-4'">
|
|
||||||
<div class="caption grey--text">Status</div>
|
<div class="caption grey--text">Status</div>
|
||||||
<v-chip
|
<v-chip
|
||||||
small
|
small
|
||||||
class="caption"
|
class="caption"
|
||||||
:class="
|
:class="
|
||||||
theme === 'light'
|
theme === 'light'
|
||||||
? `${state} white--text `
|
? `${state} white--text `
|
||||||
: `${state} black--text`">
|
: `${state} black--text`">
|
||||||
{{ torrent.state }}
|
{{ torrent.state }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
<!-- Category -->
|
<!-- Category -->
|
||||||
<v-flex v-if="torrent.category" xs4 sm1 md1>
|
<v-flex v-if="torrent.category" class="mr-2" xs6 sm1 md1>
|
||||||
<div class="caption grey--text">Category</div>
|
<div class="caption grey--text">Category</div>
|
||||||
<v-chip small class="upload white--text caption">
|
<v-chip small class="upload white--text caption">
|
||||||
{{ torrent.category }}
|
{{ torrent.category }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
<!-- Tags -->
|
<!-- Tags -->
|
||||||
<v-flex xs12 sm1>
|
<v-flex xs5 sm2 v-if="torrent.tags && torrent.tags.length">
|
||||||
<div class="caption grey--text">Tags</div>
|
<div class="caption grey--text">Tags</div>
|
||||||
<v-row wrap class="ma-0">
|
<v-row wrap class="ma-0">
|
||||||
<v-chip v-for="tag in torrent.tags" :key="tag"
|
<v-chip v-for="tag in torrent.tags" :key="tag"
|
||||||
small
|
small
|
||||||
:class="
|
:class="
|
||||||
theme === 'light'
|
theme === 'light'
|
||||||
? 'white--text'
|
? 'white--text'
|
||||||
: 'black--text'
|
: 'black--text'
|
||||||
"
|
"
|
||||||
class="download caption mb-1 mx-1"
|
class="download caption mb-1 mx-1"
|
||||||
>
|
>
|
||||||
{{ tag }}
|
{{ tag }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-row>
|
</v-row>
|
||||||
</v-flex>
|
</v-flex>
|
||||||
</v-layout>
|
</v-layout>
|
||||||
<v-divider v-if="index !== length"></v-divider>
|
</template>
|
||||||
</v-card>
|
<span>{{ torrent.name }}</span>
|
||||||
|
</v-tooltip>
|
||||||
|
<v-divider v-if="index !== length"></v-divider>
|
||||||
|
</v-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { General, Torrent } from '@/mixins'
|
import { General, TorrentSelect } from '@/mixins'
|
||||||
|
import {mapGetters} from 'vuex'
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Torrent',
|
name: 'Torrent',
|
||||||
mixins: [General, Torrent]
|
mixins: [General, TorrentSelect],
|
||||||
|
props: {
|
||||||
|
torrent: Object,
|
||||||
|
index: Number,
|
||||||
|
length: Number
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getTheme', 'getWebuiSettings']),
|
||||||
|
theme() {
|
||||||
|
return this.getTheme() ? 'dark' : 'light'
|
||||||
|
},
|
||||||
|
state() {
|
||||||
|
return this.torrent.state.toLowerCase()
|
||||||
|
},
|
||||||
|
style() {
|
||||||
|
let base = `pa-4 ml-0 sideborder ${this.state} `
|
||||||
|
if (this.index === this.length) base += ' bottomBorderRadius'
|
||||||
|
if (this.index === 0) base += ' topBorderRadius'
|
||||||
|
return base
|
||||||
|
},
|
||||||
|
phoneLayout() {
|
||||||
|
return this.$vuetify.breakpoint.xsOnly
|
||||||
|
},
|
||||||
|
denseDashboard(){
|
||||||
|
return this.getWebuiSettings().denseDashboard
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showInfo(hash) {
|
||||||
|
this.createModal('TorrentDetailModal', {hash})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.topBorderRadius {
|
.topBorderRadius {
|
||||||
border-top-left-radius: 3px;
|
border-top-left-radius: 3px;
|
||||||
}
|
}
|
||||||
.bottomBorderRadius {
|
.bottomBorderRadius {
|
||||||
border-bottom-left-radius: 3px;
|
border-bottom-left-radius: 3px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,59 +1,77 @@
|
||||||
<template>
|
<template>
|
||||||
<v-list dense rounded>
|
<v-list dense rounded>
|
||||||
<v-list-item @click="showInfo" link>
|
<v-list-item @click="resume" link>
|
||||||
<v-icon>info</v-icon>
|
<v-icon >play_arrow</v-icon>
|
||||||
<v-list-item-title class="ml-2" style="font-size: 15px"
|
<v-list-item-title class="ml-2" style="font-size: 12px"
|
||||||
>Show Info</v-list-item-title
|
>Resume</v-list-item-title
|
||||||
>
|
>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-divider />
|
<v-list-item @click="pause" link>
|
||||||
<v-list-item @click="resume" link>
|
<v-icon>pause</v-icon>
|
||||||
<v-icon>play_arrow</v-icon>
|
<v-list-item-title class="ml-2" style="font-size: 12px"
|
||||||
<v-list-item-title class="ml-2" style="font-size: 15px"
|
>Pause</v-list-item-title
|
||||||
>Resume</v-list-item-title
|
>
|
||||||
>
|
</v-list-item>
|
||||||
</v-list-item>
|
<v-divider />
|
||||||
<v-list-item @click="pause" link>
|
<v-list-item @click="deleteWithoutFiles" link>
|
||||||
<v-icon>pause</v-icon>
|
<v-icon color="red">delete</v-icon>
|
||||||
<v-list-item-title class="ml-2" style="font-size: 15px"
|
<v-list-item-title class="ml-2" style="font-size: 12px; color: red"
|
||||||
>Pause</v-list-item-title
|
>Delete</v-list-item-title
|
||||||
>
|
>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-divider />
|
<v-list-item @click="deleteWithFiles" link>
|
||||||
<v-list-item @click="directory" link>
|
<v-icon color="red">delete</v-icon>
|
||||||
<v-icon>folder</v-icon>
|
<v-list-item-title class="ml-2" style="font-size: 12px; color: red"
|
||||||
<v-list-item-title class="ml-2" style="font-size: 15px"
|
>Delete with files</v-list-item-title
|
||||||
>Change location</v-list-item-title
|
>
|
||||||
>
|
</v-list-item>
|
||||||
</v-list-item>
|
<v-divider />
|
||||||
<v-list-item @click="reannounce" link>
|
<v-list-item @click="location" link>
|
||||||
<v-icon>record_voice_over</v-icon>
|
<v-icon>folder</v-icon>
|
||||||
<v-list-item-title class="ml-2" style="font-size: 15px"
|
<v-list-item-title class="ml-2" style="font-size: 12px"
|
||||||
>Reannounce</v-list-item-title
|
>Change location</v-list-item-title
|
||||||
>
|
>
|
||||||
</v-list-item>
|
</v-list-item>
|
||||||
<v-divider />
|
<v-list-item @click="rename" link>
|
||||||
<v-list-item @click="deleteWithoutFiles" link>
|
<v-icon>edit</v-icon>
|
||||||
<v-icon color="red">delete</v-icon>
|
<v-list-item-title class="ml-2" style="font-size: 12px"
|
||||||
<v-list-item-title class="ml-2" style="font-size: 15px; color: red"
|
>Rename</v-list-item-title
|
||||||
>Delete</v-list-item-title
|
>
|
||||||
>
|
</v-list-item>
|
||||||
</v-list-item>
|
<v-list-item @click="recheck" link>
|
||||||
<v-list-item @click="deleteWithFiles" link>
|
<v-icon>widgets</v-icon>
|
||||||
<v-icon color="red">delete</v-icon>
|
<v-list-item-title class="ml-2" style="font-size: 12px;"
|
||||||
<v-list-item-title class="ml-2" style="font-size: 15px; color: red"
|
>Force recheck</v-list-item-title
|
||||||
>Delete with files</v-list-item-title
|
>
|
||||||
>
|
</v-list-item>
|
||||||
</v-list-item>
|
<v-list-item @click="reannounce" link>
|
||||||
</v-list>
|
<v-icon>record_voice_over</v-icon>
|
||||||
|
<v-list-item-title class="ml-2" style="font-size: 12px"
|
||||||
|
>Force reannounce</v-list-item-title
|
||||||
|
>
|
||||||
|
</v-list-item>
|
||||||
|
<v-divider />
|
||||||
|
<v-list-item @click="showInfo" link>
|
||||||
|
<v-icon>info</v-icon>
|
||||||
|
<v-list-item-title class="ml-2" style="font-size: 12px"
|
||||||
|
>Show Info</v-list-item-title
|
||||||
|
>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item @click="selectTorrent(hash)" link>
|
||||||
|
<v-icon>done</v-icon>
|
||||||
|
<v-list-item-title class="ml-2" style="font-size: 12px"
|
||||||
|
>Select</v-list-item-title
|
||||||
|
>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import qbit from '@/services/qbit'
|
import qbit from '@/services/qbit'
|
||||||
import { General } from '@/mixins'
|
import { General, TorrentSelect } from '@/mixins'
|
||||||
export default {
|
export default {
|
||||||
name: 'TorrentRightClickMenu',
|
name: 'TorrentRightClickMenu',
|
||||||
mixins: [General],
|
mixins: [General, TorrentSelect],
|
||||||
props: {
|
props: {
|
||||||
hash: String
|
hash: String
|
||||||
},
|
},
|
||||||
|
@ -64,9 +82,12 @@ export default {
|
||||||
pause() {
|
pause() {
|
||||||
qbit.pauseTorrents([this.hash])
|
qbit.pauseTorrents([this.hash])
|
||||||
},
|
},
|
||||||
directory() {
|
location() {
|
||||||
this.createModal('ChangeLocationModal', { hash: this.hash })
|
this.createModal('ChangeLocationModal', { hash: this.hash })
|
||||||
},
|
},
|
||||||
|
rename() {
|
||||||
|
this.createModal('RenameModal', { hash: this.hash })
|
||||||
|
},
|
||||||
reannounce() {
|
reannounce() {
|
||||||
qbit.reannounceTorrents([this.hash])
|
qbit.reannounceTorrents([this.hash])
|
||||||
},
|
},
|
||||||
|
@ -76,9 +97,13 @@ export default {
|
||||||
deleteWithFiles() {
|
deleteWithFiles() {
|
||||||
qbit.deleteTorrents([this.hash], true)
|
qbit.deleteTorrents([this.hash], true)
|
||||||
},
|
},
|
||||||
|
recheck() {
|
||||||
|
qbit.recheckTorrents([this.hash])
|
||||||
|
},
|
||||||
showInfo() {
|
showInfo() {
|
||||||
this.createModal('TorrentDetailModal', { hash: this.hash })
|
this.createModal('TorrentDetailModal', { hash: this.hash })
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
dark() {
|
dark() {
|
||||||
|
|
|
@ -1,135 +0,0 @@
|
||||||
<template>
|
|
||||||
<v-card
|
|
||||||
ripple
|
|
||||||
flat
|
|
||||||
class="pointer torrent noselect"
|
|
||||||
:class="{ torrent_selected: containsTorrent(torrent.hash) }"
|
|
||||||
@click.native="selectTorrent(torrent.hash)"
|
|
||||||
@dblclick.prevent="showInfo(torrent.hash)"
|
|
||||||
>
|
|
||||||
<v-tooltip top>
|
|
||||||
<template v-slot:activator="{ on }">
|
|
||||||
<v-layout v-on="on" row wrap :class="style">
|
|
||||||
<v-flex xs12 sm2 md3>
|
|
||||||
<div class="caption grey--text">Torrent title</div>
|
|
||||||
<div class="truncate">{{ torrent.name }}</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs6 sm1 md1 class="mr-2">
|
|
||||||
<div class="caption grey--text">Size</div>
|
|
||||||
<div>
|
|
||||||
{{ torrent.size | getDataValue }}
|
|
||||||
<span class="caption grey--text">{{
|
|
||||||
torrent.size | getDataUnit
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs5 sm1 md1 class="mr-2">
|
|
||||||
<div class="caption grey--text">Done</div>
|
|
||||||
<div>
|
|
||||||
{{ torrent.progress }}<span class="grey--text">% </span>
|
|
||||||
</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs6 sm1 md1 class="mr-2">
|
|
||||||
<div class="caption grey--text">Download</div>
|
|
||||||
<div>
|
|
||||||
{{ torrent.dlspeed | getDataValue }}
|
|
||||||
<span class="caption grey--text">{{
|
|
||||||
torrent.dlspeed | getDataUnit
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs5 sm1 md1 class="mr-2">
|
|
||||||
<div class="caption grey--text">Upload</div>
|
|
||||||
<div>
|
|
||||||
{{ torrent.upspeed | getDataValue }}
|
|
||||||
<span class="caption grey--text">{{
|
|
||||||
torrent.upspeed | getDataUnit
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs6 sm1 md1 class="mr-2">
|
|
||||||
<div class="caption grey--text">ETA</div>
|
|
||||||
<div>
|
|
||||||
{{ torrent.eta }}
|
|
||||||
</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs5 sm1 md1 class="mr-2">
|
|
||||||
<div class="caption grey--text">Peers</div>
|
|
||||||
<div>
|
|
||||||
{{ torrent.num_leechs }}
|
|
||||||
<span class="grey--text caption"
|
|
||||||
>/{{ torrent.available_peers }}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs6 sm1 md1 class="mr-2">
|
|
||||||
<div class="caption grey--text">Seeds</div>
|
|
||||||
<div>
|
|
||||||
{{ torrent.num_seeds }}
|
|
||||||
<span class="grey--text caption"
|
|
||||||
>/{{ torrent.available_seeds }}</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</v-flex>
|
|
||||||
<v-flex xs5 sm1>
|
|
||||||
<div class="caption grey--text">Status</div>
|
|
||||||
<v-chip
|
|
||||||
small
|
|
||||||
class="caption"
|
|
||||||
:class="
|
|
||||||
theme === 'light'
|
|
||||||
? `${state} white--text `
|
|
||||||
: `${state} black--text`">
|
|
||||||
{{ torrent.state }}
|
|
||||||
</v-chip>
|
|
||||||
</v-flex>
|
|
||||||
<!-- Category -->
|
|
||||||
<v-flex v-if="torrent.category" class="mr-2" xs6 sm1 md1>
|
|
||||||
<div class="caption grey--text">Category</div>
|
|
||||||
<v-chip small class="upload white--text caption">
|
|
||||||
{{ torrent.category }}
|
|
||||||
</v-chip>
|
|
||||||
</v-flex>
|
|
||||||
<!-- Tags -->
|
|
||||||
<v-flex xs5 sm4>
|
|
||||||
<div class="caption grey--text">Tags</div>
|
|
||||||
<v-row wrap class="ma-0">
|
|
||||||
<v-chip v-for="tag in torrent.tags" :key="tag"
|
|
||||||
small
|
|
||||||
:class="
|
|
||||||
theme === 'light'
|
|
||||||
? 'white--text'
|
|
||||||
: 'black--text'
|
|
||||||
"
|
|
||||||
class="download caption mb-1 mx-1"
|
|
||||||
>
|
|
||||||
{{ tag }}
|
|
||||||
</v-chip>
|
|
||||||
</v-row>
|
|
||||||
</v-flex>
|
|
||||||
</v-layout>
|
|
||||||
</template>
|
|
||||||
<span>{{ torrent.name }}</span>
|
|
||||||
</v-tooltip>
|
|
||||||
<v-divider v-if="index !== length"></v-divider>
|
|
||||||
</v-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { General, Torrent } from '@/mixins'
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'TorrentDense',
|
|
||||||
mixins: [General, Torrent]
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.topBorderRadius {
|
|
||||||
border-top-left-radius: 3px;
|
|
||||||
}
|
|
||||||
.bottomBorderRadius {
|
|
||||||
border-bottom-left-radius: 3px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,42 +0,0 @@
|
||||||
import {mapGetters} from 'vuex'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
torrent: Object,
|
|
||||||
index: Number,
|
|
||||||
length: Number
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['getTheme']),
|
|
||||||
theme() {
|
|
||||||
return this.getTheme() ? 'dark' : 'light'
|
|
||||||
},
|
|
||||||
state() {
|
|
||||||
return this.torrent.state.toLowerCase()
|
|
||||||
},
|
|
||||||
style() {
|
|
||||||
let base = `pa-4 ml-0 sideborder ${this.state} `
|
|
||||||
if (this.index === this.length) base += ' bottomBorderRadius'
|
|
||||||
if (this.index === 0) base += ' topBorderRadius'
|
|
||||||
return base
|
|
||||||
},
|
|
||||||
phoneLayout() {
|
|
||||||
return this.$vuetify.breakpoint.xsOnly
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
selectTorrent(hash) {
|
|
||||||
if (this.containsTorrent(hash)) {
|
|
||||||
this.$store.commit('SET_SELECTED', { type: 'remove', hash })
|
|
||||||
} else {
|
|
||||||
this.$store.commit('SET_SELECTED', { type: 'add', hash })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
containsTorrent(hash) {
|
|
||||||
return this.$store.getters.containsTorrent(hash)
|
|
||||||
},
|
|
||||||
showInfo(hash) {
|
|
||||||
this.createModal('TorrentDetailModal', { hash })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
14
src/mixins/TorrentSelect.js
Normal file
14
src/mixins/TorrentSelect.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
isAlreadySelected(hash) {
|
||||||
|
return this.$store.getters.containsTorrent(hash)
|
||||||
|
},
|
||||||
|
selectTorrent(hash) {
|
||||||
|
if (this.isAlreadySelected(hash)) {
|
||||||
|
this.$store.commit('SET_SELECTED', { type: 'remove', hash })
|
||||||
|
} else {
|
||||||
|
this.$store.commit('SET_SELECTED', { type: 'add', hash })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,6 @@ import Modal from './Modal'
|
||||||
import SettingsTab from './SettingsTab'
|
import SettingsTab from './SettingsTab'
|
||||||
import Tab from './Tab'
|
import Tab from './Tab'
|
||||||
import General from './General'
|
import General from './General'
|
||||||
import Torrent from './Torrent'
|
import TorrentSelect from './TorrentSelect'
|
||||||
|
|
||||||
export { FullScreenModal, Modal, SettingsTab, Tab, General, Torrent }
|
export { FullScreenModal, Modal, SettingsTab, Tab, General, TorrentSelect }
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default class Torrent {
|
||||||
this.num_leechs = data.num_leechs
|
this.num_leechs = data.num_leechs
|
||||||
this.num_seeds = data.num_seeds
|
this.num_seeds = data.num_seeds
|
||||||
this.path = data.path === undefined ? '/downloads' : data.path
|
this.path = data.path === undefined ? '/downloads' : data.path
|
||||||
this.state = this.formatState(data)
|
this.state = this.formatState(data.state)
|
||||||
// hash is used to identify
|
// hash is used to identify
|
||||||
this.hash = data.hash
|
this.hash = data.hash
|
||||||
// available seeds
|
// available seeds
|
||||||
|
@ -22,11 +22,11 @@ export default class Torrent {
|
||||||
this.ratio = Math.round(data.ratio * 100) / 100
|
this.ratio = Math.round(data.ratio * 100) / 100
|
||||||
this.tags = data.tags.length > 0 ? data.tags.split(',') : null
|
this.tags = data.tags.length > 0 ? data.tags.split(',') : null
|
||||||
this.category = data.category
|
this.category = data.category
|
||||||
|
this.tracker = data.tracker
|
||||||
}
|
}
|
||||||
|
|
||||||
formatState(item) {
|
formatState(state) {
|
||||||
if (!item.tracker) return 'Fail'
|
switch (state) {
|
||||||
switch (item.state) {
|
|
||||||
case 'forceDL':
|
case 'forceDL':
|
||||||
case 'downloading':
|
case 'downloading':
|
||||||
return 'Downloading'
|
return 'Downloading'
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { isAuthenticated } from '@/services/auth.js'
|
||||||
Vue.use(Router)
|
Vue.use(Router)
|
||||||
|
|
||||||
const router = new Router({
|
const router = new Router({
|
||||||
mode: 'history',
|
|
||||||
base: process.env.BASE_URL,
|
base: process.env.BASE_URL,
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -132,6 +132,7 @@ class Qbit {
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteTorrents(hashes, deleteFiles) {
|
deleteTorrents(hashes, deleteFiles) {
|
||||||
|
if(!hashes.length) return
|
||||||
return this.actionTorrents('delete', hashes, { deleteFiles })
|
return this.actionTorrents('delete', hashes, { deleteFiles })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,6 +185,14 @@ class Qbit {
|
||||||
return this.actionTorrents('setLocation', hashes, { location })
|
return this.actionTorrents('setLocation', hashes, { location })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTorrentName(hash, name) {
|
||||||
|
const params = {
|
||||||
|
hash,
|
||||||
|
name
|
||||||
|
}
|
||||||
|
return this.axios.get('/torrents/rename', { params })
|
||||||
|
}
|
||||||
|
|
||||||
getTorrentProperties(hash) {
|
getTorrentProperties(hash) {
|
||||||
const params = {
|
const params = {
|
||||||
hash
|
hash
|
||||||
|
@ -309,9 +318,8 @@ class Qbit {
|
||||||
// End Categories
|
// End Categories
|
||||||
|
|
||||||
actionTorrents(action, hashes, extra) {
|
actionTorrents(action, hashes, extra) {
|
||||||
if (action == 'delete' && !hashes.length) return
|
|
||||||
const params = {
|
const params = {
|
||||||
hashes: hashes.length ? hashes.join('|') : 'all',
|
hashes: hashes.join('|'),
|
||||||
...extra
|
...extra
|
||||||
}
|
}
|
||||||
const data = new URLSearchParams(params)
|
const data = new URLSearchParams(params)
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="pl-5 pr-5" color="background" @click.self="resetSelected">
|
<div class="pl-5 pr-5"
|
||||||
|
color="background"
|
||||||
|
@click.self="resetSelected"
|
||||||
|
>
|
||||||
<h1 style="font-size: 1.1em !important" class="subtitle-1 grey--text">
|
<h1 style="font-size: 1.1em !important" class="subtitle-1 grey--text">
|
||||||
Dashboard
|
Dashboard
|
||||||
<p
|
<p
|
||||||
|
@ -36,7 +39,7 @@
|
||||||
v-for="(torrent, index) in paginatedData"
|
v-for="(torrent, index) in paginatedData"
|
||||||
:key="torrent.hash"
|
:key="torrent.hash"
|
||||||
>
|
>
|
||||||
<Torrent v-if="!denseDashboard"
|
<Torrent
|
||||||
:class="{
|
:class="{
|
||||||
topBorderRadius: index === 0,
|
topBorderRadius: index === 0,
|
||||||
noBorderRadius:
|
noBorderRadius:
|
||||||
|
@ -47,17 +50,6 @@
|
||||||
:index="index"
|
:index="index"
|
||||||
:length="torrents.length - 1"
|
:length="torrents.length - 1"
|
||||||
/>
|
/>
|
||||||
<TorrentDense v-if="denseDashboard"
|
|
||||||
:class="{
|
|
||||||
topBorderRadius: index === 0,
|
|
||||||
noBorderRadius:
|
|
||||||
index !== 0 && index !== torrent.length - 1,
|
|
||||||
bottomBorderRadius: index === torrents.length - 1
|
|
||||||
}"
|
|
||||||
:torrent="torrent"
|
|
||||||
:index="index"
|
|
||||||
:length="torrents.length - 1"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<v-row v-if="pageCount > 1" xs12 justify="center">
|
<v-row v-if="pageCount > 1" xs12 justify="center">
|
||||||
<v-col>
|
<v-col>
|
||||||
|
@ -82,15 +74,16 @@
|
||||||
<script>
|
<script>
|
||||||
import { mapState, mapGetters } from 'vuex'
|
import { mapState, mapGetters } from 'vuex'
|
||||||
import Torrent from '@/components/Torrent'
|
import Torrent from '@/components/Torrent'
|
||||||
import TorrentDense from '@/components/TorrentDense'
|
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from 'fuse.js'
|
||||||
import { VueContext } from 'vue-context'
|
import { VueContext } from 'vue-context'
|
||||||
import 'vue-context/src/sass/vue-context.scss'
|
import 'vue-context/src/sass/vue-context.scss'
|
||||||
import TorrentRightClickMenu from '@/components/Torrent/TorrentRightClickMenu.vue'
|
import TorrentRightClickMenu from '@/components/Torrent/TorrentRightClickMenu.vue'
|
||||||
|
import { TorrentSelect, General } from '@/mixins'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
components: { Torrent, TorrentDense, VueContext, TorrentRightClickMenu },
|
components: { Torrent, VueContext, TorrentRightClickMenu },
|
||||||
|
mixins: [ TorrentSelect, General ],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
input: '',
|
input: '',
|
||||||
|
@ -98,7 +91,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['mainData']),
|
...mapState(['mainData', 'selected_torrents']),
|
||||||
...mapGetters(['getTorrents', 'getTorrentCountString', 'getWebuiSettings']),
|
...mapGetters(['getTorrents', 'getTorrentCountString', 'getWebuiSettings']),
|
||||||
torrents() {
|
torrents() {
|
||||||
if (!this.input || !this.input.length) return this.getTorrents()
|
if (!this.input || !this.input.length) return this.getTorrents()
|
||||||
|
@ -133,9 +126,6 @@ export default {
|
||||||
},
|
},
|
||||||
torrentCountString() {
|
torrentCountString() {
|
||||||
return this.getTorrentCountString()
|
return this.getTorrentCountString()
|
||||||
},
|
|
||||||
denseDashboard(){
|
|
||||||
return this.getWebuiSettings().denseDashboard
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -147,14 +137,39 @@ export default {
|
||||||
},
|
},
|
||||||
toTop () {
|
toTop () {
|
||||||
this.$vuetify.goTo(0)
|
this.$vuetify.goTo(0)
|
||||||
|
},
|
||||||
|
handleKeyboardShortcut(e) {
|
||||||
|
// 'ctrl + A' => select torrents
|
||||||
|
if (e.keyCode === 65 && e.ctrlKey) {
|
||||||
|
e.preventDefault()
|
||||||
|
if(this.$store.state.selected_torrents.length === this.torrents.length){
|
||||||
|
return this.$store.state.selected_torrents = []
|
||||||
|
}
|
||||||
|
const hashes = this.torrents.map(t => t.hash)
|
||||||
|
return this.$store.state.selected_torrents = hashes
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'Delete' => Delete modal
|
||||||
|
if(e.keyCode === 46) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
//no torrents select to delete
|
||||||
|
if(!this.selected_torrents.length) return
|
||||||
|
|
||||||
|
return this.createModal('ConfirmDeleteModal')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
document.addEventListener('keydown', this.handleKeyboardShortcut)
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$store.dispatch('INIT_INTERVALS')
|
this.$store.dispatch('INIT_INTERVALS')
|
||||||
this.$store.commit('FETCH_CATEGORIES')
|
this.$store.commit('FETCH_CATEGORIES')
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
this.$store.commit('REMOVE_INTERVALS')
|
this.$store.commit('REMOVE_INTERVALS')
|
||||||
|
document.removeEventListener('keydown', this.handleKeyboardShortcut)
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
torrents: function (torrents) {
|
torrents: function (torrents) {
|
||||||
|
|
Loading…
Reference in a new issue