diff --git a/src/app/features/room-settings/PolicyListViewer.tsx b/src/app/features/room-settings/PolicyListViewer.tsx index 2e4ea5973..5a120c8a3 100644 --- a/src/app/features/room-settings/PolicyListViewer.tsx +++ b/src/app/features/room-settings/PolicyListViewer.tsx @@ -24,6 +24,14 @@ const POLICY_USER_EVENT = 'm.policy.rule.user'; const POLICY_ROOM_EVENT = 'm.policy.rule.room'; const POLICY_SERVER_EVENT = 'm.policy.rule.server'; +// Legacy, unstable-prefixed event types still emitted by Draupnir/Mjolnir +// policy lists that predate MSC stabilization (or haven't migrated). Queried +// alongside the stable types and merged/de-duped so those lists don't show +// as falsely empty. +const LEGACY_POLICY_USER_EVENT = 'org.matrix.mjolnir.rule.user'; +const LEGACY_POLICY_ROOM_EVENT = 'org.matrix.mjolnir.rule.room'; +const LEGACY_POLICY_SERVER_EVENT = 'org.matrix.mjolnir.rule.server'; + type PolicyRuleContent = { entity?: string; reason?: string; @@ -76,6 +84,23 @@ function extractPolicyEntries(events: MatrixEvent[]): PolicyEntry[] { .filter((entry) => entry.entity !== ''); } +/** + * Merge policy entries from the stable and legacy event types for a rule + * kind, de-duplicating by entity+recommendation so a room that emits both a + * stable and a legacy rule for the same target isn't double-listed. + */ +export function dedupePolicyEntries(entries: PolicyEntry[]): PolicyEntry[] { + const seen = new Set(); + const result: PolicyEntry[] = []; + entries.forEach((entry) => { + const key = `${entry.entity} ${entry.recommendation}`; + if (seen.has(key)) return; + seen.add(key); + result.push(entry); + }); + return result; +} + // ── Entry row ───────────────────────────────────────────────────────────────── function PolicyEntryRow({ entry }: { entry: PolicyEntry }) { @@ -201,9 +226,24 @@ export function PolicyListViewer({ requestClose }: PolicyListViewerProps) { return; } - setUserEntries(extractPolicyEntries(getRoomPolicyEvents(room, POLICY_USER_EVENT))); - setRoomEntries(extractPolicyEntries(getRoomPolicyEvents(room, POLICY_ROOM_EVENT))); - setServerEntries(extractPolicyEntries(getRoomPolicyEvents(room, POLICY_SERVER_EVENT))); + setUserEntries( + dedupePolicyEntries([ + ...extractPolicyEntries(getRoomPolicyEvents(room, POLICY_USER_EVENT)), + ...extractPolicyEntries(getRoomPolicyEvents(room, LEGACY_POLICY_USER_EVENT)), + ]), + ); + setRoomEntries( + dedupePolicyEntries([ + ...extractPolicyEntries(getRoomPolicyEvents(room, POLICY_ROOM_EVENT)), + ...extractPolicyEntries(getRoomPolicyEvents(room, LEGACY_POLICY_ROOM_EVENT)), + ]), + ); + setServerEntries( + dedupePolicyEntries([ + ...extractPolicyEntries(getRoomPolicyEvents(room, POLICY_SERVER_EVENT)), + ...extractPolicyEntries(getRoomPolicyEvents(room, LEGACY_POLICY_SERVER_EVENT)), + ]), + ); setLoadedRoomId(roomId); setError(undefined); }, [mx, roomIdInput]);