Compare commits

..

4 Commits

Author SHA1 Message Date
Ljzd PRO aa38c7fe9c
Merge branch 'develop' into develop 2024-09-18 03:35:33 +08:00
かっこかり 3bf63dd9c5
fix(frontend): 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正 (#14543)
* fix(frontend): reloadAskが同時に複数実行されないように

* Update Changelog

* fix

* フラグ解除が確実に行われるように

* reloadAskを汎用化、理由を受け取るように

* fix
2024-09-17 22:18:06 +09:00
かっこかり ce95323e49
fix(antenna): src=list && userListId=null の場合クエリータイムアウトが発生する問題を修正 (MisskeyIO#721) (#14568)
(cherry picked from commit 47b6b97c9c6d9583dd1b11acbf8f94059e81ebaf)

Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>
2024-09-17 22:02:34 +09:00
FineArchs daf9ae5d4a
ScratchpadにUIインスペクターを追加 (#14565)
* add ui list

* Update scratchpad.vue

* experiment

* design change

* redesign

* redesign

* Update ja-JP.yml

* redesign

* component properties

* whole json

* use textarea

* fix import

* stringify function

* Update CHANGELOG.md

* UI Component Monitor -> UI Inspector

* uiInspectorOpenedFlags -> uiInspectorOpenedComponents

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>

* fix

* change key i -> c.value.id

---------

Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2024-09-17 20:11:50 +09:00
10 changed files with 123 additions and 57 deletions

View File

@ -9,10 +9,12 @@
- Enhance: サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように - Enhance: サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように
- Enhance: アイコンデコレーション管理画面にプレビューを追加 - Enhance: アイコンデコレーション管理画面にプレビューを追加
- Enhance: コントロールパネル内のファイル一覧でセンシティブなファイルを区別しやすく - Enhance: コントロールパネル内のファイル一覧でセンシティブなファイルを区別しやすく
- Enhance: ScratchpadにUIインスペクターを追加
- Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正 - Fix: サーバーメトリクスが2つ以上あるとリロード直後の表示がおかしくなる問題を修正
- Fix: 月の違う同じ日はセパレータが表示されないのを修正 - Fix: 月の違う同じ日はセパレータが表示されないのを修正
- Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正 - Fix: 縦横比が極端なカスタム絵文字を表示する際にレイアウトが崩れる箇所があるのを修正
(Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725) (Cherry-picked from https://github.com/MisskeyIO/misskey/pull/725)
- Fix: 設定変更時のリロード確認ダイアログが複数個表示されることがある問題を修正
- Fix: ERROR CODE: APP_IMPORT on iOS <= 16.3 (SyntaxError: Invalid regular expression: invalid group specifier name) - Fix: ERROR CODE: APP_IMPORT on iOS <= 16.3 (SyntaxError: Invalid regular expression: invalid group specifier name)
### Server ### Server

2
locales/index.d.ts vendored
View File

@ -3121,7 +3121,7 @@ export interface Locale extends ILocale {
*/ */
"narrow": string; "narrow": string;
/** /**
* *
*/ */
"reloadToApplySetting": string; "reloadToApplySetting": string;
/** /**

View File

@ -592,6 +592,8 @@ ascendingOrder: "昇順"
descendingOrder: "降順" descendingOrder: "降順"
scratchpad: "スクラッチパッド" scratchpad: "スクラッチパッド"
scratchpadDescription: "スクラッチパッドは、AiScriptの実験環境を提供します。Misskeyと対話するコードの記述、実行、結果の確認ができます。" scratchpadDescription: "スクラッチパッドは、AiScriptの実験環境を提供します。Misskeyと対話するコードの記述、実行、結果の確認ができます。"
uiInspector: "UIインスペクター"
uiInspectorDescription: "メモリ上に存在しているUIコンポーネントのインスタンスの一覧を見ることができます。UIコンポーネントはUi:C:系関数により生成されます。"
output: "出力" output: "出力"
script: "スクリプト" script: "スクリプト"
disablePagesScript: "Pagesのスクリプトを無効にする" disablePagesScript: "Pagesのスクリプトを無効にする"
@ -776,7 +778,7 @@ left: "左"
center: "中央" center: "中央"
wide: "広い" wide: "広い"
narrow: "狭い" narrow: "狭い"
reloadToApplySetting: "設定はページリロード後に反映されます。今すぐリロードしますか?" reloadToApplySetting: "設定はページリロード後に反映されます。"
needReloadToApply: "反映には再起動が必要です。" needReloadToApply: "反映には再起動が必要です。"
showTitlebar: "タイトルバーを表示する" showTitlebar: "タイトルバーを表示する"
clearCache: "キャッシュをクリア" clearCache: "キャッシュをクリア"

View File

@ -123,11 +123,14 @@ export class AntennaService implements OnApplicationShutdown {
if (antenna.src === 'home') { if (antenna.src === 'home') {
// TODO // TODO
} else if (antenna.src === 'list') { } else if (antenna.src === 'list') {
const listUsers = (await this.userListMembershipsRepository.findBy({ if (antenna.userListId == null) return false;
userListId: antenna.userListId!, const exists = await this.userListMembershipsRepository.exists({
})).map(x => x.userId); where: {
userListId: antenna.userListId,
if (!listUsers.includes(note.userId)) return false; userId: note.userId,
},
});
if (!exists) return false;
} else if (antenna.src === 'users') { } else if (antenna.src === 'users') {
const accts = antenna.users.map(x => { const accts = antenna.users.map(x => {
const { username, host } = Acct.parse(x); const { username, host } = Acct.parse(x);

View File

@ -30,6 +30,24 @@ SPDX-License-Identifier: AGPL-3.0-only
</div> </div>
</MkContainer> </MkContainer>
<MkContainer :foldable="true" :expanded="false">
<template #header>{{ i18n.ts.uiInspector }}</template>
<div :class="$style.uiInspector">
<div v-for="c in components" :key="c.value.id">
<div :class="$style.uiInspectorType">{{ c.value.type }}</div>
<div :class="$style.uiInspectorId">{{ c.value.id }}</div>
<button :class="$style.uiInspectorPropsToggle" @click="() => uiInspectorOpenedComponents.set(c, !uiInspectorOpenedComponents.get(c))">
<i v-if="uiInspectorOpenedComponents.get(c)" class="ti ti-chevron-up icon"></i>
<i v-else class="ti ti-chevron-down icon"></i>
</button>
<div v-if="uiInspectorOpenedComponents.get(c)">
<MkTextarea :modelValue="stringifyUiProps(c.value)" code readonly></MkTextarea>
</div>
</div>
<div :class="$style.uiInspectorDescription">{{ i18n.ts.uiInspectorDescription }}</div>
</div>
</MkContainer>
<div class=""> <div class="">
{{ i18n.ts.scratchpadDescription }} {{ i18n.ts.scratchpadDescription }}
</div> </div>
@ -43,6 +61,7 @@ import { onDeactivated, onUnmounted, Ref, ref, watch, computed } from 'vue';
import { Interpreter, Parser, utils } from '@syuilo/aiscript'; import { Interpreter, Parser, utils } from '@syuilo/aiscript';
import MkContainer from '@/components/MkContainer.vue'; import MkContainer from '@/components/MkContainer.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkCodeEditor from '@/components/MkCodeEditor.vue'; import MkCodeEditor from '@/components/MkCodeEditor.vue';
import { aiScriptReadline, createAiScriptEnv } from '@/scripts/aiscript/api.js'; import { aiScriptReadline, createAiScriptEnv } from '@/scripts/aiscript/api.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
@ -61,6 +80,7 @@ const logs = ref<any[]>([]);
const root = ref<AsUiRoot>(); const root = ref<AsUiRoot>();
const components = ref<Ref<AsUiComponent>[]>([]); const components = ref<Ref<AsUiComponent>[]>([]);
const uiKey = ref(0); const uiKey = ref(0);
const uiInspectorOpenedComponents = ref(new Map<string, boolean>);
const saved = miLocalStorage.getItem('scratchpad'); const saved = miLocalStorage.getItem('scratchpad');
if (saved) { if (saved) {
@ -71,6 +91,14 @@ watch(code, () => {
miLocalStorage.setItem('scratchpad', code.value); miLocalStorage.setItem('scratchpad', code.value);
}); });
function stringifyUiProps(uiProps) {
return JSON.stringify(
{ ...uiProps, type: undefined, id: undefined },
(k, v) => typeof v === 'function' ? '<function>' : v,
2
);
}
async function run() { async function run() {
if (aiscript) aiscript.abort(); if (aiscript) aiscript.abort();
root.value = undefined; root.value = undefined;
@ -192,4 +220,35 @@ definePageMetadata(() => ({
} }
} }
} }
.uiInspector {
display: grid;
gap: 8px;
padding: 16px;
}
.uiInspectorType {
display: inline-block;
border: hidden;
border-radius: 10px;
background-color: var(--panelHighlight);
padding: 2px 8px;
font-size: 12px;
}
.uiInspectorId {
display: inline-block;
padding-left: 8px;
}
.uiInspectorDescription {
display: block;
font-size: 12px;
padding-top: 16px;
}
.uiInspectorPropsToggle {
background: none;
border: none;
}
</style> </style>

View File

@ -258,7 +258,7 @@ import { langs } from '@@/js/config.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js'; import { misskeyApi } from '@/scripts/misskey-api.js';
import { unisonReload } from '@/scripts/unison-reload.js'; import { reloadAsk } from '@/scripts/reload-ask.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { definePageMetadata } from '@/scripts/page-metadata.js';
import { miLocalStorage } from '@/local-storage.js'; import { miLocalStorage } from '@/local-storage.js';
@ -270,16 +270,6 @@ const fontSize = ref(miLocalStorage.getItem('fontSize'));
const useSystemFont = ref(miLocalStorage.getItem('useSystemFont') != null); const useSystemFont = ref(miLocalStorage.getItem('useSystemFont') != null);
const dataSaver = ref(defaultStore.state.dataSaver); const dataSaver = ref(defaultStore.state.dataSaver);
async function reloadAsk() {
const { canceled } = await os.confirm({
type: 'info',
text: i18n.ts.reloadToApplySetting,
});
if (canceled) return;
unisonReload();
}
const hemisphere = computed(defaultStore.makeGetterSetter('hemisphere')); const hemisphere = computed(defaultStore.makeGetterSetter('hemisphere'));
const overridedDeviceKind = computed(defaultStore.makeGetterSetter('overridedDeviceKind')); const overridedDeviceKind = computed(defaultStore.makeGetterSetter('overridedDeviceKind'));
const serverDisconnectedBehavior = computed(defaultStore.makeGetterSetter('serverDisconnectedBehavior')); const serverDisconnectedBehavior = computed(defaultStore.makeGetterSetter('serverDisconnectedBehavior'));
@ -369,7 +359,7 @@ watch([
confirmWhenRevealingSensitiveMedia, confirmWhenRevealingSensitiveMedia,
contextMenu, contextMenu,
], async () => { ], async () => {
await reloadAsk(); await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
}); });
const emojiIndexLangs = ['en-US', 'ja-JP', 'ja-JP_hira'] as const; const emojiIndexLangs = ['en-US', 'ja-JP', 'ja-JP_hira'] as const;

View File

@ -54,7 +54,7 @@ import MkContainer from '@/components/MkContainer.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { navbarItemDef } from '@/navbar.js'; import { navbarItemDef } from '@/navbar.js';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import { unisonReload } from '@/scripts/unison-reload.js'; import { reloadAsk } from '@/scripts/reload-ask.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { definePageMetadata } from '@/scripts/page-metadata.js';
@ -67,16 +67,6 @@ const items = ref(defaultStore.state.menu.map(x => ({
const menuDisplay = computed(defaultStore.makeGetterSetter('menuDisplay')); const menuDisplay = computed(defaultStore.makeGetterSetter('menuDisplay'));
async function reloadAsk() {
const { canceled } = await os.confirm({
type: 'info',
text: i18n.ts.reloadToApplySetting,
});
if (canceled) return;
unisonReload();
}
async function addItem() { async function addItem() {
const menu = Object.keys(navbarItemDef).filter(k => !defaultStore.state.menu.includes(k)); const menu = Object.keys(navbarItemDef).filter(k => !defaultStore.state.menu.includes(k));
const { canceled, result: item } = await os.select({ const { canceled, result: item } = await os.select({
@ -100,7 +90,7 @@ function removeItem(index: number) {
async function save() { async function save() {
defaultStore.set('menu', items.value.map(x => x.type)); defaultStore.set('menu', items.value.map(x => x.type));
await reloadAsk(); await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
} }
function reset() { function reset() {
@ -111,7 +101,7 @@ function reset() {
} }
watch(menuDisplay, async () => { watch(menuDisplay, async () => {
await reloadAsk(); await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
}); });
const headerActions = computed(() => []); const headerActions = computed(() => []);

View File

@ -98,7 +98,7 @@ import { defaultStore } from '@/store.js';
import { signout, signinRequired } from '@/account.js'; import { signout, signinRequired } from '@/account.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { definePageMetadata } from '@/scripts/page-metadata.js';
import { unisonReload } from '@/scripts/unison-reload.js'; import { reloadAsk } from '@/scripts/reload-ask.js';
import FormSection from '@/components/form/section.vue'; import FormSection from '@/components/form/section.vue';
const $i = signinRequired(); const $i = signinRequired();
@ -132,16 +132,6 @@ async function deleteAccount() {
await signout(); await signout();
} }
async function reloadAsk() {
const { canceled } = await os.confirm({
type: 'info',
text: i18n.ts.reloadToApplySetting,
});
if (canceled) return;
unisonReload();
}
async function updateRepliesAll(withReplies: boolean) { async function updateRepliesAll(withReplies: boolean) {
const { canceled } = await os.confirm({ const { canceled } = await os.confirm({
type: 'warning', type: 'warning',
@ -155,7 +145,7 @@ async function updateRepliesAll(withReplies: boolean) {
watch([ watch([
enableCondensedLineForAcct, enableCondensedLineForAcct,
], async () => { ], async () => {
await reloadAsk(); await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
}); });
const headerActions = computed(() => []); const headerActions = computed(() => []);

View File

@ -88,19 +88,9 @@ import { uniqueBy } from '@/scripts/array.js';
import { fetchThemes, getThemes } from '@/theme-store.js'; import { fetchThemes, getThemes } from '@/theme-store.js';
import { definePageMetadata } from '@/scripts/page-metadata.js'; import { definePageMetadata } from '@/scripts/page-metadata.js';
import { miLocalStorage } from '@/local-storage.js'; import { miLocalStorage } from '@/local-storage.js';
import { unisonReload } from '@/scripts/unison-reload.js'; import { reloadAsk } from '@/scripts/reload-ask.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
async function reloadAsk() {
const { canceled } = await os.confirm({
type: 'info',
text: i18n.ts.reloadToApplySetting,
});
if (canceled) return;
unisonReload();
}
const installedThemes = ref(getThemes()); const installedThemes = ref(getThemes());
const builtinThemes = getBuiltinThemesRef(); const builtinThemes = getBuiltinThemesRef();
@ -148,13 +138,13 @@ watch(syncDeviceDarkMode, () => {
} }
}); });
watch(wallpaper, () => { watch(wallpaper, async () => {
if (wallpaper.value == null) { if (wallpaper.value == null) {
miLocalStorage.removeItem('wallpaper'); miLocalStorage.removeItem('wallpaper');
} else { } else {
miLocalStorage.setItem('wallpaper', wallpaper.value); miLocalStorage.setItem('wallpaper', wallpaper.value);
} }
reloadAsk(); await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
}); });
onActivated(() => { onActivated(() => {

View File

@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { unisonReload } from '@/scripts/unison-reload.js';
let isReloadConfirming = false;
export async function reloadAsk(opts: {
unison?: boolean;
reason?: string;
}) {
if (isReloadConfirming) {
return;
}
isReloadConfirming = true;
const { canceled } = await os.confirm(opts.reason == null ? {
type: 'info',
text: i18n.ts.reloadConfirm,
} : {
type: 'info',
title: i18n.ts.reloadConfirm,
text: opts.reason,
}).finally(() => {
isReloadConfirming = false;
});
if (canceled) return;
if (opts.unison) {
unisonReload();
} else {
location.reload();
}
}