Compare commits
24 Commits
8a9eb73b6b
...
e51a041082
Author | SHA1 | Date |
---|---|---|
|
e51a041082 | |
|
20e84838b9 | |
|
869f4e4138 | |
|
2c4d50692a | |
|
c65c181b68 | |
|
8ed8dfac00 | |
|
4aed5968f6 | |
|
ffec11e3f7 | |
|
fc8be99e57 | |
|
b7cdfa3de9 | |
|
26674c39e8 | |
|
007ed5c929 | |
|
62249403cf | |
|
d4bcb5e368 | |
|
6c1cb64ff0 | |
|
b2bb8ccc56 | |
|
0994adc748 | |
|
61c9b0757e | |
|
62e347c270 | |
|
bdf390eb7e | |
|
a52f63ec6a | |
|
5096be06ac | |
|
339086995f | |
|
bbd618a258 |
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
## 13.x.x (unreleased)
|
## 2023.x.x (unreleased)
|
||||||
|
|
||||||
### General
|
### General
|
||||||
-
|
-
|
||||||
|
@ -12,6 +12,21 @@
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
## 2023.8.0 (unreleased)
|
||||||
|
|
||||||
|
### General
|
||||||
|
- OAuth 2.0のサポート
|
||||||
|
|
||||||
|
### Client
|
||||||
|
- メニューのスイッチの動作を改善
|
||||||
|
- Enhance: ユーザーメニューでスイッチでユーザーリストに追加・削除できるように
|
||||||
|
- Enhance: 自分が押したリアクションのデザインを改善
|
||||||
|
- Fix: サーバー情報画面(`/instance-info/{domain}`)でブロックができないのを修正
|
||||||
|
- Fix: 未読のお知らせの「わかった」をクリック・タップしてもその場で「わかった」が消えない問題を修正
|
||||||
|
|
||||||
|
### Server
|
||||||
|
-
|
||||||
|
|
||||||
## 13.14.2
|
## 13.14.2
|
||||||
|
|
||||||
### Client
|
### Client
|
||||||
|
|
|
@ -147,7 +147,6 @@
|
||||||
"rss-parser": "3.13.0",
|
"rss-parser": "3.13.0",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "7.8.1",
|
||||||
"sanitize-html": "2.11.0",
|
"sanitize-html": "2.11.0",
|
||||||
"semver": "7.5.4",
|
|
||||||
"sharp": "0.32.3",
|
"sharp": "0.32.3",
|
||||||
"sharp-read-bmp": "github:misskey-dev/sharp-read-bmp",
|
"sharp-read-bmp": "github:misskey-dev/sharp-read-bmp",
|
||||||
"slacc": "0.0.10",
|
"slacc": "0.0.10",
|
||||||
|
|
|
@ -10,7 +10,6 @@ import * as os from 'node:os';
|
||||||
import cluster from 'node:cluster';
|
import cluster from 'node:cluster';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import chalkTemplate from 'chalk-template';
|
import chalkTemplate from 'chalk-template';
|
||||||
import semver from 'semver';
|
|
||||||
import Logger from '@/logger.js';
|
import Logger from '@/logger.js';
|
||||||
import { loadConfig } from '@/config.js';
|
import { loadConfig } from '@/config.js';
|
||||||
import type { Config } from '@/config.js';
|
import type { Config } from '@/config.js';
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"@rollup/plugin-replace": "5.0.2",
|
"@rollup/plugin-replace": "5.0.2",
|
||||||
"@rollup/pluginutils": "5.0.2",
|
"@rollup/pluginutils": "5.0.2",
|
||||||
"@syuilo/aiscript": "0.15.0",
|
"@syuilo/aiscript": "0.15.0",
|
||||||
"@tabler/icons-webfont": "2.25.0",
|
"@tabler/icons-webfont": "2.30.0",
|
||||||
"@vitejs/plugin-vue": "4.2.3",
|
"@vitejs/plugin-vue": "4.2.3",
|
||||||
"@vue-macros/reactivity-transform": "0.3.15",
|
"@vue-macros/reactivity-transform": "0.3.15",
|
||||||
"@vue/compiler-sfc": "3.3.4",
|
"@vue/compiler-sfc": "3.3.4",
|
||||||
|
|
|
@ -170,10 +170,10 @@ export default defineComponent({
|
||||||
> *:empty {
|
> *:empty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
> *:not(:last-child) {
|
|
||||||
margin-bottom: var(--margin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:not(.date-separated-list-nogap) > *:not(:last-child) {
|
||||||
|
margin-bottom: var(--margin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkAvatar :user="item.user" :class="$style.avatar"/><MkUserName :user="item.user"/>
|
<MkAvatar :user="item.user" :class="$style.avatar"/><MkUserName :user="item.user"/>
|
||||||
<span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span>
|
<span v-if="item.indicate" :class="$style.indicator"><i class="_indicatorCircle"></i></span>
|
||||||
</button>
|
</button>
|
||||||
<span v-else-if="item.type === 'switch'" role="menuitemcheckbox" :tabindex="i" :class="$style.item" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
<button v-else-if="item.type === 'switch'" role="menuitemcheckbox" :tabindex="i" class="_button" :class="[$style.item, $style.switch, { [$style.switchDisabled]: item.disabled } ]" @click="switchItem(item)" @mouseenter.passive="onItemMouseEnter(item)" @mouseleave.passive="onItemMouseLeave(item)">
|
||||||
<MkSwitch v-model="item.ref" :disabled="item.disabled" class="form-switch">{{ item.text }}</MkSwitch>
|
<MkSwitchButton :class="$style.switchButton" :checked="item.ref" :disabled="item.disabled" @toggle="switchItem(item)" />
|
||||||
</span>
|
<span :class="$style.switchText">{{ item.text }}</span>
|
||||||
|
</button>
|
||||||
<button v-else-if="item.type === 'parent'" role="menuitem" :tabindex="i" class="_button" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="showChildren(item, $event)">
|
<button v-else-if="item.type === 'parent'" role="menuitem" :tabindex="i" class="_button" :class="[$style.item, $style.parent, { [$style.childShowing]: childShowingItem === item }]" @mouseenter="showChildren(item, $event)">
|
||||||
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
|
<i v-if="item.icon" class="ti-fw" :class="[$style.icon, item.icon]"></i>
|
||||||
<span>{{ item.text }}</span>
|
<span>{{ item.text }}</span>
|
||||||
|
@ -63,8 +64,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
import { defineAsyncComponent, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue';
|
||||||
import { focusPrev, focusNext } from '@/scripts/focus';
|
import { focusPrev, focusNext } from '@/scripts/focus';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitchButton from '@/components/MkSwitch.button.vue';
|
||||||
import { MenuItem, InnerMenuItem, MenuPending, MenuAction } from '@/types/menu';
|
import { MenuItem, InnerMenuItem, OuterMenuItem, MenuPending, MenuAction, MenuSwitch, MenuParent } from '@/types/menu';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
|
@ -145,17 +146,17 @@ function onItemMouseLeave(item) {
|
||||||
if (childCloseTimer) window.clearTimeout(childCloseTimer);
|
if (childCloseTimer) window.clearTimeout(childCloseTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
let childrenCache = new WeakMap();
|
let childrenCache = new WeakMap<MenuParent, OuterMenuItem[]>();
|
||||||
async function showChildren(item: MenuItem, ev: MouseEvent) {
|
async function showChildren(item: MenuParent, ev: MouseEvent) {
|
||||||
const children = ref([]);
|
const children = ref<OuterMenuItem[]>([]);
|
||||||
if (childrenCache.has(item)) {
|
if (childrenCache.has(item)) {
|
||||||
children.value = childrenCache.get(item);
|
children.value = childrenCache.get(item)!;
|
||||||
} else {
|
} else {
|
||||||
if (typeof item.children === 'function') {
|
if (typeof item.children === 'function') {
|
||||||
children.value = [{
|
children.value = [{
|
||||||
type: 'pending',
|
type: 'pending',
|
||||||
}];
|
}];
|
||||||
item.children().then(x => {
|
Promise.resolve(item.children()).then(x => {
|
||||||
children.value = x;
|
children.value = x;
|
||||||
childrenCache.set(item, x);
|
childrenCache.set(item, x);
|
||||||
});
|
});
|
||||||
|
@ -191,6 +192,11 @@ function focusDown() {
|
||||||
focusNext(document.activeElement);
|
focusNext(document.activeElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function switchItem(item: MenuSwitch & { ref: any }) {
|
||||||
|
if (item.disabled) return;
|
||||||
|
item.ref = !item.ref;
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.viaKeyboard) {
|
if (props.viaKeyboard) {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
|
@ -357,6 +363,37 @@ onBeforeUnmount(() => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
user-select: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switchDisabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switchButton {
|
||||||
|
margin-left: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switchText {
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-top: 2px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switchInput {
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,15 +408,17 @@ function onContextmenu(ev: MouseEvent): void {
|
||||||
react();
|
react();
|
||||||
} else {
|
} else {
|
||||||
if (!note.value) return;
|
if (!note.value) return;
|
||||||
os.contextMenu(getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value }), ev).then(focus);
|
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, menuButton, isDeleted, currentClip: currentClip?.value });
|
||||||
|
os.contextMenu(menu, ev).then(focus).finally(cleanup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function menu(viaKeyboard = false): void {
|
function menu(viaKeyboard = false): void {
|
||||||
if (!note.value) return;
|
if (!note.value) return;
|
||||||
os.popupMenu(getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value }), menuButton.value, {
|
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value });
|
||||||
|
os.popupMenu(menu, menuButton.value, {
|
||||||
viaKeyboard,
|
viaKeyboard,
|
||||||
}).then(focus);
|
}).then(focus).finally(cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clip() {
|
async function clip() {
|
||||||
|
|
|
@ -365,15 +365,17 @@ function onContextmenu(ev: MouseEvent): void {
|
||||||
react();
|
react();
|
||||||
} else {
|
} else {
|
||||||
if (!note.value) return;
|
if (!note.value) return;
|
||||||
os.contextMenu(getNoteMenu({ note: note.value, translating, translation, menuButton, isDeleted }), ev).then(focus);
|
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
|
||||||
|
os.contextMenu(menu, ev).then(focus).finally(cleanup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function menu(viaKeyboard = false): void {
|
function menu(viaKeyboard = false): void {
|
||||||
if (!note.value) return;
|
if (!note.value) return;
|
||||||
os.popupMenu(getNoteMenu({ note: note.value, translating, translation, menuButton, isDeleted }), menuButton.value, {
|
const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted });
|
||||||
|
os.popupMenu(menu, menuButton.value, {
|
||||||
viaKeyboard,
|
viaKeyboard,
|
||||||
}).then(focus);
|
}).then(focus).finally(cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function clip() {
|
async function clip() {
|
||||||
|
|
|
@ -35,12 +35,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, shallowRef } from 'vue';
|
import { computed, shallowRef } from 'vue';
|
||||||
import MkNote from '@/components/MkNote.vue';
|
import MkNote from '@/components/MkNote.vue';
|
||||||
import MkDateSeparatedList, { MisskeyEntity } from '@/components/MkDateSeparatedList.vue';
|
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
|
||||||
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
import MkPagination, { Paging } from '@/components/MkPagination.vue';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { infoImageUrl } from '@/instance';
|
import { infoImageUrl } from '@/instance';
|
||||||
import { noteManager } from '@/scripts/entity-manager';
|
import { noteManager } from '@/scripts/entity-manager';
|
||||||
import { Note } from 'misskey-js/built/entities';
|
import { Note } from 'misskey-js/built/entities';
|
||||||
|
import { MisskeyEntity } from '@/types/date-separated-list';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
pagination: Paging;
|
pagination: Paging;
|
||||||
|
|
|
@ -751,18 +751,25 @@ async function post(ev?: MouseEvent) {
|
||||||
claimAchievement('notes1');
|
claimAchievement('notes1');
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = postData.text?.toLowerCase() ?? '';
|
const text = postData.text ?? '';
|
||||||
if ((text.includes('love') || text.includes('❤')) && text.includes('misskey')) {
|
const lowerCase = text.toLowerCase();
|
||||||
|
if ((lowerCase.includes('love') || lowerCase.includes('❤')) && lowerCase.includes('misskey')) {
|
||||||
claimAchievement('iLoveMisskey');
|
claimAchievement('iLoveMisskey');
|
||||||
}
|
}
|
||||||
if (
|
if ([
|
||||||
text.includes('https://youtu.be/Efrlqw8ytg4'.toLowerCase()) ||
|
'https://youtu.be/Efrlqw8ytg4',
|
||||||
text.includes('https://www.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
|
'https://www.youtube.com/watch?v=Efrlqw8ytg4',
|
||||||
text.includes('https://m.youtube.com/watch?v=Efrlqw8ytg4'.toLowerCase()) ||
|
'https://m.youtube.com/watch?v=Efrlqw8ytg4',
|
||||||
text.includes('https://youtu.be/XVCwzwxdHuA'.toLowerCase()) ||
|
|
||||||
text.includes('https://www.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase()) ||
|
'https://youtu.be/XVCwzwxdHuA',
|
||||||
text.includes('https://m.youtube.com/watch?v=XVCwzwxdHuA'.toLowerCase())
|
'https://www.youtube.com/watch?v=XVCwzwxdHuA',
|
||||||
) {
|
'https://m.youtube.com/watch?v=XVCwzwxdHuA',
|
||||||
|
|
||||||
|
'https://open.spotify.com/track/3Cuj0mZrlLoXx9nydNi7RB',
|
||||||
|
'https://open.spotify.com/track/7anfcaNPQWlWCwyCHmZqNy',
|
||||||
|
'https://open.spotify.com/track/5Odr16TvEN4my22K9nbH7l',
|
||||||
|
'https://open.spotify.com/album/5bOlxyl4igOrp2DwVQxBco',
|
||||||
|
].some(url => text.includes(url))) {
|
||||||
claimAchievement('brainDiver');
|
claimAchievement('brainDiver');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,15 +143,13 @@ useTooltip(buttonEl, async (showing) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.reacted {
|
&.reacted, &.reacted:hover {
|
||||||
background: var(--accent);
|
background: var(--accentedBg);
|
||||||
|
color: var(--accent);
|
||||||
&:hover {
|
border: 1px solid var(--accent);
|
||||||
background: var(--accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
> .count {
|
> .count {
|
||||||
color: var(--fgOnAccent);
|
color: var(--accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
> .icon {
|
> .icon {
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: syuilo and other misskey contributors
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<span
|
||||||
|
v-tooltip="checked ? i18n.ts.itsOn : i18n.ts.itsOff"
|
||||||
|
:class="{
|
||||||
|
[$style.button]: true,
|
||||||
|
[$style.buttonChecked]: checked,
|
||||||
|
[$style.buttonDisabled]: props.disabled
|
||||||
|
}"
|
||||||
|
data-cy-switch-toggle
|
||||||
|
@click.prevent.stop="toggle"
|
||||||
|
>
|
||||||
|
<div :class="{ [$style.knob]: true, [$style.knobChecked]: checked }"></div>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { toRefs, Ref } from 'vue';
|
||||||
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{
|
||||||
|
checked: boolean | Ref<boolean>;
|
||||||
|
disabled?: boolean;
|
||||||
|
}>(), {
|
||||||
|
disabled: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(ev: 'toggle'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const checked = toRefs(props).checked;
|
||||||
|
const toggle = () => {
|
||||||
|
emit('toggle');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" module>
|
||||||
|
.button {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 32px;
|
||||||
|
height: 23px;
|
||||||
|
outline: none;
|
||||||
|
background: var(--switchOffBg);
|
||||||
|
background-clip: content-box;
|
||||||
|
border: solid 1px var(--switchOffBg);
|
||||||
|
border-radius: 999px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: inherit;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonChecked {
|
||||||
|
background-color: var(--switchOnBg) !important;
|
||||||
|
border-color: var(--switchOnBg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttonDisabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.knob {
|
||||||
|
position: absolute;
|
||||||
|
top: 3px;
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
border-radius: 999px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:not(.knobChecked) {
|
||||||
|
left: 3px;
|
||||||
|
background: var(--switchOffFg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.knobChecked {
|
||||||
|
left: 12px;
|
||||||
|
background: var(--switchOnFg);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -12,9 +12,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
:class="$style.input"
|
:class="$style.input"
|
||||||
@keydown.enter="toggle"
|
@keydown.enter="toggle"
|
||||||
>
|
>
|
||||||
<span ref="button" v-tooltip="checked ? i18n.ts.itsOn : i18n.ts.itsOff" :class="$style.button" data-cy-switch-toggle @click.prevent="toggle">
|
<XButton :checked="checked" :disabled="disabled" @toggle="toggle" />
|
||||||
<div :class="$style.knob"></div>
|
|
||||||
</span>
|
|
||||||
<span :class="$style.body">
|
<span :class="$style.body">
|
||||||
<!-- TODO: 無名slotの方は廃止 -->
|
<!-- TODO: 無名slotの方は廃止 -->
|
||||||
<span :class="$style.label" @click="toggle"><slot name="label"></slot><slot></slot></span>
|
<span :class="$style.label" @click="toggle"><slot name="label"></slot><slot></slot></span>
|
||||||
|
@ -25,7 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { toRefs, Ref } from 'vue';
|
import { toRefs, Ref } from 'vue';
|
||||||
import { i18n } from '@/i18n';
|
import XButton from '@/components/MkSwitch.button.vue';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modelValue: boolean | Ref<boolean>;
|
modelValue: boolean | Ref<boolean>;
|
||||||
|
@ -36,7 +34,6 @@ const emit = defineEmits<{
|
||||||
(ev: 'update:modelValue', v: boolean): void;
|
(ev: 'update:modelValue', v: boolean): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
let button = $shallowRef<HTMLElement>();
|
|
||||||
const checked = toRefs(props).modelValue;
|
const checked = toRefs(props).modelValue;
|
||||||
const toggle = () => {
|
const toggle = () => {
|
||||||
if (props.disabled) return;
|
if (props.disabled) return;
|
||||||
|
@ -66,17 +63,8 @@ const toggle = () => {
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.checked {
|
//&.checked {
|
||||||
> .button {
|
//}
|
||||||
background-color: var(--switchOnBg) !important;
|
|
||||||
border-color: var(--switchOnBg) !important;
|
|
||||||
|
|
||||||
> .knob {
|
|
||||||
left: 12px;
|
|
||||||
background: var(--switchOnFg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
|
@ -86,36 +74,6 @@ const toggle = () => {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
|
||||||
position: relative;
|
|
||||||
display: inline-flex;
|
|
||||||
flex-shrink: 0;
|
|
||||||
margin: 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
width: 32px;
|
|
||||||
height: 23px;
|
|
||||||
outline: none;
|
|
||||||
background: var(--switchOffBg);
|
|
||||||
background-clip: content-box;
|
|
||||||
border: solid 1px var(--switchOffBg);
|
|
||||||
border-radius: 999px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: inherit;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.knob {
|
|
||||||
position: absolute;
|
|
||||||
top: 3px;
|
|
||||||
left: 3px;
|
|
||||||
width: 15px;
|
|
||||||
height: 15px;
|
|
||||||
background: var(--switchOffFg);
|
|
||||||
border-radius: 999px;
|
|
||||||
transition: all 0.2s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
|
|
|
@ -60,7 +60,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<template v-if="showActions">
|
<template v-if="showActions">
|
||||||
<div v-if="tweetId" :class="$style.action">
|
<div v-if="tweetId" :class="$style.action">
|
||||||
<MkButton :small="true" inline @click="tweetExpanded = true">
|
<MkButton :small="true" inline @click="tweetExpanded = true">
|
||||||
<i class="ti ti-brand-twitter"></i> {{ i18n.ts.expandTweet }}
|
<i class="ti ti-brand-x"></i> {{ i18n.ts.expandTweet }}
|
||||||
</MkButton>
|
</MkButton>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!playerEnabled && player.url" :class="$style.action">
|
<div v-if="!playerEnabled && player.url" :class="$style.action">
|
||||||
|
|
|
@ -86,7 +86,8 @@ let top = $ref(0);
|
||||||
let left = $ref(0);
|
let left = $ref(0);
|
||||||
|
|
||||||
function showMenu(ev: MouseEvent) {
|
function showMenu(ev: MouseEvent) {
|
||||||
os.popupMenu(getUserMenu(user), ev.currentTarget ?? ev.target);
|
const { menu, cleanup } = getUserMenu(user);
|
||||||
|
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -7,15 +7,15 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkStickyContainer>
|
<MkStickyContainer>
|
||||||
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
|
||||||
<MkSpacer :contentMax="800">
|
<MkSpacer :contentMax="800">
|
||||||
<MkPagination v-slot="{items}" :pagination="pagination" class="ruryvtyk _gaps_m">
|
<MkPagination ref="paginationEl" v-slot="{items}" :pagination="pagination" class="ruryvtyk _gaps_m">
|
||||||
<section v-for="(announcement, i) in items" :key="announcement.id" class="announcement _panel">
|
<section v-for="announcement in items" :key="announcement.id" class="announcement _panel">
|
||||||
<div class="header"><span v-if="$i && !announcement.isRead">🆕 </span>{{ announcement.title }}</div>
|
<div class="header"><span v-if="$i && !announcement.isRead">🆕 </span>{{ announcement.title }}</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<Mfm :text="announcement.text"/>
|
<Mfm :text="announcement.text"/>
|
||||||
<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
|
<img v-if="announcement.imageUrl" :src="announcement.imageUrl"/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="$i && !announcement.isRead" class="footer">
|
<div v-if="$i && !announcement.isRead" class="footer">
|
||||||
<MkButton primary @click="read(items, announcement, i)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton>
|
<MkButton primary @click="read(announcement.id)"><i class="ti ti-check"></i> {{ i18n.ts.gotIt }}</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</MkPagination>
|
</MkPagination>
|
||||||
|
@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { } from 'vue';
|
import { ref } from 'vue';
|
||||||
import MkPagination from '@/components/MkPagination.vue';
|
import MkPagination from '@/components/MkPagination.vue';
|
||||||
import MkButton from '@/components/MkButton.vue';
|
import MkButton from '@/components/MkButton.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
@ -37,13 +37,15 @@ const pagination = {
|
||||||
limit: 10,
|
limit: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: これは実質的に親コンポーネントから子コンポーネントのプロパティを変更してるのでなんとかしたい
|
const paginationEl = ref<InstanceType<typeof MkPagination>>();
|
||||||
function read(items, announcement, i) {
|
|
||||||
items[i] = {
|
function read(id: string) {
|
||||||
...announcement,
|
if (!paginationEl.value) return;
|
||||||
isRead: true,
|
paginationEl.value.updateItem(id, announcement => {
|
||||||
};
|
announcement.isRead = true;
|
||||||
os.api('i/read-announcement', { announcementId: announcement.id });
|
return announcement;
|
||||||
|
});
|
||||||
|
os.api('i/read-announcement', { announcementId: id });
|
||||||
}
|
}
|
||||||
|
|
||||||
const headerActions = $computed(() => []);
|
const headerActions = $computed(() => []);
|
||||||
|
|
|
@ -7,35 +7,33 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<MkStickyContainer>
|
<MkStickyContainer>
|
||||||
<template #header><MkPageHeader/></template>
|
<template #header><MkPageHeader/></template>
|
||||||
<MkSpacer :contentMax="800">
|
<MkSpacer :contentMax="800">
|
||||||
<MkPagination :pagination="pagination">
|
<MkNotes :pagination="pagination" />
|
||||||
<template #empty>
|
|
||||||
<div class="_fullinfo">
|
|
||||||
<img :src="infoImageUrl" class="_ghost"/>
|
|
||||||
<div>{{ i18n.ts.noNotes }}</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #default="{ items }">
|
|
||||||
<MkDateSeparatedList v-slot="{ item }" :items="items" :direction="'down'" :noGap="false" :ad="false">
|
|
||||||
<MkNote :key="item.id" :note="item.note" :class="$style.note"/>
|
|
||||||
</MkDateSeparatedList>
|
|
||||||
</template>
|
|
||||||
</MkPagination>
|
|
||||||
</MkSpacer>
|
</MkSpacer>
|
||||||
</MkStickyContainer>
|
</MkStickyContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import MkPagination from '@/components/MkPagination.vue';
|
import MkNotes from '@/components/MkNotes.vue';
|
||||||
import MkNote from '@/components/MkNote.vue';
|
|
||||||
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
|
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
import { infoImageUrl } from '@/instance';
|
import { noteManager } from '@/scripts/entity-manager';
|
||||||
|
import { MisskeyEntity } from '@/types/date-separated-list';
|
||||||
|
|
||||||
|
const transform = (noteFavorites: any[]): MisskeyEntity[] => {
|
||||||
|
return noteFavorites.map(noteFavorite => {
|
||||||
|
const note = noteFavorite.note;
|
||||||
|
noteManager.set(note);
|
||||||
|
return {
|
||||||
|
id: note.id,
|
||||||
|
createdAt: note.createdAt,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const pagination = {
|
const pagination = {
|
||||||
endpoint: 'i/favorites' as const,
|
endpoint: 'i/favorites' as const,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
transform,
|
||||||
};
|
};
|
||||||
|
|
||||||
definePageMetadata({
|
definePageMetadata({
|
||||||
|
|
|
@ -34,8 +34,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
<FormSection v-if="iAmModerator">
|
<FormSection v-if="iAmModerator">
|
||||||
<template #label>Moderation</template>
|
<template #label>Moderation</template>
|
||||||
<div class="_gaps_s">
|
<div class="_gaps_s">
|
||||||
<MkSwitch v-model="suspended" @update:modelValue="toggleSuspend">{{ i18n.ts.stopActivityDelivery }}</MkSwitch>
|
<MkSwitch v-model="suspended" :disabled="!instance" @update:modelValue="toggleSuspend">{{ i18n.ts.stopActivityDelivery }}</MkSwitch>
|
||||||
<MkSwitch v-model="isBlocked" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
|
<MkSwitch v-model="isBlocked" :disabled="!meta || !instance" @update:modelValue="toggleBlock">{{ i18n.ts.blockThisInstance }}</MkSwitch>
|
||||||
<MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
|
<MkButton @click="refreshMetadata"><i class="ti ti-refresh"></i> Refresh metadata</MkButton>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
|
@ -129,7 +129,7 @@ import MkSelect from '@/components/MkSelect.vue';
|
||||||
import MkSwitch from '@/components/MkSwitch.vue';
|
import MkSwitch from '@/components/MkSwitch.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import number from '@/filters/number';
|
import number from '@/filters/number';
|
||||||
import { iAmModerator } from '@/account';
|
import { iAmModerator, iAmAdmin } from '@/account';
|
||||||
import { definePageMetadata } from '@/scripts/page-metadata';
|
import { definePageMetadata } from '@/scripts/page-metadata';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
import MkUserCardMini from '@/components/MkUserCardMini.vue';
|
||||||
|
@ -143,11 +143,11 @@ const props = defineProps<{
|
||||||
|
|
||||||
let tab = $ref('overview');
|
let tab = $ref('overview');
|
||||||
let chartSrc = $ref('instance-requests');
|
let chartSrc = $ref('instance-requests');
|
||||||
let meta = $ref<misskey.entities.DetailedInstanceMetadata | null>(null);
|
let meta = $ref<misskey.entities.AdminInstanceMetadata | null>(null);
|
||||||
let instance = $ref<misskey.entities.Instance | null>(null);
|
let instance = $ref<misskey.entities.Instance | null>(null);
|
||||||
let suspended = $ref(false);
|
let suspended = $ref(false);
|
||||||
let isBlocked = $ref(false);
|
let isBlocked = $ref(false);
|
||||||
let faviconUrl = $ref(null);
|
let faviconUrl = $ref<string | null>(null);
|
||||||
|
|
||||||
const usersPagination = {
|
const usersPagination = {
|
||||||
endpoint: iAmModerator ? 'admin/show-users' : 'users' as const,
|
endpoint: iAmModerator ? 'admin/show-users' : 'users' as const,
|
||||||
|
@ -160,7 +160,10 @@ const usersPagination = {
|
||||||
offsetMode: true,
|
offsetMode: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch(): Promise<void> {
|
||||||
|
if (iAmAdmin) {
|
||||||
|
meta = await os.api('admin/meta');
|
||||||
|
}
|
||||||
instance = await os.api('federation/show-instance', {
|
instance = await os.api('federation/show-instance', {
|
||||||
host: props.host,
|
host: props.host,
|
||||||
});
|
});
|
||||||
|
@ -169,21 +172,25 @@ async function fetch() {
|
||||||
faviconUrl = getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.iconUrl, 'preview');
|
faviconUrl = getProxiedImageUrlNullable(instance.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance.iconUrl, 'preview');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleBlock(ev) {
|
async function toggleBlock(): Promise<void> {
|
||||||
if (meta == null) return;
|
if (!meta) throw new Error('No meta?');
|
||||||
|
if (!instance) throw new Error('No instance?');
|
||||||
|
const { host } = instance;
|
||||||
await os.api('admin/update-meta', {
|
await os.api('admin/update-meta', {
|
||||||
blockedHosts: isBlocked ? meta.blockedHosts.concat([instance.host]) : meta.blockedHosts.filter(x => x !== instance.host),
|
blockedHosts: isBlocked ? meta.blockedHosts.concat([host]) : meta.blockedHosts.filter(x => x !== host),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleSuspend(v) {
|
async function toggleSuspend(): Promise<void> {
|
||||||
|
if (!instance) throw new Error('No instance?');
|
||||||
await os.api('admin/federation/update-instance', {
|
await os.api('admin/federation/update-instance', {
|
||||||
host: instance.host,
|
host: instance.host,
|
||||||
isSuspended: suspended,
|
isSuspended: suspended,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshMetadata() {
|
function refreshMetadata(): void {
|
||||||
|
if (!instance) throw new Error('No instance?');
|
||||||
os.api('admin/federation/refresh-remote-instance-metadata', {
|
os.api('admin/federation/refresh-remote-instance-metadata', {
|
||||||
host: instance.host,
|
host: instance.host,
|
||||||
});
|
});
|
||||||
|
|
|
@ -214,7 +214,8 @@ const age = $computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function menu(ev) {
|
function menu(ev) {
|
||||||
os.popupMenu(getUserMenu(props.user, router), ev.currentTarget ?? ev.target);
|
const { menu, cleanup } = getUserMenu(props.user, router);
|
||||||
|
os.popupMenu(menu, ev.currentTarget ?? ev.target).finally(cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
function parallaxLoop() {
|
function parallaxLoop() {
|
||||||
|
|
|
@ -365,12 +365,10 @@ export class NoteManager {
|
||||||
const note = (!this.notesSource.has(id) || shoudFetch) ? this.fetch(id) : this.get(id)!;
|
const note = (!this.notesSource.has(id) || shoudFetch) ? this.fetch(id) : this.get(id)!;
|
||||||
let using = false;
|
let using = false;
|
||||||
const CapturePromise = Promise.resolve(note)
|
const CapturePromise = Promise.resolve(note)
|
||||||
.then(() => {
|
|
||||||
this.capture(id);
|
|
||||||
using = true;
|
|
||||||
})
|
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
this.capture(id);
|
this.capture(id);
|
||||||
using = true;
|
using = true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { defaultStore, noteActions } from '@/store';
|
||||||
import { miLocalStorage } from '@/local-storage';
|
import { miLocalStorage } from '@/local-storage';
|
||||||
import { getUserMenu } from '@/scripts/get-user-menu';
|
import { getUserMenu } from '@/scripts/get-user-menu';
|
||||||
import { clipsCache } from '@/cache';
|
import { clipsCache } from '@/cache';
|
||||||
|
import { MenuItem } from '@/types/menu';
|
||||||
|
|
||||||
export async function getNoteClipMenu(props: {
|
export async function getNoteClipMenu(props: {
|
||||||
note: misskey.entities.Note;
|
note: misskey.entities.Note;
|
||||||
|
@ -107,6 +108,8 @@ export function getNoteMenu(props: {
|
||||||
|
|
||||||
const appearNote = isRenote ? props.note.renote as misskey.entities.Note : props.note;
|
const appearNote = isRenote ? props.note.renote as misskey.entities.Note : props.note;
|
||||||
|
|
||||||
|
const cleanups = [] as (() => void)[];
|
||||||
|
|
||||||
function del(): void {
|
function del(): void {
|
||||||
os.confirm({
|
os.confirm({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
|
@ -232,7 +235,7 @@ export function getNoteMenu(props: {
|
||||||
props.translation.value = res;
|
props.translation.value = res;
|
||||||
}
|
}
|
||||||
|
|
||||||
let menu;
|
let menu: MenuItem[];
|
||||||
if ($i) {
|
if ($i) {
|
||||||
const statePromise = os.api('notes/state', {
|
const statePromise = os.api('notes/state', {
|
||||||
noteId: appearNote.id,
|
noteId: appearNote.id,
|
||||||
|
@ -294,7 +297,7 @@ export function getNoteMenu(props: {
|
||||||
action: () => toggleFavorite(true),
|
action: () => toggleFavorite(true),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
type: 'parent',
|
type: 'parent' as const,
|
||||||
icon: 'ti ti-paperclip',
|
icon: 'ti ti-paperclip',
|
||||||
text: i18n.ts.clip,
|
text: i18n.ts.clip,
|
||||||
children: () => getNoteClipMenu(props),
|
children: () => getNoteClipMenu(props),
|
||||||
|
@ -317,15 +320,17 @@ export function getNoteMenu(props: {
|
||||||
text: i18n.ts.pin,
|
text: i18n.ts.pin,
|
||||||
action: () => togglePin(true),
|
action: () => togglePin(true),
|
||||||
} : undefined,
|
} : undefined,
|
||||||
appearNote.userId !== $i.id ? {
|
{
|
||||||
type: 'parent',
|
type: 'parent' as const,
|
||||||
icon: 'ti ti-user',
|
icon: 'ti ti-user',
|
||||||
text: i18n.ts.user,
|
text: i18n.ts.user,
|
||||||
children: async () => {
|
children: async () => {
|
||||||
const user = await os.api('users/show', { userId: appearNote.userId });
|
const user = appearNote.userId === $i?.id ? $i : await os.api('users/show', { userId: appearNote.userId });
|
||||||
return getUserMenu(user);
|
const { menu, cleanup } = getUserMenu(user);
|
||||||
|
cleanups.push(cleanup);
|
||||||
|
return menu;
|
||||||
},
|
},
|
||||||
} : undefined,
|
},
|
||||||
/*
|
/*
|
||||||
...($i.isModerator || $i.isAdmin ? [
|
...($i.isModerator || $i.isAdmin ? [
|
||||||
null,
|
null,
|
||||||
|
@ -410,5 +415,13 @@ export function getNoteMenu(props: {
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return menu;
|
const cleanup = () => {
|
||||||
|
if (_DEV_) console.log('note menu cleanup', cleanups);
|
||||||
|
cleanups.forEach(cleanup => cleanup());
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
menu,
|
||||||
|
cleanup,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { toUnicode } from 'punycode';
|
import { toUnicode } from 'punycode';
|
||||||
import { defineAsyncComponent } from 'vue';
|
import { defineAsyncComponent, ref, watch } from 'vue';
|
||||||
import * as misskey from 'misskey-js';
|
import * as misskey from 'misskey-js';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
||||||
|
@ -19,6 +19,8 @@ import { antennasCache, rolesCache, userListsCache } from '@/cache';
|
||||||
export function getUserMenu(user: misskey.entities.UserDetailed, router: Router = mainRouter) {
|
export function getUserMenu(user: misskey.entities.UserDetailed, router: Router = mainRouter) {
|
||||||
const meId = $i ? $i.id : null;
|
const meId = $i ? $i.id : null;
|
||||||
|
|
||||||
|
const cleanups = [] as (() => void)[];
|
||||||
|
|
||||||
async function toggleMute() {
|
async function toggleMute() {
|
||||||
if (user.isMuted) {
|
if (user.isMuted) {
|
||||||
os.apiWithDialog('mute/delete', {
|
os.apiWithDialog('mute/delete', {
|
||||||
|
@ -168,17 +170,32 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
|
||||||
text: i18n.ts.addToList,
|
text: i18n.ts.addToList,
|
||||||
children: async () => {
|
children: async () => {
|
||||||
const lists = await userListsCache.fetch(() => os.api('users/lists/list'));
|
const lists = await userListsCache.fetch(() => os.api('users/lists/list'));
|
||||||
|
return lists.map(list => {
|
||||||
|
const isListed = ref(list.userIds.includes(user.id));
|
||||||
|
cleanups.push(watch(isListed, () => {
|
||||||
|
if (isListed.value) {
|
||||||
|
os.apiWithDialog('users/lists/push', {
|
||||||
|
listId: list.id,
|
||||||
|
userId: user.id,
|
||||||
|
}).then(() => {
|
||||||
|
list.userIds.push(user.id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
os.apiWithDialog('users/lists/pull', {
|
||||||
|
listId: list.id,
|
||||||
|
userId: user.id,
|
||||||
|
}).then(() => {
|
||||||
|
list.userIds.splice(list.userIds.indexOf(user.id), 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
return lists.map(list => ({
|
return {
|
||||||
text: list.name,
|
type: 'switch',
|
||||||
action: async () => {
|
text: list.name,
|
||||||
await os.apiWithDialog('users/lists/push', {
|
ref: isListed,
|
||||||
listId: list.id,
|
};
|
||||||
userId: user.id,
|
});
|
||||||
});
|
|
||||||
userListsCache.delete();
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
type: 'parent',
|
type: 'parent',
|
||||||
|
@ -311,5 +328,13 @@ export function getUserMenu(user: misskey.entities.UserDetailed, router: Router
|
||||||
}))]);
|
}))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return menu;
|
const cleanup = () => {
|
||||||
|
if (_DEV_) console.log('user menu cleanup', cleanups);
|
||||||
|
cleanups.forEach(cleanup => cleanup());
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
menu,
|
||||||
|
cleanup,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ export type MenuA = { type: 'a', href: string, target?: string, download?: strin
|
||||||
export type MenuUser = { type: 'user', user: Misskey.entities.User, active?: boolean, indicate?: boolean, action: MenuAction };
|
export type MenuUser = { type: 'user', user: Misskey.entities.User, active?: boolean, indicate?: boolean, action: MenuAction };
|
||||||
export type MenuSwitch = { type: 'switch', ref: Ref<boolean>, text: string, disabled?: boolean };
|
export type MenuSwitch = { type: 'switch', ref: Ref<boolean>, text: string, disabled?: boolean };
|
||||||
export type MenuButton = { type?: 'button', text: string, icon?: string, indicate?: boolean, danger?: boolean, active?: boolean, avatar?: Misskey.entities.User; action: MenuAction };
|
export type MenuButton = { type?: 'button', text: string, icon?: string, indicate?: boolean, danger?: boolean, active?: boolean, avatar?: Misskey.entities.User; action: MenuAction };
|
||||||
export type MenuParent = { type: 'parent', text: string, icon?: string, children: OuterMenuItem[] };
|
export type MenuParent = { type: 'parent', text: string, icon?: string, children: OuterMenuItem[] | (() => Promise<OuterMenuItem[]> | OuterMenuItem[]) };
|
||||||
|
|
||||||
export type MenuPending = { type: 'pending' };
|
export type MenuPending = { type: 'pending' };
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,11 @@ export type Acct = {
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
type Ad = TODO_2;
|
type Ad = TODO_2;
|
||||||
|
|
||||||
|
// @public (undocumented)
|
||||||
|
type AdminInstanceMetadata = DetailedInstanceMetadata & {
|
||||||
|
blockedHosts: string[];
|
||||||
|
};
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
type Announcement = {
|
type Announcement = {
|
||||||
id: ID;
|
id: ID;
|
||||||
|
@ -329,8 +334,8 @@ export type Endpoints = {
|
||||||
res: TODO;
|
res: TODO;
|
||||||
};
|
};
|
||||||
'admin/meta': {
|
'admin/meta': {
|
||||||
req: TODO;
|
req: NoParams;
|
||||||
res: TODO;
|
res: AdminInstanceMetadata;
|
||||||
};
|
};
|
||||||
'admin/reset-password': {
|
'admin/reset-password': {
|
||||||
req: TODO;
|
req: TODO;
|
||||||
|
@ -2226,6 +2231,7 @@ declare namespace entities {
|
||||||
LiteInstanceMetadata,
|
LiteInstanceMetadata,
|
||||||
DetailedInstanceMetadata,
|
DetailedInstanceMetadata,
|
||||||
InstanceMetadata,
|
InstanceMetadata,
|
||||||
|
AdminInstanceMetadata,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
Stats,
|
Stats,
|
||||||
Page,
|
Page,
|
||||||
|
@ -2317,7 +2323,7 @@ type ID = string;
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
type Instance = {
|
type Instance = {
|
||||||
id: ID;
|
id: ID;
|
||||||
caughtAt: DateString;
|
firstRetrievedAt: DateString;
|
||||||
host: string;
|
host: string;
|
||||||
usersCount: number;
|
usersCount: number;
|
||||||
notesCount: number;
|
notesCount: number;
|
||||||
|
@ -2331,6 +2337,7 @@ type Instance = {
|
||||||
lastCommunicatedAt: DateString;
|
lastCommunicatedAt: DateString;
|
||||||
isNotResponding: boolean;
|
isNotResponding: boolean;
|
||||||
isSuspended: boolean;
|
isSuspended: boolean;
|
||||||
|
isBlocked: boolean;
|
||||||
softwareName: string | null;
|
softwareName: string | null;
|
||||||
softwareVersion: string | null;
|
softwareVersion: string | null;
|
||||||
openRegistrations: boolean | null;
|
openRegistrations: boolean | null;
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type {
|
||||||
Ad, Announcement, Antenna, App, AuthSession, Blocking, Channel, Clip, DateString, DetailedInstanceMetadata, DriveFile, DriveFolder, Following, FollowingFolloweePopulated, FollowingFollowerPopulated, FollowRequest, GalleryPost, Instance,
|
Ad, Announcement, Antenna, App, AuthSession, Blocking, Channel, Clip, DateString, DetailedInstanceMetadata, DriveFile, DriveFolder, Following, FollowingFolloweePopulated, FollowingFollowerPopulated, FollowRequest, GalleryPost, Instance,
|
||||||
LiteInstanceMetadata,
|
LiteInstanceMetadata,
|
||||||
MeDetailed,
|
MeDetailed,
|
||||||
Note, NoteFavorite, OriginType, Page, ServerInfo, Stats, User, UserDetailed, MeSignup, UserGroup, UserList, UserSorting, Notification, NoteReaction, Signin, MessagingMessage, Invite, InviteLimit,
|
Note, NoteFavorite, OriginType, Page, ServerInfo, Stats, User, UserDetailed, MeSignup, UserGroup, UserList, UserSorting, Notification, NoteReaction, Signin, MessagingMessage, Invite, InviteLimit, AdminInstanceMetadata,
|
||||||
} from './entities.js';
|
} from './entities.js';
|
||||||
|
|
||||||
type TODO = Record<string, any> | null;
|
type TODO = Record<string, any> | null;
|
||||||
|
@ -20,7 +20,7 @@ export type Endpoints = {
|
||||||
'admin/get-table-stats': { req: TODO; res: TODO; };
|
'admin/get-table-stats': { req: TODO; res: TODO; };
|
||||||
'admin/invite': { req: TODO; res: TODO; };
|
'admin/invite': { req: TODO; res: TODO; };
|
||||||
'admin/logs': { req: TODO; res: TODO; };
|
'admin/logs': { req: TODO; res: TODO; };
|
||||||
'admin/meta': { req: TODO; res: TODO; };
|
'admin/meta': { req: NoParams; res: AdminInstanceMetadata; };
|
||||||
'admin/reset-password': { req: TODO; res: TODO; };
|
'admin/reset-password': { req: TODO; res: TODO; };
|
||||||
'admin/resolve-abuse-user-report': { req: TODO; res: TODO; };
|
'admin/resolve-abuse-user-report': { req: TODO; res: TODO; };
|
||||||
'admin/resync-chart': { req: TODO; res: TODO; };
|
'admin/resync-chart': { req: TODO; res: TODO; };
|
||||||
|
|
|
@ -346,6 +346,11 @@ export type DetailedInstanceMetadata = LiteInstanceMetadata & {
|
||||||
|
|
||||||
export type InstanceMetadata = LiteInstanceMetadata | DetailedInstanceMetadata;
|
export type InstanceMetadata = LiteInstanceMetadata | DetailedInstanceMetadata;
|
||||||
|
|
||||||
|
export type AdminInstanceMetadata = DetailedInstanceMetadata & {
|
||||||
|
// TODO: There are more fields.
|
||||||
|
blockedHosts: string[];
|
||||||
|
};
|
||||||
|
|
||||||
export type ServerInfo = {
|
export type ServerInfo = {
|
||||||
machine: string;
|
machine: string;
|
||||||
cpu: {
|
cpu: {
|
||||||
|
@ -482,7 +487,7 @@ export type Blocking = {
|
||||||
|
|
||||||
export type Instance = {
|
export type Instance = {
|
||||||
id: ID;
|
id: ID;
|
||||||
caughtAt: DateString;
|
firstRetrievedAt: DateString;
|
||||||
host: string;
|
host: string;
|
||||||
usersCount: number;
|
usersCount: number;
|
||||||
notesCount: number;
|
notesCount: number;
|
||||||
|
@ -496,6 +501,7 @@ export type Instance = {
|
||||||
lastCommunicatedAt: DateString;
|
lastCommunicatedAt: DateString;
|
||||||
isNotResponding: boolean;
|
isNotResponding: boolean;
|
||||||
isSuspended: boolean;
|
isSuspended: boolean;
|
||||||
|
isBlocked: boolean;
|
||||||
softwareName: string | null;
|
softwareName: string | null;
|
||||||
softwareVersion: string | null;
|
softwareVersion: string | null;
|
||||||
openRegistrations: boolean | null;
|
openRegistrations: boolean | null;
|
||||||
|
|
|
@ -341,9 +341,6 @@ importers:
|
||||||
sanitize-html:
|
sanitize-html:
|
||||||
specifier: 2.11.0
|
specifier: 2.11.0
|
||||||
version: 2.11.0
|
version: 2.11.0
|
||||||
semver:
|
|
||||||
specifier: 7.5.4
|
|
||||||
version: 7.5.4
|
|
||||||
sharp:
|
sharp:
|
||||||
specifier: 0.32.3
|
specifier: 0.32.3
|
||||||
version: 0.32.3
|
version: 0.32.3
|
||||||
|
@ -665,8 +662,8 @@ importers:
|
||||||
specifier: 0.15.0
|
specifier: 0.15.0
|
||||||
version: 0.15.0
|
version: 0.15.0
|
||||||
'@tabler/icons-webfont':
|
'@tabler/icons-webfont':
|
||||||
specifier: 2.25.0
|
specifier: 2.30.0
|
||||||
version: 2.25.0
|
version: 2.30.0
|
||||||
'@vitejs/plugin-vue':
|
'@vitejs/plugin-vue':
|
||||||
specifier: 4.2.3
|
specifier: 4.2.3
|
||||||
version: 4.2.3(vite@4.4.4)(vue@3.3.4)
|
version: 4.2.3(vite@4.4.4)(vue@3.3.4)
|
||||||
|
@ -5326,6 +5323,7 @@ packages:
|
||||||
/@mapbox/node-pre-gyp@1.0.9:
|
/@mapbox/node-pre-gyp@1.0.9:
|
||||||
resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==}
|
resolution: {integrity: sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-libc: 2.0.1
|
detect-libc: 2.0.1
|
||||||
https-proxy-agent: 5.0.1
|
https-proxy-agent: 5.0.1
|
||||||
|
@ -7305,7 +7303,7 @@ packages:
|
||||||
ts-dedent: 2.2.0
|
ts-dedent: 2.2.0
|
||||||
type-fest: 2.19.0
|
type-fest: 2.19.0
|
||||||
vue: 3.3.4
|
vue: 3.3.4
|
||||||
vue-component-type-helpers: 1.8.6
|
vue-component-type-helpers: 1.8.8
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- encoding
|
- encoding
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -7716,19 +7714,20 @@ packages:
|
||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect: 2.0.1
|
defer-to-connect: 2.0.1
|
||||||
|
|
||||||
/@tabler/icons-webfont@2.25.0:
|
/@tabler/icons-webfont@2.30.0:
|
||||||
resolution: {integrity: sha512-IWYVnYlCwlGC95kvpY5Hdiyn1/amXOUwsfRthtmgEtHCQly4JSLRuaD90xD0O+pQ+wZBXIVNsO3pKdg74zEaBg==}
|
resolution: {integrity: sha512-tGGKxeATvyHJBHl5FzY4oAShbAiR4ovstG62lqb2HGlOJwz4Io9TSk4eoB88nqxg3sT5no2YsAKXcr1UnlpnNQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tabler/icons': 2.25.0
|
'@tabler/icons': 2.30.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tabler/icons@2.25.0:
|
/@tabler/icons@2.30.0:
|
||||||
resolution: {integrity: sha512-Z+FtSZoG/CM1TMCgg7elUew2m0+qMdh5gutMhvxiIY77KIIsE6L/6fUBy+rPXWE9v7MV296fsnCvbpfgwpXupQ==}
|
resolution: {integrity: sha512-tvtmkI4ALjKThVVORh++sB9JnkFY7eGInKxNy+Df7WVQiF7T85tlvGADzlgX4Ic+CK5MIUzZ0jhOlQ/RRlgXpg==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@tensorflow/tfjs-backend-cpu@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
/@tensorflow/tfjs-backend-cpu@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
||||||
resolution: {integrity: sha512-d4eln500/qNym78z9IrUUzF0ITBoJGLrxV8xd92kLVoXhg35Mm+zqUXShjFcrH8joOHOFuST0qZ0TbDDqcPzPA==}
|
resolution: {integrity: sha512-d4eln500/qNym78z9IrUUzF0ITBoJGLrxV8xd92kLVoXhg35Mm+zqUXShjFcrH8joOHOFuST0qZ0TbDDqcPzPA==}
|
||||||
engines: {yarn: '>= 1.3.2'}
|
engines: {yarn: '>= 1.3.2'}
|
||||||
|
requiresBuild: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tensorflow/tfjs-core': 4.4.0
|
'@tensorflow/tfjs-core': 4.4.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7740,6 +7739,7 @@ packages:
|
||||||
/@tensorflow/tfjs-backend-webgl@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
/@tensorflow/tfjs-backend-webgl@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
||||||
resolution: {integrity: sha512-TzQKvfAPgGt9cMG+5bVoTckoG1xr/PVJM/uODkPvzcMqi3j97kuWDXwkYJIgXldStmfiKkU7f5CmyD3Cq3E6BA==}
|
resolution: {integrity: sha512-TzQKvfAPgGt9cMG+5bVoTckoG1xr/PVJM/uODkPvzcMqi3j97kuWDXwkYJIgXldStmfiKkU7f5CmyD3Cq3E6BA==}
|
||||||
engines: {yarn: '>= 1.3.2'}
|
engines: {yarn: '>= 1.3.2'}
|
||||||
|
requiresBuild: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tensorflow/tfjs-core': 4.4.0
|
'@tensorflow/tfjs-core': 4.4.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7753,6 +7753,7 @@ packages:
|
||||||
|
|
||||||
/@tensorflow/tfjs-converter@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
/@tensorflow/tfjs-converter@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
||||||
resolution: {integrity: sha512-JUjpRStrAuw37tgPd5UENu0UjQVuJT09yF7KpOur4BriJ0uQqrbEZHMPHmvUtr5nYzkqlXJTuXIyxvEY/olNpg==}
|
resolution: {integrity: sha512-JUjpRStrAuw37tgPd5UENu0UjQVuJT09yF7KpOur4BriJ0uQqrbEZHMPHmvUtr5nYzkqlXJTuXIyxvEY/olNpg==}
|
||||||
|
requiresBuild: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tensorflow/tfjs-core': 4.4.0
|
'@tensorflow/tfjs-core': 4.4.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7762,6 +7763,7 @@ packages:
|
||||||
/@tensorflow/tfjs-core@4.4.0:
|
/@tensorflow/tfjs-core@4.4.0:
|
||||||
resolution: {integrity: sha512-Anxpc7cAOA0Q7EUXdTbQKMg3reFvrdkgDlaYzH9ZfkMq2CgLV4Au6E/s6HmbYn/VrAtWy9mLY5c/lLJqh4764g==}
|
resolution: {integrity: sha512-Anxpc7cAOA0Q7EUXdTbQKMg3reFvrdkgDlaYzH9ZfkMq2CgLV4Au6E/s6HmbYn/VrAtWy9mLY5c/lLJqh4764g==}
|
||||||
engines: {yarn: '>= 1.3.2'}
|
engines: {yarn: '>= 1.3.2'}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/long': 4.0.2
|
'@types/long': 4.0.2
|
||||||
'@types/offscreencanvas': 2019.7.0
|
'@types/offscreencanvas': 2019.7.0
|
||||||
|
@ -7777,6 +7779,7 @@ packages:
|
||||||
|
|
||||||
/@tensorflow/tfjs-data@4.4.0(@tensorflow/tfjs-core@4.4.0)(seedrandom@3.0.5):
|
/@tensorflow/tfjs-data@4.4.0(@tensorflow/tfjs-core@4.4.0)(seedrandom@3.0.5):
|
||||||
resolution: {integrity: sha512-aY4eq4cgrsrXeBU6ABZAAN3tV0fG4YcHd0z+cYuNXnCo+VEQLJnPmhn+xymZ4VQZQH4GXbVS4dV9pXMclFNRFw==}
|
resolution: {integrity: sha512-aY4eq4cgrsrXeBU6ABZAAN3tV0fG4YcHd0z+cYuNXnCo+VEQLJnPmhn+xymZ4VQZQH4GXbVS4dV9pXMclFNRFw==}
|
||||||
|
requiresBuild: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tensorflow/tfjs-core': 4.4.0
|
'@tensorflow/tfjs-core': 4.4.0
|
||||||
seedrandom: ^3.0.5
|
seedrandom: ^3.0.5
|
||||||
|
@ -7792,6 +7795,7 @@ packages:
|
||||||
|
|
||||||
/@tensorflow/tfjs-layers@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
/@tensorflow/tfjs-layers@4.4.0(@tensorflow/tfjs-core@4.4.0):
|
||||||
resolution: {integrity: sha512-OGC7shfiD9Gc698hINHK4y9slOJvu5m54tVNm4xf+WSNrw/avvgpar6yyoL5bakYIZNQvFNK75Yr8VRPR7oPeQ==}
|
resolution: {integrity: sha512-OGC7shfiD9Gc698hINHK4y9slOJvu5m54tVNm4xf+WSNrw/avvgpar6yyoL5bakYIZNQvFNK75Yr8VRPR7oPeQ==}
|
||||||
|
requiresBuild: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@tensorflow/tfjs-core': 4.4.0
|
'@tensorflow/tfjs-core': 4.4.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -7821,6 +7825,7 @@ packages:
|
||||||
/@tensorflow/tfjs@4.4.0(seedrandom@3.0.5):
|
/@tensorflow/tfjs@4.4.0(seedrandom@3.0.5):
|
||||||
resolution: {integrity: sha512-EmCsnzdvawyk4b+4JKaLLuicHcJQRZtL1zSy9AWJLiiHTbDDseYgLxfaCEfLk8v2bUe7SBXwl3n3B7OjgvH11Q==}
|
resolution: {integrity: sha512-EmCsnzdvawyk4b+4JKaLLuicHcJQRZtL1zSy9AWJLiiHTbDDseYgLxfaCEfLk8v2bUe7SBXwl3n3B7OjgvH11Q==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tensorflow/tfjs-backend-cpu': 4.4.0(@tensorflow/tfjs-core@4.4.0)
|
'@tensorflow/tfjs-backend-cpu': 4.4.0(@tensorflow/tfjs-core@4.4.0)
|
||||||
'@tensorflow/tfjs-backend-webgl': 4.4.0(@tensorflow/tfjs-core@4.4.0)
|
'@tensorflow/tfjs-backend-webgl': 4.4.0(@tensorflow/tfjs-core@4.4.0)
|
||||||
|
@ -8229,6 +8234,7 @@ packages:
|
||||||
|
|
||||||
/@types/long@4.0.2:
|
/@types/long@4.0.2:
|
||||||
resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
|
resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/matter-js@0.18.5:
|
/@types/matter-js@0.18.5:
|
||||||
|
@ -8326,10 +8332,12 @@ packages:
|
||||||
|
|
||||||
/@types/offscreencanvas@2019.3.0:
|
/@types/offscreencanvas@2019.3.0:
|
||||||
resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==}
|
resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/offscreencanvas@2019.7.0:
|
/@types/offscreencanvas@2019.7.0:
|
||||||
resolution: {integrity: sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==}
|
resolution: {integrity: sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/pg@8.10.2:
|
/@types/pg@8.10.2:
|
||||||
|
@ -8418,6 +8426,7 @@ packages:
|
||||||
|
|
||||||
/@types/seedrandom@2.4.30:
|
/@types/seedrandom@2.4.30:
|
||||||
resolution: {integrity: sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==}
|
resolution: {integrity: sha512-AnxLHewubLVzoF/A4qdxBGHCKifw8cY32iro3DQX9TPcetE95zBeVt3jnsvtvAUf1vwzMfwzp4t/L2yqPlnjkQ==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/semver@7.5.0:
|
/@types/semver@7.5.0:
|
||||||
|
@ -8544,6 +8553,7 @@ packages:
|
||||||
|
|
||||||
/@types/webgl-ext@0.0.30:
|
/@types/webgl-ext@0.0.30:
|
||||||
resolution: {integrity: sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==}
|
resolution: {integrity: sha512-LKVgNmBxN0BbljJrVUwkxwRYqzsAEPcZOe6S2T6ZaBDIrFp0qu4FNlpc5sM1tGbXUYFgdVQIoeLk1Y1UoblyEg==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@types/websocket@1.0.5:
|
/@types/websocket@1.0.5:
|
||||||
|
@ -8967,6 +8977,7 @@ packages:
|
||||||
|
|
||||||
/@webgpu/types@0.1.30:
|
/@webgpu/types@0.1.30:
|
||||||
resolution: {integrity: sha512-9AXJSmL3MzY8ZL//JjudA//q+2kBRGhLBFpkdGksWIuxrMy81nFrCzj2Am+mbh8WoU6rXmv7cY5E3rdlyru2Qg==}
|
resolution: {integrity: sha512-9AXJSmL3MzY8ZL//JjudA//q+2kBRGhLBFpkdGksWIuxrMy81nFrCzj2Am+mbh8WoU6rXmv7cY5E3rdlyru2Qg==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@xmldom/xmldom@0.8.6:
|
/@xmldom/xmldom@0.8.6:
|
||||||
|
@ -9059,12 +9070,14 @@ packages:
|
||||||
/adm-zip@0.5.10:
|
/adm-zip@0.5.10:
|
||||||
resolution: {integrity: sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==}
|
resolution: {integrity: sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/agent-base@4.3.0:
|
/agent-base@4.3.0:
|
||||||
resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==}
|
resolution: {integrity: sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==}
|
||||||
engines: {node: '>= 4.0.0'}
|
engines: {node: '>= 4.0.0'}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
es6-promisify: 5.0.0
|
es6-promisify: 5.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -11760,11 +11773,13 @@ packages:
|
||||||
|
|
||||||
/es6-promise@4.2.8:
|
/es6-promise@4.2.8:
|
||||||
resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
|
resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/es6-promisify@5.0.0:
|
/es6-promisify@5.0.0:
|
||||||
resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==}
|
resolution: {integrity: sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ==}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
es6-promise: 4.2.8
|
es6-promise: 4.2.8
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -12970,6 +12985,7 @@ packages:
|
||||||
|
|
||||||
/fs-minipass@1.2.7:
|
/fs-minipass@1.2.7:
|
||||||
resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==}
|
resolution: {integrity: sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
minipass: 2.9.0
|
minipass: 2.9.0
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -13340,6 +13356,7 @@ packages:
|
||||||
|
|
||||||
/google-protobuf@3.21.2:
|
/google-protobuf@3.21.2:
|
||||||
resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==}
|
resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
@ -13792,6 +13809,7 @@ packages:
|
||||||
/https-proxy-agent@2.2.4:
|
/https-proxy-agent@2.2.4:
|
||||||
resolution: {integrity: sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==}
|
resolution: {integrity: sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==}
|
||||||
engines: {node: '>= 4.5.0'}
|
engines: {node: '>= 4.5.0'}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 4.3.0
|
agent-base: 4.3.0
|
||||||
debug: 3.2.7(supports-color@5.5.0)
|
debug: 3.2.7(supports-color@5.5.0)
|
||||||
|
@ -15674,6 +15692,7 @@ packages:
|
||||||
|
|
||||||
/long@4.0.0:
|
/long@4.0.0:
|
||||||
resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
|
resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/loose-envify@1.4.0:
|
/loose-envify@1.4.0:
|
||||||
|
@ -16118,6 +16137,7 @@ packages:
|
||||||
|
|
||||||
/minipass@2.9.0:
|
/minipass@2.9.0:
|
||||||
resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==}
|
resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
yallist: 3.1.1
|
yallist: 3.1.1
|
||||||
|
@ -16141,6 +16161,7 @@ packages:
|
||||||
|
|
||||||
/minizlib@1.3.3:
|
/minizlib@1.3.3:
|
||||||
resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==}
|
resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
minipass: 2.9.0
|
minipass: 2.9.0
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -16494,12 +16515,14 @@ packages:
|
||||||
/node-gyp-build-optional-packages@5.0.7:
|
/node-gyp-build-optional-packages@5.0.7:
|
||||||
resolution: {integrity: sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==}
|
resolution: {integrity: sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/node-gyp-build@4.6.0:
|
/node-gyp-build@4.6.0:
|
||||||
resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==}
|
resolution: {integrity: sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
|
|
||||||
/node-gyp@9.4.0:
|
/node-gyp@9.4.0:
|
||||||
resolution: {integrity: sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==}
|
resolution: {integrity: sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==}
|
||||||
|
@ -16566,6 +16589,7 @@ packages:
|
||||||
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
abbrev: 1.1.1
|
abbrev: 1.1.1
|
||||||
dev: false
|
dev: false
|
||||||
|
@ -20059,6 +20083,7 @@ packages:
|
||||||
/tar@4.4.19:
|
/tar@4.4.19:
|
||||||
resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==}
|
resolution: {integrity: sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==}
|
||||||
engines: {node: '>=4.5'}
|
engines: {node: '>=4.5'}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
chownr: 1.1.4
|
chownr: 1.1.4
|
||||||
fs-minipass: 1.2.7
|
fs-minipass: 1.2.7
|
||||||
|
@ -21181,8 +21206,8 @@ packages:
|
||||||
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
/vue-component-type-helpers@1.8.6:
|
/vue-component-type-helpers@1.8.8:
|
||||||
resolution: {integrity: sha512-vKWeoKVEV51ZzoB8+UY0apMXiifbPQxWlcZlvQRDVdiOHmEkCBClWeIGbqQ8cCR9P4j+oCyLW87sraZFMz/qnA==}
|
resolution: {integrity: sha512-Ohv9HQY92nSbpReC6WhY0X4YkOszHzwUHaaN/lev5tHQLM1AEw+LrLeB2bIGIyKGDU7ZVrncXcv/oBny4rjbYg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vue-docgen-api@4.64.1(vue@3.3.4):
|
/vue-docgen-api@4.64.1(vue@3.3.4):
|
||||||
|
|
Loading…
Reference in New Issue