From 25c2007f59e1d0592e2de5911fed7bfd7f094f33 Mon Sep 17 00:00:00 2001 From: tamaina Date: Thu, 28 Aug 2025 10:39:39 +0900 Subject: [PATCH 1/5] build-misskey-js-with-types (#16470) --- 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 */ From 3e2441998107d37f9d0f683430c5dedd4c5cd0b5 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 28 Aug 2025 11:15:17 +0900 Subject: [PATCH 2/5] refactor --- packages/frontend/src/components/MkDrive.vue | 3 ++- packages/frontend/src/components/MkLaunchPad.vue | 3 ++- packages/frontend/src/components/form/suspense.vue | 2 +- packages/frontend/src/pages/about.emojis.vue | 2 +- packages/frontend/src/pages/channels.vue | 5 +++++ packages/frontend/src/pages/explore.users.vue | 13 ++++--------- .../frontend/src/pages/settings/notifications.vue | 6 +----- packages/frontend/src/ui/_common_/navbar-h.vue | 6 +++++- 8 files changed, 21 insertions(+), 19 deletions(-) diff --git a/packages/frontend/src/components/MkDrive.vue b/packages/frontend/src/components/MkDrive.vue index 83169496ff..9f1364aec4 100644 --- a/packages/frontend/src/components/MkDrive.vue +++ b/packages/frontend/src/components/MkDrive.vue @@ -152,11 +152,12 @@ import { getDriveFileMenu } from '@/utility/get-drive-file-menu.js'; import { Paginator } from '@/utility/paginator.js'; const props = withDefaults(defineProps<{ - initialFolder?: Misskey.entities.DriveFolder['id'] | null; + initialFolder?: Misskey.entities.DriveFolder | Misskey.entities.DriveFolder['id'] | null; type?: string; multiple?: boolean; select?: 'file' | 'folder' | null; }>(), { + initialFolder: null, multiple: false, select: null, }); diff --git a/packages/frontend/src/components/MkLaunchPad.vue b/packages/frontend/src/components/MkLaunchPad.vue index 584afff55c..d8725ade0b 100644 --- a/packages/frontend/src/components/MkLaunchPad.vue +++ b/packages/frontend/src/components/MkLaunchPad.vue @@ -34,9 +34,10 @@ import { deviceKind } from '@/utility/device-kind.js'; import { prefer } from '@/preferences.js'; const props = withDefaults(defineProps<{ - anchorElement?: HTMLElement; + anchorElement?: HTMLElement | null; anchor?: { x: string; y: string; }; }>(), { + anchorElement: null, anchor: () => ({ x: 'right', y: 'center' }), }); diff --git a/packages/frontend/src/components/form/suspense.vue b/packages/frontend/src/components/form/suspense.vue index 821f07510b..3b23acf612 100644 --- a/packages/frontend/src/components/form/suspense.vue +++ b/packages/frontend/src/components/form/suspense.vue @@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
diff --git a/packages/frontend/src/pages/about.emojis.vue b/packages/frontend/src/pages/about.emojis.vue index 43133bb573..7e514c5a73 100644 --- a/packages/frontend/src/pages/about.emojis.vue +++ b/packages/frontend/src/pages/about.emojis.vue @@ -48,7 +48,7 @@ import { $i } from '@/i.js'; const customEmojiTags = getCustomEmojiTags(); const q = ref(''); -const searchEmojis = ref(null); +const searchEmojis = ref(null); const selectedTags = ref(new Set()); function search() { diff --git a/packages/frontend/src/pages/channels.vue b/packages/frontend/src/pages/channels.vue index 324e0c573a..1e7301d06d 100644 --- a/packages/frontend/src/pages/channels.vue +++ b/packages/frontend/src/pages/channels.vue @@ -110,6 +110,11 @@ async function search() { const type = searchType.value.toString().trim(); + if (type !== 'nameAndDescription' && type !== 'nameOnly') { + console.error(`Unrecognized search type: ${type}`); + return; + } + channelPaginator.value = markRaw(new Paginator('channels/search', { limit: 10, params: { diff --git a/packages/frontend/src/pages/explore.users.vue b/packages/frontend/src/pages/explore.users.vue index 72f2a6813c..08f9f5e582 100644 --- a/packages/frontend/src/pages/explore.users.vue +++ b/packages/frontend/src/pages/explore.users.vue @@ -30,7 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
@@ -39,7 +39,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- + @@ -78,22 +78,17 @@ const props = defineProps<{ }>(); const origin = ref('local'); -const tagsEl = useTemplateRef('tagsEl'); const tagsLocal = ref([]); const tagsRemote = ref([]); -watch(() => props.tag, () => { - if (tagsEl.value) tagsEl.value.toggleContent(props.tag == null); -}); - -const tagUsersPaginator = markRaw(new Paginator('hashtags/users', { +const tagUsersPaginator = props.tag != null ? markRaw(new Paginator('hashtags/users', { limit: 30, params: { tag: props.tag, origin: 'combined', sort: '+follower', }, -})); +})) : null; const pinnedUsersPaginator = markRaw(new Paginator('pinned-users', { noPaging: true, diff --git a/packages/frontend/src/pages/settings/notifications.vue b/packages/frontend/src/pages/settings/notifications.vue index 2f2b57bdaf..84ecc23e84 100644 --- a/packages/frontend/src/pages/settings/notifications.vue +++ b/packages/frontend/src/pages/settings/notifications.vue @@ -55,11 +55,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
diff --git a/packages/frontend/src/ui/_common_/navbar-h.vue b/packages/frontend/src/ui/_common_/navbar-h.vue index 4f91078893..a78bdd52d1 100644 --- a/packages/frontend/src/ui/_common_/navbar-h.vue +++ b/packages/frontend/src/ui/_common_/navbar-h.vue @@ -57,6 +57,7 @@ import { i18n } from '@/i18n.js'; import { prefer } from '@/preferences.js'; import { openAccountMenu as openAccountMenu_ } from '@/accounts.js'; import { $i } from '@/i.js'; +import { getHTMLElementOrNull } from '@/utility/get-dom-node-or-null.js'; const WINDOW_THRESHOLD = 1400; @@ -72,8 +73,11 @@ const otherNavItemIndicated = computed(() => { }); async function more(ev: MouseEvent) { + const target = getHTMLElementOrNull(ev.currentTarget ?? ev.target); + if (!target) return; + const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkLaunchPad.vue').then(x => x.default), { - anchorElement: ev.currentTarget ?? ev.target, + anchorElement: target, anchor: { x: 'center', y: 'bottom' }, }, { closed: () => dispose(), From 8c2b96ad37f9e7fa5401721d30faba3e3f106732 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 28 Aug 2025 11:16:40 +0900 Subject: [PATCH 3/5] lint --- packages/backend/src/core/WebhookTestService.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/backend/src/core/WebhookTestService.ts b/packages/backend/src/core/WebhookTestService.ts index 907b5ea6be..6714bda9a9 100644 --- a/packages/backend/src/core/WebhookTestService.ts +++ b/packages/backend/src/core/WebhookTestService.ts @@ -244,7 +244,6 @@ export class WebhookTestService { case 'reaction': return; default: { - // eslint-disable-next-line @typescript-eslint/no-unused-vars const _exhaustiveAssertion: never = params.type; return; } @@ -327,7 +326,6 @@ export class WebhookTestService { break; } default: { - // eslint-disable-next-line @typescript-eslint/no-unused-vars const _exhaustiveAssertion: never = params.type; return; } @@ -412,7 +410,7 @@ export class WebhookTestService { name: user.name, username: user.username, host: user.host, - avatarUrl: user.avatarId == null ? null : user.avatarUrl, + avatarUrl: (user.avatarId == null ? null : user.avatarUrl) ?? '', avatarBlurhash: user.avatarId == null ? null : user.avatarBlurhash, avatarDecorations: user.avatarDecorations.map(it => ({ id: it.id, From ff6f1159767808b78cc8cda45d5097e387aecece Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 28 Aug 2025 11:30:03 +0900 Subject: [PATCH 4/5] refactor --- packages/backend/src/core/entities/UserEntityService.ts | 4 ++-- packages/backend/src/models/json-schema/user.ts | 4 ++-- packages/frontend/src/pages/user/index.activity.vue | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 6abf205a56..4237de7170 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -471,8 +471,8 @@ export class UserEntityService implements OnModuleInit { (profile.followersVisibility === 'followers') && (relation && relation.isFollowing) ? user.followersCount : null; - const isModerator = isMe && isDetailed ? this.roleService.isModerator(user) : null; - const isAdmin = isMe && isDetailed ? this.roleService.isAdministrator(user) : null; + const isModerator = isMe && isDetailed ? this.roleService.isModerator(user) : false; // この場合undefinedにしたい(レスポンスに含める必要がないため)が、念のため後方互換性を確保 + const isAdmin = isMe && isDetailed ? this.roleService.isAdministrator(user) : false; // この場合undefinedにしたい(レスポンスに含める必要がないため)が、念のため後方互換性を確保 const unreadAnnouncements = isMe && isDetailed ? (await this.announcementService.getUnreadAnnouncements(user)).map((announcement) => ({ createdAt: this.idService.parse(announcement.id).date.toISOString(), diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index dfefcd96f2..d4b22cc403 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -465,11 +465,11 @@ export const packedMeDetailedOnlySchema = { }, isModerator: { type: 'boolean', - nullable: true, optional: false, + nullable: false, optional: false, // optionalにしたいが念のため後方互換性を確保 }, isAdmin: { type: 'boolean', - nullable: true, optional: false, + nullable: false, optional: false, // optionalにしたいが念のため後方互換性を確保 }, injectFeaturedNote: { type: 'boolean', diff --git a/packages/frontend/src/pages/user/index.activity.vue b/packages/frontend/src/pages/user/index.activity.vue index 45bc35067b..210021618e 100644 --- a/packages/frontend/src/pages/user/index.activity.vue +++ b/packages/frontend/src/pages/user/index.activity.vue @@ -34,7 +34,7 @@ const props = withDefaults(defineProps<{ limit: 50, }); -const chartSrc = ref('per-user-notes'); +const chartSrc = ref<'per-user-notes' | 'per-user-pv'>('per-user-notes'); function showMenu(ev: MouseEvent) { os.popupMenu([{ From fc1693f768ee997253da6bbc70bbbd6ed580e216 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 28 Aug 2025 11:39:54 +0900 Subject: [PATCH 5/5] =?UTF-8?q?=E3=81=9D=E3=82=82=E3=81=9D=E3=82=82null?= =?UTF-8?q?=E3=81=AB=E3=81=AA=E3=82=8B=E3=81=93=E3=81=A8=E3=81=AF=E3=81=82?= =?UTF-8?q?=E3=82=8A=E5=BE=97=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/core/entities/UserEntityService.ts | 4 ++-- packages/backend/src/models/json-schema/user.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 4237de7170..47021359e1 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -471,8 +471,8 @@ export class UserEntityService implements OnModuleInit { (profile.followersVisibility === 'followers') && (relation && relation.isFollowing) ? user.followersCount : null; - const isModerator = isMe && isDetailed ? this.roleService.isModerator(user) : false; // この場合undefinedにしたい(レスポンスに含める必要がないため)が、念のため後方互換性を確保 - const isAdmin = isMe && isDetailed ? this.roleService.isAdministrator(user) : false; // この場合undefinedにしたい(レスポンスに含める必要がないため)が、念のため後方互換性を確保 + const isModerator = isMe && isDetailed ? this.roleService.isModerator(user) : undefined; + const isAdmin = isMe && isDetailed ? this.roleService.isAdministrator(user) : undefined; const unreadAnnouncements = isMe && isDetailed ? (await this.announcementService.getUnreadAnnouncements(user)).map((announcement) => ({ createdAt: this.idService.parse(announcement.id).date.toISOString(), diff --git a/packages/backend/src/models/json-schema/user.ts b/packages/backend/src/models/json-schema/user.ts index d4b22cc403..c507d8d5c6 100644 --- a/packages/backend/src/models/json-schema/user.ts +++ b/packages/backend/src/models/json-schema/user.ts @@ -465,11 +465,11 @@ export const packedMeDetailedOnlySchema = { }, isModerator: { type: 'boolean', - nullable: false, optional: false, // optionalにしたいが念のため後方互換性を確保 + nullable: false, optional: false, }, isAdmin: { type: 'boolean', - nullable: false, optional: false, // optionalにしたいが念のため後方互換性を確保 + nullable: false, optional: false, }, injectFeaturedNote: { type: 'boolean',