Refactoring
This commit is contained in:
		
							parent
							
								
									10356b4041
								
							
						
					
					
						commit
						28f8933c3c
					
				
					 3 changed files with 101 additions and 95 deletions
				
			
		| 
						 | 
					@ -20,6 +20,7 @@ import Menu from './components/menu.vue';
 | 
				
			||||||
import { router } from './router';
 | 
					import { router } from './router';
 | 
				
			||||||
import { applyTheme, lightTheme, builtinThemes } from './theme';
 | 
					import { applyTheme, lightTheme, builtinThemes } from './theme';
 | 
				
			||||||
import { isDeviceDarkmode } from './scripts/is-device-darkmode';
 | 
					import { isDeviceDarkmode } from './scripts/is-device-darkmode';
 | 
				
			||||||
 | 
					import createStore from './store';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Vue.use(Vuex);
 | 
					Vue.use(Vuex);
 | 
				
			||||||
Vue.use(VueHotkey);
 | 
					Vue.use(VueHotkey);
 | 
				
			||||||
| 
						 | 
					@ -134,36 +135,38 @@ document.body.setAttribute('ontouchstart', '');
 | 
				
			||||||
// アプリ基底要素マウント
 | 
					// アプリ基底要素マウント
 | 
				
			||||||
document.body.innerHTML = '<div id="app"></div>';
 | 
					document.body.innerHTML = '<div id="app"></div>';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const os = new MiOS();
 | 
					const store = createStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const os = new MiOS(store);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
os.init(async () => {
 | 
					os.init(async () => {
 | 
				
			||||||
	window.addEventListener('storage', e => {
 | 
						window.addEventListener('storage', e => {
 | 
				
			||||||
		if (e.key === 'vuex') {
 | 
							if (e.key === 'vuex') {
 | 
				
			||||||
			os.store.replaceState(JSON.parse(localStorage['vuex']));
 | 
								store.replaceState(JSON.parse(localStorage['vuex']));
 | 
				
			||||||
		} else if (e.key === 'i') {
 | 
							} else if (e.key === 'i') {
 | 
				
			||||||
			location.reload();
 | 
								location.reload();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}, false)
 | 
						}, false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.store.watch(state => state.device.darkMode, darkMode => {
 | 
						store.watch(state => state.device.darkMode, darkMode => {
 | 
				
			||||||
		// TODO: このファイルでbuiltinThemesを参照するとcode splittingが効かず、初回読み込み時に全てのテーマコードを読み込むことになってしまい無駄なので何とかする
 | 
							// TODO: このファイルでbuiltinThemesを参照するとcode splittingが効かず、初回読み込み時に全てのテーマコードを読み込むことになってしまい無駄なので何とかする
 | 
				
			||||||
		const themes = builtinThemes.concat(os.store.state.device.themes);
 | 
							const themes = builtinThemes.concat(store.state.device.themes);
 | 
				
			||||||
		applyTheme(themes.find(x => x.id === (darkMode ? os.store.state.device.darkTheme : os.store.state.device.lightTheme)));
 | 
							applyTheme(themes.find(x => x.id === (darkMode ? store.state.device.darkTheme : store.state.device.lightTheme)));
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//#region Sync dark mode
 | 
						//#region Sync dark mode
 | 
				
			||||||
	if (os.store.state.device.syncDeviceDarkMode) {
 | 
						if (store.state.device.syncDeviceDarkMode) {
 | 
				
			||||||
		os.store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
 | 
							store.commit('device/set', { key: 'darkMode', value: isDeviceDarkmode() });
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
 | 
						window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
 | 
				
			||||||
		if (os.store.state.device.syncDeviceDarkMode) {
 | 
							if (store.state.device.syncDeviceDarkMode) {
 | 
				
			||||||
			os.store.commit('device/set', { key: 'darkMode', value: mql.matches });
 | 
								store.commit('device/set', { key: 'darkMode', value: mql.matches });
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	//#endregion
 | 
						//#endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ('Notification' in window && os.store.getters.isSignedIn) {
 | 
						if ('Notification' in window && store.getters.isSignedIn) {
 | 
				
			||||||
		// 許可を得ていなかったらリクエスト
 | 
							// 許可を得ていなかったらリクエスト
 | 
				
			||||||
		if (Notification.permission === 'default') {
 | 
							if (Notification.permission === 'default') {
 | 
				
			||||||
			Notification.requestPermission();
 | 
								Notification.requestPermission();
 | 
				
			||||||
| 
						 | 
					@ -171,7 +174,7 @@ os.init(async () => {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const app = new Vue({
 | 
						const app = new Vue({
 | 
				
			||||||
		store: os.store,
 | 
							store: store,
 | 
				
			||||||
		metaInfo: {
 | 
							metaInfo: {
 | 
				
			||||||
			title: null,
 | 
								title: null,
 | 
				
			||||||
			titleTemplate: title => title ? `${title} | ${(instanceName || 'Misskey')}` : (instanceName || 'Misskey')
 | 
								titleTemplate: title => title ? `${title} | ${(instanceName || 'Misskey')}` : (instanceName || 'Misskey')
 | 
				
			||||||
| 
						 | 
					@ -183,7 +186,7 @@ os.init(async () => {
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		methods: {
 | 
							methods: {
 | 
				
			||||||
			api: os.api,
 | 
								api: (endpoint: string, data: { [x: string]: any } = {}, token?) => store.dispatch('api', { endpoint, data, token }),
 | 
				
			||||||
			signout: os.signout,
 | 
								signout: os.signout,
 | 
				
			||||||
			new(vm, props) {
 | 
								new(vm, props) {
 | 
				
			||||||
				const x = new vm({
 | 
									const x = new vm({
 | 
				
			||||||
| 
						 | 
					@ -234,58 +237,58 @@ os.init(async () => {
 | 
				
			||||||
	// マウント
 | 
						// マウント
 | 
				
			||||||
	app.$mount('#app');
 | 
						app.$mount('#app');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (app.$store.getters.isSignedIn) {
 | 
						if (store.getters.isSignedIn) {
 | 
				
			||||||
		const main = os.stream.useSharedConnection('main');
 | 
							const main = os.stream.useSharedConnection('main');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// 自分の情報が更新されたとき
 | 
							// 自分の情報が更新されたとき
 | 
				
			||||||
		main.on('meUpdated', i => {
 | 
							main.on('meUpdated', i => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', i);
 | 
								store.dispatch('mergeMe', i);
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('readAllNotifications', () => {
 | 
							main.on('readAllNotifications', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadNotification: false
 | 
									hasUnreadNotification: false
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('unreadNotification', () => {
 | 
							main.on('unreadNotification', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadNotification: true
 | 
									hasUnreadNotification: true
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('unreadMention', () => {
 | 
							main.on('unreadMention', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadMentions: true
 | 
									hasUnreadMentions: true
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('readAllUnreadMentions', () => {
 | 
							main.on('readAllUnreadMentions', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadMentions: false
 | 
									hasUnreadMentions: false
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('unreadSpecifiedNote', () => {
 | 
							main.on('unreadSpecifiedNote', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadSpecifiedNotes: true
 | 
									hasUnreadSpecifiedNotes: true
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('readAllUnreadSpecifiedNotes', () => {
 | 
							main.on('readAllUnreadSpecifiedNotes', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadSpecifiedNotes: false
 | 
									hasUnreadSpecifiedNotes: false
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('readAllMessagingMessages', () => {
 | 
							main.on('readAllMessagingMessages', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadMessagingMessage: false
 | 
									hasUnreadMessagingMessage: false
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('unreadMessagingMessage', () => {
 | 
							main.on('unreadMessagingMessage', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadMessagingMessage: true
 | 
									hasUnreadMessagingMessage: true
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -293,13 +296,13 @@ os.init(async () => {
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('readAllAntennas', () => {
 | 
							main.on('readAllAntennas', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadAntenna: false
 | 
									hasUnreadAntenna: false
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('unreadAntenna', () => {
 | 
							main.on('unreadAntenna', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadAntenna: true
 | 
									hasUnreadAntenna: true
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -307,13 +310,13 @@ os.init(async () => {
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('readAllAnnouncements', () => {
 | 
							main.on('readAllAnnouncements', () => {
 | 
				
			||||||
			app.$store.dispatch('mergeMe', {
 | 
								store.dispatch('mergeMe', {
 | 
				
			||||||
				hasUnreadAnnouncement: false
 | 
									hasUnreadAnnouncement: false
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		main.on('clientSettingUpdated', x => {
 | 
							main.on('clientSettingUpdated', x => {
 | 
				
			||||||
			app.$store.commit('settings/set', {
 | 
								store.commit('settings/set', {
 | 
				
			||||||
				key: x.key,
 | 
									key: x.key,
 | 
				
			||||||
				value: x.value
 | 
									value: x.value
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,16 +2,11 @@ import autobind from 'autobind-decorator';
 | 
				
			||||||
import Vue from 'vue';
 | 
					import Vue from 'vue';
 | 
				
			||||||
import { EventEmitter } from 'eventemitter3';
 | 
					import { EventEmitter } from 'eventemitter3';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import initStore from './store';
 | 
					 | 
				
			||||||
import { apiUrl, version } from './config';
 | 
					import { apiUrl, version } from './config';
 | 
				
			||||||
import Progress from './scripts/loading';
 | 
					import Progress from './scripts/loading';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Stream from './scripts/stream';
 | 
					import Stream from './scripts/stream';
 | 
				
			||||||
 | 
					import store from './store';
 | 
				
			||||||
//#region api requests
 | 
					 | 
				
			||||||
let spinner = null;
 | 
					 | 
				
			||||||
let pending = 0;
 | 
					 | 
				
			||||||
//#endregion
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Misskey Operating System
 | 
					 * Misskey Operating System
 | 
				
			||||||
| 
						 | 
					@ -19,7 +14,7 @@ let pending = 0;
 | 
				
			||||||
export default class MiOS extends EventEmitter {
 | 
					export default class MiOS extends EventEmitter {
 | 
				
			||||||
	public app: Vue;
 | 
						public app: Vue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	public store: ReturnType<typeof initStore>;
 | 
						public store: ReturnType<typeof store>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * A connection manager of home stream
 | 
						 * A connection manager of home stream
 | 
				
			||||||
| 
						 | 
					@ -31,6 +26,11 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	private swRegistration: ServiceWorkerRegistration = null;
 | 
						private swRegistration: ServiceWorkerRegistration = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						constructor(vuex: MiOS['store']) {
 | 
				
			||||||
 | 
							super();
 | 
				
			||||||
 | 
							this.store = vuex;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@autobind
 | 
						@autobind
 | 
				
			||||||
	public signout() {
 | 
						public signout() {
 | 
				
			||||||
		this.store.dispatch('logout');
 | 
							this.store.dispatch('logout');
 | 
				
			||||||
| 
						 | 
					@ -52,8 +52,6 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.store = initStore(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// ユーザーをフェッチしてコールバックする
 | 
							// ユーザーをフェッチしてコールバックする
 | 
				
			||||||
		const fetchme = (token, cb) => {
 | 
							const fetchme = (token, cb) => {
 | 
				
			||||||
			let me = null;
 | 
								let me = null;
 | 
				
			||||||
| 
						 | 
					@ -187,10 +185,13 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Register
 | 
									// Register
 | 
				
			||||||
				this.api('sw/register', {
 | 
									this.store.dispatch('api', {
 | 
				
			||||||
					endpoint: subscription.endpoint,
 | 
										endpoint: 'sw/register',
 | 
				
			||||||
					auth: encode(subscription.getKey('auth')),
 | 
										data: {
 | 
				
			||||||
					publickey: encode(subscription.getKey('p256dh'))
 | 
											endpoint: subscription.endpoint,
 | 
				
			||||||
 | 
											auth: encode(subscription.getKey('auth')),
 | 
				
			||||||
 | 
											publickey: encode(subscription.getKey('p256dh'))
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			// When subscribe failed
 | 
								// When subscribe failed
 | 
				
			||||||
| 
						 | 
					@ -214,52 +215,6 @@ export default class MiOS extends EventEmitter {
 | 
				
			||||||
		// Register service worker
 | 
							// Register service worker
 | 
				
			||||||
		navigator.serviceWorker.register(sw);
 | 
							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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,7 @@
 | 
				
			||||||
import Vuex from 'vuex';
 | 
					import Vuex from 'vuex';
 | 
				
			||||||
import createPersistedState from 'vuex-persistedstate';
 | 
					import createPersistedState from 'vuex-persistedstate';
 | 
				
			||||||
import * as nestedProperty from 'nested-property';
 | 
					import * as nestedProperty from 'nested-property';
 | 
				
			||||||
 | 
					import { apiUrl } from './config';
 | 
				
			||||||
import MiOS from './mios';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const defaultSettings = {
 | 
					const defaultSettings = {
 | 
				
			||||||
	tutorial: 0,
 | 
						tutorial: 0,
 | 
				
			||||||
| 
						 | 
					@ -57,13 +56,15 @@ function copy<T>(data: T): T {
 | 
				
			||||||
	return JSON.parse(JSON.stringify(data));
 | 
						return JSON.parse(JSON.stringify(data));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default (os: MiOS) => new Vuex.Store({
 | 
					export default () => new Vuex.Store({
 | 
				
			||||||
	plugins: [createPersistedState({
 | 
						plugins: [createPersistedState({
 | 
				
			||||||
		paths: ['i', 'device', 'deviceUser', 'settings', 'instance']
 | 
							paths: ['i', 'device', 'deviceUser', 'settings', 'instance']
 | 
				
			||||||
	})],
 | 
						})],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	state: {
 | 
						state: {
 | 
				
			||||||
		i: null,
 | 
							i: null,
 | 
				
			||||||
 | 
							pendingApiRequestsCount: 0,
 | 
				
			||||||
 | 
							spinner: null
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	getters: {
 | 
						getters: {
 | 
				
			||||||
| 
						 | 
					@ -121,6 +122,47 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
				ctx.commit('settings/init', me.clientData);
 | 
									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: {
 | 
						modules: {
 | 
				
			||||||
| 
						 | 
					@ -139,9 +181,12 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			actions: {
 | 
								actions: {
 | 
				
			||||||
				async fetch(ctx) {
 | 
									async fetch(ctx) {
 | 
				
			||||||
					const meta = await os.api('meta', {
 | 
										const meta = await ctx.dispatch('api', {
 | 
				
			||||||
						detail: false
 | 
											endpoint: 'meta',
 | 
				
			||||||
					});
 | 
											data: {
 | 
				
			||||||
 | 
												detail: false
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}, { root: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					ctx.commit('set', meta);
 | 
										ctx.commit('set', meta);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -246,10 +291,13 @@ export default (os: MiOS) => new Vuex.Store({
 | 
				
			||||||
					ctx.commit('set', x);
 | 
										ctx.commit('set', x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					if (ctx.rootGetters.isSignedIn) {
 | 
										if (ctx.rootGetters.isSignedIn) {
 | 
				
			||||||
						os.api('i/update-client-setting', {
 | 
											ctx.dispatch('api', {
 | 
				
			||||||
							name: x.key,
 | 
												endpoint: 'i/update-client-setting',
 | 
				
			||||||
							value: x.value
 | 
												data: {
 | 
				
			||||||
						});
 | 
													name: x.key,
 | 
				
			||||||
 | 
													value: x.value
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}, { root: true });
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue