From e81b9e0db2d621e10cc22aebaadb5bf20177a30b Mon Sep 17 00:00:00 2001 From: CzBiX Date: Mon, 16 Sep 2019 04:06:28 +0800 Subject: [PATCH] Refine vuex store --- .eslintrc.js | 1 + src/App.vue | 15 +++--- src/components/AddForm.vue | 15 +++--- src/store/config.ts | 51 ++++++++++++++++++++ src/{store.ts => store/index.ts} | 55 ++++++--------------- src/store/types.ts | 12 +++++ src/types.ts | 83 ++++++++++++++++++++++++++++++++ src/utils.ts | 4 ++ 8 files changed, 179 insertions(+), 57 deletions(-) create mode 100644 src/store/config.ts rename src/{store.ts => store/index.ts} (73%) create mode 100644 src/store/types.ts create mode 100644 src/types.ts 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; +}