web/timeline: implement MSC4205 for policy list rendering

This commit is contained in:
Tulir Asokan 2025-03-13 02:25:18 +02:00
parent 92d3ab64bf
commit 0f2263ce8d
2 changed files with 16 additions and 4 deletions

View file

@ -116,6 +116,9 @@ export interface PolicyRuleContent {
entity: string entity: string
reason: string reason: string
recommendation: string recommendation: string
"org.matrix.msc4205.hashes"?: {
sha256: string
}
} }
export interface PowerLevelEventContent { export interface PowerLevelEventContent {

View file

@ -25,14 +25,21 @@ const PolicyRuleBody = ({ event, sender }: EventContentProps) => {
const mainScreen = use(MainScreenContext) const mainScreen = use(MainScreenContext)
const entity = content.entity ?? prevContent?.entity const entity = content.entity ?? prevContent?.entity
const hashedEntity = content["org.matrix.msc4205.hashes"]?.sha256
?? prevContent?.["org.matrix.msc4205.hashes"]?.sha256
const recommendation = content.recommendation ?? prevContent?.recommendation const recommendation = content.recommendation ?? prevContent?.recommendation
if (!entity || !recommendation) { if ((!entity && !hashedEntity) || !recommendation) {
return <div className="policy-body"> return <div className="policy-body">
{getDisplayname(event.sender, sender?.content)} sent an invalid policy rule {getDisplayname(event.sender, sender?.content)} sent an invalid policy rule
</div> </div>
} }
const target = event.type.replace(/^m\.policy\.rule\./, "")
let entityElement = <>{entity}</> let entityElement = <>{entity}</>
if(event.type === "m.policy.rule.user" && !entity?.includes("*") && !entity?.includes("?")) { let matchingWord = `${target}s matching`
if (!entity && hashedEntity) {
matchingWord = `the ${target} with hash`
entityElement = <>{hashedEntity}</>
} else if (event.type === "m.policy.rule.user" && entity && !entity.includes("*") && !entity.includes("?")) {
entityElement = ( entityElement = (
<a <a
className="hicli-matrix-uri hicli-matrix-uri-user" className="hicli-matrix-uri hicli-matrix-uri-user"
@ -44,16 +51,18 @@ const PolicyRuleBody = ({ event, sender }: EventContentProps) => {
{entity} {entity}
</a> </a>
) )
matchingWord = "user"
} }
let recommendationElement: JSX.Element | string = <code>{recommendation}</code> let recommendationElement: JSX.Element | string = <code>{recommendation}</code>
if (recommendation === "m.ban") { if (recommendation === "m.ban") {
recommendationElement = "ban" recommendationElement = "ban"
} else if (recommendation === "org.matrix.msc4204.takedown") {
recommendationElement = "takedown"
} }
const action = prevContent ? ((content.entity && content.recommendation) ? "updated" : "removed") : "added" const action = prevContent ? ((content.entity && content.recommendation) ? "updated" : "removed") : "added"
const target = event.type.replace(/^m\.policy\.rule\./, "")
return <div className="policy-body"> return <div className="policy-body">
{getDisplayname(event.sender, sender?.content)} {action} a {recommendationElement} rule {getDisplayname(event.sender, sender?.content)} {action} a {recommendationElement} rule
for {target}s matching <code>{entityElement}</code> for {matchingWord} <code>{entityElement}</code>
{content.reason ? <> for <code>{content.reason}</code></> : null} {content.reason ? <> for <code>{content.reason}</code></> : null}
</div> </div>
} }