This commit is contained in:
syuilo 2020-09-06 14:25:42 +09:00
parent 73a94798c4
commit 26b16124e6
5 changed files with 72 additions and 82 deletions

View File

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

View File

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

View File

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

View File

@ -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">

View File

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