From 26b16124e633c2af71a575425a06aafdfa754608 Mon Sep 17 00:00:00 2001 From: syuilo <syuilotan@yahoo.co.jp> Date: Sun, 6 Sep 2020 14:25:42 +0900 Subject: [PATCH] wip --- src/client/components/dialog.vue | 4 +- src/client/components/menu.vue | 3 +- src/client/os.ts | 43 +++++++++++-- src/client/root.vue | 4 +- src/client/store.ts | 100 +++++++++---------------------- 5 files changed, 72 insertions(+), 82 deletions(-) diff --git a/src/client/components/dialog.vue b/src/client/components/dialog.vue index 6d4b5b115a..52d9dea8b1 100644 --- a/src/client/components/dialog.vue +++ b/src/client/components/dialog.vue @@ -1,5 +1,5 @@ <template> -<x-modal ref="modal" @closed="$store.commit('removeDialog', id)" @click="onBgClick" :showing="showing"> +<x-modal ref="modal" @closed="$store.commit('removePopup', id)" @click="onBgClick" :showing="showing"> <div class="mk-dialog" :class="{ iconOnly }"> <template v-if="type == 'signin'"> <mk-signin/> @@ -160,7 +160,7 @@ export default defineComponent({ methods: { done(canceled, result?) { this.showing = false; - this.$store.commit('dialogDone', { id: this.id, result: { canceled, result } }); + os.dialogCallbacks[this.id]({ canceled, result }); }, async ok() { diff --git a/src/client/components/menu.vue b/src/client/components/menu.vue index 425c28e295..71920b15e8 100644 --- a/src/client/components/menu.vue +++ b/src/client/components/menu.vue @@ -1,5 +1,5 @@ <template> -<x-modal :source="source" :no-center="noCenter" ref="popup" @click="close()" @closed="$store.commit('removeDialog', id)" :showing="showing"> +<x-modal :source="source" :no-center="noCenter" ref="popup" @click="close()" @closed="$store.commit('removePopup', id)" :showing="showing"> <div class="rrevdjwt" :class="{ left: align === 'left' }" ref="items" :style="{ width: width + 'px' }"> <template v-for="(item, i) in items.filter(item => item !== undefined)"> <div v-if="item === null" class="divider" :key="i"></div> @@ -103,7 +103,6 @@ export default defineComponent({ }, close() { this.showing = false; - this.$store.commit('dialogDone', { id: this.id }); }, focusUp() { focusPrev(document.activeElement); diff --git a/src/client/os.ts b/src/client/os.ts index f3d3c72bdd..c58204a071 100644 --- a/src/client/os.ts +++ b/src/client/os.ts @@ -1,22 +1,57 @@ import { defineAsyncComponent } from 'vue'; import Stream from '@/scripts/stream'; -import { store } from './store'; +import { store } from '@/store'; +import { apiUrl } from '@/config'; export const stream = new Stream(); +export const dialogCallbacks = {}; + export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) { - return store.dispatch('api', { endpoint, data, token }); + store.commit('beginApiRequest'); + + const onFinally = () => { + store.commit('endApiRequest'); + }; + + const promise = new Promise((resolve, reject) => { + // Append a credential + if (store.getters.isSignedIn) (data as any).i = store.state.i.token; + if (token !== undefined) (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; } export function dialog(props: Record<string, any>) { - return store.dispatch('showDialog', { + return store.dispatch('popup', { component: defineAsyncComponent(() => import('@/components/dialog.vue')), props }); } export function menu(props: Record<string, any>) { - return store.dispatch('showDialog', { + return store.dispatch('popup', { component: defineAsyncComponent(() => import('@/components/menu.vue')), props }); diff --git a/src/client/root.vue b/src/client/root.vue index 3ca565d191..b2232fa45c 100644 --- a/src/client/root.vue +++ b/src/client/root.vue @@ -2,7 +2,9 @@ <DeckUI v-if="deckmode"/> <DefaultUI v-else/> -<component v-for="dialog in $store.state.dialogs" :is="dialog.component" v-bind="dialog.props" :key="dialog.id"/> +<component v-for="popup in $store.state.popups" :is="popup.component" v-bind="popup.props" :key="popup.id"/> + +<div id="wait" v-if="$store.state.pendingApiRequestsCount > 0"></div> </template> <script lang="ts"> diff --git a/src/client/store.ts b/src/client/store.ts index 8dd682a8e9..f9ce4eed9e 100644 --- a/src/client/store.ts +++ b/src/client/store.ts @@ -1,11 +1,11 @@ -import { reactive, watch } from 'vue'; import { createStore } from 'vuex'; import createPersistedState from 'vuex-persistedstate'; import * as nestedProperty from 'nested-property'; import { faSatelliteDish, faTerminal, faHashtag, faBroadcastTower, faFireAlt, faSearch, faStar, faAt, faListUl, faUserClock, faUsers, faCloud, faGamepad, faFileAlt, faSatellite, faDoorClosed, faColumns } from '@fortawesome/free-solid-svg-icons'; import { faBell, faEnvelope, faComments } from '@fortawesome/free-regular-svg-icons'; import { AiScript, utils, values } from '@syuilo/aiscript'; -import { apiUrl, deckmode } from '@/config'; +import { deckmode } from '@/config'; +import { api, dialogCallbacks } from '@/os'; import { erase } from '../prelude/array'; export const defaultSettings = { @@ -108,11 +108,10 @@ export const store = createStore({ i: null, pendingApiRequestsCount: 0, spinner: null, - dialogs: [] as { + popups: [] as { id: any; component: any; props: Record<string, any>; - result: any; }[], fullView: false, @@ -262,17 +261,20 @@ export const store = createStore({ state.i[key] = value; }, - addDialog(state, dialog) { - state.dialogs.push(dialog); + beginApiRequest(state) { + state.pendingApiRequestsCount++; }, - dialogDone(state, { id: dialogId, result }) { - const dialog = state.dialogs.find(d => d.id === dialogId); - dialog.result = result; + endApiRequest(state) { + state.pendingApiRequestsCount--; }, - removeDialog(state, dialogId) { - state.dialogs = state.dialogs.filter(d => d.id !== dialogId); + addPopup(state, popup) { + state.popups.push(popup); + }, + + removePopup(state, popupId) { + state.popups = state.popups.filter(x => x.id !== popupId); }, setFullView(state, v) { @@ -370,66 +372,24 @@ export const store = createStore({ } }, - showDialog(ctx, { component, props }) { + popup(ctx, { component, props }) { return new Promise((res, rej) => { const id = Math.random().toString(); // TODO: uuidとか使う - const dialog = reactive({ + const popup = { component, props: { ...props, id }, - result: null, id, - }); - ctx.commit('addDialog', dialog); - const unwatch = watch(() => dialog.result, result => { - unwatch(); + }; + dialogCallbacks[id] = result => { + delete dialogCallbacks[id]; res(result); - }); + }; + ctx.commit('addPopup', popup); }); }, - - 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 !== undefined) (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: { @@ -448,12 +408,9 @@ export const store = createStore({ actions: { async fetch(ctx) { - const meta = await ctx.dispatch('api', { - endpoint: 'meta', - data: { - detail: false - } - }, { root: true }); + const meta = await api('meta', { + detail: false + }); ctx.commit('set', meta); } @@ -716,13 +673,10 @@ export const store = createStore({ ctx.commit('set', x); if (ctx.rootGetters.isSignedIn) { - ctx.dispatch('api', { - endpoint: 'i/update-client-setting', - data: { - name: x.key, - value: x.value - } - }, { root: true }); + api('i/update-client-setting', { + name: x.key, + value: x.value + }); } }, }