Refine vuex store

This commit is contained in:
CzBiX
2019-09-16 04:06:28 +08:00
parent cf1d48ea7a
commit e81b9e0db2
8 changed files with 179 additions and 57 deletions

View File

@@ -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',

View File

@@ -35,7 +35,7 @@
<torrents />
</v-content>
<add-form v-if="preferences" :url="pasteUrl" @input="pasteUrl = null"/>
<add-form v-if="preferences" />
<login-form v-if="needAuth" v-model="needAuth" />
<logs-dialog v-if="drawerOptions.showLogs" v-model="drawerOptions.showLogs" />
@@ -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,
});
}
},
},

View File

@@ -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();

51
src/store/config.ts Normal file
View File

@@ -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<ConfigState, RootState> = {
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);
},
},
};

View File

@@ -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<RootState>({
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;
},

12
src/store/types.ts Normal file
View File

@@ -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;
}

83
src/types.ts Normal file
View File

@@ -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<string, Category>;
server_state: ServerState;
torrents: Record<string, Torrent>;
}

View File

@@ -87,3 +87,7 @@ export function getSameNamedTorrents(allTorrents: Array<any>, torrents: Array<an
return result;
}
export function typed<T>(value: T): T {
return value;
}