From d2fd7460ed81a3b470c8341130682e589e072884 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 00:41:11 +0900 Subject: [PATCH 01/22] Update CHANGELOG.md #16465 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71273f705a..7de981d49a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ - 既存のサーバーで当機能を有効化した場合は、処理量が多くなるため、一時的にストレージ使用量が増加する可能性があります。 - 増加量を抑えるには、最大処理継続時間をデフォルトより短くしてください。 - データベースサイズへの効果が見られない場合はautovacuumが有効になっているか確認してください + - ハイパーリンクによる参照は検知できないためリンク切れとなります。 + - 現時点では、2023-10-01以前にクリップされたリモートのノートは検知しないため削除対象となります。 - サーバーの初期設定が完了するまでは連合がオンにならないようになりました - 日本語における公開範囲名称の「ダイレクト」が「指名」に改称されました - 実際の動作に即した名称になり、馴染みのない人でも理解しやすくなりました From 2e0a34300a69805fc1c34b1212afad97caa75902 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 09:46:31 +0900 Subject: [PATCH 02/22] refactor --- packages/backend/src/core/entities/UserEntityService.ts | 1 + packages/backend/src/models/json-schema/user.ts | 2 +- packages/frontend/src/components/MkFlashPreview.vue | 2 +- packages/frontend/src/components/global/RouterView.vue | 8 +++++--- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index d4769d24d4..6abf205a56 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -481,6 +481,7 @@ export class UserEntityService implements OnModuleInit { const notificationsInfo = isMe && isDetailed ? await this.getNotificationsInfo(user.id) : null; + // TODO: 例えば avatarUrl: true など間違った型を設定しても型エラーにならないのをどうにかする(ジェネリクス使わない方法で実装するしかなさそう?) const packed = { id: user.id, name: user.name, diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index 2b5f706ff9..9c88a078c0 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -65,7 +65,7 @@ export const packedUserLiteSchema = { avatarUrl: { type: 'string', format: 'url', - nullable: true, optional: false, + nullable: false, optional: false, }, avatarBlurhash: { type: 'string', diff --git a/packages/frontend/src/components/MkFlashPreview.vue b/packages/frontend/src/components/MkFlashPreview.vue index f8f6143a7c..b7278ac742 100644 --- a/packages/frontend/src/components/MkFlashPreview.vue +++ b/packages/frontend/src/components/MkFlashPreview.vue @@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only

diff --git a/packages/frontend/src/components/global/RouterView.vue b/packages/frontend/src/components/global/RouterView.vue index 27f7b18559..3a508eaca0 100644 --- a/packages/frontend/src/components/global/RouterView.vue +++ b/packages/frontend/src/components/global/RouterView.vue @@ -30,19 +30,21 @@ const props = defineProps<{ router?: Router; }>(); -const router = props.router ?? inject(DI.router); +const _router = props.router ?? inject(DI.router); -if (router == null) { +if (_router == null) { throw new Error('no router provided'); } +const router = _router; + const viewId = randomId(); provide(DI.viewId, viewId); const currentDepth = inject(DI.routerCurrentDepth, 0); provide(DI.routerCurrentDepth, currentDepth + 1); -const current = router.current!; +const current = router.current; const currentPageComponent = shallowRef('component' in current.route ? current.route.component : MkLoadingPage); const currentPageProps = ref(current.props); let currentRoutePath = current.route.path; From 231ccae006c607ff457522f5a6b2087b0a1eece3 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 09:57:33 +0900 Subject: [PATCH 03/22] tweak locale --- locales/index.d.ts | 6 +++--- locales/ja-JP.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index c078f4ece3..3ec4e2b241 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -12032,15 +12032,15 @@ export interface Locale extends ILocale { */ "youCanConfigureMoreFederationSettingsLater": string; /** - * 受信コンテンツの自動クリーニング + * リモートコンテンツの自動クリーニング */ "remoteContentsCleaning": string; /** - * 連合を行うと、継続して多くのコンテンツを受信します。自動クリーニングを有効にすると、参照されていない古くなったコンテンツを自動でサーバーから削除し、ストレージを節約できます。 + * 連合を行うと、継続して多くのコンテンツを受信します。自動クリーニングを有効にすると、参照されていない古くなったリモートコンテンツを自動でサーバーから削除し、ストレージを節約できます。 */ "remoteContentsCleaning_description": string; /** - * ハイパーリンクなど、一部の参照方法はシステム上で検知できません。 + * ローカル内リモートコンテンツへのハイパーリンクはリンク切れとなります。 */ "remoteContentsCleaning_description2": string; /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index f24b93d139..0043386ad9 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -3216,9 +3216,9 @@ _serverSetupWizard: doYouConnectToFediverse_description1: "分散型サーバーで構成されるネットワーク(Fediverse)に接続すると、他のサーバーと相互にコンテンツのやり取りが可能です。" doYouConnectToFediverse_description2: "Fediverseと接続することは「連合」とも呼ばれます。" youCanConfigureMoreFederationSettingsLater: "連合可能なサーバーの指定など、高度な設定も後ほど可能です。" - remoteContentsCleaning: "受信コンテンツの自動クリーニング" - remoteContentsCleaning_description: "連合を行うと、継続して多くのコンテンツを受信します。自動クリーニングを有効にすると、参照されていない古くなったコンテンツを自動でサーバーから削除し、ストレージを節約できます。" - remoteContentsCleaning_description2: "ハイパーリンクなど、一部の参照方法はシステム上で検知できません。" + remoteContentsCleaning: "リモートコンテンツの自動クリーニング" + remoteContentsCleaning_description: "連合を行うと、継続して多くのコンテンツを受信します。自動クリーニングを有効にすると、参照されていない古くなったリモートコンテンツを自動でサーバーから削除し、ストレージを節約できます。" + remoteContentsCleaning_description2: "ローカル内リモートコンテンツへのハイパーリンクはリンク切れとなります。" adminInfo: "管理者情報" adminInfo_description: "問い合わせを受け付けるために使用される管理者情報を設定します。" adminInfo_mustBeFilled: "オープンサーバー、または連合がオンの場合は必ず入力が必要です。" From 25df56dfd0b97acfb4d6c76c9154f560f56ab150 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:14:17 +0900 Subject: [PATCH 04/22] refactor --- .../frontend/src/components/MkMediaList.vue | 2 ++ .../frontend/src/components/MkPageWindow.vue | 31 ++++++++----------- .../src/components/MkRoleSelectDialog.vue | 4 +-- .../src/pages/settings/plugin.install.vue | 2 +- .../src/pages/welcome.entrance.classic.vue | 2 +- .../frontend/src/utility/extract-mentions.ts | 2 +- 6 files changed, 19 insertions(+), 24 deletions(-) diff --git a/packages/frontend/src/components/MkMediaList.vue b/packages/frontend/src/components/MkMediaList.vue index 4a1100c324..bfc8179e13 100644 --- a/packages/frontend/src/components/MkMediaList.vue +++ b/packages/frontend/src/components/MkMediaList.vue @@ -94,6 +94,8 @@ async function calcAspectRatio() { onMounted(() => { calcAspectRatio(); + if (gallery.value == null) return; // TSを黙らすため + lightbox = new PhotoSwipeLightbox({ dataSource: props.mediaList .filter(media => { diff --git a/packages/frontend/src/components/MkPageWindow.vue b/packages/frontend/src/components/MkPageWindow.vue index cf60c1ca3e..d21e09a984 100644 --- a/packages/frontend/src/components/MkPageWindow.vue +++ b/packages/frontend/src/components/MkPageWindow.vue @@ -23,8 +23,8 @@ SPDX-License-Identifier: AGPL-3.0-only
- - + +
@@ -58,20 +58,15 @@ const windowRouter = createRouter(props.initialPath); const pageMetadata = ref(null); const windowEl = useTemplateRef('windowEl'); -const history = ref<{ path: string; }[]>([{ +const _history_ = ref<{ path: string; }[]>([{ path: windowRouter.getCurrentFullPath(), }]); const buttonsLeft = computed(() => { - const buttons: Record[] = []; - - if (history.value.length > 1) { - buttons.push({ - icon: 'ti ti-arrow-left', - onClick: back, - }); - } - - return buttons; + return _history_.value.length > 1 ? [{ + icon: 'ti ti-arrow-left', + title: i18n.ts.goBack, + onClick: back, + }] : []; }); const buttonsRight = computed(() => { const buttons = [{ @@ -97,12 +92,12 @@ function getSearchMarker(path: string) { const searchMarkerId = ref(getSearchMarker(props.initialPath)); windowRouter.addListener('push', ctx => { - history.value.push({ path: ctx.fullPath }); + _history_.value.push({ path: ctx.fullPath }); }); windowRouter.addListener('replace', ctx => { - history.value.pop(); - history.value.push({ path: ctx.fullPath }); + _history_.value.pop(); + _history_.value.push({ path: ctx.fullPath }); }); windowRouter.addListener('change', ctx => { @@ -150,8 +145,8 @@ const contextmenu = computed(() => ([{ }])); function back() { - history.value.pop(); - windowRouter.replaceByPath(history.value.at(-1)!.path); + _history_.value.pop(); + windowRouter.replaceByPath(_history_.value.at(-1)!.path); } function reload() { diff --git a/packages/frontend/src/components/MkRoleSelectDialog.vue b/packages/frontend/src/components/MkRoleSelectDialog.vue index fc7ba50fb3..f1cc98def4 100644 --- a/packages/frontend/src/components/MkRoleSelectDialog.vue +++ b/packages/frontend/src/components/MkRoleSelectDialog.vue @@ -105,9 +105,7 @@ async function addRole() { .map(r => ({ text: r.name, value: r })); const { canceled, result: role } = await os.select({ items }); - if (canceled) { - return; - } + if (canceled || role == null) return; selectedRoleIds.value.push(role.id); } diff --git a/packages/frontend/src/pages/settings/plugin.install.vue b/packages/frontend/src/pages/settings/plugin.install.vue index 22b53b4b96..8ed7f2a7b6 100644 --- a/packages/frontend/src/pages/settings/plugin.install.vue +++ b/packages/frontend/src/pages/settings/plugin.install.vue @@ -40,7 +40,7 @@ async function install() { code.value = null; router.push('/settings/plugin'); - } catch (err) { + } catch (err: any) { os.alert({ type: 'error', title: 'Install failed', diff --git a/packages/frontend/src/pages/welcome.entrance.classic.vue b/packages/frontend/src/pages/welcome.entrance.classic.vue index c2cf937c71..cddec3332e 100644 --- a/packages/frontend/src/pages/welcome.entrance.classic.vue +++ b/packages/frontend/src/pages/welcome.entrance.classic.vue @@ -53,7 +53,7 @@ function getInstanceIcon(instance: Misskey.entities.FederationInstance): string misskeyApiGet('federation/instances', { sort: '+pubSub', limit: 20, - blocked: 'false', + blocked: false, }).then(_instances => { instances.value = _instances; }); diff --git a/packages/frontend/src/utility/extract-mentions.ts b/packages/frontend/src/utility/extract-mentions.ts index d518562053..2ec9349718 100644 --- a/packages/frontend/src/utility/extract-mentions.ts +++ b/packages/frontend/src/utility/extract-mentions.ts @@ -9,7 +9,7 @@ import * as mfm from 'mfm-js'; export function extractMentions(nodes: mfm.MfmNode[]): mfm.MfmMention['props'][] { // TODO: 重複を削除 - const mentionNodes = mfm.extract(nodes, (node) => node.type === 'mention'); + const mentionNodes = mfm.extract(nodes, (node) => node.type === 'mention') as mfm.MfmMention[]; const mentions = mentionNodes.map(x => x.props); return mentions; From 3e9118af3dc84d4842d7ef9f1a36053d30e97ba8 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:15:11 +0900 Subject: [PATCH 05/22] =?UTF-8?q?fix(frontend):=20lookup=E3=83=9A=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=A7=E3=83=AA=E3=83=A2=E3=83=BC=E3=83=88URL?= =?UTF-8?q?=E3=82=92=E6=8C=87=E5=AE=9A=E3=81=97=E3=81=9F=E9=9A=9B=E3=81=AB?= =?UTF-8?q?=E6=AD=A3=E3=81=97=E3=81=8F=E5=8B=95=E4=BD=9C=E3=81=97=E3=81=AA?= =?UTF-8?q?=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + packages/frontend/src/pages/lookup.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de981d49a..ddd6c86f80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,7 @@ - Fix: 照会ダイアログでap/showでローカルユーザーを解決した際@username@nullに飛ばされる問題を修正 - Fix: アイコンのデコレーションを付ける際にデコレーションが表示されなくなる問題を修正 - Fix: 管理中アカウント一覧で正しい表示が行われない問題を修正 +- Fix: lookupページでリモートURLを指定した際に正しく動作しない問題を修正 ### Server - Feat: サーバー管理コマンド diff --git a/packages/frontend/src/pages/lookup.vue b/packages/frontend/src/pages/lookup.vue index 8a1e952d85..182b2f703d 100644 --- a/packages/frontend/src/pages/lookup.vue +++ b/packages/frontend/src/pages/lookup.vue @@ -48,7 +48,7 @@ function _fetch_() { if (res.type === 'User') { mainRouter.replace('/@:acct/:page?', { params: { - acct: res.host != null ? `${res.object.username}@${res.object.host}` : res.object.username, + acct: res.object.host != null ? `${res.object.username}@${res.object.host}` : res.object.username, }, }); } else if (res.type === 'Note') { From aa8daca914c663c1bb923bc31d3ae60485a25220 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:23:41 +0900 Subject: [PATCH 06/22] chore(frontend): skip typecheck for auto-generated files --- packages/frontend/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index c445ada034..662dc6ed4e 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -55,6 +55,7 @@ "./@types/**/*.ts" ], "exclude": [ - ".storybook/**/*" + ".storybook/**/*", + "./src/**/*.stories.ts" ] } From 55eb18f5a6aa1cb12f8e1c401656253fa1b09068 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:29:45 +0900 Subject: [PATCH 07/22] Update CHANGELOG.md --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddd6c86f80..c1be9ba1f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,8 @@ - サーバーの初期設定が完了するまでは連合がオンにならないようになりました - 日本語における公開範囲名称の「ダイレクト」が「指名」に改称されました - 実際の動作に即した名称になり、馴染みのない人でも理解しやすくなりました - - 他サービスにおける「ダイレクトメッセージ」に相当するMisskeyの機能は「チャット」ですが、「ダイレクト投稿」という名称の機能が存在するとそちらがダイレクトメッセージ機能であるような誤解を生んでいました + - 他サービスにおける「ダイレクトメッセージ」に相当するMisskeyの機能は「チャット」ですが(過去のバージョンのMisskeyでも、当該機能は「チャット」ではなく「ダイレクトメッセージ」でした)、「ダイレクト投稿」という名称の機能が存在するとそちらがダイレクトメッセージ機能であるような誤解を生んでいました + - 今後、「チャット」の名称を「ダイレクトメッセージ」に戻す可能性があります - mfm.jsをアップデートしました - Enhance: Unicode 15.1 および 16.0 に収録されている絵文字に対応 - Enhance: acctに `.` が入っているユーザーのメンションに対応 @@ -29,6 +30,7 @@ - プラグインは1.xに対応したものが必要です - Playはそのまま動作しますが、新規に作られるプリセットは1.xになります - 以前のバージョンから無効化されていた note_view_interruptor が有効になりました + - ハンドラは同期的である必要があります - Feat: セーフモード - プラグイン・テーマ・カスタムCSSの使用でクライアントの起動に問題が発生した際に、これらを無効にして起動できます - 以下の方法でセーフモードを起動できます From ee96f77ef28466a71f24c46edbea6a4f687834ca Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:09:19 +0900 Subject: [PATCH 08/22] refactor --- packages/frontend/lib/vite-plugin-create-search-index.ts | 2 +- .../src/components/global/MkPageHeader.stories.impl.ts | 4 +++- packages/frontend/src/ui/_common_/statusbar-federation.vue | 2 +- packages/frontend/test/home.test.ts | 2 +- packages/frontend/test/note.test.ts | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/frontend/lib/vite-plugin-create-search-index.ts b/packages/frontend/lib/vite-plugin-create-search-index.ts index 4e20828909..f17b43b0e3 100644 --- a/packages/frontend/lib/vite-plugin-create-search-index.ts +++ b/packages/frontend/lib/vite-plugin-create-search-index.ts @@ -8,7 +8,7 @@ import { parse as vueSfcParse } from 'vue/compiler-sfc'; import { createLogger, - EnvironmentModuleGraph, + type EnvironmentModuleGraph, type LogErrorOptions, type LogOptions, normalizePath, diff --git a/packages/frontend/src/components/global/MkPageHeader.stories.impl.ts b/packages/frontend/src/components/global/MkPageHeader.stories.impl.ts index 15938d0495..0ac6304054 100644 --- a/packages/frontend/src/components/global/MkPageHeader.stories.impl.ts +++ b/packages/frontend/src/components/global/MkPageHeader.stories.impl.ts @@ -2,7 +2,7 @@ * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ - + import { waitFor } from '@storybook/test'; import MkPageHeader from './MkPageHeader.vue'; import type { StoryObj } from '@storybook/vue3'; @@ -59,6 +59,7 @@ export const Icon = { { ...OneTab.args.tabs[0], icon: 'ti ti-home', + title: 'Home', }, ], }, @@ -71,6 +72,7 @@ export const IconOnly = { { key: Icon.args.tabs[0].key, icon: Icon.args.tabs[0].icon, + title: Icon.args.tabs[0].title, iconOnly: true, }, ], diff --git a/packages/frontend/src/ui/_common_/statusbar-federation.vue b/packages/frontend/src/ui/_common_/statusbar-federation.vue index c79f690cff..079f1f92bb 100644 --- a/packages/frontend/src/ui/_common_/statusbar-federation.vue +++ b/packages/frontend/src/ui/_common_/statusbar-federation.vue @@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only mode="default" > - + {{ instance.host }} diff --git a/packages/frontend/test/home.test.ts b/packages/frontend/test/home.test.ts index a67ea40176..f3fa89d6ae 100644 --- a/packages/frontend/test/home.test.ts +++ b/packages/frontend/test/home.test.ts @@ -15,7 +15,7 @@ import 'intersection-observer'; describe('XHome', () => { const renderHome = (user: Partial): RenderResult => { return render(XHome, { - props: { user, disableNotes: true }, + props: { user: user as Misskey.entities.UserDetailed, disableNotes: true }, global: { directives, components }, }); }; diff --git a/packages/frontend/test/note.test.ts b/packages/frontend/test/note.test.ts index fda2d9ad7b..2d5d2712d6 100644 --- a/packages/frontend/test/note.test.ts +++ b/packages/frontend/test/note.test.ts @@ -29,7 +29,7 @@ describe('MkMediaImage', () => { comment: null, properties: {}, ...image, - } as DriveFile, + } as Misskey.entities.DriveFile, }, global: { directives, components }, }); From c5bb88143850fb0544054d67e505171674887e8c Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:40:11 +0900 Subject: [PATCH 09/22] refactor --- packages/frontend/src/aiscript/ui.ts | 8 +++----- packages/frontend/src/pages/scratchpad.vue | 10 ++++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/frontend/src/aiscript/ui.ts b/packages/frontend/src/aiscript/ui.ts index a27ece512e..9c330da3c5 100644 --- a/packages/frontend/src/aiscript/ui.ts +++ b/packages/frontend/src/aiscript/ui.ts @@ -4,11 +4,11 @@ */ import { utils, values } from '@syuilo/aiscript'; -import { genId } from '@/utility/id.js'; import { ref } from 'vue'; -import type { Ref } from 'vue'; import * as Misskey from 'misskey-js'; import { assertStringAndIsIn } from './common.js'; +import type { Ref } from 'vue'; +import { genId } from '@/utility/id.js'; const ALIGNS = ['left', 'center', 'right'] as const; const FONTS = ['serif', 'sans-serif', 'monospace'] as const; @@ -21,16 +21,15 @@ type BorderStyle = (typeof BORDER_STYLES)[number]; export type AsUiComponentBase = { id: string; hidden?: boolean; + children?: AsUiComponent['id'][]; }; export type AsUiRoot = AsUiComponentBase & { type: 'root'; - children: AsUiComponent['id'][]; }; export type AsUiContainer = AsUiComponentBase & { type: 'container'; - children?: AsUiComponent['id'][]; align?: Align; bgColor?: string; fgColor?: string; @@ -123,7 +122,6 @@ export type AsUiSelect = AsUiComponentBase & { export type AsUiFolder = AsUiComponentBase & { type: 'folder'; - children?: AsUiComponent['id'][]; title?: string; opened?: boolean; }; diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue index 751a67190a..7fb64c2947 100644 --- a/packages/frontend/src/pages/scratchpad.vue +++ b/packages/frontend/src/pages/scratchpad.vue @@ -82,10 +82,10 @@ const logs = ref<{ text: string; print: boolean; }[]>([]); -const root = ref(); +const root = ref(); const components = ref[]>([]); const uiKey = ref(0); -const uiInspectorOpenedComponents = ref(new Map); +const uiInspectorOpenedComponents = ref(new Map, boolean>); const saved = miLocalStorage.getItem('scratchpad'); if (saved) { @@ -186,11 +186,13 @@ const headerActions = computed(() => []); const headerTabs = computed(() => []); const showns = computed(() => { + if (root.value == null) return new Set(); const result = new Set(); (function addChildrenToResult(c: AsUiComponent) { result.add(c.id); - if (c.children) { - const childComponents = components.value.filter(v => c.children.includes(v.value.id)); + const children = c.children; + if (children) { + const childComponents = components.value.filter(v => children.includes(v.value.id)); for (const child of childComponents) { addChildrenToResult(child.value); } From 98e07c3bd113306496920f7ceafe91228228b22f Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 12:41:24 +0900 Subject: [PATCH 10/22] perf(frontend): use WeakMap --- packages/frontend/src/pages/scratchpad.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/scratchpad.vue b/packages/frontend/src/pages/scratchpad.vue index 7fb64c2947..d73363d058 100644 --- a/packages/frontend/src/pages/scratchpad.vue +++ b/packages/frontend/src/pages/scratchpad.vue @@ -85,7 +85,7 @@ const logs = ref<{ const root = ref(); const components = ref[]>([]); const uiKey = ref(0); -const uiInspectorOpenedComponents = ref(new Map, boolean>); +const uiInspectorOpenedComponents = ref(new WeakMap, boolean>); const saved = miLocalStorage.getItem('scratchpad'); if (saved) { From 87d09f255dd702627bbc6fa58692eebba3830889 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 15:59:39 +0900 Subject: [PATCH 11/22] refactor --- packages/backend/src/misc/json-schema.ts | 2 + .../src/models/json-schema/user-webhook.ts | 55 +++++++++++++++++++ .../server/api/endpoints/i/webhooks/list.ts | 48 ++++------------ .../server/api/endpoints/i/webhooks/show.ts | 24 +------- .../frontend/src/pages/settings/navbar.vue | 2 +- 5 files changed, 71 insertions(+), 60 deletions(-) create mode 100644 packages/backend/src/models/json-schema/user-webhook.ts diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index dca92e1037..ed7d5bfc3a 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -65,6 +65,7 @@ import { packedMetaDetailedSchema, packedMetaLiteSchema, } from '@/models/json-schema/meta.js'; +import { packedUserWebhookSchema } from '@/models/json-schema/user-webhook.js'; import { packedSystemWebhookSchema } from '@/models/json-schema/system-webhook.js'; import { packedAbuseReportNotificationRecipientSchema } from '@/models/json-schema/abuse-report-notification-recipient.js'; import { packedChatMessageSchema, packedChatMessageLiteSchema, packedChatMessageLiteForRoomSchema, packedChatMessageLiteFor1on1Schema } from '@/models/json-schema/chat-message.js'; @@ -134,6 +135,7 @@ export const refs = { MetaLite: packedMetaLiteSchema, MetaDetailedOnly: packedMetaDetailedOnlySchema, MetaDetailed: packedMetaDetailedSchema, + UserWebhook: packedUserWebhookSchema, SystemWebhook: packedSystemWebhookSchema, AbuseReportNotificationRecipient: packedAbuseReportNotificationRecipientSchema, ChatMessage: packedChatMessageSchema, diff --git a/packages/backend/src/models/json-schema/user-webhook.ts b/packages/backend/src/models/json-schema/user-webhook.ts new file mode 100644 index 0000000000..8ea0991716 --- /dev/null +++ b/packages/backend/src/models/json-schema/user-webhook.ts @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { webhookEventTypes } from '@/models/Webhook.js'; + +export const packedUserWebhookSchema = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'id', + optional: false, nullable: false, + }, + userId: { + type: 'string', + format: 'id', + optional: false, nullable: false, + }, + name: { + type: 'string', + optional: false, nullable: false, + }, + on: { + type: 'array', + items: { + type: 'string', + optional: false, nullable: false, + enum: webhookEventTypes, + }, + }, + url: { + type: 'string', + optional: false, nullable: false, + }, + secret: { + type: 'string', + optional: false, nullable: false, + }, + active: { + type: 'boolean', + optional: false, nullable: false, + }, + latestSentAt: { + type: 'string', + format: 'date-time', + optional: false, nullable: true, + }, + latestStatus: { + type: 'integer', + optional: false, nullable: true, + }, + }, +} as const; diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/list.ts b/packages/backend/src/server/api/endpoints/i/webhooks/list.ts index 394c178f2a..8a3ba9e026 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/list.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/list.ts @@ -21,29 +21,7 @@ export const meta = { type: 'array', items: { type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - userId: { - type: 'string', - format: 'misskey:id', - }, - name: { type: 'string' }, - on: { - type: 'array', - items: { - type: 'string', - enum: webhookEventTypes, - }, - }, - url: { type: 'string' }, - secret: { type: 'string' }, - active: { type: 'boolean' }, - latestSentAt: { type: 'string', format: 'date-time', nullable: true }, - latestStatus: { type: 'integer', nullable: true }, - }, + ref: 'UserWebhook', }, }, } as const; @@ -65,19 +43,17 @@ export default class extends Endpoint { // eslint- userId: me.id, }); - return webhooks.map(webhook => ( - { - id: webhook.id, - userId: webhook.userId, - name: webhook.name, - on: webhook.on, - url: webhook.url, - secret: webhook.secret, - active: webhook.active, - latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null, - latestStatus: webhook.latestStatus, - } - )); + return webhooks.map(webhook => ({ + id: webhook.id, + userId: webhook.userId, + name: webhook.name, + on: webhook.on, + url: webhook.url, + secret: webhook.secret, + active: webhook.active, + latestSentAt: webhook.latestSentAt ? webhook.latestSentAt.toISOString() : null, + latestStatus: webhook.latestStatus, + })); }); } } diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts index 4a0c09ff0c..1c19081c98 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts @@ -28,29 +28,7 @@ export const meta = { res: { type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - userId: { - type: 'string', - format: 'misskey:id', - }, - name: { type: 'string' }, - on: { - type: 'array', - items: { - type: 'string', - enum: webhookEventTypes, - }, - }, - url: { type: 'string' }, - secret: { type: 'string' }, - active: { type: 'boolean' }, - latestSentAt: { type: 'string', format: 'date-time', nullable: true }, - latestStatus: { type: 'integer', nullable: true }, - }, + ref: 'UserWebhook', }, } as const; diff --git a/packages/frontend/src/pages/settings/navbar.vue b/packages/frontend/src/pages/settings/navbar.vue index 09c1199d0c..f7c634b42e 100644 --- a/packages/frontend/src/pages/settings/navbar.vue +++ b/packages/frontend/src/pages/settings/navbar.vue @@ -91,7 +91,7 @@ async function addItem() { value: '-', text: i18n.ts.divider, }], }); - if (canceled) return; + if (canceled || item == null) return; items.value = [...items.value, { id: genId(), type: item, From bf82b4963357161df2b310ec40992636c54d90b9 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 16:27:16 +0900 Subject: [PATCH 12/22] refactor --- packages/frontend/src/pages/emoji-edit-dialog.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue index b4fc4a46d9..201ce003f0 100644 --- a/packages/frontend/src/pages/emoji-edit-dialog.vue +++ b/packages/frontend/src/pages/emoji-edit-dialog.vue @@ -156,12 +156,9 @@ async function done() { isSensitive: isSensitive.value, localOnly: localOnly.value, roleIdsThatCanBeUsedThisEmojiAsReaction: rolesThatCanBeUsedThisEmojiAsReaction.value.map(x => x.id), + fileId: file.value ? file.value.id : undefined, }; - if (file.value) { - params.fileId = file.value.id; - } - if (props.emoji) { await os.apiWithDialog('admin/emoji/update', { id: props.emoji.id, @@ -177,7 +174,12 @@ async function done() { windowEl.value?.close(); } else { - const created = await os.apiWithDialog('admin/emoji/add', params); + if (params.fileId == null) return; + + const created = await os.apiWithDialog('admin/emoji/add', { + ...params, + fileId: params.fileId, // TSを黙らすため + }); emit('done', { created: created, From 575379a6838ef71fa0a5bd52d81308bc5f8426a8 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 27 Aug 2025 16:48:32 +0900 Subject: [PATCH 13/22] refactor --- packages/frontend/src/components/MkWidgets.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/MkWidgets.vue b/packages/frontend/src/components/MkWidgets.vue index f606b0b001..08a018ea9b 100644 --- a/packages/frontend/src/components/MkWidgets.vue +++ b/packages/frontend/src/components/MkWidgets.vue @@ -51,6 +51,7 @@ export type DefaultStoredWidget = { diff --git a/packages/frontend/src/utility/drive.ts b/packages/frontend/src/utility/drive.ts index 5ff066f61b..fb2825e7f7 100644 --- a/packages/frontend/src/utility/drive.ts +++ b/packages/frontend/src/utility/drive.ts @@ -300,15 +300,13 @@ export async function createCroppedImageDriveFileFromImageDriveFile(imageDriveFi }); } -export async function selectDriveFolder(initialFolder: Misskey.entities.DriveFolder['id'] | null): Promise { +export async function selectDriveFolder(initialFolder: Misskey.entities.DriveFolder['id'] | null): Promise<(Misskey.entities.DriveFolder | null)[]> { return new Promise(async resolve => { const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkDriveFolderSelectDialog.vue').then(x => x.default), { initialFolder, }, { done: folders => { - if (folders) { - resolve(folders); - } + resolve(folders); }, closed: () => dispose(), }); From 3bf39a5c99d9eab087632b2d0395c59ed969c5a2 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 28 Aug 2025 10:38:41 +0900 Subject: [PATCH 22/22] build-misskey-js-with-types --- packages/misskey-js/src/autogen/types.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index be24e3ec5f..908a9289f3 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -9329,8 +9329,10 @@ export interface operations { mcaptchaSecretKey: string | null; recaptchaSecretKey: string | null; turnstileSecretKey: string | null; - sensitiveMediaDetection: string; - sensitiveMediaDetectionSensitivity: string; + /** @enum {string} */ + sensitiveMediaDetection: 'none' | 'all' | 'local' | 'remote'; + /** @enum {string} */ + sensitiveMediaDetectionSensitivity: 'medium' | 'low' | 'high' | 'veryLow' | 'veryHigh'; setSensitiveFlagAutomatically: boolean; enableSensitiveMediaDetectionForVideos: boolean; /** Format: id */