Merge branch 'develop' into vue3

This commit is contained in:
syuilo 2020-08-25 08:54:57 +09:00
commit 7326f45ffd
24 changed files with 390 additions and 145 deletions

View file

@ -2,7 +2,7 @@
<x-column :column="column" :is-stacked="isStacked" :menu="menu">
<template #header><fa :icon="faBell" style="margin-right: 8px;"/>{{ column.name }}</template>
<x-notifications/>
<x-notifications :include-types="column.includingTypes"/>
</x-column>
</template>
@ -38,28 +38,14 @@ export default defineComponent({
},
created() {
if (this.column.notificationType == null) {
this.column.notificationType = 'all';
this.$store.commit('deviceUser/updateDeckColumn', this.column);
}
this.menu = [{
icon: faCog,
text: this.$t('notificationType'),
action: () => {
this.$root.dialog({
title: this.$t('notificationType'),
type: null,
select: {
items: ['all', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest'].map(x => ({
value: x, text: this.$t(`_notification._types.${x}`)
}))
default: this.column.notificationType,
},
showCancelButton: true
}).then(({ canceled, result: type }) => {
if (canceled) return;
this.column.notificationType = type;
text: this.$t('notificationSetting'),
action: async () => {
this.$root.new(await import('../notification-setting-window.vue').then(m => m.default), {
includingTypes: this.column.includingTypes,
}).$on('ok', async ({ includingTypes }) => {
this.$set(this.column, 'includingTypes', includingTypes);
this.$store.commit('deviceUser/updateDeckColumn', this.column);
});
}

View file

@ -0,0 +1,98 @@
<template>
<x-window ref="window" :width="400" :height="450" :no-padding="true" @closed="() => { $emit('closed'); destroyDom(); }" :with-ok-button="true" :ok-button-disabled="false" @ok="ok()">
<template #header>{{ $t('notificationSetting') }}</template>
<div class="vv94n3oa">
<div v-if="showGlobalToggle">
<mk-switch v-model="useGlobalSetting">
{{ $t('useGlobalSetting') }}
<template #desc>{{ $t('useGlobalSettingDesc') }}</template>
</mk-switch>
</div>
<div v-if="!useGlobalSetting">
<mk-info>{{ $t('notificationSettingDesc') }}</mk-info>
<mk-button inline @click="disableAll">{{ $t('disableAll') }}</mk-button>
<mk-button inline @click="enableAll">{{ $t('enableAll') }}</mk-button>
<mk-switch v-for="type in notificationTypes" :key="type" v-model="typesMap[type]">{{ $t(`_notification._types.${type}`) }}</mk-switch>
</div>
</div>
</x-window>
</template>
<script lang="ts">
import Vue, { PropType } from 'vue';
import XWindow from './window.vue';
import MkSwitch from './ui/switch.vue';
import MkInfo from './ui/info.vue';
import MkButton from './ui/button.vue';
import { notificationTypes } from '../../types';
export default Vue.extend({
components: {
XWindow,
MkSwitch,
MkInfo,
MkButton
},
props: {
includingTypes: {
// TODO: 調
type: Array as PropType<typeof notificationTypes[number][]>,
required: false,
default: null,
},
showGlobalToggle: {
type: Boolean,
required: false,
default: true,
}
},
data() {
return {
typesMap: {} as Record<typeof notificationTypes[number], boolean>,
useGlobalSetting: false,
notificationTypes,
};
},
created() {
this.useGlobalSetting = this.includingTypes === null && this.showGlobalToggle;
for (const type of this.notificationTypes) {
Vue.set(this.typesMap, type, this.includingTypes === null || this.includingTypes.includes(type));
}
},
methods: {
ok() {
const includingTypes = this.useGlobalSetting ? null : (Object.keys(this.typesMap) as typeof notificationTypes[number][])
.filter(type => this.typesMap[type]);
this.$emit('ok', { includingTypes });
this.$refs.window.close();
},
disableAll() {
for (const type in this.typesMap) {
this.typesMap[type as typeof notificationTypes[number]] = false;
}
},
enableAll() {
for (const type in this.typesMap) {
this.typesMap[type as typeof notificationTypes[number]] = true;
}
}
}
});
</script>
<style lang="scss" scoped>
.vv94n3oa {
> div {
border-top: solid 1px var(--divider);
padding: 24px;
}
}
</style>

View file

@ -17,11 +17,12 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, PropType } from 'vue';
import paging from '../scripts/paging';
import XNotification from './notification.vue';
import XList from './date-separated-list.vue';
import XNote from './note.vue';
import { notificationTypes } from '../../types';
export default defineComponent({
components: {
@ -35,9 +36,10 @@ export default defineComponent({
],
props: {
type: {
type: String,
required: false
includeTypes: {
type: Array as PropType<typeof notificationTypes[number][]>,
required: false,
default: null,
},
},
@ -48,15 +50,26 @@ export default defineComponent({
endpoint: 'i/notifications',
limit: 10,
params: () => ({
includeTypes: this.type ? [this.type] : undefined
includeTypes: this.allIncludeTypes || undefined,
})
},
};
},
computed: {
allIncludeTypes() {
return this.includeTypes ?? this.$store.state.i.includingNotificationTypes;
}
},
watch: {
type() {
includeTypes() {
this.reload();
},
'$store.state.i.includingNotificationTypes'() {
if (this.includeTypes === null) {
this.reload();
}
}
},
@ -71,16 +84,20 @@ export default defineComponent({
methods: {
onNotification(notification) {
if (document.visibilityState === 'visible') {
//
const isMuted = !!this.allIncludeTypes && !this.allIncludeTypes.includes(notification.type);
if (isMuted || document.visibilityState === 'visible') {
this.$root.stream.send('readNotification', {
id: notification.id
});
}
this.prepend({
...notification,
isRead: document.visibilityState === 'visible'
});
if (!isMuted) {
this.prepend({
...notification,
isRead: document.visibilityState === 'visible'
});
}
},
noteUpdated(oldValue, newValue) {

View file

@ -13,7 +13,11 @@
>
<slot></slot>
</select>
<div class="suffix"><slot name="suffix"></slot></div>
<div class="suffix">
<slot name="suffix">
<fa :icon="faChevronDown"/>
</slot>
</div>
</div>
<div class="text"><slot name="text"></slot></div>
</div>
@ -21,6 +25,7 @@
<script lang="ts">
import { defineComponent } from 'vue';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
export default defineComponent({
props: {
@ -43,7 +48,8 @@ export default defineComponent({
},
data() {
return {
focused: false
focused: false,
faChevronDown,
};
},
computed: {
@ -157,6 +163,8 @@ export default defineComponent({
border-radius: 0;
outline: none;
box-shadow: none;
appearance: none;
-webkit-appearance: none;
color: var(--fg);
option,
@ -172,7 +180,7 @@ export default defineComponent({
justify-self: center;
font-size: 1em;
line-height: 32px;
color: rgba(#000, 0.54);
color: var(--inputLabel);
pointer-events: none;
&:empty {

View file

@ -155,6 +155,11 @@ export default defineComponent({
},
async onNotification(notification) {
const t = this.$store.state.i.includingNotificationTypes;
if (!!t && !t.includes(notification.type)) {
return;
}
if (document.visibilityState === 'visible') {
this.$root.stream.send('readNotification', {
id: notification.id
@ -164,7 +169,6 @@ export default defineComponent({
notification
});
}
this.$root.sound('notification');
},

View file

@ -325,6 +325,10 @@ export default defineComponent({
},
async onNotification(notification) {
const t = this.$store.state.i.includingNotificationTypes;
if (!!t && !t.includes(notification.type)) {
return;
}
if (document.visibilityState === 'visible') {
this.$root.stream.send('readNotification', {
id: notification.id

View file

@ -21,6 +21,9 @@
<mk-button @click="readAllUnreadNotes">{{ $t('markAsReadAllUnreadNotes') }}</mk-button>
<mk-button @click="readAllMessagingMessages">{{ $t('markAsReadAllTalkMessages') }}</mk-button>
</div>
<div class="_content">
<mk-button @click="configure">{{ $t('notificationSetting') }}</mk-button>
</div>
</section>
<x-import-export class="_vMargin"/>
@ -108,6 +111,24 @@ export default defineComponent({
readAllNotifications() {
this.$root.api('notifications/mark-all-as-read');
},
async configure() {
this.$root.new(await import('../../components/notification-setting-window.vue').then(m => m.default), {
includingTypes: this.$store.state.i.includingNotificationTypes,
showGlobalToggle: false,
}).$on('ok', async ({ includingTypes: value }: any) => {
await this.$root.api('i/update', {
includingNotificationTypes: value,
}).then(i => {
this.$store.state.i.includingNotificationTypes = i.includingNotificationTypes;
}).catch(err => {
this.$root.dialog({
type: 'error',
text: err.message
});
});
});
}
}
});
</script>

View file

@ -76,7 +76,7 @@
<mk-container :body-togglable="true" :expanded="true">
<template #header><fa :icon="faCode"/> {{ $t('script') }}</template>
<div>
<prism-editor v-model="script" :line-numbers="false" language="js"/>
<prism-editor class="_code" v-model="script" :highlight="highlighter" :line-numbers="false"/>
</div>
</mk-container>
</div>
@ -85,9 +85,13 @@
<script lang="ts">
import { defineComponent } from 'vue';
import * as XDraggable from 'vuedraggable';
import "prismjs";
import 'prismjs';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import 'prismjs/themes/prism-okaidia.css';
import PrismEditor from 'vue-prism-editor';
import { PrismEditor } from 'vue-prism-editor';
import 'vue-prism-editor/dist/prismeditor.min.css';
import { faICursor, faPlus, faMagic, faCog, faCode, faExternalLinkSquareAlt } from '@fortawesome/free-solid-svg-icons';
import { faSave, faStickyNote, faTrashAlt } from '@fortawesome/free-regular-svg-icons';
import { v4 as uuid } from 'uuid';
@ -416,7 +420,11 @@ export default defineComponent({
removeEyeCatchingImage() {
this.eyeCatchingImageId = null;
}
},
highlighter(code) {
return highlight(code, languages.js, 'javascript');
},
}
});
</script>

View file

@ -3,7 +3,7 @@
<teleport to="#_teleport_header"><fa :icon="faTerminal"/>{{ $t('scratchpad') }}</teleport>
<div class="_panel">
<prism-editor v-model="code" :line-numbers="false" language="js"/>
<prism-editor class="_code" v-model="code" :highlight="highlighter" :line-numbers="false"/>
<mk-button style="position: absolute; top: 8px; right: 8px;" @click="run()" primary><fa :icon="faPlay"/></mk-button>
</div>
@ -23,9 +23,13 @@
<script lang="ts">
import { defineComponent } from 'vue';
import { faTerminal, faPlay } from '@fortawesome/free-solid-svg-icons';
import "prismjs";
import 'prismjs';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import 'prismjs/themes/prism-okaidia.css';
import PrismEditor from 'vue-prism-editor';
import { PrismEditor } from 'vue-prism-editor';
import 'vue-prism-editor/dist/prismeditor.min.css';
import { AiScript, parse, utils, values } from '@syuilo/aiscript';
import MkContainer from '../components/ui/container.vue';
import MkButton from '../components/ui/button.vue';
@ -118,7 +122,11 @@ export default defineComponent({
text: e
});
}
}
},
highlighter(code) {
return highlight(code, languages.js, 'javascript');
},
}
});
</script>

View file

@ -21,6 +21,11 @@ export type FormItem = {
default: string | null;
hidden?: boolean;
enum: string[];
} | {
label?: string;
type: 'array';
default: unknown[] | null;
hidden?: boolean;
};
export type Form = Record<string, FormItem>;

View file

@ -448,6 +448,19 @@ hr {
opacity: 0.7;
}
._code {
background: #2d2d2d;
color: #ccc;
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
font-size: 14px;
line-height: 1.5;
padding: 5px;
}
.prism-editor__textarea:focus {
outline: none;
}
.zoom-enter-active, .zoom-leave-active {
transition: opacity 0.5s, transform 0.5s !important;
}

View file

@ -1,16 +1,17 @@
<template>
<mk-container :style="`height: ${props.height}px;`" :show-header="props.showHeader" :scrollable="true">
<template #header><fa :icon="faBell"/>{{ $t('notifications') }}</template>
<template #func><button @click="configure()" class="_button"><fa :icon="faCog"/></button></template>
<div>
<x-notifications/>
<x-notifications :include-types="props.includingTypes"/>
</div>
</mk-container>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { faBell } from '@fortawesome/free-solid-svg-icons';
import { faBell, faCog } from '@fortawesome/free-solid-svg-icons';
import MkContainer from '../components/ui/container.vue';
import XNotifications from '../components/notifications.vue';
import define from './define';
@ -26,6 +27,11 @@ const widget = define({
type: 'number',
default: 300,
},
includingTypes: {
type: 'array',
hidden: true,
default: null,
},
})
});
@ -38,8 +44,19 @@ export default defineComponent({
data() {
return {
faBell
faBell, faCog
};
},
methods: {
async configure() {
this.$root.new(await import('../components/notification-setting-window.vue').then(m => m.default), {
includingTypes: this.props.includingTypes,
}).$on('ok', async ({ includingTypes }) => {
this.props.includingTypes = includingTypes;
this.save();
});
}
}
});
</script>