next.misskey.ioで起こった色々なバグを修正#1463
Conversation
2025.4.1-io.12a
2025.4.1-io.12b
2025.4.1-io.13
normalizeDimensionの境界条件を修正(<=0から<0に)して、 dimension=0を許容するようにしました。
初回読み込みのAPI結果とストリーミング更新で返信の除外条件がずれていたため、リロード後だけ見える返信がありました。stream 側の追加フィルタを外して表示条件を揃えます。
アンテナ編集ダイアログの更新結果を列ヘッダーへ反映していなかったため、古い名前が残っていました。updated イベントで timelineNameCache を更新します。
ユーザーページ概要タブの notes リクエストで withChannelNotes が渡っておらず、チャンネル投稿だけ除外されていました。all タブでは channel notes も含めて取得します。
投稿フォームのアカウント切替アイコンで生の img を使っていたため、デコレーションが表示されていませんでした。MkAvatar を使って通常表示と同じ描画経路に揃えます。
予約投稿の権限がないユーザーにも導線が見えていて、実行時にだけ失敗していました。投稿フォームの表示・復元・実行を canScheduleNote に合わせて制御します。
アップロード中の終了確認をキャンセルした経路で投稿フォームの readonly 状態が戻らず、絵文字入力などが効かなくなっていました。キャンセル時に textAreaReadOnly を解除します。
共通ヘッダだけに閉じる操作を依存していて見つけづらかったため、コンテンツ内にも明示的な close ボタンを追加して閉じやすくします。
空文字や空白だけのキーワードが混ざるとワードミュート判定が崩れていました。キーワード正規化を加え、ミュート解除クリックの伝播も止めて意図しない開閉を防ぎます。
投稿失敗時の再オープン処理が空の composer を開き直していたため、channel 投稿が失われて通常投稿に戻っていました。元の props を引き継いで再オープンするようにします。
ミュート語のプレースホルダをクリックしたときに soft mute だけ解除され、hard mute 側が残って false 表示になることがありました。展開時に両方のミュート状態を解除して本体ノートへ切り替えます。
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
packages/backend/test/unit/misc/check-word-mute.ts (1)
42-46: 空白のみキーワードのケースもテストに追加してください。Line 42〜46 は
''をカバーできていますが、実装はtrim()ベースなので' '(空白のみ)も同様に検証しておくと回帰に強くなります。✅ テスト追加例
it('should ignore empty keywords in keyword filters', async () => { expect(await checkWordMute({ userId: '1', text: 'foo bar' }, null, [['foo', '']])).toBe(true); expect(await checkWordMute({ userId: '1', text: 'foo bar' }, null, [['', 'bar']])).toBe(true); + expect(await checkWordMute({ userId: '1', text: 'foo bar' }, null, [['foo', ' ']])).toBe(true); + expect(await checkWordMute({ userId: '1', text: 'foo bar' }, null, [[' ']])).toBe(false); expect(await checkWordMute({ userId: '1', text: 'foo bar' }, null, [['']])).toBe(false); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/backend/test/unit/misc/check-word-mute.ts` around lines 42 - 46, The test for checkWordMute needs to also cover keywords that are whitespace-only (e.g., ' ') because the implementation trims inputs; update the unit test in the same it block (or add a new spec) referencing checkWordMute to assert that filters containing [' '] are treated like empty and ignored (expect true for patterns where one side is whitespace-only and expect false for a single whitespace-only keyword array like [' '] mirroring the existing assertions for ''). Ensure you include both leading/trailing-space variants so the trim-based logic is exercised.packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue (1)
94-105: 未使用スタイルが追加されていますLine 94-105 の
.actionsと.closeButtonはこの SFC 内で参照されておらず、現時点では死蔵コードです。使わないなら削除、使う予定があるならテンプレート側への適用をお願いします。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue` around lines 94 - 105, Remove the unused CSS rules .actions and .closeButton from MkCustomEmojiDetailedDialog.vue if they are not needed, or if intended to be used, add the appropriate class attributes to the template elements (e.g., apply class="actions" to the actions container and class="closeButton" to the close button element) so the styles are referenced by the component.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/backend/src/misc/check-word-mute.ts`:
- Around line 54-59: The cache-size check runs before inserting, allowing the
cache to become 1001 entries; change the logic in the block using acCache,
acCacheKey and ac so you set acCache.set(acCacheKey, ac) first, then evict until
the size is <= 1000 (iterate acCache.keys() and delete oldest entries until
acCache.size <= 1000), ensuring you stop early once the limit is satisfied.
In `@packages/frontend/src/components/MkModalWindow.vue`:
- Line 10: In MkModalWindow.vue the close button uses v-if="withOkButton ||
withCloseButton" so withCloseButton=false can be overridden when withOkButton is
true; change the conditional on the close button (the <button ...
`@click`="emit('close')"> element) to depend only on withCloseButton (e.g.,
v-if="withCloseButton") so the close button visibility is controlled solely by
the withCloseButton prop.
---
Nitpick comments:
In `@packages/backend/test/unit/misc/check-word-mute.ts`:
- Around line 42-46: The test for checkWordMute needs to also cover keywords
that are whitespace-only (e.g., ' ') because the implementation trims inputs;
update the unit test in the same it block (or add a new spec) referencing
checkWordMute to assert that filters containing [' '] are treated like empty
and ignored (expect true for patterns where one side is whitespace-only and
expect false for a single whitespace-only keyword array like [' '] mirroring
the existing assertions for ''). Ensure you include both leading/trailing-space
variants so the trim-based logic is exercised.
In `@packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue`:
- Around line 94-105: Remove the unused CSS rules .actions and .closeButton from
MkCustomEmojiDetailedDialog.vue if they are not needed, or if intended to be
used, add the appropriate class attributes to the template elements (e.g., apply
class="actions" to the actions container and class="closeButton" to the close
button element) so the styles are referenced by the component.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3b8c0927-6fc5-4899-a071-c5f5c2c98a65
📒 Files selected for processing (39)
locales/ca-ES.ymllocales/en-US.ymllocales/es-ES.ymllocales/index.d.tslocales/it-IT.ymllocales/ja-JP.ymllocales/ko-KR.ymllocales/pt-PT.ymllocales/th-TH.ymllocales/zh-CN.ymllocales/zh-TW.ymlpackages/backend/src/core/RoleService.tspackages/backend/src/misc/check-word-mute.tspackages/backend/src/misc/dimension.tspackages/backend/src/models/json-schema/role.tspackages/backend/src/server/api/stream/channels/global-timeline.tspackages/backend/test/unit/misc/check-word-mute.tspackages/frontend/.storybook/fakes.tspackages/frontend/src/components/MkCustomEmojiDetailedDialog.vuepackages/frontend/src/components/MkModalWindow.vuepackages/frontend/src/components/MkNote.vuepackages/frontend/src/components/MkNoteDetailed.vuepackages/frontend/src/components/MkNoteScheduledDialog.vuepackages/frontend/src/components/MkNoteSub.vuepackages/frontend/src/components/MkPostForm.vuepackages/frontend/src/components/MkPostFormDialog.vuepackages/frontend/src/components/MkStreamingNotesTimeline.vuepackages/frontend/src/pages/admin/roles.editor.vuepackages/frontend/src/pages/admin/roles.vuepackages/frontend/src/pages/user/index.timeline.vuepackages/frontend/src/ui/deck/antenna-column.vuepackages/frontend/src/ui/deck/channel-column.vuepackages/frontend/src/ui/deck/role-timeline-column.vuepackages/frontend/src/utility/check-word-mute.tspackages/frontend/src/utility/focus-trap.tspackages/frontend/test/focus-trap.test.tspackages/misskey-js/etc/misskey-js.api.mdpackages/misskey-js/src/autogen/types.tspackages/misskey-js/src/consts.ts
💤 Files with no reviewable changes (18)
- packages/frontend/src/pages/admin/roles.vue
- packages/frontend/.storybook/fakes.ts
- locales/zh-CN.yml
- packages/misskey-js/src/consts.ts
- locales/ko-KR.yml
- packages/backend/src/models/json-schema/role.ts
- locales/es-ES.yml
- locales/pt-PT.yml
- packages/frontend/src/pages/admin/roles.editor.vue
- locales/it-IT.yml
- locales/ja-JP.yml
- locales/ca-ES.yml
- packages/backend/src/server/api/stream/channels/global-timeline.ts
- locales/index.d.ts
- packages/backend/src/core/RoleService.ts
- locales/th-TH.yml
- locales/en-US.yml
- locales/zh-TW.yml
There was a problem hiding this comment.
🧹 Nitpick comments (2)
packages/frontend/test/focus-trap.test.ts (1)
31-36:afterEachのDOMクリアはreplaceChildren()に寄せるのがおすすめです。
innerHTML書き換えの静的解析ノイズを避けつつ、意図も明確になります。差分案
afterEach(() => { for (const release of releases.splice(0).reverse()) { release(); } - document.body.innerHTML = ''; + document.body.replaceChildren(); });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/frontend/test/focus-trap.test.ts` around lines 31 - 36, Replace the DOM clearing in the afterEach block to use document.body.replaceChildren() instead of setting document.body.innerHTML = ''; update the afterEach (the teardown that iterates releases.splice(0).reverse() and calls release()) so that after running the release callbacks it calls document.body.replaceChildren() to clear children; this avoids innerHTML static-analysis noise while preserving the same teardown semantics in focus-trap.test.ts.packages/frontend/src/utility/focus-trap.ts (1)
72-83: 同一条件のcanInteractWithSibling呼び出しは1回にまとめられます。分岐前に結果をキャッシュすると、読みやすさと微小な実行コストの両方を改善できます。
差分案
if (!siblingEl) return; if (ignoreElements.includes(siblingEl.tagName.toLowerCase())) return; + const canInteract = + highestZIndexElement != null && + canInteractWithSibling(siblingEl, highestZIndexElement.el, highestZIndexElementAllowsInteraction); if ( ( siblingEl === el || highestZIndexElement == null || - canInteractWithSibling(siblingEl, highestZIndexElement.el, highestZIndexElementAllowsInteraction) + canInteract ) ) { siblingEl.inert = false; } else if ( highestZIndexElement != null && - !canInteractWithSibling(siblingEl, highestZIndexElement.el, highestZIndexElementAllowsInteraction) + !canInteract ) { siblingEl.inert = true; } else { siblingEl.inert = false; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/frontend/src/utility/focus-trap.ts` around lines 72 - 83, The two identical calls to canInteractWithSibling should be computed once and reused: before the if, compute a boolean (e.g., siblingCanInteract) using siblingEl, highestZIndexElement.el and highestZIndexElementAllowsInteraction when highestZIndexElement is not null (default to true/appropriate fallback when null), then replace both canInteractWithSibling(...) calls in the conditional branches with that cached siblingCanInteract; this keeps the existing logic that sets siblingEl.inert = false when siblingEl === el or siblingCanInteract, and the else branch when siblingCanInteract is false.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@packages/frontend/src/utility/focus-trap.ts`:
- Around line 72-83: The two identical calls to canInteractWithSibling should be
computed once and reused: before the if, compute a boolean (e.g.,
siblingCanInteract) using siblingEl, highestZIndexElement.el and
highestZIndexElementAllowsInteraction when highestZIndexElement is not null
(default to true/appropriate fallback when null), then replace both
canInteractWithSibling(...) calls in the conditional branches with that cached
siblingCanInteract; this keeps the existing logic that sets siblingEl.inert =
false when siblingEl === el or siblingCanInteract, and the else branch when
siblingCanInteract is false.
In `@packages/frontend/test/focus-trap.test.ts`:
- Around line 31-36: Replace the DOM clearing in the afterEach block to use
document.body.replaceChildren() instead of setting document.body.innerHTML = '';
update the afterEach (the teardown that iterates releases.splice(0).reverse()
and calls release()) so that after running the release callbacks it calls
document.body.replaceChildren() to clear children; this avoids innerHTML
static-analysis noise while preserving the same teardown semantics in
focus-trap.test.ts.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: af20de16-7400-4f77-a2d2-84953dd8ecba
📒 Files selected for processing (8)
locales/index.d.tspackages/backend/src/core/FanoutTimelineEndpointService.tspackages/backend/src/misc/check-word-mute.tspackages/backend/test-federation/compose.a.ymlpackages/backend/test-federation/compose.b.ymlpackages/frontend/src/components/MkNoteDetailed.vuepackages/frontend/src/utility/focus-trap.tspackages/frontend/test/focus-trap.test.ts
💤 Files with no reviewable changes (1)
- locales/index.d.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/backend/src/misc/check-word-mute.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/frontend/src/utility/focus-trap.ts`:
- Around line 73-78: The conditional that allows a siblingEl === el to bypass
the highestZIndexElement check is enabling released subtrees to become
interactive again; update the logic in the release flow (the block referencing
siblingEl, el, highestZIndexElement, and canInteract) to remove the special-case
check for siblingEl === el so the highestZIndexElement/null and canInteract
checks take precedence (i.e., only allow making elements interactive when
highestZIndexElement is null or canInteract is true), ensuring stacked
focus-traps are released in correct order and inert state is preserved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4a2694ac-cd15-4291-a7e2-0e1aed693e18
📒 Files selected for processing (8)
packages/backend/src/misc/check-word-mute.tspackages/backend/test/unit/misc/check-word-mute.tspackages/frontend/src/components/MkCustomEmojiDetailedDialog.vuepackages/frontend/src/components/MkModalWindow.vuepackages/frontend/src/components/MkPostForm.vuepackages/frontend/src/components/MkStreamingNotesTimeline.vuepackages/frontend/src/utility/focus-trap.tspackages/frontend/test/focus-trap.test.ts
✅ Files skipped from review due to trivial changes (1)
- packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/frontend/src/components/MkModalWindow.vue
- packages/frontend/src/components/MkStreamingNotesTimeline.vue
- packages/backend/src/misc/check-word-mute.ts
- packages/frontend/test/focus-trap.test.ts
There was a problem hiding this comment.
Pull request overview
next.misskey.io で発生していた複数の不具合を、フロントエンド/バックエンド/SDK/翻訳/テストまで跨いで修正・整備するPRです。
Changes:
- ワードミュートのキーワード正規化(空文字・空白の扱い)をフロント/バックで改善し、テストを追加
- Streaming(特に globalTimeline)の返信扱いと、Deck/Timelineの dimension 連携を改善
- モーダル/ノート表示まわり(focus trap、ミュート解除クリック、クローズボタン等)のUI挙動を改善し、関連テストを追加
Reviewed changes
Copilot reviewed 39 out of 41 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/misskey-js/src/consts.ts | rolePolicies から scheduledNoteLimit を削除 |
| packages/misskey-js/src/autogen/types.ts | API型更新(replyUserId追加、scheduledNoteLimit削除等) |
| packages/misskey-js/etc/misskey-js.api.md | 公開API定義の rolePolicies 更新 |
| packages/frontend/test/focus-trap.test.ts | focusTrap の回帰テストを追加 |
| packages/frontend/src/utility/focus-trap.ts | focus trap の相互作用/解除ロジック改善 |
| packages/frontend/src/utility/check-word-mute.ts | ワードミュートのtrim・空要素除外 |
| packages/frontend/src/ui/deck/role-timeline-column.vue | role TL に dimension を渡す |
| packages/frontend/src/ui/deck/channel-column.vue | channel TL に dimension を渡す |
| packages/frontend/src/ui/deck/antenna-column.vue | アンテナ編集をダイアログ化してキャッシュ更新 |
| packages/frontend/src/pages/user/index.timeline.vue | users/notes に withChannelNotes を追加 |
| packages/frontend/src/pages/admin/roles.vue | scheduledNoteLimit の設定UI削除 |
| packages/frontend/src/pages/admin/roles.editor.vue | scheduledNoteLimit の設定UI削除(詳細) |
| packages/frontend/src/components/MkStreamingNotesTimeline.vue | streaming接続/ページングに dimension を追加 |
| packages/frontend/src/components/MkPostFormDialog.vue | postError時に props を維持して post を呼ぶ |
| packages/frontend/src/components/MkPostForm.vue | スケジュール投稿の可否判定・UI制御の見直し等 |
| packages/frontend/src/components/MkNoteSub.vue | ミュート解除クリックの伝播制御 |
| packages/frontend/src/components/MkNoteScheduledDialog.vue | closeボタン表示を有効化 |
| packages/frontend/src/components/MkNoteDetailed.vue | ミュート解除クリックの伝播制御 |
| packages/frontend/src/components/MkNote.vue | ミュート表示ロジック整理(表示条件/文言分岐) |
| packages/frontend/src/components/MkModalWindow.vue | closeボタン表示条件を修正 |
| packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue | モーダル呼び出しの微調整 |
| packages/frontend/.storybook/fakes.ts | scheduledNoteLimit をfakeから削除 |
| packages/backend/test/unit/misc/check-word-mute.ts | 空/空白キーワードのテスト追加 |
| packages/backend/test/e2e/streaming.ts | globalTimelineの返信挙動テストを修正 |
| packages/backend/test-federation/compose.b.yml | federationテストのDB volume mount変更 |
| packages/backend/test-federation/compose.a.yml | federationテストのDB volume mount変更 |
| packages/backend/src/server/api/stream/channels/global-timeline.ts | globalTimelineの返信除外ロジック削除 |
| packages/backend/src/models/json-schema/role.ts | scheduledNoteLimit をschemaから削除 |
| packages/backend/src/misc/check-word-mute.ts | 正規化・ACキャッシュ改善、判定関数抽出 |
| packages/backend/src/core/RoleService.ts | scheduledNoteLimit をポリシーから削除 |
| locales/zh-TW.yml | scheduledNoteLimit 文言削除 |
| locales/zh-CN.yml | scheduledNoteLimit 文言削除 |
| locales/th-TH.yml | scheduledNoteLimit 文言削除 |
| locales/pt-PT.yml | scheduledNoteLimit 文言削除 |
| locales/ko-KR.yml | scheduledNoteLimit 文言削除 |
| locales/ja-JP.yml | scheduledNoteLimit 文言削除 |
| locales/it-IT.yml | scheduledNoteLimit 文言削除 |
| locales/index.d.ts | scheduledNoteLimit 型定義削除 |
| locales/es-ES.yml | scheduledNoteLimit 文言削除 |
| locales/en-US.yml | scheduledNoteLimit 文言削除 |
| locales/ca-ES.yml | scheduledNoteLimit 文言削除 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
f1476e6 to
97583d2
Compare
|



What
Why
Additional info (optional)
Checklist
Summary by CodeRabbit
リリースノート
Bug Fixes
UI改善
Other Changes