From b941c896aa5512240de9121a1850d55aa5f8b68b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:02:50 +0900 Subject: [PATCH] =?UTF-8?q?refactor(frontend):=20MkRadios=E3=81=AE?= =?UTF-8?q?=E6=8C=87=E5=AE=9A=E3=82=92props=E3=81=8B=E3=82=89=E8=A1=8C?= =?UTF-8?q?=E3=81=86=E3=82=88=E3=81=86=E3=81=AB=20(#16597)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(frontend): MkRadiosの指定をpropsから行うように * spdx * fix lint * fix: mkradiosを動的slotsに対応させる * fix: remove comment [ci skip] * fix lint * fix lint * migrate * rename * fix * fix * fix types * remove unused imports * fix * wip --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- .../core/entities/ReversiGameEntityService.ts | 8 +- .../src/models/json-schema/reversi-game.ts | 2 + packages/frontend/src/components/MkDialog.vue | 3 +- packages/frontend/src/components/MkForm.vue | 14 +- .../src/components/MkImageEffectorFxForm.vue | 6 +- packages/frontend/src/components/MkMenu.vue | 15 +- packages/frontend/src/components/MkRadio.vue | 6 +- packages/frontend/src/components/MkRadios.vue | 197 ++++++++++-------- packages/frontend/src/components/MkSelect.vue | 2 +- .../src/components/MkServerSetupWizard.vue | 52 +++-- .../MkUserAnnouncementEditDialog.vue | 26 ++- .../frontend/src/composables/use-mkselect.ts | 3 +- packages/frontend/src/os.ts | 3 +- packages/frontend/src/pages/admin/ads.vue | 24 ++- .../src/pages/admin/announcements.vue | 26 ++- .../src/pages/admin/bot-protection.vue | 18 +- .../frontend/src/pages/admin/branding.vue | 10 +- .../frontend/src/pages/admin/security.vue | 14 +- .../frontend/src/pages/admin/settings.vue | 12 +- packages/frontend/src/pages/channels.vue | 17 +- .../src/pages/reversi/game.setting.vue | 45 ++-- packages/frontend/src/pages/search.note.vue | 28 ++- packages/frontend/src/pages/search.user.vue | 14 +- packages/frontend/src/pages/settings/deck.vue | 32 ++- .../src/pages/settings/emoji-palette.vue | 53 +++-- .../frontend/src/pages/settings/navbar.vue | 10 +- .../src/pages/settings/preferences.vue | 102 +++++---- .../pages/settings/statusbar.statusbar.vue | 16 +- packages/frontend/src/preferences/def.ts | 4 +- packages/frontend/src/store.ts | 4 +- packages/frontend/src/types/menu.ts | 3 +- packages/frontend/src/types/option-value.ts | 6 + packages/frontend/src/utility/form.ts | 8 +- packages/misskey-js/src/autogen/types.ts | 6 +- 34 files changed, 505 insertions(+), 284 deletions(-) create mode 100644 packages/frontend/src/types/option-value.ts diff --git a/packages/backend/src/core/entities/ReversiGameEntityService.ts b/packages/backend/src/core/entities/ReversiGameEntityService.ts index df042e75c1..21099bad3e 100644 --- a/packages/backend/src/core/entities/ReversiGameEntityService.ts +++ b/packages/backend/src/core/entities/ReversiGameEntityService.ts @@ -14,6 +14,10 @@ import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; import { UserEntityService } from './UserEntityService.js'; +function assertBw(bw: string): bw is Packed<'ReversiGameDetailed'>['bw'] { + return ['random', '1', '2'].includes(bw); +} + @Injectable() export class ReversiGameEntityService { constructor( @@ -58,7 +62,7 @@ export class ReversiGameEntityService { surrenderedUserId: game.surrenderedUserId, timeoutUserId: game.timeoutUserId, black: game.black, - bw: game.bw, + bw: assertBw(game.bw) ? game.bw : 'random', isLlotheo: game.isLlotheo, canPutEverywhere: game.canPutEverywhere, loopedBoard: game.loopedBoard, @@ -116,7 +120,7 @@ export class ReversiGameEntityService { surrenderedUserId: game.surrenderedUserId, timeoutUserId: game.timeoutUserId, black: game.black, - bw: game.bw, + bw: assertBw(game.bw) ? game.bw : 'random', isLlotheo: game.isLlotheo, canPutEverywhere: game.canPutEverywhere, loopedBoard: game.loopedBoard, diff --git a/packages/backend/src/models/json-schema/reversi-game.ts b/packages/backend/src/models/json-schema/reversi-game.ts index cb37200384..378ae41cb5 100644 --- a/packages/backend/src/models/json-schema/reversi-game.ts +++ b/packages/backend/src/models/json-schema/reversi-game.ts @@ -81,6 +81,7 @@ export const packedReversiGameLiteSchema = { bw: { type: 'string', optional: false, nullable: false, + enum: ['random', '1', '2'], }, noIrregularRules: { type: 'boolean', @@ -199,6 +200,7 @@ export const packedReversiGameDetailedSchema = { bw: { type: 'string', optional: false, nullable: false, + enum: ['random', '1', '2'], }, noIrregularRules: { type: 'boolean', diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue index bea0392d2d..4801b412f8 100644 --- a/packages/frontend/src/components/MkDialog.vue +++ b/packages/frontend/src/components/MkDialog.vue @@ -52,7 +52,8 @@ import MkModal from '@/components/MkModal.vue'; import MkButton from '@/components/MkButton.vue'; import MkInput from '@/components/MkInput.vue'; import MkSelect from '@/components/MkSelect.vue'; -import type { MkSelectItem, OptionValue } from '@/components/MkSelect.vue'; +import type { MkSelectItem } from '@/components/MkSelect.vue'; +import type { OptionValue } from '@/types/option-value.js'; import { useMkSelect } from '@/composables/use-mkselect.js'; import { i18n } from '@/i18n.js'; diff --git a/packages/frontend/src/components/MkForm.vue b/packages/frontend/src/components/MkForm.vue index 3d4724e6b7..1ece0ad4c3 100644 --- a/packages/frontend/src/components/MkForm.vue +++ b/packages/frontend/src/components/MkForm.vue @@ -26,9 +26,8 @@ SPDX-License-Identifier: AGPL-3.0-only - + - @@ -60,6 +59,7 @@ import MkButton from '@/components/MkButton.vue'; import MkRadios from '@/components/MkRadios.vue'; import { i18n } from '@/i18n.js'; import type { MkSelectItem } from '@/components/MkSelect.vue'; +import type { MkRadiosOption } from '@/components/MkRadios.vue'; import type { Form, EnumFormItem, RadioFormItem } from '@/utility/form.js'; const props = defineProps<{ @@ -113,7 +113,13 @@ function getMkSelectDef(def: EnumFormItem): MkSelectItem[] { }); } -function getRadioKey(e: RadioFormItem['options'][number]) { - return typeof e.value === 'string' ? e.value : JSON.stringify(e.value); +function getRadioOptionsDef(def: RadioFormItem): MkRadiosOption[] { + return def.options.map((v) => { + if (typeof v === 'string') { + return { value: v, label: v }; + } else { + return { value: v.value, label: v.label }; + } + }); } diff --git a/packages/frontend/src/components/MkImageEffectorFxForm.vue b/packages/frontend/src/components/MkImageEffectorFxForm.vue index 51485977a9..723b5f093e 100644 --- a/packages/frontend/src/components/MkImageEffectorFxForm.vue +++ b/packages/frontend/src/components/MkImageEffectorFxForm.vue @@ -28,13 +28,9 @@ SPDX-License-Identifier: AGPL-3.0-only - + -
diff --git a/packages/frontend/src/components/MkMenu.vue b/packages/frontend/src/components/MkMenu.vue index 22d5802596..b618dab6b2 100644 --- a/packages/frontend/src/components/MkMenu.vue +++ b/packages/frontend/src/components/MkMenu.vue @@ -323,9 +323,20 @@ async function showRadioOptions(item: MenuRadio, ev: MouseEvent | PointerEvent | type: 'radioOption', text: key, action: () => { - item.ref = value; + if ('value' in item.ref) { + item.ref.value = value; + } else { + // @ts-expect-error リアクティビティは保たれる + item.ref = value; + } }, - active: computed(() => item.ref === value), + active: computed(() => { + if ('value' in item.ref) { + return item.ref.value === value; + } else { + return item.ref === value; + } + }), }; }); diff --git a/packages/frontend/src/components/MkRadio.vue b/packages/frontend/src/components/MkRadio.vue index a7d77dd118..19ba90052c 100644 --- a/packages/frontend/src/components/MkRadio.vue +++ b/packages/frontend/src/components/MkRadio.vue @@ -24,8 +24,9 @@ SPDX-License-Identifier: AGPL-3.0-only
- - diff --git a/packages/frontend/src/components/MkSelect.vue b/packages/frontend/src/components/MkSelect.vue index f130145e36..6f6957d504 100644 --- a/packages/frontend/src/components/MkSelect.vue +++ b/packages/frontend/src/components/MkSelect.vue @@ -40,7 +40,7 @@ SPDX-License-Identifier: AGPL-3.0-only