mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2025-05-06 23:35:00 +03:00
0.4.5 (#69)
This commit is contained in:
parent
80d1c1f6a0
commit
8b590e4e98
51 changed files with 760 additions and 653 deletions
src/components/Modals
AddModal.vueConfirmDeleteModal.vueRenameModal.vueSearchModal.vue
SearchModal
SettingsModal/Tabs
TorrentDetailModal/Tabs
|
@ -121,6 +121,7 @@ import Modal from '@/mixins/Modal'
|
|||
import qbit from '@/services/qbit'
|
||||
export default {
|
||||
name: 'AddModal',
|
||||
props: ['initialMagnet'],
|
||||
mixins: [Modal],
|
||||
data() {
|
||||
return {
|
||||
|
@ -144,14 +145,13 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
addDropFile(e)
|
||||
{
|
||||
addDropFile(e) {
|
||||
this.files.push(...Array.from(e.dataTransfer.files))
|
||||
},
|
||||
submit() {
|
||||
if (this.files.length || this.urls) {
|
||||
let torrents = []
|
||||
let params = { urls: null, autoTMM: this.autoTMM }
|
||||
const torrents = []
|
||||
const params = { urls: null, autoTMM: this.autoTMM }
|
||||
if (this.files.length) torrents.push(...this.files)
|
||||
if (this.urls) params.urls = this.urls
|
||||
if (this.category) params.category = this.category
|
||||
|
@ -188,7 +188,7 @@ export default {
|
|||
let savePath = this.getSettings().save_path
|
||||
if (this.category) {
|
||||
savePath += this.category
|
||||
let category = this.getCategories()[this.category]
|
||||
const category = this.getCategories()[this.category]
|
||||
if (category && category.savePath) savePath = category.savePath
|
||||
}
|
||||
return savePath
|
||||
|
@ -201,6 +201,7 @@ export default {
|
|||
this.$store.commit('FETCH_SETTINGS')
|
||||
this.$store.commit('FETCH_CATEGORIES')
|
||||
this.directory = this.savepath
|
||||
this.urls = this.initialMagnet
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -63,9 +63,9 @@ export default {
|
|||
computed: {
|
||||
...mapState(['selected_torrents']),
|
||||
...mapGetters(['getTorrents']),
|
||||
torrents(){
|
||||
torrents() {
|
||||
return this.getTorrents().filter(t => this.selected_torrents.includes(t.hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -77,4 +77,4 @@ export default {
|
|||
this.name = this.torrent.name
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -1,184 +0,0 @@
|
|||
<template>
|
||||
<v-dialog
|
||||
v-model="dialog"
|
||||
scrollable
|
||||
:width="dialogWidth"
|
||||
:fullscreen="phoneLayout"
|
||||
>
|
||||
<v-card :style="{ height: phoneLayout ? '100vh' : '' }">
|
||||
<v-container
|
||||
:style="{ height: phoneLayout ? '100vh' : '' }"
|
||||
:class="`pa-0 project done`"
|
||||
>
|
||||
<v-card-title class="justify-center">
|
||||
<h2>Search Torrent</h2>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<div>
|
||||
<v-container>
|
||||
<v-row no-gutters>
|
||||
<v-col ref="fileZone">
|
||||
<v-text-field
|
||||
label="Search"
|
||||
prepend-icon="search"
|
||||
required
|
||||
:autofocus="!phoneLayout"
|
||||
v-model="searchTerm"
|
||||
v-on:keydown.enter="search"
|
||||
/>
|
||||
<v-text-field
|
||||
label="Category"
|
||||
prepend-icon="category"
|
||||
v-model="searchCategory"
|
||||
v-on:keydown.enter="search"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</div>
|
||||
</v-card-text>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
<div>
|
||||
<v-card-actions class="justify-center">
|
||||
<v-btn
|
||||
text
|
||||
@click="search"
|
||||
:loading="status === 'Running'"
|
||||
class="blue_accent white--text"
|
||||
>Search</v-btn
|
||||
>
|
||||
</v-card-actions>
|
||||
</div>
|
||||
<div class="text-center mt-6">
|
||||
<p
|
||||
v-if="noResults"
|
||||
class="red--text"
|
||||
style="font-size: 1.3em"
|
||||
>
|
||||
No results could be found
|
||||
</p>
|
||||
<div v-if="results.length">
|
||||
<h2>Results</h2>
|
||||
<perfect-scrollbar>
|
||||
<v-list
|
||||
rounded
|
||||
style="max-height: 500px; min-height: 400px"
|
||||
>
|
||||
<v-list-item>
|
||||
<v-list-item-title
|
||||
>FileName</v-list-item-title
|
||||
>
|
||||
<v-list-item-subtitle style="max-width: 20%"
|
||||
>Size</v-list-item-subtitle
|
||||
>
|
||||
<v-list-item-subtitle style="max-width: 20%"
|
||||
>Seeders</v-list-item-subtitle
|
||||
>
|
||||
<v-list-item-subtitle style="max-width: 20%"
|
||||
>Leechers</v-list-item-subtitle
|
||||
>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
@click="addTorrent(res.fileUrl)"
|
||||
v-for="res in results"
|
||||
:key="res.title"
|
||||
>
|
||||
<v-list-item-title>
|
||||
{{ res.fileName }}
|
||||
</v-list-item-title>
|
||||
<v-list-item-subtitle
|
||||
style="max-width: 20%"
|
||||
>
|
||||
{{ res.fileSize | size }}
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle
|
||||
style="max-width: 20%"
|
||||
>
|
||||
{{ res.nbSeeders }}
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle
|
||||
style="max-width: 20%"
|
||||
>
|
||||
{{ res.nbLeechers }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</perfect-scrollbar>
|
||||
</div>
|
||||
</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 { Modal, FullScreenModal } from '@/mixins'
|
||||
import qbit from '@/services/qbit'
|
||||
export default {
|
||||
name: 'SearchModal',
|
||||
mixins: [Modal, FullScreenModal],
|
||||
data() {
|
||||
return {
|
||||
searchTerm: null,
|
||||
searchCategory: null,
|
||||
searchId: null,
|
||||
status: null,
|
||||
searchInterval: null,
|
||||
results: [],
|
||||
noResults: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
dialogWidth() {
|
||||
return this.phoneLayout ? '100%' : '750px'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async search() {
|
||||
this.noResults = false
|
||||
if (this.searchTerm && !this.searchInterval) {
|
||||
this.status = 'Running'
|
||||
this.results = []
|
||||
const { data } = await qbit.startSearch(
|
||||
this.searchTerm,
|
||||
this.searchCategory
|
||||
)
|
||||
this.searchId = data.id
|
||||
this.searchInterval = setInterval(async () => {
|
||||
let status = await this.getStatus()
|
||||
if (status === 'Stopped') {
|
||||
clearInterval(this.searchInterval)
|
||||
this.searchInterval = null
|
||||
this.getResults()
|
||||
}
|
||||
}, 2000)
|
||||
}
|
||||
},
|
||||
async getStatus() {
|
||||
if (this.searchId) {
|
||||
const { data } = await qbit.getSearchStatus(this.searchId)
|
||||
return (this.status = data[0].status)
|
||||
}
|
||||
},
|
||||
async getResults() {
|
||||
const { data } = await qbit.getSearchResults(this.searchId)
|
||||
this.results = data.results
|
||||
if (data.results.length === 0) this.noResults = true
|
||||
},
|
||||
addTorrent(torrent) {
|
||||
let params = { urls: null }
|
||||
params.urls = torrent
|
||||
qbit.addTorrents(params)
|
||||
},
|
||||
close() {
|
||||
this.$store.commit('DELETE_MODAL', this.guid)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
67
src/components/Modals/SearchModal/PluginManager.vue
Normal file
67
src/components/Modals/SearchModal/PluginManager.vue
Normal file
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<div>
|
||||
<v-btn @click="opened = true">
|
||||
<v-icon>mdi-cog</v-icon> Plugin manager
|
||||
</v-btn>
|
||||
|
||||
<v-bottom-sheet
|
||||
scrollable
|
||||
inset
|
||||
v-model="opened"
|
||||
v-if="this.$vuetify.breakpoint.smAndDown"
|
||||
>
|
||||
<v-sheet>
|
||||
<v-card>
|
||||
<v-card-title> <v-icon>mdi-toy-brick</v-icon> Plugin manager </v-card-title>
|
||||
<v-card-text>
|
||||
<v-switch
|
||||
v-for="(plugin, key) in searchPlugins"
|
||||
:key="key"
|
||||
:input-value="plugin.enabled"
|
||||
:label="plugin.fullName"
|
||||
@change="togglePlugin(plugin)"
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-sheet>
|
||||
</v-bottom-sheet>
|
||||
<v-dialog v-model="opened" width="50%" v-else>
|
||||
<v-card>
|
||||
<v-card-title> <v-icon>mdi-toy-brick</v-icon> Plugin manager </v-card-title>
|
||||
<v-card-text>
|
||||
<v-switch
|
||||
v-for="(plugin, key) in searchPlugins"
|
||||
:key="key"
|
||||
v-model="plugin.enabled"
|
||||
:label="plugin.fullName"
|
||||
@change="togglePlugin(plugin)"
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import qbit from '@/services/qbit'
|
||||
export default {
|
||||
name: 'PluginsManager',
|
||||
data: () =>({
|
||||
opened: false
|
||||
}),
|
||||
computed: {
|
||||
...mapState(['searchPlugins'])
|
||||
},
|
||||
methods: {
|
||||
togglePlugin(plugin) {
|
||||
qbit.enableSearchPlugin([plugin.name], plugin.enabled)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
opened() {
|
||||
this.$store.commit('FETCH_SEARCH_PLUGINS')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
166
src/components/Modals/SearchModal/SearchModal.vue
Normal file
166
src/components/Modals/SearchModal/SearchModal.vue
Normal file
|
@ -0,0 +1,166 @@
|
|||
<template>
|
||||
<v-dialog
|
||||
v-model="dialog"
|
||||
scrollable
|
||||
:width="dialogWidth"
|
||||
:fullscreen="phoneLayout"
|
||||
:style="{ height: phoneLayout ? '100vh' : '' }"
|
||||
>
|
||||
<v-card :style="{ height: phoneLayout ? '100vh' : '' }">
|
||||
<v-card-title class="justify-center">
|
||||
<h2>Search</h2>
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<v-form
|
||||
ref="form"
|
||||
v-model="searchForm.valid"
|
||||
>
|
||||
<v-container fluid>
|
||||
<v-flex row class="col-12 col-sm-6 col-md-8 mx-auto">
|
||||
<v-text-field
|
||||
v-model="searchForm.pattern"
|
||||
prepend-inner-icon="mdi-magnify"
|
||||
@keypress.enter="$refs.searchButton.click"
|
||||
label="Search"
|
||||
:rules="[v => !!v || 'Searchterm is required']"
|
||||
clearable
|
||||
style="width: 70%"
|
||||
/>
|
||||
<v-spacer/>
|
||||
<v-btn
|
||||
ref="searchButton"
|
||||
:disabled="!searchForm.valid"
|
||||
:color="loading ? 'warning' : 'primary'"
|
||||
@click="loading ? stopSearch() : startSearch()"
|
||||
>
|
||||
{{ loading ? "Stop" : "Search"}}
|
||||
</v-btn>
|
||||
</v-flex>
|
||||
</v-container>
|
||||
</v-form>
|
||||
<perfect-scrollbar>
|
||||
<v-data-table
|
||||
:headers="grid.headers"
|
||||
:items="search.results"
|
||||
:items-per-page="10"
|
||||
:loading="loading"
|
||||
:style="{ maxHeight: '60vh'}"
|
||||
>
|
||||
<template #[`item.fileName`]="{ item }">
|
||||
<a
|
||||
:href="item.descrLink"
|
||||
target="_blank"
|
||||
v-text="item.fileName"
|
||||
/>
|
||||
</template>
|
||||
<template v-slot:[`item.fileSize`]="{ item }">
|
||||
{{ item.fileSize | formatSize }}
|
||||
</template>
|
||||
<template v-slot:[`item.actions`]="{ item }">
|
||||
<v-icon @click="downloadTorrent(item)">mdi-download</v-icon>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</perfect-scrollbar>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<PluginManager/>
|
||||
</v-card-actions>
|
||||
<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 qbit from '@/services/qbit'
|
||||
import { Modal, FullScreenModal, General } from '@/mixins'
|
||||
import PluginManager from './PluginManager'
|
||||
|
||||
export default {
|
||||
name: 'SearchModal',
|
||||
components: { PluginManager },
|
||||
mixins: [Modal, FullScreenModal, General],
|
||||
data() {
|
||||
return {
|
||||
search: {
|
||||
id: null,
|
||||
status: null,
|
||||
interval: null,
|
||||
results: []
|
||||
},
|
||||
loading: false,
|
||||
grid: {
|
||||
headers: [
|
||||
{ text: 'Name', value: 'fileName' },
|
||||
{ text: 'Size', value: 'fileSize' },
|
||||
{ text: 'Seeds', value: 'nbSeeders' },
|
||||
{ text: 'Peers', value: 'nbLeechers' },
|
||||
{ text: 'Search_engine', value: 'siteUrl' },
|
||||
{ text: 'Action', value: 'actions', sortable: false }
|
||||
]
|
||||
},
|
||||
searchForm: {
|
||||
valid: false,
|
||||
pattern: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['getSearchPlugins']),
|
||||
dialogWidth() {
|
||||
return this.phoneLayout ? '100%' : '60%'
|
||||
},
|
||||
enabledSearchPlugins() {
|
||||
return this.getSearchPlugins().filter(p => p.enabled)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async startSearch() {
|
||||
if (this.searchForm.pattern.length && !this.search.interval) {
|
||||
this.loading = true
|
||||
this.search.status = 'Running'
|
||||
this.search.results = []
|
||||
const data = await qbit.startSearch(
|
||||
this.searchForm.pattern,
|
||||
this.enabledSearchPlugins.map(p => p.name)
|
||||
)
|
||||
this.search.id = data.id
|
||||
await this.getStatus()
|
||||
this.search.interval = setInterval(async () => {
|
||||
const status = await this.getStatus()
|
||||
if (status === 'Stopped') {
|
||||
clearInterval(this.search.interval)
|
||||
this.search.interval = null
|
||||
await this.getResults()
|
||||
}
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
async getStatus() {
|
||||
if (this.search.id) {
|
||||
const data = await qbit.getSearchStatus(this.search.id)
|
||||
return (this.search.status = data[0].status)
|
||||
}
|
||||
},
|
||||
async getResults() {
|
||||
const data = await qbit.getSearchResults(this.search.id)
|
||||
this.search.results = data.results
|
||||
this.loading = false
|
||||
},
|
||||
downloadTorrent(item) {
|
||||
this.createModal('addModal', { initialMagnet: item.fileUrl })
|
||||
},
|
||||
stopSearch() {
|
||||
qbit.stopSearch(this.search.id)
|
||||
},
|
||||
close() {
|
||||
this.$store.commit('DELETE_MODAL', this.guid)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -144,7 +144,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {SettingsTab, FullScreenModal} from '@/mixins'
|
||||
import { SettingsTab, FullScreenModal } from '@/mixins'
|
||||
|
||||
export default {
|
||||
name: 'BitTorrent',
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {FullScreenModal, SettingsTab} from '@/mixins'
|
||||
import { FullScreenModal, SettingsTab } from '@/mixins'
|
||||
|
||||
export default {
|
||||
name: 'Downloads',
|
||||
|
|
|
@ -77,7 +77,7 @@ import { mapGetters } from 'vuex'
|
|||
|
||||
import qbit from '@/services/qbit'
|
||||
|
||||
import { Tab, General,FullScreenModal } from '@/mixins'
|
||||
import { Tab, General, FullScreenModal } from '@/mixins'
|
||||
|
||||
export default {
|
||||
name: 'TagsAndCategories',
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<script>
|
||||
import General from './Vuetorrent/General'
|
||||
import Dashboard from './Vuetorrent/Dashboard'
|
||||
import {FullScreenModal} from '@/mixins'
|
||||
import { FullScreenModal } from '@/mixins'
|
||||
|
||||
export default {
|
||||
name: 'VueTorrent',
|
||||
|
@ -31,7 +31,7 @@ export default {
|
|||
General, Dashboard
|
||||
},
|
||||
mixins: [FullScreenModal],
|
||||
data : () => ({
|
||||
data: () => ({
|
||||
tab: null
|
||||
}),
|
||||
methods: {
|
||||
|
@ -40,4 +40,4 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -65,11 +65,11 @@ export default {
|
|||
components: {
|
||||
draggable
|
||||
},
|
||||
computed : {
|
||||
busyTorrentProperties(){
|
||||
computed: {
|
||||
busyTorrentProperties() {
|
||||
return this.$store.state.webuiSettings.busyTorrentProperties
|
||||
},
|
||||
doneTorrentProperties(){
|
||||
doneTorrentProperties() {
|
||||
return this.$store.state.webuiSettings.doneTorrentProperties
|
||||
}
|
||||
}
|
||||
|
@ -78,4 +78,4 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/assets/styles/SettingsTab.scss';
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -172,8 +172,8 @@ export default {
|
|||
return this.getAppVersion()
|
||||
}
|
||||
},
|
||||
methods : {
|
||||
async fetchQbitVersion(){
|
||||
methods: {
|
||||
async fetchQbitVersion() {
|
||||
this.Qbitversion = await qbit.getAppVersion()
|
||||
}
|
||||
},
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import {FullScreenModal, SettingsTab} from '@/mixins'
|
||||
import { FullScreenModal, SettingsTab } from '@/mixins'
|
||||
|
||||
export default {
|
||||
name: 'WebUI',
|
||||
|
|
|
@ -114,12 +114,15 @@ export default {
|
|||
.filter(f => f.priority === 0)
|
||||
.map(f => f.id)
|
||||
|
||||
if (filesToExclude.length)
|
||||
if (filesToExclude.length) {
|
||||
await qbit.setTorrentFilePriority(this.hash, filesToExclude, 0)
|
||||
if (filesToInclude.length)
|
||||
}
|
||||
if (filesToInclude.length) {
|
||||
await qbit.setTorrentFilePriority(this.hash, filesToInclude, 1)
|
||||
if (filesToExclude.length || filesToInclude.length)
|
||||
}
|
||||
if (filesToExclude.length || filesToInclude.length) {
|
||||
await this.getTorrentFiles()
|
||||
}
|
||||
},
|
||||
togleEditing(item) {
|
||||
item.editing = !item.editing
|
||||
|
|
|
@ -114,8 +114,8 @@ export default {
|
|||
return this.getTorrent(this.hash)
|
||||
},
|
||||
availableTags() {
|
||||
let availableTags = this.getAvailableTags()
|
||||
let currentTags = this.getTorrent(this.hash).tags
|
||||
const availableTags = this.getAvailableTags()
|
||||
const currentTags = this.getTorrent(this.hash).tags
|
||||
return difference(availableTags, currentTags)
|
||||
},
|
||||
availableCategories() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue