mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-20 10:33:41 -05:00
web/timeline: add support for spoilers
This commit is contained in:
parent
989b0fa0e5
commit
3b8767d504
3 changed files with 30 additions and 3 deletions
|
@ -98,6 +98,20 @@ div.html-body {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span[data-mx-spoiler] {
|
||||
filter: blur(4px);
|
||||
transition: filter .5s;
|
||||
cursor: pointer;
|
||||
|
||||
&.spoiler-revealed {
|
||||
filter: none;
|
||||
}
|
||||
|
||||
&:not(.spoiler-revealed) a {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 2px solid #ccc;
|
||||
padding-left: .5rem;
|
||||
|
|
|
@ -62,6 +62,13 @@ interface LocationMessageEventContent extends BaseMessageEventContent {
|
|||
|
||||
type MessageEventContent = TextMessageEventContent | MediaMessageEventContent | LocationMessageEventContent
|
||||
|
||||
const onClickHTML = (evt: React.MouseEvent<HTMLDivElement>) => {
|
||||
if ((evt.target as HTMLElement).closest("span[data-mx-spoiler]")?.classList.toggle("spoiler-revealed")) {
|
||||
// When unspoilering, don't trigger links and other clickables inside the spoiler
|
||||
evt.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
const MessageBody = ({ event }: EventContentProps) => {
|
||||
const content = event.content as MessageEventContent
|
||||
if (event.type === "m.sticker") {
|
||||
|
@ -78,7 +85,7 @@ const MessageBody = ({ event }: EventContentProps) => {
|
|||
case "m.emote":
|
||||
case "m.notice":
|
||||
if (__html) {
|
||||
return <div className="html-body" dangerouslySetInnerHTML={{ __html }}/>
|
||||
return <div onClick={onClickHTML} className="html-body" dangerouslySetInnerHTML={{ __html }}/>
|
||||
}
|
||||
return content.body
|
||||
case "m.image": {
|
||||
|
@ -86,7 +93,7 @@ const MessageBody = ({ event }: EventContentProps) => {
|
|||
const style = calculateMediaSize(content.info?.w, content.info?.h)
|
||||
let caption = null
|
||||
if (__html) {
|
||||
caption = <div className="html-body" dangerouslySetInnerHTML={{ __html }}/>
|
||||
caption = <div onClick={onClickHTML} className="html-body" dangerouslySetInnerHTML={{ __html }}/>
|
||||
} else if (content.body && content.filename && content.body !== content.filename) {
|
||||
caption = content.body
|
||||
}
|
||||
|
|
|
@ -106,6 +106,10 @@ export const transformTags: NonNullable<sanitizeHtml.IOptions["transformTags"]>
|
|||
delete attribs.style
|
||||
}
|
||||
|
||||
if (tagName === "span") {
|
||||
attribs.title = attribs["data-mx-spoiler"]
|
||||
}
|
||||
|
||||
// Sanitise and transform data-mx-color and data-mx-bg-color to their CSS
|
||||
// equivalents
|
||||
const customCSSMapper: Record<string, string> = {
|
||||
|
@ -184,7 +188,9 @@ export const sanitizeHtmlParams: sanitizeHtml.IOptions = {
|
|||
// but strip during the transformation.
|
||||
// custom ones first:
|
||||
font: ["color", "data-mx-bg-color", "data-mx-color", "style"], // custom to matrix
|
||||
span: ["data-mx-maths", "data-mx-bg-color", "data-mx-color", "data-mx-spoiler", "style"], // custom to matrix
|
||||
span: [
|
||||
"data-mx-maths", "data-mx-bg-color", "data-mx-color", "data-mx-spoiler", "style", "title"
|
||||
], // custom to matrix
|
||||
div: ["data-mx-maths"],
|
||||
// eslint-disable-next-line id-length
|
||||
a: ["href", "name", "target", "rel"], // remote target: custom to matrix
|
||||
|
|
Loading…
Add table
Reference in a new issue