web/preferences: add option to disable inline images

This commit is contained in:
Tulir Asokan 2025-03-09 16:55:47 +02:00
parent 6b9f6bebd5
commit 86843d61f6
4 changed files with 42 additions and 9 deletions

View file

@ -414,24 +414,42 @@ var HTMLSanitizerImgSrcTemplate = "mxc://%s/%s"
func writeImg(w *strings.Builder, attr []html.Attribute) id.ContentURI {
src, alt, title, isCustomEmoji, width, height := parseImgAttributes(attr)
mxc := id.ContentURIString(src).ParseOrIgnore()
if !mxc.IsValid() {
w.WriteString("<span")
writeAttribute(w, "class", "hicli-inline-img-fallback hicli-invalid-inline-img")
w.WriteString(">")
writeEscapedString(w, alt)
w.WriteString("</span>")
return id.ContentURI{}
}
url := fmt.Sprintf(HTMLSanitizerImgSrcTemplate, mxc.Homeserver, mxc.FileID)
w.WriteString("<a")
writeAttribute(w, "class", "hicli-inline-img-fallback hicli-mxc-url")
writeAttribute(w, "title", title)
writeAttribute(w, "style", "display: none;")
writeAttribute(w, "target", "_blank")
writeAttribute(w, "data-mxc", mxc.String())
writeAttribute(w, "href", url)
w.WriteString(">")
writeEscapedString(w, alt)
w.WriteString("</a>")
w.WriteString("<img")
writeAttribute(w, "alt", alt)
if title != "" {
writeAttribute(w, "title", title)
}
mxc := id.ContentURIString(src).ParseOrIgnore()
if !mxc.IsValid() {
return id.ContentURI{}
}
writeAttribute(w, "src", fmt.Sprintf(HTMLSanitizerImgSrcTemplate, mxc.Homeserver, mxc.FileID))
writeAttribute(w, "src", url)
writeAttribute(w, "loading", "lazy")
if isCustomEmoji {
writeAttribute(w, "class", "hicli-custom-emoji")
writeAttribute(w, "class", "hicli-inline-img hicli-custom-emoji")
} else if cWidth, cHeight, sizeOK := calculateMediaSize(width, height); sizeOK {
writeAttribute(w, "class", "hicli-sized-inline-img")
writeAttribute(w, "class", "hicli-inline-img hicli-sized-inline-img")
writeAttribute(w, "style", fmt.Sprintf("width: %.2fpx; height: %.2fpx;", cWidth, cHeight))
} else {
writeAttribute(w, "class", "hicli-sizeless-inline-img")
writeAttribute(w, "class", "hicli-inline-img hicli-sizeless-inline-img")
}
return mxc
}

View file

@ -598,7 +598,7 @@ func (h *HiClient) calculateLocalContent(ctx context.Context, dbEvt *database.Ev
return nil, nil
}
const CurrentHTMLSanitizerVersion = 8
const CurrentHTMLSanitizerVersion = 10
func (h *HiClient) ReprocessExistingEvent(ctx context.Context, evt *database.Event) {
if (evt.Type != event.EventMessage.Type && evt.DecryptedType != event.EventMessage.Type) ||

View file

@ -59,6 +59,12 @@ export const preferences = {
allowedContexts: anyContext,
defaultValue: true,
}),
show_inline_images: new Preference<boolean>({
displayName: "Show inline images",
description: "If disabled, custom emojis and other inline images will not be rendered and the alt attribute will be shown instead.",
allowedContexts: anyContext,
defaultValue: true,
}),
code_block_line_wrap: new Preference<boolean>({
displayName: "Code block line wrap",
description: "Whether to wrap long lines in code blocks instead of scrolling horizontally.",

View file

@ -117,6 +117,15 @@ const StylePreferences = ({ client, activeRoom }: StylePreferencesProps) => {
--timeline-status-size: 2rem;
}
`, [preferences.display_read_receipts])
useStyle(() => !preferences.show_inline_images && css`
a.hicli-inline-img-fallback {
display: inline !important;
}
img.hicli-inline-img {
display: none;
}
`, [preferences.show_inline_images])
useAsyncStyle(() => preferences.code_block_theme === "auto" ? `
@import url("_gomuks/codeblock/github.css") (prefers-color-scheme: light);
@import url("_gomuks/codeblock/github-dark.css") (prefers-color-scheme: dark);