Merge branch 'develop' into swn

This commit is contained in:
tamaina 2021-09-17 22:42:40 +09:00
commit ab237868ff
51 changed files with 872 additions and 660 deletions

View File

@ -2,6 +2,7 @@
.github .github
.travis .travis
.vscode .vscode
.config
Dockerfile Dockerfile
build/ build/
built/ built/

View File

@ -15,6 +15,7 @@
- リモートユーザーのDeleteアクティビティに対応 - リモートユーザーのDeleteアクティビティに対応
### Bugfixes ### Bugfixes
- popupで設定ページを表示すると、アカウントの削除ページにアクセスすることができない問題を修正
## 12.90.1 (2021/09/05) ## 12.90.1 (2021/09/05)

View File

@ -15,6 +15,7 @@ services:
- external_network - external_network
volumes: volumes:
- ./files:/misskey/files - ./files:/misskey/files
- ./.config:/misskey/.config:ro
redis: redis:
restart: always restart: always

View File

@ -0,0 +1,28 @@
GitHub Actionsを使用してDocker Hubへpushする方法
================================================================
[/.github/workflows/docker.yml](/.github/workflows/docker.yml) に
GitHub ActionによりDocker Hubへpushするワークフローが記述されています。
オリジナルリポジトリでは、リリースされたタイミングで `latest`, `<リリース名>` それぞれのタグでDocker Hubにpushされます。
※ Docker Hub に`<ブランチ名>`のようなタグがあるかもしれませんが、こちらは自動push対象ではありません。
Fork先でこのワークフローを実行すると失敗します。
以下では、Fork先で自分のDocker Hubリポジトリにpushするようにする方法を記述します。
## 自分のDocker Hubリポジトリにpushするように設定する方法
1. Docker Hubでリポジトリを作成します。
2. ワークフローファイルの [images](https://github.com/misskey-dev/misskey/blob/53f3b779bf16abcda4f6e026c51384f3b8fbcc62/.github/workflows/docker.yml#L20) を作成したリポジトリに置き換えます。
3. GitHubにて [暗号化されたシークレット](https://docs.github.com/ja/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository) を作成します。
作成が必要なのは `DOCKER_USERNAME``DOCKER_PASSWORD` で、それぞれDocker Hubのユーザーとパスワードになります。
## pushする方法
上記設定によりリリース時に自動的にDocker Hubにpushされるようになります。
具体的には、GitHubのリリース機能でリリースしたタイミングで `latest`, `<リリース名>` それぞれのタグでDocker Hubにpushされます。
また、GitHub上から手動でpushすることも出来ます。
それを行うには、Actions => Publish Docker image => Run workflow からbranchを選択してワークフローを実行します。
ただし、この場合作成されるタグは`<ブランチ名>`になります。

View File

@ -104,9 +104,9 @@
"@types/websocket": "1.0.4", "@types/websocket": "1.0.4",
"@types/ws": "7.4.7", "@types/ws": "7.4.7",
"@typescript-eslint/parser": "4.29.2", "@typescript-eslint/parser": "4.29.2",
"@vue/compiler-sfc": "3.2.4", "@vue/compiler-sfc": "3.2.11",
"abort-controller": "3.0.0", "abort-controller": "3.0.0",
"apexcharts": "3.27.3", "apexcharts": "3.28.1",
"autobind-decorator": "2.4.0", "autobind-decorator": "2.4.0",
"autosize": "4.0.4", "autosize": "4.0.4",
"autwh": "0.1.0", "autwh": "0.1.0",
@ -114,8 +114,8 @@
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"blurhash": "1.1.4", "blurhash": "1.1.4",
"broadcast-channel": "4.2.0", "broadcast-channel": "4.2.0",
"bull": "3.28.1", "bull": "3.29.2",
"cacheable-lookup": "6.0.0", "cacheable-lookup": "6.0.1",
"cafy": "15.2.1", "cafy": "15.2.1",
"cbor": "8.0.0", "cbor": "8.0.0",
"chalk": "4.1.2", "chalk": "4.1.2",
@ -131,7 +131,7 @@
"dateformat": "4.5.1", "dateformat": "4.5.1",
"escape-regexp": "0.0.1", "escape-regexp": "0.0.1",
"eslint": "7.32.0", "eslint": "7.32.0",
"eslint-plugin-vue": "7.16.0", "eslint-plugin-vue": "7.17.0",
"eventemitter3": "4.0.7", "eventemitter3": "4.0.7",
"feed": "4.2.2", "feed": "4.2.2",
"file-type": "16.5.3", "file-type": "16.5.3",
@ -156,7 +156,7 @@
"json5-loader": "4.0.1", "json5-loader": "4.0.1",
"jsonld": "5.2.0", "jsonld": "5.2.0",
"jsrsasign": "8.0.20", "jsrsasign": "8.0.20",
"katex": "0.13.13", "katex": "0.13.18",
"koa": "2.13.1", "koa": "2.13.1",
"koa-bodyparser": "4.3.0", "koa-bodyparser": "4.3.0",
"koa-favicon": "2.1.0", "koa-favicon": "2.1.0",
@ -190,7 +190,7 @@
"promise-limit": "2.7.0", "promise-limit": "2.7.0",
"pug": "3.0.2", "pug": "3.0.2",
"punycode": "2.1.1", "punycode": "2.1.1",
"pureimage": "0.3.2", "pureimage": "0.3.5",
"qrcode": "1.4.4", "qrcode": "1.4.4",
"random-seed": "0.3.0", "random-seed": "0.3.0",
"ratelimiter": "3.4.1", "ratelimiter": "3.4.1",
@ -204,16 +204,16 @@
"rimraf": "3.0.2", "rimraf": "3.0.2",
"rndstr": "1.0.0", "rndstr": "1.0.0",
"s-age": "1.1.2", "s-age": "1.1.2",
"sass": "1.38.0", "sass": "1.41.0",
"sass-loader": "12.1.0", "sass-loader": "12.1.0",
"seedrandom": "3.0.5", "seedrandom": "3.0.5",
"sharp": "0.29.0", "sharp": "0.29.1",
"speakeasy": "2.0.0", "speakeasy": "2.0.0",
"stringz": "2.1.0", "stringz": "2.1.0",
"style-loader": "3.2.1", "style-loader": "3.2.1",
"summaly": "2.4.1", "summaly": "2.4.1",
"syslog-pro": "1.0.0", "syslog-pro": "1.0.0",
"systeminformation": "5.8.0", "systeminformation": "5.9.2",
"syuilo-password-strength": "0.0.1", "syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0", "textarea-caret": "3.1.0",
"three": "0.117.1", "three": "0.117.1",
@ -223,16 +223,16 @@
"ts-loader": "9.2.5", "ts-loader": "9.2.5",
"ts-node": "10.2.1", "ts-node": "10.2.1",
"tsc-alias": "1.3.9", "tsc-alias": "1.3.9",
"tsconfig-paths": "3.10.1", "tsconfig-paths": "3.11.0",
"tslint": "6.1.3", "tslint": "6.1.3",
"tslint-sonarts": "1.9.0", "tslint-sonarts": "1.9.0",
"twemoji-parser": "13.1.0", "twemoji-parser": "13.1.0",
"typeorm": "0.2.37", "typeorm": "0.2.37",
"typescript": "4.3.5", "typescript": "4.4.3",
"ulid": "2.3.0", "ulid": "2.3.0",
"uuid": "8.3.2", "uuid": "8.3.2",
"v-debounce": "0.1.2", "v-debounce": "0.1.2",
"vue": "3.2.4", "vue": "3.2.11",
"vue-loader": "16.5.0", "vue-loader": "16.5.0",
"vue-prism-editor": "2.0.0-alpha.2", "vue-prism-editor": "2.0.0-alpha.2",
"vue-router": "4.0.5", "vue-router": "4.0.5",
@ -240,10 +240,10 @@
"vue-svg-loader": "0.17.0-beta.2", "vue-svg-loader": "0.17.0-beta.2",
"vuedraggable": "4.0.1", "vuedraggable": "4.0.1",
"web-push": "3.4.5", "web-push": "3.4.5",
"webpack": "5.51.0", "webpack": "5.52.1",
"webpack-cli": "4.8.0", "webpack-cli": "4.8.0",
"websocket": "1.0.34", "websocket": "1.0.34",
"ws": "8.2.0", "ws": "8.2.2",
"xev": "2.0.1" "xev": "2.0.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -73,6 +73,22 @@ export default defineComponent({
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@keyframes earwiggleleft {
from { transform: rotate(37.6deg) skew(30deg); }
25% { transform: rotate(10deg) skew(30deg); }
50% { transform: rotate(20deg) skew(30deg); }
75% { transform: rotate(0deg) skew(30deg); }
to { transform: rotate(37.6deg) skew(30deg); }
}
@keyframes earwiggleright {
from { transform: rotate(-37.6deg) skew(-30deg); }
30% { transform: rotate(-10deg) skew(-30deg); }
55% { transform: rotate(-20deg) skew(-30deg); }
75% { transform: rotate(0deg) skew(-30deg); }
to { transform: rotate(-37.6deg) skew(-30deg); }
}
.eiwwqkts { .eiwwqkts {
position: relative; position: relative;
display: inline-block; display: inline-block;
@ -132,6 +148,16 @@ export default defineComponent({
border-radius: 75% 0 75% 75%; border-radius: 75% 0 75% 75%;
transform: rotate(-37.5deg) skew(-30deg); transform: rotate(-37.5deg) skew(-30deg);
} }
&:hover {
&:before {
animation: earwiggleleft 1s infinite;
}
&:after {
animation: earwiggleright 1s infinite;
}
}
} }
} }
</style> </style>

View File

@ -99,7 +99,8 @@ export default defineComponent({
z-index: 10; z-index: 10;
position: sticky; position: sticky;
top: var(--stickyTop, 0px); top: var(--stickyTop, 0px);
background: var(--panel); padding: var(--x-padding);
background: var(--x-header, var(--panel));
/* TODO panel /* TODO panel
background: var(--X17); background: var(--X17);
-webkit-backdrop-filter: var(--blur, blur(8px)); -webkit-backdrop-filter: var(--blur, blur(8px));

View File

@ -245,7 +245,7 @@ export default defineComponent({
font-size: 1em; font-size: 1em;
color: var(--fg); color: var(--fg);
background: var(--panel); background: var(--panel);
border: solid 1px var(--inputBorder); border: solid 0.5px var(--inputBorder);
border-radius: 6px; border-radius: 6px;
outline: none; outline: none;
box-shadow: none; box-shadow: none;

View File

@ -212,7 +212,7 @@ export default defineComponent({
font-size: 1em; font-size: 1em;
color: var(--fg); color: var(--fg);
background: var(--panel); background: var(--panel);
border: solid 1px var(--inputBorder); border: solid 0.5px var(--inputBorder);
border-radius: 6px; border-radius: 6px;
outline: none; outline: none;
box-shadow: none; box-shadow: none;

View File

@ -15,7 +15,7 @@ if (localStorage.getItem('accounts') != null) {
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import { Integrations } from '@sentry/tracing'; import { Integrations } from '@sentry/tracing';
import { computed, createApp, watch, markRaw } from 'vue'; import { computed, createApp, watch, markRaw, version as vueVersion } from 'vue';
import compareVersions from 'compare-versions'; import compareVersions from 'compare-versions';
import widgets from '@client/widgets'; import widgets from '@client/widgets';
@ -49,6 +49,8 @@ window.onunhandledrejection = null;
if (_DEV_) { if (_DEV_) {
console.warn('Development mode!!!'); console.warn('Development mode!!!');
console.info(`vue ${vueVersion}`);
(window as any).$i = $i; (window as any).$i = $i;
(window as any).$store = defaultStore; (window as any).$store = defaultStore;

View File

@ -0,0 +1,134 @@
<template>
<div class="driuhtrh">
<div class="query">
<MkInput v-model="q" class="_inputNoTopMargin _inputNoBottomMargin" :placeholder="$ts.search">
<template #prefix><i class="fas fa-search"></i></template>
</MkInput>
<div class="tags">
<span class="tag _button" v-for="tag in tags" :class="{ active: selectedTags.has(tag) }" @click="toggleTag(tag)">{{ tag }}</span>
</div>
</div>
<MkFolder class="emojis" v-if="searchEmojis">
<template #header>{{ $ts.searchResult }}</template>
<div class="zuvgdzyt">
<XEmoji v-for="emoji in searchEmojis" :key="emoji.name" class="emoji" :emoji="emoji"/>
</div>
</MkFolder>
<MkFolder class="emojis" v-for="category in customEmojiCategories" :key="category">
<template #header>{{ category || $ts.other }}</template>
<div class="zuvgdzyt">
<XEmoji v-for="emoji in customEmojis.filter(e => e.category === category)" :key="emoji.name" class="emoji" :emoji="emoji"/>
</div>
</MkFolder>
</div>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue';
import MkSelect from '@client/components/ui/select.vue';
import MkFolder from '@client/components/ui/folder.vue';
import MkTab from '@client/components/tab.vue';
import * as os from '@client/os';
import * as symbols from '@client/symbols';
import { emojiCategories, emojiTags } from '@client/instance';
import XEmoji from './emojis.emoji.vue';
export default defineComponent({
components: {
MkButton,
MkInput,
MkSelect,
MkFolder,
MkTab,
XEmoji,
},
data() {
return {
q: '',
customEmojiCategories: emojiCategories,
customEmojis: this.$instance.emojis,
tags: emojiTags,
selectedTags: new Set(),
searchEmojis: null,
}
},
watch: {
q() { this.search(); },
selectedTags: {
handler() {
this.search();
},
deep: true
},
},
methods: {
search() {
if ((this.q === '' || this.q == null) && this.selectedTags.size === 0) {
this.searchEmojis = null;
return;
}
if (this.selectedTags.size === 0) {
this.searchEmojis = this.customEmojis.filter(e => e.name.includes(this.q) || e.aliases.includes(this.q));
} else {
this.searchEmojis = this.customEmojis.filter(e => (e.name.includes(this.q) || e.aliases.includes(this.q)) && [...this.selectedTags].every(t => e.aliases.includes(t)));
}
},
toggleTag(tag) {
if (this.selectedTags.has(tag)) {
this.selectedTags.delete(tag);
} else {
this.selectedTags.add(tag);
}
}
}
});
</script>
<style lang="scss" scoped>
.driuhtrh {
background: var(--bg);
> .query {
background: var(--bg);
padding: 16px;
> .tags {
> .tag {
display: inline-block;
margin: 8px 8px 0 0;
padding: 4px 8px;
font-size: 0.9em;
background: var(--panel);
border: solid 0.5px var(--divider);
border-radius: 5px;
&.active {
border-color: var(--accent);
}
}
}
}
> .emojis {
--x-header: var(--bg);
--x-padding: 0 16px;
.zuvgdzyt {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
grid-gap: 12px;
margin: 0 var(--margin) var(--margin) var(--margin);
}
}
}
</style>

View File

@ -0,0 +1,92 @@
<template>
<button class="zuvgdzyu _button" @click="menu">
<img :src="emoji.url" class="img" :alt="emoji.name"/>
<div class="body">
<div class="name _monospace">{{ emoji.name }}</div>
<div class="info">{{ emoji.aliases.join(' ') }}</div>
</div>
</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import * as os from '@client/os';
import copyToClipboard from '@client/scripts/copy-to-clipboard';
import VanillaTilt from 'vanilla-tilt';
export default defineComponent({
props: {
emoji: {
type: Object,
required: true,
}
},
mounted() {
VanillaTilt.init(this.$el, {
reverse: true,
gyroscope: false,
scale: 1.1,
speed: 500,
});
},
methods: {
menu(ev) {
os.popupMenu([{
type: 'label',
text: ':' + this.emoji.name + ':',
}, {
text: this.$ts.copy,
icon: 'fas fa-copy',
action: () => {
copyToClipboard(`:${this.emoji.name}:`);
os.success();
}
}], ev.currentTarget || ev.target);
}
}
});
</script>
<style lang="scss" scoped>
.zuvgdzyu {
display: flex;
align-items: center;
padding: 12px;
text-align: left;
background: var(--panel);
border-radius: 8px;
transform-style: preserve-3d;
transform: perspective(1000px);
&:hover {
border-color: var(--accent);
}
> .img {
width: 42px;
height: 42px;
transform: translateZ(20px);
}
> .body {
padding: 0 0 0 8px;
white-space: nowrap;
overflow: hidden;
transform: translateZ(10px);
> .name {
text-overflow: ellipsis;
overflow: hidden;
}
> .info {
opacity: 0.5;
font-size: 0.9em;
text-overflow: ellipsis;
overflow: hidden;
}
}
}
</style>

View File

@ -1,151 +1,30 @@
<template> <template>
<div class="driuhtrh"> <XCategory v-if="tab === 'category'"/>
<div class="query">
<MkInput v-model="q" class="_inputNoTopMargin _inputNoBottomMargin" :placeholder="$ts.search">
<template #prefix><i class="fas fa-search"></i></template>
</MkInput>
</div>
<div class="emojis">
<MkFolder v-if="searchEmojis">
<template #header>{{ $ts.searchResult }}</template>
<div class="zuvgdzyt">
<button v-for="emoji in searchEmojis" :key="emoji.name" class="emoji _button" @click="menu(emoji, $event)">
<img :src="emoji.url" class="img" :alt="emoji.name"/>
<div class="body">
<div class="name _monospace">{{ emoji.name }}</div>
<div class="info">{{ emoji.aliases.join(' ') }}</div>
</div>
</button>
</div>
</MkFolder>
<MkFolder v-for="category in customEmojiCategories" :key="category">
<template #header>{{ category || $ts.other }}</template>
<div class="zuvgdzyt">
<button v-for="emoji in customEmojis.filter(e => e.category === category)" :key="emoji.name" class="emoji _button" @click="menu(emoji, $event)">
<img :src="emoji.url" class="img" :alt="emoji.name"/>
<div class="body">
<div class="name _monospace">{{ emoji.name }}</div>
<div class="info">{{ emoji.aliases.join(' ') }}</div>
</div>
</button>
</div>
</MkFolder>
</div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent, computed } from 'vue';
import MkButton from '@client/components/ui/button.vue';
import MkInput from '@client/components/ui/input.vue';
import MkSelect from '@client/components/ui/select.vue';
import MkFolder from '@client/components/ui/folder.vue';
import * as os from '@client/os'; import * as os from '@client/os';
import * as symbols from '@client/symbols'; import * as symbols from '@client/symbols';
import { emojiCategories } from '@client/instance'; import XCategory from './emojis.category.vue';
import copyToClipboard from '@client/scripts/copy-to-clipboard';
export default defineComponent({ export default defineComponent({
components: { components: {
MkButton, XCategory,
MkInput,
MkSelect,
MkFolder,
}, },
data() { data() {
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: computed(() => ({
title: this.$ts.customEmojis, title: this.$ts.customEmojis,
icon: 'fas fa-laugh' icon: 'fas fa-laugh',
}, bg: 'var(--bg)',
q: '', })),
customEmojiCategories: emojiCategories, tab: 'category',
customEmojis: this.$instance.emojis,
searchEmojis: null,
} }
}, },
watch: {
q() {
if (this.q === '' || this.q == null) {
this.searchEmojis = null;
return;
}
this.searchEmojis = this.customEmojis.filter(e => e.name.includes(this.q) || e.aliases.includes(this.q));
}
},
methods: {
menu(emoji, ev) {
os.popupMenu([{
type: 'label',
text: ':' + emoji.name + ':',
}, {
text: this.$ts.copy,
icon: 'fas fa-copy',
action: () => {
copyToClipboard(`:${emoji.name}:`);
os.success();
}
}], ev.currentTarget || ev.target);
}
}
}); });
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.driuhtrh {
> .query {
background: var(--bg);
padding: 16px;
}
> .emojis {
.zuvgdzyt {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
grid-gap: 12px;
margin: 0 var(--margin) var(--margin) var(--margin);
> .emoji {
display: flex;
align-items: center;
padding: 12px;
text-align: left;
border: solid 1px var(--divider);
border-radius: 8px;
&:hover {
border-color: var(--accent);
}
> .img {
width: 42px;
height: 42px;
}
> .body {
padding: 0 0 0 8px;
white-space: nowrap;
overflow: hidden;
> .name {
text-overflow: ellipsis;
overflow: hidden;
}
> .info {
opacity: 0.5;
font-size: 0.9em;
text-overflow: ellipsis;
overflow: hidden;
}
}
}
}
}
}
</style> </style>

View File

@ -22,7 +22,8 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.favorites, title: this.$ts.favorites,
icon: 'fas fa-star' icon: 'fas fa-star',
bg: 'var(--bg)',
}, },
pagination: { pagination: {
endpoint: 'i/favorites', endpoint: 'i/favorites',

View File

@ -1,5 +1,6 @@
<template> <template>
<div class="fcuexfpr _root"> <div class="fcuexfpr">
<div class="_root">
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<div v-if="note" class="note"> <div v-if="note" class="note">
<div class="_gap" v-if="showNext"> <div class="_gap" v-if="showNext">
@ -33,6 +34,7 @@
<MkLoading v-else/> <MkLoading v-else/>
</transition> </transition>
</div> </div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -63,12 +65,14 @@ export default defineComponent({
return { return {
[symbols.PAGE_INFO]: computed(() => this.note ? { [symbols.PAGE_INFO]: computed(() => this.note ? {
title: this.$ts.note, title: this.$ts.note,
subtitle: new Date(this.note.createdAt).toLocaleString(),
avatar: this.note.user, avatar: this.note.user,
path: `/notes/${this.note.id}`, path: `/notes/${this.note.id}`,
share: { share: {
title: this.$t('noteOf', { user: this.note.user.name }), title: this.$t('noteOf', { user: this.note.user.name }),
text: this.note.text, text: this.note.text,
}, },
bg: 'var(--bg)',
} : null), } : null),
note: null, note: null,
clips: null, clips: null,
@ -149,6 +153,7 @@ export default defineComponent({
.fcuexfpr { .fcuexfpr {
background: var(--bg); background: var(--bg);
> ._root {
> .note { > .note {
> .main { > .main {
> .load { > .load {
@ -202,4 +207,5 @@ export default defineComponent({
} }
} }
} }
}
</style> </style>

View File

@ -21,6 +21,7 @@ export default defineComponent({
[symbols.PAGE_INFO]: { [symbols.PAGE_INFO]: {
title: this.$ts.notifications, title: this.$ts.notifications,
icon: 'fas fa-bell', icon: 'fas fa-bell',
bg: 'var(--bg)',
actions: [{ actions: [{
text: this.$ts.markAllAsRead, text: this.$ts.markAllAsRead,
icon: 'fas fa-check', icon: 'fas fa-check',

View File

@ -86,7 +86,8 @@ export default defineComponent({
setup(props, context) { setup(props, context) {
const indexInfo = { const indexInfo = {
title: i18n.locale.settings, title: i18n.locale.settings,
icon: 'fas fa-cog' icon: 'fas fa-cog',
bg: 'var(--bg)',
}; };
const INFO = ref(indexInfo); const INFO = ref(indexInfo);
const page = ref(props.initialPage); const page = ref(props.initialPage);

View File

@ -26,7 +26,7 @@
<FormLink to="/bios" behavior="browser"><template #icon><i class="fas fa-door-open"></i></template>BIOS</FormLink> <FormLink to="/bios" behavior="browser"><template #icon><i class="fas fa-door-open"></i></template>BIOS</FormLink>
<FormLink to="/cli" behavior="browser"><template #icon><i class="fas fa-door-open"></i></template>CLI</FormLink> <FormLink to="/cli" behavior="browser"><template #icon><i class="fas fa-door-open"></i></template>CLI</FormLink>
<FormLink to="./delete-account"><template #icon><i class="fas fa-exclamation-triangle"></i></template>{{ $ts.closeAccount }}</FormLink> <FormLink to="/settings/delete-account"><template #icon><i class="fas fa-exclamation-triangle"></i></template>{{ $ts.closeAccount }}</FormLink>
</FormBase> </FormBase>
</template> </template>

View File

@ -1,25 +1,10 @@
<template> <template>
<div class="cmuxhskf" v-hotkey.global="keymap" v-size="{ min: [800] }"> <div class="cmuxhskf" v-hotkey.global="keymap" v-size="{ min: [800] }">
<XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block _isolated"/> <XTutorial v-if="$store.reactiveState.tutorial.value != -1" class="tutorial _block"/>
<XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block _isolated" fixed/> <XPostForm v-if="$store.reactiveState.showFixedPostForm.value" class="post-form _block" fixed/>
<div class="tabs">
<div class="left">
<button class="_button tab" @click="() => { src = 'home'; saveSrc(); }" :class="{ active: src === 'home' }" v-tooltip="$ts._timelines.home"><i class="fas fa-home"></i></button>
<button class="_button tab" @click="() => { src = 'local'; saveSrc(); }" :class="{ active: src === 'local' }" v-tooltip="$ts._timelines.local" v-if="isLocalTimelineAvailable"><i class="fas fa-comments"></i></button>
<button class="_button tab" @click="() => { src = 'social'; saveSrc(); }" :class="{ active: src === 'social' }" v-tooltip="$ts._timelines.social" v-if="isLocalTimelineAvailable"><i class="fas fa-share-alt"></i></button>
<button class="_button tab" @click="() => { src = 'global'; saveSrc(); }" :class="{ active: src === 'global' }" v-tooltip="$ts._timelines.global" v-if="isGlobalTimelineAvailable"><i class="fas fa-globe"></i></button>
<span class="divider"></span>
<button class="_button tab" @click="() => { src = 'mentions'; saveSrc(); }" :class="{ active: src === 'mentions' }" v-tooltip="$ts.mentions"><i class="fas fa-at"></i><i v-if="$i.hasUnreadMentions" class="fas fa-circle i"></i></button>
<button class="_button tab" @click="() => { src = 'directs'; saveSrc(); }" :class="{ active: src === 'directs' }" v-tooltip="$ts.directNotes"><i class="fas fa-envelope"></i><i v-if="$i.hasUnreadSpecifiedNotes" class="fas fa-circle i"></i></button>
</div>
<div class="right">
<button class="_button tab" @click="chooseChannel" :class="{ active: src === 'channel' }" v-tooltip="$ts.channel"><i class="fas fa-satellite-dish"></i><i v-if="$i.hasUnreadChannel" class="fas fa-circle i"></i></button>
<button class="_button tab" @click="chooseAntenna" :class="{ active: src === 'antenna' }" v-tooltip="$ts.antennas"><i class="fas fa-satellite"></i><i v-if="$i.hasUnreadAntenna" class="fas fa-circle i"></i></button>
<button class="_button tab" @click="chooseList" :class="{ active: src === 'list' }" v-tooltip="$ts.lists"><i class="fas fa-list-ul"></i></button>
</div>
</div>
<div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div> <div class="new" v-if="queue > 0"><button class="_buttonPrimary" @click="top()">{{ $ts.newNoteRecived }}</button></div>
<div class="tl"> <div class="tl _block">
<XTimeline ref="tl" class="tl" <XTimeline ref="tl" class="tl"
:key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src === 'channel' ? `channel:${channel.id}` : src" :key="src === 'list' ? `list:${list.id}` : src === 'antenna' ? `antenna:${antenna.id}` : src === 'channel' ? `channel:${channel.id}` : src"
:src="src" :src="src"
@ -63,12 +48,37 @@ export default defineComponent({
queue: 0, queue: 0,
[symbols.PAGE_INFO]: computed(() => ({ [symbols.PAGE_INFO]: computed(() => ({
title: this.$ts.timeline, title: this.$ts.timeline,
subtitle: this.src === 'local' ? this.$ts._timelines.local : this.src === 'social' ? this.$ts._timelines.social : this.src === 'global' ? this.$ts._timelines.global : this.$ts._timelines.home,
icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home', icon: this.src === 'local' ? 'fas fa-comments' : this.src === 'social' ? 'fas fa-share-alt' : this.src === 'global' ? 'fas fa-globe' : 'fas fa-home',
bg: 'var(--bg)',
actions: [{ actions: [{
icon: 'fas fa-calendar-alt', icon: 'fas fa-calendar-alt',
text: this.$ts.jumpToSpecifiedDate, text: this.$ts.jumpToSpecifiedDate,
handler: this.timetravel handler: this.timetravel
}],
tabs: [{
active: this.src === 'home',
title: this.$ts._timelines.home,
icon: 'fas fa-home',
iconOnly: true,
onClick: () => { this.src = 'home'; this.saveSrc(); },
}, {
active: this.src === 'local',
title: this.$ts._timelines.local,
icon: 'fas fa-comments',
iconOnly: true,
onClick: () => { this.src = 'local'; this.saveSrc(); },
}, {
active: this.src === 'social',
title: this.$ts._timelines.social,
icon: 'fas fa-share-alt',
iconOnly: true,
onClick: () => { this.src = 'social'; this.saveSrc(); },
}, {
active: this.src === 'global',
title: this.$ts._timelines.global,
icon: 'fas fa-globe',
iconOnly: true,
onClick: () => { this.src = 'global'; this.saveSrc(); },
}] }]
})), })),
}; };
@ -213,6 +223,8 @@ export default defineComponent({
<style lang="scss" scoped> <style lang="scss" scoped>
.cmuxhskf { .cmuxhskf {
padding: var(--margin);
> .new { > .new {
position: sticky; position: sticky;
top: calc(var(--stickyTop, 0px) + 16px); top: calc(var(--stickyTop, 0px) + 16px);
@ -227,79 +239,15 @@ export default defineComponent({
} }
} }
> .tabs { > .tl {
display: flex; background: var(--bg);
box-sizing: border-box; border-radius: var(--radius);
padding: 0 8px; overflow: clip;
white-space: nowrap;
overflow: auto;
border-bottom: solid 0.5px var(--divider);
//
position: relative;
> .right {
margin-left: auto;
}
> .left, > .right {
> .tab {
position: relative;
height: 50px;
padding: 0 12px;
&:hover {
color: var(--fgHighlighted);
}
&.active {
color: var(--fgHighlighted);
&:after {
content: "";
display: block;
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin: 0 auto;
width: 100%;
height: 2px;
background: var(--accent);
}
}
> .i {
position: absolute;
top: 16px;
right: 8px;
color: var(--indicator);
font-size: 8px;
animation: blink 1s infinite;
}
}
> .divider {
display: inline-block;
width: 1px;
height: 28px;
vertical-align: middle;
margin: 0 8px;
background: var(--divider);
}
}
} }
&.min-width_800px { &.min-width_800px {
> .tl {
background: var(--bg);
padding: 32px 0;
> .tl {
max-width: 800px; max-width: 800px;
margin: 0 auto; margin: 0 auto;
} }
} }
}
}
</style> </style>

View File

@ -60,24 +60,10 @@
<XPhotos :user="user" :key="user.id" class="_gap"/> <XPhotos :user="user" :key="user.id" class="_gap"/>
</div> </div>
<div class="main"> <div class="main">
<div class="nav _gap">
<MkA :to="userPage(user)" :class="{ active: page === 'index' }" class="link">
<i class="fas fa-comment-alt icon"></i>
<span>{{ $ts.notes }}</span>
</MkA>
<MkA :to="userPage(user, 'clips')" :class="{ active: page === 'clips' }" class="link">
<i class="fas fa-paperclip icon"></i>
<span>{{ $ts.clips }}</span>
</MkA>
<MkA :to="userPage(user, 'pages')" :class="{ active: page === 'pages' }" class="link">
<i class="fas fa-file-alt icon"></i>
<span>{{ $ts.pages }}</span>
</MkA>
<div class="actions"> <div class="actions">
<button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button> <button @click="menu" class="menu _button"><i class="fas fa-ellipsis-h"></i></button>
<MkFollowButton v-if="!$i || $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" large class="koudoku"/> <MkFollowButton v-if="!$i || $i.id != user.id" :user="user" :inline="true" :transparent="false" :full="true" large class="koudoku"/>
</div> </div>
</div>
<template v-if="page === 'index'"> <template v-if="page === 'index'">
<div v-if="user.pinnedNotes.length > 0" class="_gap"> <div v-if="user.pinnedNotes.length > 0" class="_gap">
<XNote v-for="note in user.pinnedNotes" class="note _gap" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/> <XNote v-for="note in user.pinnedNotes" class="note _gap" :note="note" @update:note="pinnedNoteUpdated(note, $event)" :key="note.id" :pinned="true"/>
@ -178,25 +164,6 @@
</div> </div>
<div class="contents"> <div class="contents">
<div class="nav _gap">
<MkA :to="userPage(user)" :class="{ active: page === 'index' }" class="link" v-click-anime>
<i class="fas fa-comment-alt icon"></i>
<span>{{ $ts.notes }}</span>
</MkA>
<MkA :to="userPage(user, 'clips')" :class="{ active: page === 'clips' }" class="link" v-click-anime>
<i class="fas fa-paperclip icon"></i>
<span>{{ $ts.clips }}</span>
</MkA>
<MkA :to="userPage(user, 'pages')" :class="{ active: page === 'pages' }" class="link" v-click-anime>
<i class="fas fa-file-alt icon"></i>
<span>{{ $ts.pages }}</span>
</MkA>
<MkA :to="userPage(user, 'gallery')" :class="{ active: page === 'gallery' }" class="link" v-click-anime>
<i class="fas fa-icons icon"></i>
<span>{{ $ts.gallery }}</span>
</MkA>
</div>
<template v-if="page === 'index'"> <template v-if="page === 'index'">
<div> <div>
<div v-if="user.pinnedNotes.length > 0" class="_gap"> <div v-if="user.pinnedNotes.length > 0" class="_gap">
@ -283,6 +250,27 @@ export default defineComponent({
share: { share: {
title: this.user.name, title: this.user.name,
}, },
bg: 'var(--bg)',
tabs: [{
active: this.page === 'index',
title: this.$ts.overview,
icon: 'fas fa-home',
}, {
active: this.page === 'clips',
title: this.$ts.clips,
icon: 'fas fa-paperclip',
onClick: () => { this.page = 'clips'; },
}, {
active: this.page === 'pages',
title: this.$ts.pages,
icon: 'fas fa-file-alt',
onClick: () => { this.page = 'pages'; },
}, {
active: this.page === 'gallery',
title: this.$ts.gallery,
icon: 'fas fa-icons',
onClick: () => { this.page = 'gallery'; },
}]
} : null), } : null),
user: null, user: null,
error: null, error: null,
@ -314,7 +302,7 @@ export default defineComponent({
mounted() { mounted() {
window.requestAnimationFrame(this.parallaxLoop); window.requestAnimationFrame(this.parallaxLoop);
this.narrow = this.$el.clientWidth < 1000; this.narrow = true//this.$el.clientWidth < 1000;
}, },
beforeUnmount() { beforeUnmount() {
@ -772,37 +760,6 @@ export default defineComponent({
} }
> .contents { > .contents {
> .nav {
display: flex;
align-items: center;
font-size: 90%;
> .link {
flex: 1;
display: inline-block;
padding: 16px;
text-align: center;
border-bottom: solid 3px transparent;
&:hover {
text-decoration: none;
}
&.active {
color: var(--accent);
border-bottom-color: var(--accent);
}
&:not(.active):hover {
color: var(--fgHighlighted);
}
> .icon {
margin-right: 6px;
}
}
}
> .content { > .content {
margin-bottom: var(--margin); margin-bottom: var(--margin);
} }

View File

@ -245,7 +245,6 @@ hr {
._panel { ._panel {
background: var(--panel); background: var(--panel);
border-radius: var(--radius); border-radius: var(--radius);
border: var(--panelBorder);
overflow: clip; overflow: clip;
} }

View File

@ -36,7 +36,7 @@
navFg: '@fg', navFg: '@fg',
navHoverFg: ':lighten<17<@fg', navHoverFg: ':lighten<17<@fg',
navActive: '@accent', navActive: '@accent',
navIndicator: '@accent', navIndicator: '@indicator',
link: '#44a4c1', link: '#44a4c1',
hashtag: '#ff9156', hashtag: '#ff9156',
mention: '@accent', mention: '@accent',

View File

@ -36,7 +36,7 @@
navFg: '@fg', navFg: '@fg',
navHoverFg: ':darken<17<@fg', navHoverFg: ':darken<17<@fg',
navActive: '@accent', navActive: '@accent',
navIndicator: '@accent', navIndicator: '@indicator',
link: '#44a4c1', link: '#44a4c1',
hashtag: '#ff9156', hashtag: '#ff9156',
mention: '@accent', mention: '@accent',

View File

@ -1,25 +1,35 @@
<template> <template>
<div class="fdidabkb" :class="{ center }" :style="`--height:${height};`" :key="key"> <div class="fdidabkb" :class="{ slim: titleOnly || narrow }" :style="`--height:${height};`" :key="key">
<transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear> <transition :name="$store.state.animation ? 'header' : ''" mode="out-in" appear>
<div class="buttons left" v-if="backButton"> <div class="buttons left" v-if="backButton">
<button class="_button button back" @click.stop="$emit('back')" @touchstart="preventDrag" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button> <button class="_button button back" @click.stop="$emit('back')" @touchstart="preventDrag" v-tooltip="$ts.goBack"><i class="fas fa-chevron-left"></i></button>
</div> </div>
</transition> </transition>
<template v-if="info"> <template v-if="info">
<div class="titleContainer"> <div class="titleContainer" @click="showTabsPopup">
<i v-if="info.icon" class="icon" :class="info.icon"></i> <i v-if="info.icon" class="icon" :class="info.icon"></i>
<MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/> <MkAvatar v-else-if="info.avatar" class="avatar" :user="info.avatar" :disable-preview="true" :show-indicator="true"/>
<div class="title"> <div class="title">
<MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="title"/> <MkUserName v-if="info.userName" :user="info.userName" :nowrap="false" class="title"/>
<div v-else-if="info.title" class="title">{{ info.title }}</div> <div v-else-if="info.title" class="title">{{ info.title }}</div>
<div class="subtitle" v-if="info.subtitle"> <div class="subtitle" v-if="!narrow && info.subtitle">
{{ info.subtitle }} {{ info.subtitle }}
</div> </div>
<div class="subtitle activeTab" v-if="narrow && hasTabs">
{{ info.tabs.find(tab => tab.active)?.title }}
<i class="chevron fas fa-chevron-down"></i>
</div> </div>
</div> </div>
</div>
<div class="tabs" v-if="!narrow">
<button class="tab _button" v-for="tab in info.tabs" :class="{ active: tab.active }" @click="tab.onClick" v-tooltip="tab.title">
<i v-if="tab.icon" class="icon" :class="tab.icon"></i>
<span v-if="!tab.iconOnly" class="title">{{ tab.title }}</span>
</button>
</div>
<div class="buttons right"> <div class="buttons right">
<template v-if="info.actions && showActions"> <template v-if="info.actions && !narrow">
<button v-for="action in info.actions" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" @touchstart="preventDrag" v-tooltip="action.text"><i :class="action.icon"></i></button> <button v-for="action in info.actions" class="_button button" :class="{ highlighted: action.highlighted }" @click.stop="action.handler" @touchstart="preventDrag" v-tooltip="action.text"><i :class="action.icon"></i></button>
</template> </template>
<button v-if="shouldShowMenu" class="_button button" @click.stop="showMenu" @touchstart="preventDrag" v-tooltip="$ts.menu"><i class="fas fa-ellipsis-h"></i></button> <button v-if="shouldShowMenu" class="_button button" @click.stop="showMenu" @touchstart="preventDrag" v-tooltip="$ts.menu"><i class="fas fa-ellipsis-h"></i></button>
@ -52,24 +62,28 @@ export default defineComponent({
required: false, required: false,
default: false, default: false,
}, },
center: { titleOnly: {
type: Boolean, type: Boolean,
required: false, required: false,
default: true, default: false,
}, },
}, },
data() { data() {
return { return {
showActions: false, narrow: false,
height: 0, height: 0,
key: 0, key: 0,
}; };
}, },
computed: { computed: {
hasTabs(): boolean {
return this.info.tabs && this.info.tabs.length > 0;
},
shouldShowMenu() { shouldShowMenu() {
if (this.info.actions != null && !this.showActions) return true; if (this.info.actions != null && this.narrow) return true;
if (this.info.menu != null) return true; if (this.info.menu != null) return true;
if (this.info.share != null) return true; if (this.info.share != null) return true;
if (this.menu != null) return true; if (this.menu != null) return true;
@ -85,10 +99,10 @@ export default defineComponent({
mounted() { mounted() {
this.height = this.$el.parentElement.offsetHeight + 'px'; this.height = this.$el.parentElement.offsetHeight + 'px';
this.showActions = this.$el.parentElement.offsetWidth >= 500; this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500;
new ResizeObserver((entries, observer) => { new ResizeObserver((entries, observer) => {
this.height = this.$el.parentElement.offsetHeight + 'px'; this.height = this.$el.parentElement.offsetHeight + 'px';
this.showActions = this.$el.parentElement.offsetWidth >= 500; this.narrow = this.titleOnly || this.$el.parentElement.offsetWidth < 500;
}).observe(this.$el); }).observe(this.$el);
}, },
@ -102,7 +116,7 @@ export default defineComponent({
showMenu(ev) { showMenu(ev) {
let menu = this.info.menu ? this.info.menu() : []; let menu = this.info.menu ? this.info.menu() : [];
if (!this.showActions && this.info.actions) { if (this.narrow && this.info.actions) {
menu = [...this.info.actions.map(x => ({ menu = [...this.info.actions.map(x => ({
text: x.text, text: x.text,
icon: x.icon, icon: x.icon,
@ -124,6 +138,18 @@ export default defineComponent({
popupMenu(menu, ev.currentTarget || ev.target); popupMenu(menu, ev.currentTarget || ev.target);
}, },
showTabsPopup(ev) {
if (!this.hasTabs) return;
ev.preventDefault();
ev.stopPropagation();
const menu = this.info.tabs.map(tab => ({
text: tab.title,
icon: tab.icon,
action: tab.onClick,
}));
popupMenu(menu, ev.currentTarget || ev.target);
},
preventDrag(ev) { preventDrag(ev) {
ev.stopPropagation(); ev.stopPropagation();
} }
@ -135,7 +161,7 @@ export default defineComponent({
.fdidabkb { .fdidabkb {
display: flex; display: flex;
&.center { &.slim {
text-align: center; text-align: center;
> .titleContainer { > .titleContainer {
@ -190,6 +216,7 @@ export default defineComponent({
overflow: auto; overflow: auto;
white-space: nowrap; white-space: nowrap;
text-align: left; text-align: left;
font-weight: bold;
> .avatar { > .avatar {
$size: 32px; $size: 32px;
@ -219,6 +246,54 @@ export default defineComponent({
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
&.activeTab {
text-align: center;
> .chevron {
display: inline-block;
margin-left: 6px;
}
}
}
}
}
> .tabs {
margin-left: 16px;
font-size: 0.8em;
> .tab {
display: inline-block;
position: relative;
padding: 0 10px;
height: 100%;
font-weight: normal;
opacity: 0.7;
&:hover {
opacity: 1;
}
&.active {
opacity: 1;
&:after {
content: "";
display: block;
position: absolute;
bottom: 0;
left: 0;
right: 0;
margin: 0 auto;
width: 100%;
height: 3px;
background: var(--accent);
}
}
> .icon + .title {
margin-left: 8px;
} }
} }
} }

View File

@ -12,7 +12,7 @@
</div> </div>
</template> </template>
<main class="main" @contextmenu.stop="onContextmenu"> <main class="main" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
<header class="header" @click="onHeaderClick"> <header class="header" @click="onHeaderClick">
<XHeader :info="pageInfo" :back-button="true" @back="back()"/> <XHeader :info="pageInfo" :back-button="true" @back="back()"/>
</header> </header>
@ -145,6 +145,15 @@ export default defineComponent({
} }
}, '*'); }, '*');
}, { passive: true }); }, { passive: true });
window.addEventListener('touchmove', ev => {
this.$refs.live2d.contentWindow.postMessage({
type: 'moveCursor',
body: {
x: ev.touches[0].clientX - iframeRect.left,
y: ev.touches[0].clientY - iframeRect.top,
}
}, '*');
}, { passive: true });
} }
}, },

View File

@ -2,8 +2,8 @@
<div class="mk-app" :class="{ wallpaper }"> <div class="mk-app" :class="{ wallpaper }">
<XSidebar ref="nav" class="sidebar"/> <XSidebar ref="nav" class="sidebar"/>
<div class="contents" ref="contents" @contextmenu.stop="onContextmenu"> <div class="contents" ref="contents" @contextmenu.stop="onContextmenu" :style="{ background: pageInfo?.bg }">
<header class="header" ref="header" @click="onHeaderClick"> <header class="header" ref="header" @click="onHeaderClick" :style="{ background: pageInfo?.bg }">
<XHeader :info="pageInfo" :back-button="true" @back="back()"/> <XHeader :info="pageInfo" :back-button="true" @back="back()"/>
</header> </header>
<main ref="main"> <main ref="main">
@ -258,7 +258,6 @@ export default defineComponent({
} }
> .sidebar { > .sidebar {
border-right: solid 0.5px var(--divider);
} }
> .contents { > .contents {
@ -313,7 +312,8 @@ export default defineComponent({
> .widgets { > .widgets {
padding: 0 var(--margin); padding: 0 var(--margin);
border-left: solid 0.5px var(--divider); //border-left: solid 0.5px var(--divider);
background: var(--navBg);
@media (max-width: $widgets-hide-threshold) { @media (max-width: $widgets-hide-threshold) {
display: none; display: none;

View File

@ -1,15 +1,57 @@
export type Schema = { import { SimpleObj, SimpleSchema } from './simple-schema';
type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; import { packedUserSchema } from '@/models/repositories/user';
nullable: boolean; import { packedNoteSchema } from '@/models/repositories/note';
optional: boolean; import { packedUserListSchema } from '@/models/repositories/user-list';
import { packedAppSchema } from '@/models/repositories/app';
import { packedMessagingMessageSchema } from '@/models/repositories/messaging-message';
import { packedNotificationSchema } from '@/models/repositories/notification';
import { packedDriveFileSchema } from '@/models/repositories/drive-file';
import { packedDriveFolderSchema } from '@/models/repositories/drive-folder';
import { packedFollowingSchema } from '@/models/repositories/following';
import { packedMutingSchema } from '@/models/repositories/muting';
import { packedBlockingSchema } from '@/models/repositories/blocking';
import { packedNoteReactionSchema } from '@/models/repositories/note-reaction';
import { packedHashtagSchema } from '@/models/repositories/hashtag';
import { packedPageSchema } from '@/models/repositories/page';
import { packedUserGroupSchema } from '@/models/repositories/user-group';
import { packedNoteFavoriteSchema } from '@/models/repositories/note-favorite';
import { packedChannelSchema } from '@/models/repositories/channel';
import { packedAntennaSchema } from '@/models/repositories/antenna';
import { packedClipSchema } from '@/models/repositories/clip';
import { packedFederationInstanceSchema } from '@/models/repositories/federation-instance';
import { packedQueueCountSchema } from '@/models/repositories/queue';
import { packedGalleryPostSchema } from '@/models/repositories/gallery-post';
export const refs = {
User: packedUserSchema,
UserList: packedUserListSchema,
UserGroup: packedUserGroupSchema,
App: packedAppSchema,
MessagingMessage: packedMessagingMessageSchema,
Note: packedNoteSchema,
NoteReaction: packedNoteReactionSchema,
NoteFavorite: packedNoteFavoriteSchema,
Notification: packedNotificationSchema,
DriveFile: packedDriveFileSchema,
DriveFolder: packedDriveFolderSchema,
Following: packedFollowingSchema,
Muting: packedMutingSchema,
Blocking: packedBlockingSchema,
Hashtag: packedHashtagSchema,
Page: packedPageSchema,
Channel: packedChannelSchema,
QueueCount: packedQueueCountSchema,
Antenna: packedAntennaSchema,
Clip: packedClipSchema,
FederationInstance: packedFederationInstanceSchema,
GalleryPost: packedGalleryPostSchema,
};
export interface Schema extends SimpleSchema {
items?: Schema; items?: Schema;
properties?: Obj; properties?: Obj;
description?: string; ref?: keyof typeof refs;
example?: any; }
format?: string;
ref?: string;
enum?: string[];
};
type NonUndefinedPropertyNames<T extends Obj> = { type NonUndefinedPropertyNames<T extends Obj> = {
[K in keyof T]: T[K]['optional'] extends true ? never : K [K in keyof T]: T[K]['optional'] extends true ? never : K
@ -22,7 +64,7 @@ type UndefinedPropertyNames<T extends Obj> = {
type OnlyRequired<T extends Obj> = Pick<T, NonUndefinedPropertyNames<T>>; type OnlyRequired<T extends Obj> = Pick<T, NonUndefinedPropertyNames<T>>;
type OnlyOptional<T extends Obj> = Pick<T, UndefinedPropertyNames<T>>; type OnlyOptional<T extends Obj> = Pick<T, UndefinedPropertyNames<T>>;
export type Obj = { [key: string]: Schema }; export interface Obj extends SimpleObj { [key: string]: Schema; }
export type ObjType<s extends Obj> = export type ObjType<s extends Obj> =
{ [P in keyof OnlyOptional<s>]?: SchemaType<s[P]> } & { [P in keyof OnlyOptional<s>]?: SchemaType<s[P]> } &
@ -48,6 +90,10 @@ export type SchemaType<p extends Schema> =
p['type'] extends 'string' ? NullOrUndefined<p, string> : p['type'] extends 'string' ? NullOrUndefined<p, string> :
p['type'] extends 'boolean' ? NullOrUndefined<p, boolean> : p['type'] extends 'boolean' ? NullOrUndefined<p, boolean> :
p['type'] extends 'array' ? NullOrUndefined<p, MyType<NonNullable<p['items']>>[]> : p['type'] extends 'array' ? NullOrUndefined<p, MyType<NonNullable<p['items']>>[]> :
p['type'] extends 'object' ? NullOrUndefined<p, ObjType<NonNullable<p['properties']>>> : p['type'] extends 'object' ? (
p['ref'] extends keyof typeof refs
? NullOrUndefined<p, SchemaType<typeof refs[p['ref']]>>
: NullOrUndefined<p, ObjType<NonNullable<p['properties']>>>
) :
p['type'] extends 'any' ? NullOrUndefined<p, any> : p['type'] extends 'any' ? NullOrUndefined<p, any> :
any; any;

15
src/misc/simple-schema.ts Normal file
View File

@ -0,0 +1,15 @@
export interface SimpleSchema {
type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any';
nullable: boolean;
optional: boolean;
items?: SimpleSchema;
properties?: SimpleObj;
description?: string;
example?: any;
format?: string;
ref?: string;
enum?: string[];
default?: boolean | null;
}
export interface SimpleObj { [key: string]: SimpleSchema; }

View File

@ -56,7 +56,7 @@ export const packedBlockingSchema = {
blockee: { blockee: {
type: 'object' as const, type: 'object' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
ref: 'User', ref: 'User' as const,
}, },
} }
}; };

View File

@ -53,7 +53,7 @@ export const packedClipSchema = {
}, },
user: { user: {
type: 'object' as const, type: 'object' as const,
ref: 'User', ref: 'User' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
}, },
name: { name: {

View File

@ -234,7 +234,7 @@ export const packedDriveFileSchema = {
folder: { folder: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'DriveFolder' ref: 'DriveFolder' as const,
}, },
userId: { userId: {
type: 'string' as const, type: 'string' as const,
@ -245,7 +245,7 @@ export const packedDriveFileSchema = {
user: { user: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'User' ref: 'User' as const,
} }
}, },
}; };

View File

@ -87,7 +87,7 @@ export const packedDriveFolderSchema = {
parent: { parent: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'DriveFolder' ref: 'DriveFolder' as const,
}, },
}, },
}; };

View File

@ -110,7 +110,7 @@ export const packedFollowingSchema = {
followee: { followee: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: false as const, optional: true as const, nullable: false as const,
ref: 'User', ref: 'User' as const,
}, },
followerId: { followerId: {
type: 'string' as const, type: 'string' as const,
@ -120,7 +120,7 @@ export const packedFollowingSchema = {
follower: { follower: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: false as const, optional: true as const, nullable: false as const,
ref: 'User', ref: 'User' as const,
}, },
} }
}; };

View File

@ -1,6 +1,6 @@
import { EntityRepository, Repository } from 'typeorm'; import { EntityRepository, Repository } from 'typeorm';
import { GalleryPost } from '@/models/entities/gallery-post'; import { GalleryPost } from '@/models/entities/gallery-post';
import { SchemaType } from '../../misc/schema'; import { SchemaType } from '@/misc/schema';
import { Users, DriveFiles, GalleryLikes } from '../index'; import { Users, DriveFiles, GalleryLikes } from '../index';
import { awaitAll } from '@/prelude/await-all'; import { awaitAll } from '@/prelude/await-all';
import { User } from '@/models/entities/user'; import { User } from '@/models/entities/user';
@ -76,7 +76,7 @@ export const packedGalleryPostSchema = {
}, },
user: { user: {
type: 'object' as const, type: 'object' as const,
ref: 'User', ref: 'User' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
}, },
fileIds: { fileIds: {
@ -94,7 +94,7 @@ export const packedGalleryPostSchema = {
items: { items: {
type: 'object' as const, type: 'object' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
ref: 'DriveFile' ref: 'DriveFile' as const,
} }
}, },
tags: { tags: {

View File

@ -67,7 +67,7 @@ export const packedMessagingMessageSchema = {
}, },
user: { user: {
type: 'object' as const, type: 'object' as const,
ref: 'User', ref: 'User' as const,
optional: true as const, nullable: false as const, optional: true as const, nullable: false as const,
}, },
text: { text: {
@ -82,7 +82,7 @@ export const packedMessagingMessageSchema = {
file: { file: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'DriveFile', ref: 'DriveFile' as const,
}, },
recipientId: { recipientId: {
type: 'string' as const, type: 'string' as const,
@ -92,7 +92,7 @@ export const packedMessagingMessageSchema = {
recipient: { recipient: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'User' ref: 'User' as const,
}, },
groupId: { groupId: {
type: 'string' as const, type: 'string' as const,
@ -102,7 +102,7 @@ export const packedMessagingMessageSchema = {
group: { group: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'UserGroup' ref: 'UserGroup' as const,
}, },
isRead: { isRead: {
type: 'boolean' as const, type: 'boolean' as const,

View File

@ -56,7 +56,7 @@ export const packedMutingSchema = {
mutee: { mutee: {
type: 'object' as const, type: 'object' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
ref: 'User', ref: 'User' as const,
}, },
} }
}; };

View File

@ -45,7 +45,7 @@ export const packedNoteFavoriteSchema = {
note: { note: {
type: 'object' as const, type: 'object' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
ref: 'Note', ref: 'Note' as const,
}, },
noteId: { noteId: {
type: 'string' as const, type: 'string' as const,

View File

@ -42,7 +42,7 @@ export const packedNoteReactionSchema = {
user: { user: {
type: 'object' as const, type: 'object' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
ref: 'User', ref: 'User' as const,
}, },
type: { type: {
type: 'string' as const, type: 'string' as const,

View File

@ -95,7 +95,7 @@ export class NoteRepository extends Repository<Note> {
hide = true; hide = true;
} else if (meId === packedNote.userId) { } else if (meId === packedNote.userId) {
hide = false; hide = false;
} else if (packedNote.reply && (meId === (packedNote.reply as PackedNote).userId)) { } else if (packedNote.reply && (meId === packedNote.reply.userId)) {
// 自分の投稿に対するリプライ // 自分の投稿に対するリプライ
hide = false; hide = false;
} else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) { } else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) {
@ -353,7 +353,7 @@ export const packedNoteSchema = {
}, },
user: { user: {
type: 'object' as const, type: 'object' as const,
ref: 'User', ref: 'User' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
}, },
replyId: { replyId: {
@ -371,12 +371,12 @@ export const packedNoteSchema = {
reply: { reply: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'Note' ref: 'Note' as const,
}, },
renote: { renote: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'Note' ref: 'Note' as const,
}, },
viaMobile: { viaMobile: {
type: 'boolean' as const, type: 'boolean' as const,
@ -423,7 +423,7 @@ export const packedNoteSchema = {
items: { items: {
type: 'object' as const, type: 'object' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
ref: 'DriveFile' ref: 'DriveFile' as const,
} }
}, },
tags: { tags: {
@ -447,11 +447,24 @@ export const packedNoteSchema = {
channel: { channel: {
type: 'object' as const, type: 'object' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
ref: 'Channel' items: {
type: 'object' as const,
optional: false as const, nullable: false as const,
properties: {
id: {
type: 'string' as const,
optional: false as const, nullable: false as const,
},
name: {
type: 'string' as const,
optional: false as const, nullable: true as const,
},
},
},
}, },
localOnly: { localOnly: {
type: 'boolean' as const, type: 'boolean' as const,
optional: false as const, nullable: true as const, optional: true as const, nullable: false as const,
}, },
emojis: { emojis: {
type: 'array' as const, type: 'array' as const,
@ -466,7 +479,7 @@ export const packedNoteSchema = {
}, },
url: { url: {
type: 'string' as const, type: 'string' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: true as const,
}, },
}, },
}, },
@ -485,11 +498,11 @@ export const packedNoteSchema = {
}, },
uri: { uri: {
type: 'string' as const, type: 'string' as const,
optional: false as const, nullable: true as const, optional: true as const, nullable: false as const,
}, },
url: { url: {
type: 'string' as const, type: 'string' as const,
optional: false as const, nullable: true as const, optional: true as const, nullable: false as const,
}, },
myReaction: { myReaction: {

View File

@ -136,7 +136,7 @@ export const packedNotificationSchema = {
}, },
user: { user: {
type: 'object' as const, type: 'object' as const,
ref: 'User', ref: 'User' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
}, },
userId: { userId: {
@ -146,7 +146,7 @@ export const packedNotificationSchema = {
}, },
note: { note: {
type: 'object' as const, type: 'object' as const,
ref: 'Note', ref: 'Note' as const,
optional: true as const, nullable: true as const, optional: true as const, nullable: true as const,
}, },
reaction: { reaction: {

View File

@ -137,7 +137,7 @@ export const packedPageSchema = {
}, },
user: { user: {
type: 'object' as const, type: 'object' as const,
ref: 'User', ref: 'User' as const,
optional: false as const, nullable: false as const, optional: false as const, nullable: false as const,
}, },
} }

View File

@ -375,12 +375,12 @@ export const packedUserSchema = {
}, },
isAdmin: { isAdmin: {
type: 'boolean' as const, type: 'boolean' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: true as const,
default: false default: false
}, },
isModerator: { isModerator: {
type: 'boolean' as const, type: 'boolean' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: true as const,
default: false default: false
}, },
isBot: { isBot: {
@ -402,23 +402,11 @@ export const packedUserSchema = {
type: 'string' as const, type: 'string' as const,
nullable: false as const, optional: false as const nullable: false as const, optional: false as const
}, },
host: {
type: 'string' as const,
nullable: true as const, optional: false as const
},
url: { url: {
type: 'string' as const, type: 'string' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: false as const,
format: 'url' format: 'url'
}, },
aliases: {
type: 'array' as const,
nullable: false as const, optional: false as const,
items: {
type: 'string' as const,
nullable: false as const, optional: false as const
}
}
} }
} }
}, },
@ -457,7 +445,7 @@ export const packedUserSchema = {
}, },
isSuspended: { isSuspended: {
type: 'boolean' as const, type: 'boolean' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: true as const,
example: false example: false
}, },
description: { description: {
@ -476,7 +464,7 @@ export const packedUserSchema = {
}, },
fields: { fields: {
type: 'array' as const, type: 'array' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: true as const,
items: { items: {
type: 'object' as const, type: 'object' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: false as const,
@ -520,31 +508,31 @@ export const packedUserSchema = {
items: { items: {
type: 'object' as const, type: 'object' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: false as const,
ref: 'Note' ref: 'Note' as const,
} }
}, },
pinnedPageId: { pinnedPageId: {
type: 'string' as const, type: 'string' as const,
nullable: true as const, optional: false as const nullable: true as const, optional: true as const
}, },
pinnedPage: { pinnedPage: {
type: 'object' as const, type: 'object' as const,
nullable: true as const, optional: false as const, nullable: true as const, optional: true as const,
ref: 'Page' ref: 'Page' as const,
}, },
twoFactorEnabled: { twoFactorEnabled: {
type: 'boolean' as const, type: 'boolean' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: true as const,
default: false default: false
}, },
usePasswordLessLogin: { usePasswordLessLogin: {
type: 'boolean' as const, type: 'boolean' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: true as const,
default: false default: false
}, },
securityKeys: { securityKeys: {
type: 'boolean' as const, type: 'boolean' as const,
nullable: false as const, optional: false as const, nullable: false as const, optional: true as const,
default: false default: false
}, },
avatarId: { avatarId: {

View File

@ -3,7 +3,7 @@ import { dirname } from 'path';
import { Context } from 'cafy'; import { Context } from 'cafy';
import * as path from 'path'; import * as path from 'path';
import * as glob from 'glob'; import * as glob from 'glob';
import { Schema } from '@/misc/schema'; import { SimpleSchema } from '@/misc/simple-schema';
//const _filename = fileURLToPath(import.meta.url); //const _filename = fileURLToPath(import.meta.url);
const _filename = __filename; const _filename = __filename;
@ -34,7 +34,7 @@ export interface IEndpointMeta {
}; };
}; };
res?: Schema; res?: SimpleSchema;
/** /**
* *

View File

@ -1,26 +1,4 @@
import { packedUserSchema } from '@/models/repositories/user'; import { refs, Schema } from '@/misc/schema';
import { Schema } from '@/misc/schema';
import { packedNoteSchema } from '@/models/repositories/note';
import { packedUserListSchema } from '@/models/repositories/user-list';
import { packedAppSchema } from '@/models/repositories/app';
import { packedMessagingMessageSchema } from '@/models/repositories/messaging-message';
import { packedNotificationSchema } from '@/models/repositories/notification';
import { packedDriveFileSchema } from '@/models/repositories/drive-file';
import { packedDriveFolderSchema } from '@/models/repositories/drive-folder';
import { packedFollowingSchema } from '@/models/repositories/following';
import { packedMutingSchema } from '@/models/repositories/muting';
import { packedBlockingSchema } from '@/models/repositories/blocking';
import { packedNoteReactionSchema } from '@/models/repositories/note-reaction';
import { packedHashtagSchema } from '@/models/repositories/hashtag';
import { packedPageSchema } from '@/models/repositories/page';
import { packedUserGroupSchema } from '@/models/repositories/user-group';
import { packedNoteFavoriteSchema } from '@/models/repositories/note-favorite';
import { packedChannelSchema } from '@/models/repositories/channel';
import { packedAntennaSchema } from '@/models/repositories/antenna';
import { packedClipSchema } from '@/models/repositories/clip';
import { packedFederationInstanceSchema } from '@/models/repositories/federation-instance';
import { packedQueueCountSchema } from '@/models/repositories/queue';
import { packedGalleryPostSchema } from '@/models/repositories/gallery-post';
export function convertSchemaToOpenApiSchema(schema: Schema) { export function convertSchemaToOpenApiSchema(schema: Schema) {
const res: any = schema; const res: any = schema;
@ -72,26 +50,7 @@ export const schemas = {
required: ['error'] required: ['error']
}, },
User: convertSchemaToOpenApiSchema(packedUserSchema), ...Object.fromEntries(
UserList: convertSchemaToOpenApiSchema(packedUserListSchema), Object.entries(refs).map(([key, schema]) => [key, convertSchemaToOpenApiSchema(schema)])
UserGroup: convertSchemaToOpenApiSchema(packedUserGroupSchema), ),
App: convertSchemaToOpenApiSchema(packedAppSchema),
MessagingMessage: convertSchemaToOpenApiSchema(packedMessagingMessageSchema),
Note: convertSchemaToOpenApiSchema(packedNoteSchema),
NoteReaction: convertSchemaToOpenApiSchema(packedNoteReactionSchema),
NoteFavorite: convertSchemaToOpenApiSchema(packedNoteFavoriteSchema),
Notification: convertSchemaToOpenApiSchema(packedNotificationSchema),
DriveFile: convertSchemaToOpenApiSchema(packedDriveFileSchema),
DriveFolder: convertSchemaToOpenApiSchema(packedDriveFolderSchema),
Following: convertSchemaToOpenApiSchema(packedFollowingSchema),
Muting: convertSchemaToOpenApiSchema(packedMutingSchema),
Blocking: convertSchemaToOpenApiSchema(packedBlockingSchema),
Hashtag: convertSchemaToOpenApiSchema(packedHashtagSchema),
Page: convertSchemaToOpenApiSchema(packedPageSchema),
Channel: convertSchemaToOpenApiSchema(packedChannelSchema),
QueueCount: convertSchemaToOpenApiSchema(packedQueueCountSchema),
Antenna: convertSchemaToOpenApiSchema(packedAntennaSchema),
Clip: convertSchemaToOpenApiSchema(packedClipSchema),
FederationInstance: convertSchemaToOpenApiSchema(packedFederationInstanceSchema),
GalleryPost: convertSchemaToOpenApiSchema(packedGalleryPostSchema),
}; };

View File

@ -43,7 +43,7 @@ export default class extends Channel {
// 関係ない返信は除外 // 関係ない返信は除外
if (note.reply) { if (note.reply) {
const reply = note.reply as PackedNote; const reply = note.reply;
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
} }

View File

@ -51,7 +51,7 @@ export default class extends Channel {
// 関係ない返信は除外 // 関係ない返信は除外
if (note.reply) { if (note.reply) {
const reply = note.reply as PackedNote; const reply = note.reply;
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
} }

View File

@ -4,7 +4,6 @@ import Channel from '../channel';
import { fetchMeta } from '@/misc/fetch-meta'; import { fetchMeta } from '@/misc/fetch-meta';
import { Notes } from '@/models/index'; import { Notes } from '@/models/index';
import { PackedNote } from '@/models/repositories/note'; import { PackedNote } from '@/models/repositories/note';
import { PackedUser } from '@/models/repositories/user';
import { checkWordMute } from '@/misc/check-word-mute'; import { checkWordMute } from '@/misc/check-word-mute';
import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related';
@ -31,7 +30,7 @@ export default class extends Channel {
if (!( if (!(
(note.channelId == null && this.user!.id === note.userId) || (note.channelId == null && this.user!.id === note.userId) ||
(note.channelId == null && this.following.has(note.userId)) || (note.channelId == null && this.following.has(note.userId)) ||
(note.channelId == null && ((note.user as PackedUser).host == null && note.visibility === 'public')) || (note.channelId == null && (note.user.host == null && note.visibility === 'public')) ||
(note.channelId != null && this.followingChannels.has(note.channelId)) (note.channelId != null && this.followingChannels.has(note.channelId))
)) return; )) return;
@ -60,7 +59,7 @@ export default class extends Channel {
// 関係ない返信は除外 // 関係ない返信は除外
if (note.reply) { if (note.reply) {
const reply = note.reply as PackedNote; const reply = note.reply;
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
} }

View File

@ -4,7 +4,6 @@ import Channel from '../channel';
import { fetchMeta } from '@/misc/fetch-meta'; import { fetchMeta } from '@/misc/fetch-meta';
import { Notes } from '@/models/index'; import { Notes } from '@/models/index';
import { PackedNote } from '@/models/repositories/note'; import { PackedNote } from '@/models/repositories/note';
import { PackedUser } from '@/models/repositories/user';
import { checkWordMute } from '@/misc/check-word-mute'; import { checkWordMute } from '@/misc/check-word-mute';
import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related';
@ -26,7 +25,7 @@ export default class extends Channel {
@autobind @autobind
private async onNote(note: PackedNote) { private async onNote(note: PackedNote) {
if ((note.user as PackedUser).host !== null) return; if (note.user.host !== null) return;
if (note.visibility !== 'public') return; if (note.visibility !== 'public') return;
if (note.channelId != null && !this.followingChannels.has(note.channelId)) return; if (note.channelId != null && !this.followingChannels.has(note.channelId)) return;
@ -45,7 +44,7 @@ export default class extends Channel {
// 関係ない返信は除外 // 関係ない返信は除外
if (note.reply) { if (note.reply) {
const reply = note.reply as PackedNote; const reply = note.reply;
// 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合
if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return;
} }

View File

@ -165,8 +165,8 @@ export default class Connection {
}; };
add(note); add(note);
if (note.reply) add(note.reply as PackedNote); if (note.reply) add(note.reply);
if (note.renote) add(note.renote as PackedNote); if (note.renote) add(note.renote);
} }
@autobind @autobind

View File

@ -7,7 +7,7 @@
import * as nestedProperty from 'nested-property'; import * as nestedProperty from 'nested-property';
import autobind from 'autobind-decorator'; import autobind from 'autobind-decorator';
import Logger from '../logger'; import Logger from '../logger';
import { Schema } from '@/misc/schema'; import { SimpleSchema } from '@/misc/simple-schema';
import { EntitySchema, getRepository, Repository, LessThan, Between } from 'typeorm'; import { EntitySchema, getRepository, Repository, LessThan, Between } from 'typeorm';
import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/prelude/time'; import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/prelude/time';
import { getChartInsertLock } from '@/misc/app-lock'; import { getChartInsertLock } from '@/misc/app-lock';
@ -56,7 +56,7 @@ export default abstract class Chart<T extends Record<string, any>> {
diff: DeepPartial<T>; diff: DeepPartial<T>;
group: string | null; group: string | null;
}[] = []; }[] = [];
public schema: Schema; public schema: SimpleSchema;
protected repository: Repository<Log>; protected repository: Repository<Log>;
protected abstract genNewLog(latest: T): DeepPartial<T>; protected abstract genNewLog(latest: T): DeepPartial<T>;
@ -69,7 +69,7 @@ export default abstract class Chart<T extends Record<string, any>> {
protected abstract fetchActual(group: string | null): Promise<DeepPartial<T>>; protected abstract fetchActual(group: string | null): Promise<DeepPartial<T>>;
@autobind @autobind
private static convertSchemaToFlatColumnDefinitions(schema: Schema) { private static convertSchemaToFlatColumnDefinitions(schema: SimpleSchema) {
const columns = {} as any; const columns = {} as any;
const flatColumns = (x: Obj, path?: string) => { const flatColumns = (x: Obj, path?: string) => {
for (const [k, v] of Object.entries(x)) { for (const [k, v] of Object.entries(x)) {
@ -181,7 +181,7 @@ export default abstract class Chart<T extends Record<string, any>> {
} }
@autobind @autobind
public static schemaToEntity(name: string, schema: Schema): EntitySchema { public static schemaToEntity(name: string, schema: SimpleSchema): EntitySchema {
return new EntitySchema({ return new EntitySchema({
name: `__chart__${camelToSnake(name)}`, name: `__chart__${camelToSnake(name)}`,
columns: { columns: {
@ -211,7 +211,7 @@ export default abstract class Chart<T extends Record<string, any>> {
}); });
} }
constructor(name: string, schema: Schema, grouped = false) { constructor(name: string, schema: SimpleSchema, grouped = false) {
this.name = name; this.name = name;
this.schema = schema; this.schema = schema;
const entity = Chart.schemaToEntity(name, schema); const entity = Chart.schemaToEntity(name, schema);
@ -546,8 +546,8 @@ export default abstract class Chart<T extends Record<string, any>> {
} }
} }
export function convertLog(logSchema: Schema): Schema { export function convertLog(logSchema: SimpleSchema): SimpleSchema {
const v: Schema = JSON.parse(JSON.stringify(logSchema)); // copy const v: SimpleSchema = JSON.parse(JSON.stringify(logSchema)); // copy
if (v.type === 'number') { if (v.type === 'number') {
v.type = 'array'; v.type = 'array';
v.items = { v.items = {

289
yarn.lock
View File

@ -21,6 +21,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==
"@babel/helper-validator-identifier@^7.14.9":
version "7.14.9"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz#6654d171b2024f6d8ee151bf2509699919131d48"
integrity sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==
"@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": "@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13":
version "7.12.13" version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c"
@ -30,16 +35,16 @@
chalk "^2.0.0" chalk "^2.0.0"
js-tokens "^4.0.0" js-tokens "^4.0.0"
"@babel/parser@^7.12.0", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6": "@babel/parser@^7.15.0":
version "7.15.6"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549"
integrity sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==
"@babel/parser@^7.6.0", "@babel/parser@^7.9.6":
version "7.13.9" version "7.13.9"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.9.tgz#ca34cb95e1c2dd126863a84465ae8ef66114be99"
integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw== integrity sha512-nEUfRiARCcaVo3ny3ZQjURjHQZUo/JkEw7rLlSZy/psWGnvwXFtPcr6jb7Yb41DVW5LTe6KRq9LGleRNsg1Frw==
"@babel/parser@^7.13.9":
version "7.13.13"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.13.tgz#42f03862f4aed50461e543270916b47dd501f0df"
integrity sha512-OhsyMrqygfk5v8HmWwOzlYjJrtLaFhF34MrfG/Z73DgYCI6ojNUTUp2TYbtnjo8PegeJp12eamsNettCQjKjVw==
"@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2": "@babel/runtime@^7.6.2", "@babel/runtime@^7.7.2":
version "7.12.13" version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.13.tgz#0a21452352b02542db0ffb928ac2d3ca7cb6d66d" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.13.tgz#0a21452352b02542db0ffb928ac2d3ca7cb6d66d"
@ -47,7 +52,15 @@
dependencies: dependencies:
regenerator-runtime "^0.13.4" regenerator-runtime "^0.13.4"
"@babel/types@^7.12.0", "@babel/types@^7.13.0", "@babel/types@^7.6.1", "@babel/types@^7.9.6": "@babel/types@^7.15.0":
version "7.15.6"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.15.6.tgz#99abdc48218b2881c058dd0a7ab05b99c9be758f"
integrity sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==
dependencies:
"@babel/helper-validator-identifier" "^7.14.9"
to-fast-properties "^2.0.0"
"@babel/types@^7.6.1", "@babel/types@^7.9.6":
version "7.13.0" version "7.13.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80"
integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA==
@ -690,6 +703,11 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818"
integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg== integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==
"@types/json5@^0.0.29":
version "0.0.29"
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
"@types/jsonld@1.5.6": "@types/jsonld@1.5.6":
version "1.5.6" version "1.5.6"
resolved "https://registry.yarnpkg.com/@types/jsonld/-/jsonld-1.5.6.tgz#4396c0b17128abf5773bb68b5453b88fc565b0d4" resolved "https://registry.yarnpkg.com/@types/jsonld/-/jsonld-1.5.6.tgz#4396c0b17128abf5773bb68b5453b88fc565b0d4"
@ -1240,39 +1258,40 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@vue/compiler-core@3.2.4": "@vue/compiler-core@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.4.tgz#a98d295771998c1e8dccc4ee3d52feb14b02aea9" resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.2.11.tgz#10af3777dba303ee7aae668029f131cb90391bee"
integrity sha512-c8NuQq7mUXXxA4iqD5VUKpyVeklK53+DMbojYMyZ0VPPrb0BUWrZWFiqSDT+MFDv0f6Hv3QuLiHWb1BWMXBbrw== integrity sha512-bcbsLx5XyQg8WDDEGwmpX0BfEfv82wIs9fWFelpyVhNRGMaABvUTalYINyfhVT+jOqNaD4JBhJiVKd/8TmsHWg==
dependencies: dependencies:
"@babel/parser" "^7.12.0" "@babel/parser" "^7.15.0"
"@babel/types" "^7.12.0" "@babel/types" "^7.15.0"
"@vue/shared" "3.2.4" "@vue/shared" "3.2.11"
estree-walker "^2.0.1" estree-walker "^2.0.2"
source-map "^0.6.1" source-map "^0.6.1"
"@vue/compiler-dom@3.2.4": "@vue/compiler-dom@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.4.tgz#3a43de243eba127abbe57e796a0b969d2df78c08" resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.2.11.tgz#d066f8e1f1812b4e881593819ade0fe6d654c776"
integrity sha512-uj1nwO4794fw2YsYas5QT+FU/YGrXbS0Qk+1c7Kp1kV7idhZIghWLTjyvYibpGoseFbYLPd+sW2/noJG5H04EQ== integrity sha512-DNvhUHI/1Hn0/+ZYDYGAuDGasUm+XHKC3FE4GqkNCTO/fcLaJMRg/7eT1m1lkc7jPffUwwfh1rZru5mwzOjrNw==
dependencies: dependencies:
"@vue/compiler-core" "3.2.4" "@vue/compiler-core" "3.2.11"
"@vue/shared" "3.2.4" "@vue/shared" "3.2.11"
"@vue/compiler-sfc@3.2.4": "@vue/compiler-sfc@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.4.tgz#9807868cc950291f163c3930a81bb16e870df097" resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.2.11.tgz#628fa12238760d9b9b339ac2e125a759224fadbf"
integrity sha512-GM+ouDdDzhqgkLmBH4bgq4kiZxJQArSppJiZHWHIx9XRaefHLmc1LBNPmN8ivm4SVfi2i7M2t9k8ZnjsScgzPQ== integrity sha512-cUIaS8mgJrQ6yucj2AupWAwBRITK3W/a8wCOn9g5fJGtOl8h4APY8vN3lzP8HIJDyEeRF3I8SfRhL+oX97kSnw==
dependencies: dependencies:
"@babel/parser" "^7.13.9" "@babel/parser" "^7.15.0"
"@babel/types" "^7.13.0" "@babel/types" "^7.15.0"
"@types/estree" "^0.0.48" "@types/estree" "^0.0.48"
"@vue/compiler-core" "3.2.4" "@vue/compiler-core" "3.2.11"
"@vue/compiler-dom" "3.2.4" "@vue/compiler-dom" "3.2.11"
"@vue/compiler-ssr" "3.2.4" "@vue/compiler-ssr" "3.2.11"
"@vue/shared" "3.2.4" "@vue/ref-transform" "3.2.11"
"@vue/shared" "3.2.11"
consolidate "^0.16.0" consolidate "^0.16.0"
estree-walker "^2.0.1" estree-walker "^2.0.2"
hash-sum "^2.0.0" hash-sum "^2.0.0"
lru-cache "^5.1.1" lru-cache "^5.1.1"
magic-string "^0.25.7" magic-string "^0.25.7"
@ -1282,42 +1301,53 @@
postcss-selector-parser "^6.0.4" postcss-selector-parser "^6.0.4"
source-map "^0.6.1" source-map "^0.6.1"
"@vue/compiler-ssr@3.2.4": "@vue/compiler-ssr@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.4.tgz#be51f219c2042b3e530373e60bc126ada6bb1cc0" resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.2.11.tgz#702cef3429651645bdbe09fe5962803b5a621abb"
integrity sha512-bKZuXu9/4XwsFHFWIKQK+5kN7mxIIWmMmT2L4VVek7cvY/vm3p4WTsXYDGZJy0htOTXvM2ifr6sflg012T0hsw== integrity sha512-+ptAdUlFDij+Z0VGCbRRkxQlNev5LkbZAntvkxrFjc08CTMhZmiV4Js48n2hAmuSXaKNEpmGkDGU26c/vf1+xw==
dependencies: dependencies:
"@vue/compiler-dom" "3.2.4" "@vue/compiler-dom" "3.2.11"
"@vue/shared" "3.2.4" "@vue/shared" "3.2.11"
"@vue/reactivity@3.2.4": "@vue/reactivity@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.4.tgz#a020ad7e50f674219a07764b105b5922e61597ea" resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.2.11.tgz#ec04d33acaf2b92cca2960535bec81b26cc5772b"
integrity sha512-ljWTR0hr8Tn09hM2tlmWxZzCBPlgGLnq/k8K8X6EcJhtV+C8OzFySnbWqMWataojbrQOocThwsC8awKthSl2uQ== integrity sha512-hEQstxPQbgGZq5qApzrvbDmRdK1KP96O/j4XrwT8fVkT1ytkFs4fH2xNEh9QKwXfybbQkLs77W7OfXCv5o6qbA==
dependencies: dependencies:
"@vue/shared" "3.2.4" "@vue/shared" "3.2.11"
"@vue/runtime-core@3.2.4": "@vue/ref-transform@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.4.tgz#da5dde3dc1e48df99dd31ea9a972f5c02acdc3f5" resolved "https://registry.yarnpkg.com/@vue/ref-transform/-/ref-transform-3.2.11.tgz#4d282b9570d1485a73e7bf5d57cce27b4a7aa690"
integrity sha512-W6PtEOs8P8jKYPo3JwaMAozZQivxInUleGfNwI2pK1t8ZLZIxn4kAf7p4VF4jJdQB8SZBzpfWdLUc06j7IOmpQ== integrity sha512-7rX0YsfYb7+1PeKPME1tQyUQcQgt0sIXRRnPD1Vw8Zs2KIo90YLy9CrvwalcRCxGw0ScsjBEhVjJtWIT79TElg==
dependencies: dependencies:
"@vue/reactivity" "3.2.4" "@babel/parser" "^7.15.0"
"@vue/shared" "3.2.4" "@vue/compiler-core" "3.2.11"
"@vue/shared" "3.2.11"
estree-walker "^2.0.2"
magic-string "^0.25.7"
"@vue/runtime-dom@3.2.4": "@vue/runtime-core@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.4.tgz#1025595f2ae99a12fe0e1e6bce8df6761efec24b" resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.2.11.tgz#0dbe801be4bd0bfde253226797e7d304c8fdda30"
integrity sha512-HcVtLyn2SGwsf6BFPwkvDPDOhOqkOKcfHDpBp5R1coX+qMsOFrY8lJnGXIY+JnxqFjND00E9+u+lq5cs/W7ooA== integrity sha512-horlxjWwSvModC87WdsWswzzHE5IexmKkQA65S5vFgP5hLUBW+HRyScDeuB/RRcFmqnf+ozacNCfap0kqcpODw==
dependencies: dependencies:
"@vue/runtime-core" "3.2.4" "@vue/reactivity" "3.2.11"
"@vue/shared" "3.2.4" "@vue/shared" "3.2.11"
"@vue/runtime-dom@3.2.11":
version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.2.11.tgz#04f9054a9e64bdf156c2fc22cad67cfaa8b84616"
integrity sha512-cOK1g0INdiCbds2xrrJKrrN+pDHuLz6esUs/crdEiupDuX7IeiMbdqrAQCkYHp5P1KLWcbGlkmwfVD7HQGii0Q==
dependencies:
"@vue/runtime-core" "3.2.11"
"@vue/shared" "3.2.11"
csstype "^2.6.8" csstype "^2.6.8"
"@vue/shared@3.2.4": "@vue/shared@3.2.11":
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.4.tgz#ba2a09527afff27b28d08f921b4a597e9504ca7a" resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.11.tgz#01899f54949caf1ac241de397bd17069632574de"
integrity sha512-j2j1MRmjalVKr3YBTxl/BClSIc8UQ8NnPpLYclxerK65JIowI4O7n8O8lElveEtEoHxy1d7BelPUDI0Q4bumqg== integrity sha512-ovfXAsSsCvV9JVceWjkqC/7OF5HbgLOtCWjCIosmPGG8lxbPuavhIxRH1dTx4Dg9xLgRTNLvI3pVxG4ItQZekg==
"@webassemblyjs/ast@1.11.0": "@webassemblyjs/ast@1.11.0":
version "1.11.0" version "1.11.0"
@ -1812,10 +1842,10 @@ anymatch@~3.1.1:
normalize-path "^3.0.0" normalize-path "^3.0.0"
picomatch "^2.0.4" picomatch "^2.0.4"
apexcharts@3.27.3: apexcharts@3.28.1:
version "3.27.3" version "3.28.1"
resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.27.3.tgz#1b921ac64dea2f28a2b1aad4b396b38464223849" resolved "https://registry.yarnpkg.com/apexcharts/-/apexcharts-3.28.1.tgz#35a17ea9ef9a1a93fb01ce79d245af8aedb59a7b"
integrity sha512-1ZrqiQT0VahkqW0kVjf5QVURYGaHMlGN08BoIZG2c2U/gY2AtnEoFN4r9q4d/pYYYKvI9AyLBHq0otzcVGrHAw== integrity sha512-5M1KitI/XmY2Sx6ih9vQOXyQUTmotDG/cML2N6bkBlVseF10RPSzM7dkrf7Y68apSZF6e7J581gXXu1+qkLhCA==
dependencies: dependencies:
svg.draggable.js "^2.2.2" svg.draggable.js "^2.2.2"
svg.easing.js "^2.0.0" svg.easing.js "^2.0.0"
@ -2413,10 +2443,10 @@ builtin-modules@^1.1.1:
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
bull@3.28.1: bull@3.29.2:
version "3.28.1" version "3.29.2"
resolved "https://registry.yarnpkg.com/bull/-/bull-3.28.1.tgz#33bc7bbe640e71258a2a800935a692a24a2d7236" resolved "https://registry.yarnpkg.com/bull/-/bull-3.29.2.tgz#30051fd14c7214b1e90c212585674f77fd982650"
integrity sha512-TasVWD1410Q8druRG6SIAN5hwAT3F4QICcGszReD859qAerq+VwbW3vPg6lV60reJkWyWBK11FHa2FsQ8iDBmQ== integrity sha512-zWHyza/ElwVvJUqIEDJdUhGKd1V9EHjituUL7sJAmJoxS9Z7QMhYcMOWcgbUlWPgtiKN1g9ZlOtFAoq7C4/SQw==
dependencies: dependencies:
cron-parser "^2.13.0" cron-parser "^2.13.0"
debuglog "^1.0.0" debuglog "^1.0.0"
@ -2488,10 +2518,10 @@ cache-content-type@^1.0.0:
mime-types "^2.1.18" mime-types "^2.1.18"
ylru "^1.2.0" ylru "^1.2.0"
cacheable-lookup@6.0.0: cacheable-lookup@6.0.1:
version "6.0.0" version "6.0.1"
resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.0.0.tgz#6fd7e364a0929ee50af00843aaf6e31b9b9f200e" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.0.1.tgz#f32ab50c3212302d9f49aa094c8a7593c162af7c"
integrity sha512-5qeyMn8/BERrUPdIfcOLkdMrwltVbxIpgnYM61OLWOg3BuSSh9HrkUtTTRxYthQpBrocvYqD0tJ7vU0y6T7OWw== integrity sha512-vaccXt7hUfa5UzrtbdzHTWnL6V6ir39QtLuvGZys32j4HboAeiWVhrcdAm8ecTz1rLubxPhec2n22BBb5/dgVA==
cacheable-lookup@^5.0.3: cacheable-lookup@^5.0.3:
version "5.0.3" version "5.0.3"
@ -4245,10 +4275,10 @@ escodegen@^2.0.0:
optionalDependencies: optionalDependencies:
source-map "~0.6.1" source-map "~0.6.1"
eslint-plugin-vue@7.16.0: eslint-plugin-vue@7.17.0:
version "7.16.0" version "7.17.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.16.0.tgz#7fe9fea039a190b108319c1380adf543ef57707d" resolved "https://registry.yarnpkg.com/eslint-plugin-vue/-/eslint-plugin-vue-7.17.0.tgz#41e0bdb5effca5ee26f087f924be987eb41ef573"
integrity sha512-0E2dVvVC7I2Xm1HXyx+ZwPj9CNX4NJjs4K4r+GVsHWyt5Pew3JLD4fI7A91b2jeL0TXE7LlszrwLSTJU9eqehw== integrity sha512-Rq5R2QetDCgC+kBFQw1+aJ5B93tQ4xqZvoCUxuIzwTonngNArsdP8ChM8PowIzsJvRtWl4ltGh/bZcN3xhFWSw==
dependencies: dependencies:
eslint-utils "^2.1.0" eslint-utils "^2.1.0"
natural-compare "^1.4.0" natural-compare "^1.4.0"
@ -4388,10 +4418,10 @@ estraverse@^5.2.0:
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
estree-walker@^2.0.1: estree-walker@^2.0.2:
version "2.0.1" version "2.0.2"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.1.tgz#f8e030fb21cefa183b44b7ad516b747434e7a3e0" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-tF0hv+Yi2Ot1cwj9eYHtxC0jB9bmjacjQs6ZBTj82H8JwUywFuc+7E83NWfNMwHXZc11mjfFcVXPe9gEP4B8dg== integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
esutils@^2.0.2: esutils@^2.0.2:
version "2.0.3" version "2.0.3"
@ -6356,7 +6386,7 @@ json5-loader@4.0.1:
loader-utils "^2.0.0" loader-utils "^2.0.0"
schema-utils "^3.0.0" schema-utils "^3.0.0"
json5@2.2.0, json5@^2.2.0: json5@2.2.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
@ -6441,10 +6471,10 @@ jws@^4.0.0:
jwa "^2.0.0" jwa "^2.0.0"
safe-buffer "^5.0.1" safe-buffer "^5.0.1"
katex@0.13.13: katex@0.13.18:
version "0.13.13" version "0.13.18"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.13.tgz#15a796e95516869bc6d483443b58b2df872ee40f" resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.18.tgz#ba89e8e4b70cc2325e25e019a62b9fe71e5c2931"
integrity sha512-cCMcil4jwMm7behpXGiQfXJA29sko/Gd/26iCsr53Dv5Jn2iHbHyEb14dm9uVrIijUXx6Zz1WhlFhHE6DckvkQ== integrity sha512-a3dC4NSVSDU3O1WZbTnOiA8rVNJ2lSiomOl0kmckCIGObccIHXof7gAseIY0o1gjEspe+34ZeSEX2D1ChFKIvA==
dependencies: dependencies:
commander "^6.0.0" commander "^6.0.0"
@ -7488,10 +7518,10 @@ node-abi@^2.21.0:
dependencies: dependencies:
semver "^5.4.1" semver "^5.4.1"
node-addon-api@^4.0.0: node-addon-api@^4.1.0:
version "4.0.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.0.0.tgz#ac128f43eff7fac4b5f5ef2f39d6d7c2709efead" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.1.0.tgz#f1722f1f60793584632ffffb79e12ca042c48bd0"
integrity sha512-ALmRVBFzfwldBfk3SbKfl6+PVMXiCPKZBEfsJqB/EjXAMAI+MfFrEHR+GMRBuI162DihZ1QjEZ8ieYKuRCJ8Hg== integrity sha512-Zz1o1BDX2VtduiAt6kgiUl8jX1Vm3NMboljFYKQJ6ee8AGfiTvM2mlZFI3xPbqjs80rCQgiVJI/DjQ/1QJ0HwA==
node-fetch@2.6.1, node-fetch@^2.6.1: node-fetch@2.6.1, node-fetch@^2.6.1:
version "2.6.1" version "2.6.1"
@ -9113,10 +9143,10 @@ punycode@2.1.1, punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
pureimage@0.3.2: pureimage@0.3.5:
version "0.3.2" version "0.3.5"
resolved "https://registry.yarnpkg.com/pureimage/-/pureimage-0.3.2.tgz#3cae06abaf2735e806c089bcbd188e3c7926bf2e" resolved "https://registry.yarnpkg.com/pureimage/-/pureimage-0.3.5.tgz#cd5e91f7b6409fcf4880297aaa3e7fc0afc24d5e"
integrity sha512-9gcx43yMuqG3Oe5uhRKk29HHZS0eE6pnDv+VJnWGScU99Cd4aDvHSUkqmbppNAXRrGjWjRiTutXW/iGLPpA3tQ== integrity sha512-+CFUEpoX6GemlKlHihI7Ii4IqKqF5KZjd682sAxwzbc4t4zU4Gwhxd4W3UMZW94nJzf0n4nA9zJrwTR4jZB4TA==
dependencies: dependencies:
jpeg-js "^0.4.1" jpeg-js "^0.4.1"
opentype.js "^0.4.3" opentype.js "^0.4.3"
@ -9733,10 +9763,10 @@ sass-loader@12.1.0:
klona "^2.0.4" klona "^2.0.4"
neo-async "^2.6.2" neo-async "^2.6.2"
sass@1.38.0: sass@1.41.0:
version "1.38.0" version "1.41.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.38.0.tgz#2f3e60a1efdcdc910586fa79dc89d3399a145b4f" resolved "https://registry.yarnpkg.com/sass/-/sass-1.41.0.tgz#f7b41dc00336a4c03429c37b9680b86758af61d4"
integrity sha512-WBccZeMigAGKoI+NgD7Adh0ab1HUq+6BmyBUEaGxtErbUtWUevEbdgo5EZiJQofLUGcKtlNaO2IdN73AHEua5g== integrity sha512-wb8nT60cjo9ZZMcHzG7TzdbFtCAmHEKWrH+zAdScPb4ZxL64WQBnGdbp5nwlenW5wJPcHva1JWmVa0h6iqA5eg==
dependencies: dependencies:
chokidar ">=3.0.0 <4.0.0" chokidar ">=3.0.0 <4.0.0"
@ -9880,14 +9910,14 @@ shallow-clone@^3.0.0:
dependencies: dependencies:
kind-of "^6.0.2" kind-of "^6.0.2"
sharp@0.29.0: sharp@0.29.1:
version "0.29.0" version "0.29.1"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.0.tgz#1fa302bd5f60292138c823aa0905609f64d710ba" resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.29.1.tgz#f60b50f24f399464a24187c86bd2da41aae50b85"
integrity sha512-mdN1Up0eN+SwyForPls59dWO0nx64J1XRQYy5ZiKSADAccGYCB10UAGJHSVG9VObzJdhHqrVJzQcq6gx8USyoA== integrity sha512-DpgdAny9TuS+oWCQ7MRS8XyY9x6q1+yW3a5wNx0J3HrGuB/Jot/8WcT+lElHY9iJu2pwtegSGxqMaqFiMhs4rQ==
dependencies: dependencies:
color "^4.0.1" color "^4.0.1"
detect-libc "^1.0.3" detect-libc "^1.0.3"
node-addon-api "^4.0.0" node-addon-api "^4.1.0"
prebuild-install "^6.1.4" prebuild-install "^6.1.4"
semver "^7.3.5" semver "^7.3.5"
simple-get "^3.1.0" simple-get "^3.1.0"
@ -10598,10 +10628,10 @@ syslog-pro@1.0.0:
dependencies: dependencies:
moment "^2.22.2" moment "^2.22.2"
systeminformation@5.8.0: systeminformation@5.9.2:
version "5.8.0" version "5.9.2"
resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.8.0.tgz#43e6d0918d7d42c65e53e36059f0849354ab2873" resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.9.2.tgz#c8483afa2f957fa4bbb54b1c148be71d1b2df256"
integrity sha512-l4drbK2PtNynGKblaShY9hDLW/gg1zxUq2+Yk4gTyd6a2JUvFyTGP8PhHV9iOh+MzS25PQa8W1t0kvcIvr9n7Q== integrity sha512-KfW+dwGx4NX2J08IKeeptKnA8NioKB6YVDeqkvIVL+5GQfHSVenoA6Y9h8EnYall52OrOOggGTap0xbZH7pyUQ==
syuilo-password-strength@0.0.1: syuilo-password-strength@0.0.1:
version "0.0.1" version "0.0.1"
@ -10981,12 +11011,13 @@ tsc-alias@1.3.9:
globby "^11.0.2" globby "^11.0.2"
normalize-path "^3.0.0" normalize-path "^3.0.0"
tsconfig-paths@3.10.1: tsconfig-paths@3.11.0:
version "3.10.1" version "3.11.0"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz#79ae67a68c15289fdf5c51cb74f397522d795ed7" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz#954c1fe973da6339c78e06b03ce2e48810b65f36"
integrity sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q== integrity sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==
dependencies: dependencies:
json5 "^2.2.0" "@types/json5" "^0.0.29"
json5 "^1.0.1"
minimist "^1.2.0" minimist "^1.2.0"
strip-bom "^3.0.0" strip-bom "^3.0.0"
@ -11169,10 +11200,10 @@ typeorm@0.2.37:
yargs "^17.0.1" yargs "^17.0.1"
zen-observable-ts "^1.0.0" zen-observable-ts "^1.0.0"
typescript@4.3.5: typescript@4.4.3:
version "4.3.5" version "4.4.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.3.tgz#bdc5407caa2b109efd4f82fe130656f977a29324"
integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== integrity sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==
uc.micro@^1.0.1, uc.micro@^1.0.5: uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.6" version "1.0.6"
@ -11535,14 +11566,14 @@ vue-svg-loader@0.17.0-beta.2:
semver "^7.3.2" semver "^7.3.2"
svgo "^1.3.2" svgo "^1.3.2"
vue@3.2.4: vue@3.2.11:
version "3.2.4" version "3.2.11"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.4.tgz#d94d88675e41c050d3a722d0848a7063b5e87a60" resolved "https://registry.yarnpkg.com/vue/-/vue-3.2.11.tgz#6b92295048df705ddac558fd3e3ed553e55e57c8"
integrity sha512-rNCFmoewm8IwmTK0nj3ysKq53iRpNEFKoBJ4inar6tIh7Oj7juubS39RI8UI+VE7x+Cs2z6PBsadtZu7z2qppg== integrity sha512-JkI3/eIgfk4E0f/p319TD3EZgOwBQfftgnkRsXlT7OrRyyiyoyUXn6embPGZXSBxD3LoZ9SWhJoxLhFh5AleeA==
dependencies: dependencies:
"@vue/compiler-dom" "3.2.4" "@vue/compiler-dom" "3.2.11"
"@vue/runtime-dom" "3.2.4" "@vue/runtime-dom" "3.2.11"
"@vue/shared" "3.2.4" "@vue/shared" "3.2.11"
vuedraggable@4.0.1: vuedraggable@4.0.1:
version "4.0.1" version "4.0.1"
@ -11654,10 +11685,10 @@ webpack-sources@^3.2.0:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.0.tgz#b16973bcf844ebcdb3afde32eda1c04d0b90f89d"
integrity sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw== integrity sha512-fahN08Et7P9trej8xz/Z7eRu8ltyiygEo/hnRi9KqBUs80KeDcnf96ZJo++ewWd84fEf3xSX9bp4ZS9hbw0OBw==
webpack@5.51.0: webpack@5.52.1:
version "5.51.0" version "5.52.1"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.51.0.tgz#b6683d92e4bd84db588bacb6ade6441d9c5fd2f3" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.52.1.tgz#2dc1d9029ecb7acfb80da7bf67baab67baa517a7"
integrity sha512-oySQoKUuf5r0JaPIYi8q90c/GmU9fGdSbZ0cAjFq3OWx57wniRTWvta1T9t+e5WZ6H6mHrxksNatkqfIEuTWGg== integrity sha512-wkGb0hLfrS7ML3n2xIKfUIwHbjB6gxwQHyLmVHoAqEQBw+nWo+G6LoHL098FEXqahqximsntjBLuewStrnJk0g==
dependencies: dependencies:
"@types/eslint-scope" "^3.7.0" "@types/eslint-scope" "^3.7.0"
"@types/estree" "^0.0.50" "@types/estree" "^0.0.50"
@ -11856,10 +11887,10 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
ws@8.2.0: ws@8.2.2:
version "8.2.0" version "8.2.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.0.tgz#0b738cd484bfc9303421914b11bb4011e07615bb" resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.2.tgz#ca684330c6dd6076a737250ed81ac1606cb0a63e"
integrity sha512-uYhVJ/m9oXwEI04iIVmgLmugh2qrZihkywG9y5FfZV2ATeLIzHf93qs+tUNqlttbQK957/VX3mtwAS+UfIwA4g== integrity sha512-Q6B6H2oc8QY3llc3cB8kVmQ6pnJWVQbP7Q5algTcIxx7YEpc0oU4NBVHlztA7Ekzfhw2r0rPducMUiCGWKQRzw==
ws@^7.4.6: ws@^7.4.6:
version "7.5.3" version "7.5.3"