mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2025-03-14 12:10:18 +03:00
parent
1c06247283
commit
a00a6d539e
13 changed files with 526 additions and 35 deletions
46
.gitignore
vendored
46
.gitignore
vendored
|
@ -1,24 +1,24 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
vuetorrent
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
|
||||
vuetorrent
|
||||
config
|
|
@ -1,22 +1,24 @@
|
|||
<template>
|
||||
<v-app :style="{ backgroundColor: background }">
|
||||
<AddModal />
|
||||
<OldUIModal />
|
||||
<SettingsModal />
|
||||
<SearchModal />
|
||||
<Navbar v-if="isAuthenticated" />
|
||||
<v-content fill-height fill-width>
|
||||
<v-main fill-height fill-width>
|
||||
<router-view></router-view>
|
||||
</v-content>
|
||||
</v-main>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import Navbar from '@/components/Navbar.vue'
|
||||
import SettingsModal from '@/components/SettingsModal/SettingsModal.vue'
|
||||
import { isAuthenticated } from '@/services/auth.js'
|
||||
|
||||
export default {
|
||||
components: { Navbar },
|
||||
components: { Navbar, SettingsModal },
|
||||
name: 'App',
|
||||
data() {
|
||||
return {}
|
||||
|
|
|
@ -52,7 +52,7 @@ import { mapState } from 'vuex'
|
|||
import Modal from '@/mixins/Modal'
|
||||
import qbit from '@/services/qbit'
|
||||
export default {
|
||||
name: 'SettingsModal',
|
||||
name: 'OldUIModal',
|
||||
mixins: [Modal],
|
||||
methods: {
|
||||
async switchOldUI() {
|
||||
|
@ -61,7 +61,7 @@ export default {
|
|||
window.location.reload(true)
|
||||
},
|
||||
save() {
|
||||
this.$store.commit('TOGGLE_MODAL', 'settingsmodal')
|
||||
this.$store.commit('TOGGLE_MODAL', 'olduimodal')
|
||||
}
|
||||
},
|
||||
computed: {
|
185
src/components/SettingsModal/BitTorrent.vue
Normal file
185
src/components/SettingsModal/BitTorrent.vue
Normal file
|
@ -0,0 +1,185 @@
|
|||
<template>
|
||||
<v-container>
|
||||
<v-card flat>
|
||||
<v-card-text>
|
||||
<h3>Privacy</h3>
|
||||
<div class="settings_content ml-5 mr-5">
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Enable DHT (decentralized network) to find more peers`"
|
||||
v-model="settings.dht"
|
||||
/>
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Enable Peer Exchange (PeX) to find more peers`"
|
||||
v-model="settings.pex"
|
||||
/>
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Enable Local Peer Discovery to find more peers`"
|
||||
v-model="settings.lsd"
|
||||
/>
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Enable anonymous mode`"
|
||||
v-model="settings.anonymous_mode"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Torrent Queueing`"
|
||||
v-model="settings.queueing_enabled"
|
||||
/>
|
||||
<div class="settings_content ml-5 mr-5">
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:label="`Maximum active downloads`"
|
||||
:disabled="!settings.queueing_enabled"
|
||||
v-model="settings.max_active_downloads"
|
||||
/>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:label="`Maximum active uploads`"
|
||||
:disabled="!settings.queueing_enabled"
|
||||
v-model="settings.max_active_uploads"
|
||||
/>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:label="`Maximum active torrents`"
|
||||
:disabled="!settings.queueing_enabled"
|
||||
v-model="settings.max_active_torrents"
|
||||
/>
|
||||
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Do not count slow torrents in these limits`"
|
||||
v-model="settings.dont_count_slow_torrents"
|
||||
/>
|
||||
|
||||
<div class="settings_content">
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:label="`Download rate threshold KiB/s`"
|
||||
:disabled="!settings.dont_count_slow_torrents"
|
||||
v-model="settings.slow_torrent_dl_rate_threshold"
|
||||
/>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:label="`Upload rate threshold KiB/s`"
|
||||
:disabled="!settings.dont_count_slow_torrents"
|
||||
v-model="settings.slow_torrent_ul_rate_threshold"
|
||||
/>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:label="`Torrent inactivity timer`"
|
||||
:disabled="!settings.dont_count_slow_torrents"
|
||||
v-model="settings.slow_torrent_inactive_timer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Seeding Limits</h3>
|
||||
<div class="settings_content ml-5 mr-5">
|
||||
<v-row dense>
|
||||
<v-col cols="10">
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`When ratio reaches`"
|
||||
v-model="settings.max_ratio_enabled"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:disabled="!settings.max_ratio_enabled"
|
||||
v-model="settings.max_ratio"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row dense>
|
||||
<v-col cols="10">
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`When seeding time reaches`"
|
||||
v-model="settings.max_seeding_time_enabled"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:disabled="!settings.max_seeding_time_enabled"
|
||||
v-model="settings.max_seeding_time"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions class="d-flex justify-center">
|
||||
<v-btn color="success" @click="save_settings">Save</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import qbit from '@/services/qbit'
|
||||
|
||||
export default {
|
||||
name: 'BitTorrent',
|
||||
methods: {
|
||||
async save_settings() {
|
||||
await qbit.setPreferences(this.getSettings())
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['getSettings']),
|
||||
settings() {
|
||||
return this.getSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.v-input--selection-controls {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.settings_content {
|
||||
border-left: 2px solid black;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin: 2px;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
115
src/components/SettingsModal/Downloads.vue
Normal file
115
src/components/SettingsModal/Downloads.vue
Normal file
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<v-container>
|
||||
<v-card flat>
|
||||
<v-card-text>
|
||||
<h3>When adding a torrent</h3>
|
||||
<div class="settings_content ml-5 mr-5">
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Create subfolder for torrents with multiple files`"
|
||||
v-model="settings.create_subfolder_enabled"
|
||||
/>
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Do not start the download automatically`"
|
||||
v-model="settings.start_paused_enabled"
|
||||
/>
|
||||
<!-- <v-checkbox
|
||||
dense
|
||||
:label="`Delete .torrent files afterwards`"
|
||||
v-model="settings.lsd"
|
||||
/> -->
|
||||
</div>
|
||||
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Pre-allocate disk space for all files`"
|
||||
v-model="settings.preallocate_all"
|
||||
/>
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="` Append .!qB extension to incomplete files`"
|
||||
v-model="settings.incomplete_files_ext"
|
||||
/>
|
||||
|
||||
<h3>Saving Management</h3>
|
||||
<div class="settings_content ml-5 mr-5">
|
||||
<v-row dense>
|
||||
<v-col cols="5" class="d-flex align-center">
|
||||
<h4>Default Save Path</h4>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
v-model="settings.save_path"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row dense>
|
||||
<v-col cols="5">
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Keep incomplete torrents in:`"
|
||||
v-model="settings.temp_path_enabled"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
class="mb-2"
|
||||
outlined
|
||||
dense
|
||||
hide-details
|
||||
:disabled="!settings.temp_path_enabled"
|
||||
v-model="settings.temp_path"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions class="d-flex justify-center">
|
||||
<v-btn color="success" @click="save_settings">Save</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import qbit from '@/services/qbit'
|
||||
|
||||
export default {
|
||||
name: 'BitTorrent',
|
||||
methods: {
|
||||
async save_settings() {
|
||||
await qbit.setPreferences(this.getSettings())
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['getSettings']),
|
||||
settings() {
|
||||
return this.getSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.v-input--selection-controls {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.settings_content {
|
||||
border-left: 2px solid black;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.box {
|
||||
margin: 2px;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
75
src/components/SettingsModal/SettingsModal.vue
Normal file
75
src/components/SettingsModal/SettingsModal.vue
Normal file
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<v-dialog max-width="750px" v-model="dialog">
|
||||
<v-card>
|
||||
<div :style="{ height: phoneLayout ? '100vh' : '' }">
|
||||
<v-card-title class="pb-0 justify-center primary">
|
||||
<h2 class="white--text">Settings</h2>
|
||||
</v-card-title>
|
||||
<v-tabs v-model="tab" background-color="primary" center-active>
|
||||
<v-tab href="#downloads">Downloads</v-tab>
|
||||
<v-tab href="#bittorrent">BitTorrent</v-tab>
|
||||
<v-tab href="#webui">WebUI</v-tab>
|
||||
</v-tabs>
|
||||
<v-tabs-items v-model="tab" touchless>
|
||||
<v-tab-item value="webui">
|
||||
<WebUI :is-active="tab === 'webui'" />
|
||||
</v-tab-item>
|
||||
<v-tab-item value="bittorrent">
|
||||
<BitTorrent :is-active="tab === 'bittorrent'" />
|
||||
</v-tab-item>
|
||||
<v-tab-item value="downloads">
|
||||
<Downloads :is-active="tab === 'downloads'" />
|
||||
</v-tab-item>
|
||||
</v-tabs-items>
|
||||
</div>
|
||||
<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>
|
||||
/* eslint-disable vue/no-unused-components */
|
||||
import Modal from '@/mixins/Modal'
|
||||
// import { mapGetters } from 'vuex'
|
||||
import WebUI from '@/components/SettingsModal/WebUI.vue'
|
||||
import BitTorrent from '@/components/SettingsModal/BitTorrent.vue'
|
||||
import Downloads from '@/components/SettingsModal/Downloads.vue'
|
||||
|
||||
export default {
|
||||
name: 'SettingsModal',
|
||||
mixins: [Modal],
|
||||
components: { WebUI, BitTorrent, Downloads },
|
||||
data() {
|
||||
return {
|
||||
tab: null,
|
||||
items: [],
|
||||
peers: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$store.commit('TOGGLE_MODAL', 'SettingsModal')
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
phoneLayout() {
|
||||
return this.$vuetify.breakpoint.xsOnly
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
dialog(visible) {
|
||||
if (!visible) {
|
||||
this.tab = null
|
||||
} else {
|
||||
// Grab the settings from qbittorrent again
|
||||
this.$store.commit('SET_SETTINGS')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
88
src/components/SettingsModal/WebUI.vue
Normal file
88
src/components/SettingsModal/WebUI.vue
Normal file
|
@ -0,0 +1,88 @@
|
|||
<template>
|
||||
<v-container>
|
||||
<v-card flat>
|
||||
<v-card-text class="pa-0" style="font-size: 1.1em;">
|
||||
<div class="box">
|
||||
<v-subheader>Use Alternative WebUI</v-subheader>
|
||||
<div class="ml-5 mr-5">
|
||||
<v-checkbox
|
||||
dense
|
||||
:label="`Use Alternative WebUI`"
|
||||
v-model="settings.alternative_webui_enabled"
|
||||
/>
|
||||
<v-text-field
|
||||
outlined
|
||||
dense
|
||||
hide-details="true"
|
||||
:label="`Files location`"
|
||||
:disabled="!settings.alternative_webui_enabled"
|
||||
v-model="settings.alternative_webui_path"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<v-subheader
|
||||
>Web User Interface (Remote Control)</v-subheader
|
||||
>
|
||||
<v-row class="ml-5 mr-5">
|
||||
<v-col cols="10">
|
||||
<v-text-field
|
||||
class="mr-1"
|
||||
outlined
|
||||
dense
|
||||
hide-details="true"
|
||||
:label="`IP Address:`"
|
||||
v-model="settings.web_ui_address"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field
|
||||
class="ml-1"
|
||||
outlined
|
||||
dense
|
||||
hide-details="true"
|
||||
:label="`Port`"
|
||||
v-model="settings.web_ui_port"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</v-card-text>
|
||||
<v-card-actions class="d-flex justify-center">
|
||||
<v-btn color="success" @click="save_settings">Save</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import qbit from '@/services/qbit'
|
||||
|
||||
export default {
|
||||
name: 'WebUI',
|
||||
props: {
|
||||
// localSettings: {}
|
||||
},
|
||||
methods: {
|
||||
async save_settings() {
|
||||
await qbit.setPreferences(this.getSettings())
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['getSettings']),
|
||||
settings() {
|
||||
return this.getSettings()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box {
|
||||
margin: 2px;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
|
@ -175,7 +175,10 @@ export default {
|
|||
|
||||
<style>
|
||||
.project.done {
|
||||
border-left: 4px solid #3cd1c2;
|
||||
border-left: 4px solid #2e5eaa;
|
||||
}
|
||||
.project.downloading {
|
||||
border-left: 4px solid #1fc176;
|
||||
}
|
||||
.project.busy {
|
||||
border-left: 4px solid #ffaa2c;
|
||||
|
@ -184,13 +187,16 @@ export default {
|
|||
border-left: 4px solid #f83e70;
|
||||
}
|
||||
.project.paused {
|
||||
border-left: 4px solid #cfd8dc;
|
||||
border-left: 4px solid #eb8a90;
|
||||
}
|
||||
.project.queued {
|
||||
border-left: 4px solid #2e5eaa;
|
||||
}
|
||||
.v-chip.done {
|
||||
background: #3cd1c2 !important;
|
||||
background: #2e5eaa !important;
|
||||
}
|
||||
.v-chip.downloading {
|
||||
background: #1fc176 !important;
|
||||
}
|
||||
.v-chip.busy {
|
||||
background: #ffaa2c !important;
|
||||
|
@ -199,7 +205,16 @@ export default {
|
|||
background: #f83e70 !important;
|
||||
}
|
||||
.v-chip.paused {
|
||||
background: #cfd8dc !important;
|
||||
background: #eb8a90 !important;
|
||||
}
|
||||
.noselect {
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-khtml-user-select: none; /* Konqueror HTML */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none; /* Non-prefixed version, currently
|
||||
supported by Chrome and Opera */
|
||||
}
|
||||
.v-chip.queued {
|
||||
background: #2e5eaa !important;
|
||||
|
|
|
@ -67,7 +67,7 @@ import Tags from '@/components/TorrentDetailModal/Tags'
|
|||
export default {
|
||||
name: 'TorrentDetailModal',
|
||||
mixins: [Modal],
|
||||
components: { Content, Info, Peers, Trackers,Tags },
|
||||
components: { Content, Info, Peers, Trackers, Tags },
|
||||
data() {
|
||||
return {
|
||||
tab: null,
|
||||
|
|
|
@ -30,7 +30,7 @@ export default class Torrent {
|
|||
case 'pausedDL':
|
||||
return 'paused'
|
||||
case 'downloading':
|
||||
return 'busy'
|
||||
return 'downloading'
|
||||
case 'stalledDL':
|
||||
return 'fail'
|
||||
case 'pausedUP':
|
||||
|
|
|
@ -35,6 +35,7 @@ export default new Vuex.Store({
|
|||
addmodal: false,
|
||||
deletemodal: false,
|
||||
settingsmodal: false,
|
||||
olduimodal: false,
|
||||
torrentdetailmodal: false
|
||||
},
|
||||
settings: {},
|
||||
|
|
|
@ -52,7 +52,10 @@ export default {
|
|||
},
|
||||
SET_SETTINGS: async state => {
|
||||
const { data } = await qbit.getAppPreferences()
|
||||
state.settings.savePath = data.save_path
|
||||
state.settings = data
|
||||
// state.settings.savePath = data.save_path
|
||||
// state.settings.alternative_webui_enabled = data.alternative_webui_enabled
|
||||
// state.settings.alternative_webui_path = data.alternative_webui_path
|
||||
},
|
||||
SET_SELECTED_TORRENT_DETAIL: (state, hash) => {
|
||||
state.selectedDetailTorrent = hash
|
||||
|
|
|
@ -2,7 +2,14 @@ module.exports = {
|
|||
outputDir: 'vuetorrent/public',
|
||||
publicPath: './',
|
||||
transpileDependencies: ['vuetify'],
|
||||
configureWebpack: {
|
||||
devtool: 'source-map'
|
||||
},
|
||||
devServer: {
|
||||
watchOptions: {
|
||||
poll: true
|
||||
},
|
||||
host: 'localhost',
|
||||
port: 8000,
|
||||
proxy: {
|
||||
'/api': {
|
||||
|
|
Loading…
Add table
Reference in a new issue