diff --git a/.eslintrc.js b/.eslintrc.js
index e218bef..30a75ab 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -14,6 +14,7 @@ module.exports = {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+ 'import/prefer-default-export': 'off',
'no-restricted-syntax': 'off',
'no-await-in-loop': 'off',
'no-plusplus': 'off',
diff --git a/src/App.vue b/src/App.vue
index d6f9116..c5cffb4 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -35,7 +35,7 @@
-
+
@@ -86,13 +86,12 @@ export default Vue.extend({
drawerOptions: {
showLogs: false,
},
- pasteUrl: null,
task: 0,
};
},
async created() {
await this.getInitData();
- appWrapEl = this.$refs.app.$el.querySelector('.v-application--wrap');
+ appWrapEl = (this.$refs.app as any).$el.querySelector('.v-application--wrap');
appWrapEl.addEventListener('paste', this.onPaste);
},
beforeDestroy() {
@@ -150,18 +149,20 @@ export default Vue.extend({
}
await sleep(3000);
- this.$refs.end.scrollIntoView({
+ (this.$refs.end as HTMLElement).scrollIntoView({
behavior: 'smooth',
});
},
onPaste(e: ClipboardEvent) {
- if (e.target.tagName === 'INPUT') {
+ if ((e.target as HTMLElement).tagName === 'INPUT') {
return;
}
- const text = e.clipboardData.getData('text');
+ const text = e.clipboardData!.getData('text');
if (text) {
- this.pasteUrl = text;
+ this.$store.commit('setPasteUrl', {
+ url: text,
+ });
}
},
},
diff --git a/src/components/AddForm.vue b/src/components/AddForm.vue
index 5ef2ed2..e36a85e 100644
--- a/src/components/AddForm.vue
+++ b/src/components/AddForm.vue
@@ -141,10 +141,6 @@ const defaultParams = {
};
export default Vue.extend({
- props: {
- url: String,
- },
-
data() {
return {
placeholder: 'Upload torrents by drop them here,\nor click attachment button at right to select.',
@@ -159,7 +155,10 @@ export default Vue.extend({
},
computed: {
...mapState({
+ pasteUrl: 'pasteUrl',
prefs: 'preferences',
+ }),
+ ...mapState({
categories(state, getters) {
return getters.allCategories.map(c => ({ text: c.name, value: c.key }));
},
@@ -187,10 +186,10 @@ export default Vue.extend({
this.showMore = !this.phoneLayout;
},
mounted() {
- this.$refs.fileZone.addEventListener('drop', this.onDrop, true);
+ (this.$refs.fileZone as HTMLElement).addEventListener('drop', this.onDrop, true);
},
beforeDestroy() {
- this.$refs.fileZone.removeEventListener('drop', this.onDrop, true);
+ (this.$refs.fileZone as HTMLElement).removeEventListener('drop', this.onDrop, true);
},
methods: {
@@ -256,7 +255,7 @@ export default Vue.extend({
},
watch: {
- url(v) {
+ pasteUrl(v) {
if (!v) {
return;
}
@@ -265,8 +264,6 @@ export default Vue.extend({
Vue.set(this.userParams, 'urls', v);
this.dialog = true;
}
-
- this.$emit('input', null);
},
files(v) {
this.$refs.form.validate();
diff --git a/src/store/config.ts b/src/store/config.ts
new file mode 100644
index 0000000..4148bf7
--- /dev/null
+++ b/src/store/config.ts
@@ -0,0 +1,51 @@
+import _ from 'lodash';
+import Vue from 'vue';
+import { Module } from 'vuex';
+import { RootState, ConfigState } from './types';
+
+const configKey = 'qb-config';
+
+const defaultConfig = {
+ updateInterval: 2000,
+ pageOptions: {
+ itemsPerPage: 50,
+ },
+ filter: {
+ state: null,
+ category: null,
+ site: null,
+ },
+};
+
+function saveConfig(obj: any) {
+ localStorage[configKey] = JSON.stringify(obj);
+}
+
+function loadConfig() {
+ const tmp = localStorage[configKey];
+ if (!tmp) {
+ return {};
+ }
+
+ return JSON.parse(tmp);
+}
+
+export const configStore : Module = {
+ state: {
+ userConfig: loadConfig(),
+ },
+ mutations: {
+ updateConfig(state, payload) {
+ const { key, value } = payload;
+ const tmp = _.merge({}, state.userConfig[key], value);
+ Vue.set(state.userConfig, key, tmp);
+
+ saveConfig(state.userConfig);
+ },
+ },
+ getters: {
+ config(state) {
+ return _.merge({}, defaultConfig, state.userConfig);
+ },
+ },
+};
diff --git a/src/store.ts b/src/store/index.ts
similarity index 73%
rename from src/store.ts
rename to src/store/index.ts
index 9500655..9936351 100644
--- a/src/store.ts
+++ b/src/store/index.ts
@@ -1,50 +1,30 @@
import Vue from 'vue';
import Vuex from 'vuex';
import _ from 'lodash';
-import { AllStateTypes } from './consts';
-import { torrentIsState } from './utils';
+import { configStore } from './config';
+import { AllStateTypes } from '../consts';
+import { torrentIsState } from '../utils';
+import { RootState } from './types';
Vue.use(Vuex);
-const defaultConfig = {
- updateInterval: 2000,
- pageOptions: {
- itemsPerPage: 50,
+export default new Vuex.Store({
+ modules: {
+ config: configStore,
},
- filter: {
- state: null,
- category: null,
- site: null,
- },
-};
-
-const configKey = 'qb-config';
-
-function saveConfig(obj: any) {
- localStorage[configKey] = JSON.stringify(obj);
-}
-
-function loadConfig() {
- const tmp = localStorage[configKey];
- if (!tmp) {
- return {};
- }
-
- return JSON.parse(tmp);
-}
-
-export default new Vuex.Store({
state: {
rid: 0,
- mainData: null,
- userConfig: loadConfig(),
+ mainData: undefined,
preferences: null,
+ pasteUrl: null,
},
mutations: {
/* eslint-disable no-param-reassign */
updateMainData(state, payload) {
state.rid = payload.rid;
+ delete payload.rid;
if (payload.full_update) {
+ delete payload.full_update;
state.mainData = payload;
} else {
const tmp: any = _.cloneDeep(state.mainData);
@@ -66,20 +46,13 @@ export default new Vuex.Store({
updatePreferences(state, payload) {
state.preferences = payload;
},
- updateConfig(state, payload) {
- const { key } = payload;
- const { value } = payload;
- const tmp = _.merge({}, state.userConfig[key], value);
- Vue.set(state.userConfig, key, tmp);
-
- saveConfig(state.userConfig);
+ setPasteUrl(state, payload) {
+ const { url } = payload;
+ state.pasteUrl = url;
},
/* eslint-enable no-param-reassign */
},
getters: {
- config(state) {
- return _.merge({}, defaultConfig, state.userConfig);
- },
isDataReady(state) {
return !!state.mainData;
},
diff --git a/src/store/types.ts b/src/store/types.ts
new file mode 100644
index 0000000..0ee1b50
--- /dev/null
+++ b/src/store/types.ts
@@ -0,0 +1,12 @@
+import { MainData } from '@/types';
+
+export interface RootState {
+ rid: number;
+ mainData?: MainData;
+ preferences: any;
+ pasteUrl: string | null;
+}
+
+export interface ConfigState {
+ userConfig: any;
+}
diff --git a/src/types.ts b/src/types.ts
new file mode 100644
index 0000000..7344c52
--- /dev/null
+++ b/src/types.ts
@@ -0,0 +1,83 @@
+/* eslint-disable camelcase */
+export interface Torrent {
+ added_on: number;
+ amount_left: number;
+ auto_tmm: boolean
+ availability: number;
+ category: string;
+ completed: number;
+ completion_on: number;
+ dl_limit: number;
+ dlspeed: number;
+ downloaded: number;
+ downloaded_session: number;
+ eta: number;
+ f_l_piece_prio: boolean
+ force_start: boolean
+ last_activity: number;
+ magnet_uri: string;
+ max_ratio: number;
+ max_seeding_time: number;
+ name: string;
+ num_complete: number;
+ num_incomplete: number;
+ num_leechs: number;
+ num_seeds: number;
+ priority: number;
+ progress: number;
+ ratio: number;
+ ratio_limit: number;
+ save_path: string;
+ seeding_time_limit: number;
+ seen_complete: number;
+ seq_dl: boolean
+ size: number;
+ state: string;
+ super_seeding: boolean
+ tags: string;
+ time_active: number;
+ total_size: number;
+ tracker: string;
+ up_limit: number;
+ uploaded: number;
+ uploaded_session: number;
+ upspeed: number;
+}
+
+export interface Category {
+ name: string;
+ savePath: string;
+}
+
+export interface ServerState {
+ alltime_dl: number;
+ alltime_ul: number;
+ average_time_queue: number;
+ connection_status: string;
+ dht_nodes: number;
+ dl_info_data: number;
+ dl_info_speed: number;
+ dl_rate_limit: number;
+ free_space_on_disk: number;
+ global_ratio: string;
+ queued_io_jobs: number;
+ queueing: boolean;
+ read_cache_hits: string;
+ read_cache_overload: string;
+ refresh_interval: number;
+ total_buffers_size: number;
+ total_peer_connections: number;
+ total_queued_size: number;
+ total_wasted_session: number;
+ up_info_data: number;
+ up_info_speed: number;
+ up_rate_limit: number;
+ use_alt_speed_limits: boolean;
+ write_cache_overload: string;
+}
+
+export interface MainData {
+ categories: Record;
+ server_state: ServerState;
+ torrents: Record;
+}
diff --git a/src/utils.ts b/src/utils.ts
index 4cc5fc1..1c19c86 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -87,3 +87,7 @@ export function getSameNamedTorrents(allTorrents: Array, torrents: Array(value: T): T {
+ return value;
+}