diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2020-11-01 22:09:16 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2020-11-01 22:09:16 +0900 |
| commit | 7060625adfa4fe10daefa871510620c34db14987 (patch) | |
| tree | 03bae495a6301efccc83ee29e2abb00f763b4f1f /src/client | |
| parent | メモリリークの一因になってそうだったのでrefを渡すの... (diff) | |
| download | misskey-7060625adfa4fe10daefa871510620c34db14987.tar.gz misskey-7060625adfa4fe10daefa871510620c34db14987.tar.bz2 misskey-7060625adfa4fe10daefa871510620c34db14987.zip | |
Improve task manager etc
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/components/dialog.vue | 6 | ||||
| -rw-r--r-- | src/client/components/taskmanager.vue | 53 | ||||
| -rw-r--r-- | src/client/directives/follow-append.ts | 25 | ||||
| -rw-r--r-- | src/client/os.ts | 33 | ||||
| -rw-r--r-- | src/client/pages/test.vue | 8 | ||||
| -rw-r--r-- | src/client/themes/_dark.json5 | 3 | ||||
| -rw-r--r-- | src/client/themes/_light.json5 | 3 |
7 files changed, 108 insertions, 23 deletions
diff --git a/src/client/components/dialog.vue b/src/client/components/dialog.vue index f157a37eac..f8d700202a 100644 --- a/src/client/components/dialog.vue +++ b/src/client/components/dialog.vue @@ -169,15 +169,15 @@ export default defineComponent({ font-size: 32px; &.success { - color: var(--accent); + color: var(--success); } &.error { - color: #ec4137; + color: var(--error); } &.warning { - color: #ecb637; + color: var(--warn); } > * { diff --git a/src/client/components/taskmanager.vue b/src/client/components/taskmanager.vue index 29b054d0fa..704e2d3e89 100644 --- a/src/client/components/taskmanager.vue +++ b/src/client/components/taskmanager.vue @@ -7,7 +7,7 @@ <MkTab v-model:value="tab" :items="[{ label: 'Windows', value: 'windows', }, { label: 'Stream', value: 'stream', }, { label: 'Stream (Pool)', value: 'streamPool', }, { label: 'API', value: 'api', }]" style="border-bottom: solid 1px var(--divider);"/> <div class="content"> - <div v-if="tab === 'windows'" class="windows"> + <div v-if="tab === 'windows'" class="windows" v-follow> <div class="header"> <div>#ID</div> <div>Component</div> @@ -19,7 +19,7 @@ <div><button class="_textButton" @click="killPopup(p)">Kill</button></div> </div> </div> - <div v-if="tab === 'stream'" class="stream"> + <div v-if="tab === 'stream'" class="stream" v-follow> <div class="header"> <div>#ID</div> <div>Ch</div> @@ -36,7 +36,7 @@ <div>{{ c.out }}</div> </div> </div> - <div v-if="tab === 'streamPool'" class="streamPool"> + <div v-if="tab === 'streamPool'" class="streamPool" v-follow> <div class="header"> <div>#ID</div> <div>Ch</div> @@ -48,6 +48,18 @@ <div>{{ p.users }}</div> </div> </div> + <div v-if="tab === 'api'" class="api" v-follow> + <div class="header"> + <div>#ID</div> + <div>Endpoint</div> + <div>State</div> + </div> + <div v-for="req in apiRequests"> + <div>#{{ req.id }}</div> + <div>{{ req.endpoint }}</div> + <div class="state" :class="req.state">{{ req.state }}</div> + </div> + </div> </div> <footer> @@ -65,6 +77,7 @@ import { faTerminal } from '@fortawesome/free-solid-svg-icons'; import XWindow from '@/components/ui/window.vue'; import MkTab from '@/components/tab.vue'; import MkButton from '@/components/ui/button.vue'; +import follow from '@/directives/follow-append'; import * as os from '@/os'; export default defineComponent({ @@ -74,6 +87,10 @@ export default defineComponent({ MkButton, }, + directives: { + follow + }, + props: { }, @@ -105,6 +122,7 @@ export default defineComponent({ return { tab: ref('stream'), popups: os.popups, + apiRequests: os.apiRequests, connections, pools, killPopup, @@ -125,9 +143,7 @@ export default defineComponent({ flex: 1; overflow: auto; - > .windows, - > .stream, - > .streamPool { + > div { display: table; width: 100%; padding: 16px; @@ -140,8 +156,31 @@ export default defineComponent({ opacity: 0.7; } - > * { + > div { display: table-cell; + white-space: nowrap; + + &:not(:last-child) { + padding-right: 8px; + } + } + } + + &.api { + > div { + > .state { + &.pending { + color: var(--warn); + } + + &.success { + color: var(--success); + } + + &.failed { + color: var(--error); + } + } } } } diff --git a/src/client/directives/follow-append.ts b/src/client/directives/follow-append.ts new file mode 100644 index 0000000000..26f9e9f82b --- /dev/null +++ b/src/client/directives/follow-append.ts @@ -0,0 +1,25 @@ +import { Directive } from 'vue'; +import { getScrollContainer, getScrollPosition } from '@/scripts/scroll'; + +export default { + mounted(src, binding, vn) { + const ro = new ResizeObserver((entries, observer) => { + const pos = getScrollPosition(src); + const container = getScrollContainer(src); + const viewHeight = container.clientHeight; + const height = container.scrollHeight; + if (pos + viewHeight > height - 32) { + container.scrollTop = height; + } + }); + + ro.observe(src); + + // TODO: 新たにプロパティを作るのをやめMapを使う + src._ro_ = ro; + }, + + unmounted(src, binding, vn) { + src._ro_.unobserve(src); + } +} as Directive; diff --git a/src/client/os.ts b/src/client/os.ts index 86fdd21b61..a9b56e60f1 100644 --- a/src/client/os.ts +++ b/src/client/os.ts @@ -2,7 +2,7 @@ import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vu import { EventEmitter } from 'eventemitter3'; import Stream from '@/scripts/stream'; import { store } from '@/store'; -import { apiUrl } from '@/config'; +import { apiUrl, debug } from '@/config'; import MkPostFormDialog from '@/components/post-form-dialog.vue'; import MkWaitingDialog from '@/components/waiting-dialog.vue'; import { resolve } from '@/router'; @@ -13,28 +13,26 @@ export const isMobile = /mobile|iphone|ipad|android/.test(ua); export const stream = markRaw(new Stream()); export const pendingApiRequestsCount = ref(0); +export const apiRequests = ref([]); // for debug export const windows = new Map(); export function api(endpoint: string, data: Record<string, any> = {}, token?: string | null | undefined) { pendingApiRequestsCount.value++; - if (_DEV_) { - performance.mark(_PERF_PREFIX_ + 'api:begin'); - } - const onFinally = () => { pendingApiRequestsCount.value--; - - if (_DEV_) { - performance.mark(_PERF_PREFIX_ + 'api:end'); - - performance.measure(_PERF_PREFIX_ + 'api', - _PERF_PREFIX_ + 'api:begin', - _PERF_PREFIX_ + 'api:end'); - } }; + const log = debug ? reactive({ + id: apiRequests.value.length, + endpoint, + state: 'pending' + }) : null; + if (debug) { + apiRequests.value.push(log); + } + const promise = new Promise((resolve, reject) => { // Append a credential if (store.getters.isSignedIn) (data as any).i = store.state.i.token; @@ -51,10 +49,19 @@ export function api(endpoint: string, data: Record<string, any> = {}, token?: st if (res.status === 200) { resolve(body); + if (debug) { + log.state = 'success'; + } } else if (res.status === 204) { resolve(); + if (debug) { + log.state = 'success'; + } } else { reject(body.error); + if (debug) { + log.state = 'failed'; + } } }).catch(reject); }); diff --git a/src/client/pages/test.vue b/src/client/pages/test.vue index 5a3929d630..bcfe891c8f 100644 --- a/src/client/pages/test.vue +++ b/src/client/pages/test.vue @@ -10,6 +10,10 @@ <MkInput v-model:value="dialogBody"> <span>Body</span> </MkInput> + <MkRadio v-model="dialogType" value="info">Info</MkRadio> + <MkRadio v-model="dialogType" value="success">Success</MkRadio> + <MkRadio v-model="dialogType" value="warning">Warn</MkRadio> + <MkRadio v-model="dialogType" value="error">Error</MkRadio> <MkSwitch v-model:value="dialogCancel"> <span>With cancel button</span> </MkSwitch> @@ -133,6 +137,7 @@ import MkButton from '@/components/ui/button.vue'; import MkInput from '@/components/ui/input.vue'; import MkSwitch from '@/components/ui/switch.vue'; import MkTextarea from '@/components/ui/textarea.vue'; +import MkRadio from '@/components/ui/radio.vue'; import * as os from '@/os'; export default defineComponent({ @@ -141,6 +146,7 @@ export default defineComponent({ MkInput, MkSwitch, MkTextarea, + MkRadio, }, data() { @@ -153,6 +159,7 @@ export default defineComponent({ }, dialogTitle: 'Hello', dialogBody: 'World!', + dialogType: 'info', dialogCancel: false, dialogCancelByBgClick: true, dialogInput: false, @@ -192,6 +199,7 @@ export default defineComponent({ async showDialog() { this.dialogResult = null; this.dialogResult = await os.dialog({ + type: this.dialogType, title: this.dialogTitle, text: this.dialogBody, showCancelButton: this.dialogCancel, diff --git a/src/client/themes/_dark.json5 b/src/client/themes/_dark.json5 index ce06618aca..ee6d9b49e9 100644 --- a/src/client/themes/_dark.json5 +++ b/src/client/themes/_dark.json5 @@ -56,6 +56,9 @@ wallpaperOverlay: 'rgba(0, 0, 0, 0.5)', badge: '#31b1ce', messageBg: ':lighten<5<@bg', + success: '#86b300', + error: '#ec4137', + warn: '#ecb637', htmlThemeColor: '@bg', X1: ':alpha<0<@bg', X2: ':darken<2<@panel', diff --git a/src/client/themes/_light.json5 b/src/client/themes/_light.json5 index 9862e8fdc6..8821999395 100644 --- a/src/client/themes/_light.json5 +++ b/src/client/themes/_light.json5 @@ -56,6 +56,9 @@ wallpaperOverlay: 'rgba(255, 255, 255, 0.5)', badge: '#31b1ce', messageBg: '@panel', + success: '#86b300', + error: '#ec4137', + warn: '#ecb637', htmlThemeColor: '@bg', X1: ':alpha<0<@bg', X2: ':darken<2<@panel', |