summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2020-03-31 09:11:43 +0900
committersyuilo <syuilotan@yahoo.co.jp>2020-03-31 09:11:43 +0900
commit28f8933c3c7a838bc159b58428b0f0cf57c18a5a (patch)
tree8865b348d5f90055a5fe65fb5f6536940a83332a /src
parentMerge branch 'master' into develop (diff)
downloadmisskey-28f8933c3c7a838bc159b58428b0f0cf57c18a5a.tar.gz
misskey-28f8933c3c7a838bc159b58428b0f0cf57c18a5a.tar.bz2
misskey-28f8933c3c7a838bc159b58428b0f0cf57c18a5a.zip
Refactoring
Diffstat (limited to 'src')
-rw-r--r--src/client/init.ts55
-rw-r--r--src/client/mios.ts73
-rw-r--r--src/client/store.ts68
3 files changed, 101 insertions, 95 deletions
diff --git a/src/client/init.ts b/src/client/init.ts
index 1fcd97190d..73e02145d5 100644
--- a/src/client/init.ts
+++ b/src/client/init.ts
@@ -20,6 +20,7 @@ import Menu from './components/menu.vue';
import { router } from './router';
import { applyTheme, lightTheme, builtinThemes } from './theme';
import { isDeviceDarkmode } from './scripts/is-device-darkmode';
+import createStore from './store';
Vue.use(Vuex);
Vue.use(VueHotkey);
@@ -134,36 +135,38 @@ document.body.setAttribute('ontouchstart', '');
// アプリ基底要素マウント
document.body.innerHTML = '<div id="app"></div>';
-const os = new MiOS();
+const store = createStore();
+
+const os = new MiOS(store);
os.init(async () => {
window.addEventListener('storage', e => {
if (e.key === 'vuex') {
- os.store.replaceState(JSON.parse(localStorage['vuex']));
+ store.replaceState(JSON.parse(localStorage['vuex']));
} else if (e.key === 'i') {
location.reload();
}
}, false)
- os.store.watch(state => state.device.darkMode, darkMode => {
+ store.watch(state => state.device.darkMode, darkMode => {
// TODO: このファイルでbuiltinThemesを参照するとcode splittingが効かず、初回読み込み時に全てのテーマコードを読み込むことになってしまい無駄なので何とかする
- const themes = builtinThemes.concat(os.store.state.device.themes);
- applyTheme(themes.find(x => x.id === (darkMode ? os.store.state.device.darkTheme : os.store.state.device.lightTheme)));
+ const themes = builtinThemes.concat(store.state.device.themes);
+ applyTheme(themes.find(x => x.id === (darkMode ? store.state.device.darkTheme : store.state.device.lightTheme)));
});
//#region Sync dark mode
- if (os.store.state.device.syncDeviceDarkMode) {
- os.store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
+ if (store.state.device.syncDeviceDarkMode) {
+ store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
}
window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
- if (os.store.state.device.syncDeviceDarkMode) {
- os.store.commit('device/set', { key: 'darkMode', value: mql.matches });
+ if (store.state.device.syncDeviceDarkMode) {
+ store.commit('device/set', { key: 'darkMode', value: mql.matches });
}
});
//#endregion
- if ('Notification' in window && os.store.getters.isSignedIn) {
+ if ('Notification' in window && store.getters.isSignedIn) {
// 許可を得ていなかったらリクエスト
if (Notification.permission === 'default') {
Notification.requestPermission();
@@ -171,7 +174,7 @@ os.init(async () => {
}
const app = new Vue({
- store: os.store,
+ store: store,
metaInfo: {
title: null,
titleTemplate: title => title ? `${title} | ${(instanceName || 'Misskey')}` : (instanceName || 'Misskey')
@@ -183,7 +186,7 @@ os.init(async () => {
};
},
methods: {
- api: os.api,
+ api: (endpoint: string, data: { [x: string]: any } = {}, token?) => store.dispatch('api', { endpoint, data, token }),
signout: os.signout,
new(vm, props) {
const x = new vm({
@@ -234,58 +237,58 @@ os.init(async () => {
// マウント
app.$mount('#app');
- if (app.$store.getters.isSignedIn) {
+ if (store.getters.isSignedIn) {
const main = os.stream.useSharedConnection('main');
// 自分の情報が更新されたとき
main.on('meUpdated', i => {
- app.$store.dispatch('mergeMe', i);
+ store.dispatch('mergeMe', i);
});
main.on('readAllNotifications', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadNotification: false
});
});
main.on('unreadNotification', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadNotification: true
});
});
main.on('unreadMention', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadMentions: true
});
});
main.on('readAllUnreadMentions', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadMentions: false
});
});
main.on('unreadSpecifiedNote', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadSpecifiedNotes: true
});
});
main.on('readAllUnreadSpecifiedNotes', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadSpecifiedNotes: false
});
});
main.on('readAllMessagingMessages', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadMessagingMessage: false
});
});
main.on('unreadMessagingMessage', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadMessagingMessage: true
});
@@ -293,13 +296,13 @@ os.init(async () => {
});
main.on('readAllAntennas', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadAntenna: false
});
});
main.on('unreadAntenna', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadAntenna: true
});
@@ -307,13 +310,13 @@ os.init(async () => {
});
main.on('readAllAnnouncements', () => {
- app.$store.dispatch('mergeMe', {
+ store.dispatch('mergeMe', {
hasUnreadAnnouncement: false
});
});
main.on('clientSettingUpdated', x => {
- app.$store.commit('settings/set', {
+ store.commit('settings/set', {
key: x.key,
value: x.value
});
diff --git a/src/client/mios.ts b/src/client/mios.ts
index aa2b202abd..63d9f7d3a0 100644
--- a/src/client/mios.ts
+++ b/src/client/mios.ts
@@ -2,16 +2,11 @@ import autobind from 'autobind-decorator';
import Vue from 'vue';
import { EventEmitter } from 'eventemitter3';
-import initStore from './store';
import { apiUrl, version } from './config';
import Progress from './scripts/loading';
import Stream from './scripts/stream';
-
-//#region api requests
-let spinner = null;
-let pending = 0;
-//#endregion
+import store from './store';
/**
* Misskey Operating System
@@ -19,7 +14,7 @@ let pending = 0;
export default class MiOS extends EventEmitter {
public app: Vue;
- public store: ReturnType<typeof initStore>;
+ public store: ReturnType<typeof store>;
/**
* A connection manager of home stream
@@ -31,6 +26,11 @@ export default class MiOS extends EventEmitter {
*/
private swRegistration: ServiceWorkerRegistration = null;
+ constructor(vuex: MiOS['store']) {
+ super();
+ this.store = vuex;
+ }
+
@autobind
public signout() {
this.store.dispatch('logout');
@@ -52,8 +52,6 @@ export default class MiOS extends EventEmitter {
});
};
- this.store = initStore(this);
-
// ユーザーをフェッチしてコールバックする
const fetchme = (token, cb) => {
let me = null;
@@ -187,10 +185,13 @@ export default class MiOS extends EventEmitter {
}
// Register
- this.api('sw/register', {
- endpoint: subscription.endpoint,
- auth: encode(subscription.getKey('auth')),
- publickey: encode(subscription.getKey('p256dh'))
+ this.store.dispatch('api', {
+ endpoint: 'sw/register',
+ data: {
+ endpoint: subscription.endpoint,
+ auth: encode(subscription.getKey('auth')),
+ publickey: encode(subscription.getKey('p256dh'))
+ }
});
})
// When subscribe failed
@@ -214,52 +215,6 @@ export default class MiOS extends EventEmitter {
// Register service worker
navigator.serviceWorker.register(sw);
}
-
- /**
- * Misskey APIにリクエストします
- * @param endpoint エンドポイント名
- * @param data パラメータ
- */
- @autobind
- public api(endpoint: string, data: { [x: string]: any } = {}, token?): Promise<{ [x: string]: any }> {
- if (++pending === 1) {
- spinner = document.createElement('div');
- spinner.setAttribute('id', 'wait');
- document.body.appendChild(spinner);
- }
-
- const onFinally = () => {
- if (--pending === 0) spinner.parentNode.removeChild(spinner);
- };
-
- const promise = new Promise((resolve, reject) => {
- // Append a credential
- if (this.store.getters.isSignedIn) (data as any).i = this.store.state.i.token;
- if (token) (data as any).i = token;
-
- // Send request
- fetch(endpoint.indexOf('://') > -1 ? endpoint : `${apiUrl}/${endpoint}`, {
- method: 'POST',
- body: JSON.stringify(data),
- credentials: 'omit',
- cache: 'no-cache'
- }).then(async (res) => {
- const body = res.status === 204 ? null : await res.json();
-
- if (res.status === 200) {
- resolve(body);
- } else if (res.status === 204) {
- resolve();
- } else {
- reject(body.error);
- }
- }).catch(reject);
- });
-
- promise.then(onFinally, onFinally);
-
- return promise;
- }
}
/**
diff --git a/src/client/store.ts b/src/client/store.ts
index 35b932d624..6d007493d8 100644
--- a/src/client/store.ts
+++ b/src/client/store.ts
@@ -1,8 +1,7 @@
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate';
import * as nestedProperty from 'nested-property';
-
-import MiOS from './mios';
+import { apiUrl } from './config';
const defaultSettings = {
tutorial: 0,
@@ -57,13 +56,15 @@ function copy<T>(data: T): T {
return JSON.parse(JSON.stringify(data));
}
-export default (os: MiOS) => new Vuex.Store({
+export default () => new Vuex.Store({
plugins: [createPersistedState({
paths: ['i', 'device', 'deviceUser', 'settings', 'instance']
})],
state: {
i: null,
+ pendingApiRequestsCount: 0,
+ spinner: null
},
getters: {
@@ -121,6 +122,47 @@ export default (os: MiOS) => new Vuex.Store({
ctx.commit('settings/init', me.clientData);
}
},
+
+ api(ctx, { endpoint, data, token }) {
+ if (++ctx.state.pendingApiRequestsCount === 1) {
+ // TODO: spinnerの表示はstoreでやらない
+ ctx.state.spinner = document.createElement('div');
+ ctx.state.spinner.setAttribute('id', 'wait');
+ document.body.appendChild(ctx.state.spinner);
+ }
+
+ const onFinally = () => {
+ if (--ctx.state.pendingApiRequestsCount === 0) ctx.state.spinner.parentNode.removeChild(ctx.state.spinner);
+ };
+
+ const promise = new Promise((resolve, reject) => {
+ // Append a credential
+ if (ctx.getters.isSignedIn) (data as any).i = ctx.state.i.token;
+ if (token) (data as any).i = token;
+
+ // Send request
+ fetch(endpoint.indexOf('://') > -1 ? endpoint : `${apiUrl}/${endpoint}`, {
+ method: 'POST',
+ body: JSON.stringify(data),
+ credentials: 'omit',
+ cache: 'no-cache'
+ }).then(async (res) => {
+ const body = res.status === 204 ? null : await res.json();
+
+ if (res.status === 200) {
+ resolve(body);
+ } else if (res.status === 204) {
+ resolve();
+ } else {
+ reject(body.error);
+ }
+ }).catch(reject);
+ });
+
+ promise.then(onFinally, onFinally);
+
+ return promise;
+ }
},
modules: {
@@ -139,9 +181,12 @@ export default (os: MiOS) => new Vuex.Store({
actions: {
async fetch(ctx) {
- const meta = await os.api('meta', {
- detail: false
- });
+ const meta = await ctx.dispatch('api', {
+ endpoint: 'meta',
+ data: {
+ detail: false
+ }
+ }, { root: true });
ctx.commit('set', meta);
}
@@ -246,10 +291,13 @@ export default (os: MiOS) => new Vuex.Store({
ctx.commit('set', x);
if (ctx.rootGetters.isSignedIn) {
- os.api('i/update-client-setting', {
- name: x.key,
- value: x.value
- });
+ ctx.dispatch('api', {
+ endpoint: 'i/update-client-setting',
+ data: {
+ name: x.key,
+ value: x.value
+ }
+ }, { root: true });
}
},
}