diff --git a/src/Helpers/ArrayHelper.js b/src/Helpers/ArrayHelper.js new file mode 100644 index 00000000..f3ab9840 --- /dev/null +++ b/src/Helpers/ArrayHelper.js @@ -0,0 +1,14 @@ +import * as _ from 'lodash' + +export class ArrayHelper { + static remove(array, item) { + const toRemove = Array.isArray(item) ? item : [item] + _.remove(array, item => toRemove.indexOf(item) > -1) + + return array + } + + static concat(a, b) { + return _.concat(a, b) + } +} diff --git a/src/Helpers/Hostname.js b/src/Helpers/Hostname.js new file mode 100644 index 00000000..5df86c9b --- /dev/null +++ b/src/Helpers/Hostname.js @@ -0,0 +1,13 @@ +export class Hostname { + static get(url) { + const match = url.match(/:\/\/(www[0-9]?\.)?(.[^/:]+)/i) + if (match != null && + match.length > 2 && + typeof match[2] === 'string' && + match[2].length > 0) { + return match[2] + } else { + return '' + } + } +} diff --git a/src/Helpers/index.js b/src/Helpers/index.js new file mode 100644 index 00000000..63a46a89 --- /dev/null +++ b/src/Helpers/index.js @@ -0,0 +1,6 @@ +import { ArrayHelper } from './ArrayHelper' +import { Hostname } from './Hostname' + +export { + ArrayHelper, Hostname +} diff --git a/src/actions/DocumentTitle.js b/src/actions/DocumentTitle.js index c16baf0e..6875bc8f 100644 --- a/src/actions/DocumentTitle.js +++ b/src/actions/DocumentTitle.js @@ -1,29 +1,33 @@ import { formatBytes } from '@/helpers' +import store from '../store' + export class DocumentTitle { static setDefault() { this.set('VueTorrent') } - static setGlobalSpeed(speeds) { - if (!speeds || speeds.length !== 2) return - this.set(`[D: ${formatBytes(speeds[0])}/s, U: ${formatBytes(speeds[1])}/s] VueTorrent`) + static setGlobalSpeed() { + const status = store.getters.getStatus() + this.set(`[D: ${formatBytes(status.upspeed)}/s, U: ${formatBytes(status.dlspeed)}/s] VueTorrent`) } - static setFirstTorrentStatus(torrent) { - if (!torrent) return + static setFirstTorrentStatus() { + const torrents = store.getters.getTorrents() + if (!torrents && !torrents.length) return + const torrent = torrents[0] this.set(`[D: ${formatBytes(torrent.dlspeed)}/s, U: ${formatBytes(torrent.upspeed)}/s] ${torrent.progress}%`) } - static updateTitle(mode, speeds, torrent) { - if (!mode || !speeds.length || !torrent) return + static update() { + const mode = store.getters.getWebuiSettings().title switch (mode) { case 'Default': return this.setDefault() case 'Global Speed': - return this.setGlobalSpeed(speeds) + return this.setGlobalSpeed() case 'First Torrent Status': - return this.setFirstTorrentStatus(torrent) + return this.setFirstTorrentStatus() default: return this.setDefault() } diff --git a/src/actions/Graph.js b/src/actions/Graph.js new file mode 100644 index 00000000..7ffc3f81 --- /dev/null +++ b/src/actions/Graph.js @@ -0,0 +1,11 @@ +import store from '../store' + +export class Graph { + static update() { + const state = store.state + state.download_data.shift() + state.download_data.push(state.status.dlspeedRaw || 0) + state.upload_data.shift() + state.upload_data.push(state.status.upspeedRaw || 0) + } +} diff --git a/src/actions/ServerStatus.js b/src/actions/ServerStatus.js new file mode 100644 index 00000000..af58b889 --- /dev/null +++ b/src/actions/ServerStatus.js @@ -0,0 +1,10 @@ +import store from '../store' +import Status from '@/models/Status' + +export class ServerStatus { + static update(response) { + if (response.server_state) { + store.state.status = new Status(response.server_state) + } + } +} diff --git a/src/actions/Tags.js b/src/actions/Tags.js new file mode 100644 index 00000000..9054cc18 --- /dev/null +++ b/src/actions/Tags.js @@ -0,0 +1,24 @@ +import store from '../store' +import { ArrayHelper } from '@/Helpers' + +export class Tags { + static update(response) { + if (response?.full_update === true) { + store.state.tags = response.tags + + return + } + + if (response.tags_removed) { + store.state.tags = ArrayHelper.remove(store.state.tags, response.tags_removed) + + return + } + + if (response.tags) { + store.state.tags = ArrayHelper.concat(store.state.tags, response.tags) + + + } + } +} diff --git a/src/actions/Torrents.js b/src/actions/Torrents.js new file mode 100644 index 00000000..05618fdf --- /dev/null +++ b/src/actions/Torrents.js @@ -0,0 +1,17 @@ +import store from '../store' +import { Hostname } from '@/Helpers' +import Torrent from '@/models/Torrent' + +export class Torrents { + static update(data) { + if (store.state.webuiSettings.showTrackerFilter) { // dont calculate trackers when disabled + + if (store.state.sort_options.tracker !== null) { + data = data.filter(d => Hostname.get(d.tracker) === store.state.sort_options.tracker) + } + } + + // update torrents + store.state.torrents = data.map(t => new Torrent(t)) + } +} diff --git a/src/actions/Trackers.js b/src/actions/Trackers.js new file mode 100644 index 00000000..2a1db8f3 --- /dev/null +++ b/src/actions/Trackers.js @@ -0,0 +1,13 @@ +import store from '../store' +import { Hostname } from '@/Helpers' + +export class Trackers { + static update(data) { + if (store.state.webuiSettings.showTrackerFilter) { + store.state.trackers = data.map(t => t.tracker) + .map(url => Hostname.get(url)) + .filter((domain, index, self) => index === self.indexOf(domain) && domain) + .sort() + } + } +} diff --git a/src/actions/index.js b/src/actions/index.js index 955e08ff..c562db80 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,5 +1,11 @@ import { DocumentTitle } from './DocumentTitle' +import { Tags } from './Tags' +import { Torrents } from './Torrents' +import { Trackers } from './Trackers' +import { Graph } from './Graph' +import { ServerStatus } from './ServerStatus' export { - DocumentTitle + DocumentTitle, Tags, Torrents, Trackers, + Graph, ServerStatus } diff --git a/src/models/Status.js b/src/models/Status.js index 1e6b6db4..865ca614 100644 --- a/src/models/Status.js +++ b/src/models/Status.js @@ -1,18 +1,29 @@ +import store from '../store' + export default class Status { - constructor(data, tags) { - if (data) { - this.status = data.connection_status - this.downloaded = data.dl_info_data - this.uploaded = data.up_info_data - this.dlspeed = data.dl_info_speed - this.upspeed = data.up_info_speed - this.freeDiskSpace = data.free_space_on_disk - this.altSpeed = data.use_alt_speed_limits - this.dlspeedRaw = this.formatSpeed(data.dl_info_speed) - this.upspeedRaw = this.formatSpeed(data.up_info_speed) - this.tags = tags - Object.freeze(this) - } + constructor({ + connection_status, + dl_info_data, + up_info_data, + dl_info_speed, + up_info_speed, + free_space_on_disk, + use_alt_speed_limits + }) { + + const previous = store.state.status + + this.status = connection_status || previous.status + this.downloaded = dl_info_data || previous.downloaded + this.uploaded = up_info_data || previous.uploaded + this.dlspeed = dl_info_speed || previous.dlspeed + this.upspeed = up_info_speed || previous.upspeed + this.freeDiskSpace = free_space_on_disk || previous.freeDiskSpace + this.altSpeed = use_alt_speed_limits || previous.altSpeed + this.dlspeedRaw = this.formatSpeed(dl_info_speed) || previous.dlspeedRaw + this.upspeedRaw = this.formatSpeed(up_info_speed) || previous.upspeedRaw + Object.freeze(this) + } formatSpeed(value) { diff --git a/src/services/qbit.js b/src/services/qbit.js index f02e40f1..08c3ec09 100644 --- a/src/services/qbit.js +++ b/src/services/qbit.js @@ -12,7 +12,7 @@ class Qbit { execute(method, action, params) { if (method === 'post') { const data = new URLSearchParams(params) - + return this.axios.post(action, data).then(res => res.data) } } @@ -35,7 +35,7 @@ class Qbit { return status === 200 || status === 403 } }) - + return data } @@ -62,6 +62,7 @@ class Qbit { getMainData(rid) { return this.axios.get( '/sync/maindata', { params: { rid } }) + .then(res => res.data) } switchToOldUi() { @@ -121,7 +122,7 @@ class Qbit { hash, name } - + return this.axios.get('/torrents/rename', { params }) } @@ -167,7 +168,7 @@ class Qbit { } else { data = new URLSearchParams(params) } - + return this.axios.post('/torrents/add', data) } @@ -177,13 +178,13 @@ class Qbit { id: idList.join('|'), priority } - + return this.execute('post', '/torrents/filePrio', params) } deleteTorrents(hashes, deleteFiles) { if (!hashes.length) return - + return this.torrentAction('delete', hashes, { deleteFiles }) } @@ -248,16 +249,16 @@ class Qbit { hash, urls: trackers } - + return this.execute('post', '/torrents/addTrackers', params) } removeTorrentTrackers(hash, trackers) { const params = { hash, - urls: trackers.join('|') + urls: trackers.join('|') } - + return this.execute('post', '/torrents/removeTrackers', params) } @@ -266,7 +267,7 @@ class Qbit { hashes: hashes.length ? hashes.join('|') : 'all', ...extra } - + return this.execute('post', `/torrents/${action}`, params) } @@ -276,7 +277,7 @@ class Qbit { id, name } - + return this.execute('post', '/torrents/renameFile', params) } @@ -344,7 +345,7 @@ class Qbit { category: cat.name, savePath: cat.savePath } - + return this.execute('post', '/torrents/editCategory', params) } @@ -359,7 +360,7 @@ class Qbit { names: plugins.join('|'), enable } - + return this.execute('post', '/search/enablePlugin', params) } @@ -369,7 +370,7 @@ class Qbit { plugins: Array.isArray(plugins) ? plugins.join('|') : 'all', category: 'all' } - + return this.execute('post', '/search/start', params) } diff --git a/src/store/getters.js b/src/store/getters.js index c48cd8e9..40096ef5 100644 --- a/src/store/getters.js +++ b/src/store/getters.js @@ -9,7 +9,7 @@ export default { getTorrent: state => hash => state.torrents.filter(el => el.hash === hash)[0], getWebuiSettings: state => () => state.webuiSettings, - getAvailableTags: state => () => state.status.tags, + getAvailableTags: state => () => state.tags, getCategories: state => () => state.categories, getModals: state => () => state.modals, getTorrents: state => () => state.torrents, diff --git a/src/store/index.js b/src/store/index.js index 50f6b0d9..61810e33 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -97,6 +97,7 @@ export default new Vuex.Store({ }, categories: [], trackers: [], + tags: [], filteredTorrentsCount: 0, latestSelectedTorrent: null, selectMode: false, diff --git a/src/store/mutations.js b/src/store/mutations.js index ba840554..017a1250 100644 --- a/src/store/mutations.js +++ b/src/store/mutations.js @@ -1,8 +1,5 @@ -import Torrent from '../models/Torrent' -import Status from '../models/Status' import qbit from '../services/qbit' -import { getHostName } from '@/helpers' -import { DocumentTitle } from '@/actions' +import { DocumentTitle, Tags, Trackers, Torrents, Graph, ServerStatus } from '@/actions' export default { SET_APP_VERSION(state, version) { @@ -45,49 +42,27 @@ export default { TOGGLE_THEME(state) { state.webuiSettings.darkTheme = !state.webuiSettings.darkTheme }, - LOGOUT: state => { - qbit.logout() + LOGOUT: async state => { + await qbit.logout() state.authenticated = false }, LOGIN: async (state, payload) => { state.authenticated = payload }, updateMainData: async state => { - const res = await qbit.getMainData(undefined) + const response = await qbit.getMainData(state.rid || undefined) + state.rid = response.rid || undefined - // status - state.status = new Status(res.data.server_state, res.data.tags) + ServerStatus.update(response) + Tags.update(response) + Graph.update() - // graph - state.download_data.splice(0, 1) - state.download_data.push(state.status.dlspeedRaw) - state.upload_data.splice(0, 1) - state.upload_data.push(state.status.upspeedRaw) + // fetch torrent data + const { data } = await qbit.getTorrents(state.sort_options) - // torrents - let { data } = await qbit.getTorrents(state.sort_options) - - // trackers - if (state.webuiSettings.showTrackerFilter) { // dont calculate trackers when disabled - state.trackers = data.map(t => t.tracker) - .map(url => getHostName(url)) - .filter((domain, index, self) => index === self.indexOf(domain) && domain) - .sort() - - if (state.sort_options.tracker !== null) { - data = data.filter(d => getHostName(d.tracker) === state.sort_options.tracker) - } - } - - // torrents - state.torrents = data.map(t => new Torrent(t)) - - // update document title - DocumentTitle.updateTitle( - state.webuiSettings.title, - [state.status.dlspeed, state.status.upspeed], - state.torrents ? state.torrents[0] : null - ) + Trackers.update(data) + Torrents.update(data) + DocumentTitle.update() }, FETCH_SETTINGS: async state => { const { data } = await qbit.getAppPreferences()