Render inline images/custom emotes
<img> tags that either have a width and height (needed for QML to render correctly) or the data-mx-emote attribute (if they have no width/height, we assume 32x32) will be rendered inline. QML's support for img tags with remote src URLs seems buggy on Qt 5.15 especially, not working sometimes. We need to download and cache these images (like done for matrix media events), and use the local path in the img's src.
This commit is contained in:
parent
1a32c26b4d
commit
9dc0688557
3
TODO.md
3
TODO.md
|
@ -1,5 +1,8 @@
|
||||||
# TODO
|
# TODO
|
||||||
|
|
||||||
|
- issue templates
|
||||||
|
- ctrl-tab highlight
|
||||||
|
|
||||||
## Refactoring
|
## Refactoring
|
||||||
|
|
||||||
- General change/upload avatar component for account and room settings
|
- General change/upload avatar component for account and room settings
|
||||||
|
|
|
@ -12,6 +12,8 @@ import mistune
|
||||||
from html_sanitizer.sanitizer import Sanitizer
|
from html_sanitizer.sanitizer import Sanitizer
|
||||||
from lxml.html import HtmlElement, etree # nosec
|
from lxml.html import HtmlElement, etree # nosec
|
||||||
|
|
||||||
|
import nio
|
||||||
|
|
||||||
from .svg_colors import SVG_COLORS
|
from .svg_colors import SVG_COLORS
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,7 +113,7 @@ class HTMLProcessor:
|
||||||
|
|
||||||
block_tags = {
|
block_tags = {
|
||||||
"h1", "h2", "h3", "h4", "h5", "h6","blockquote",
|
"h1", "h2", "h3", "h4", "h5", "h6","blockquote",
|
||||||
"p", "ul", "ol", "li", "hr", "br",
|
"p", "ul", "ol", "li", "hr", "br", "img",
|
||||||
"table", "thead", "tbody", "tr", "th", "td", "pre",
|
"table", "thead", "tbody", "tr", "th", "td", "pre",
|
||||||
"mx-reply",
|
"mx-reply",
|
||||||
}
|
}
|
||||||
|
@ -283,7 +285,6 @@ class HTMLProcessor:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def sanitize_settings(
|
def sanitize_settings(
|
||||||
self, inline: bool = False, outgoing: bool = False, room_id: str = "",
|
self, inline: bool = False, outgoing: bool = False, room_id: str = "",
|
||||||
) -> dict:
|
) -> dict:
|
||||||
|
@ -303,6 +304,9 @@ class HTMLProcessor:
|
||||||
"ol": {"start"},
|
"ol": {"start"},
|
||||||
"hr": {"width"},
|
"hr": {"width"},
|
||||||
"span": {"data-mx-color"},
|
"span": {"data-mx-color"},
|
||||||
|
"img": {
|
||||||
|
"data-mx-emote", "src", "alt", "title", "width", "height",
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
username_link_regexes = []
|
username_link_regexes = []
|
||||||
|
@ -316,9 +320,9 @@ class HTMLProcessor:
|
||||||
return {
|
return {
|
||||||
"tags": inline_tags if inline else all_tags,
|
"tags": inline_tags if inline else all_tags,
|
||||||
"attributes": inlines_attributes if inline else attributes,
|
"attributes": inlines_attributes if inline else attributes,
|
||||||
"empty": {} if inline else {"hr", "br"},
|
"empty": {} if inline else {"hr", "br", "img"},
|
||||||
"separate": {"a"} if inline else {
|
"separate": {"a"} if inline else {
|
||||||
"a", "p", "li", "table", "tr", "th", "td", "br", "hr",
|
"a", "p", "li", "table", "tr", "th", "td", "br", "hr", "img",
|
||||||
},
|
},
|
||||||
"whitespace": {},
|
"whitespace": {},
|
||||||
"keep_typographic_whitespace": True,
|
"keep_typographic_whitespace": True,
|
||||||
|
@ -388,7 +392,28 @@ class HTMLProcessor:
|
||||||
def _img_to_a(el: HtmlElement) -> HtmlElement:
|
def _img_to_a(el: HtmlElement) -> HtmlElement:
|
||||||
"""Linkify images by wrapping `<img>` tags in `<a>`."""
|
"""Linkify images by wrapping `<img>` tags in `<a>`."""
|
||||||
|
|
||||||
if el.tag == "img":
|
if el.tag != "img":
|
||||||
|
return el
|
||||||
|
|
||||||
|
src = el.attrib.get("src")
|
||||||
|
width = el.attrib.get("width")
|
||||||
|
height = el.attrib.get("height")
|
||||||
|
is_emote = "data-mx-emote" in el.attrib
|
||||||
|
|
||||||
|
if src.startswith("mxc://"):
|
||||||
|
el.attrib["src"] = nio.Api.mxc_to_http(src)
|
||||||
|
|
||||||
|
if is_emote and not width and not height:
|
||||||
|
el.attrib["width"] = 32
|
||||||
|
el.attrib["height"] = 32
|
||||||
|
|
||||||
|
elif is_emote and width and not height:
|
||||||
|
el.attrib["height"] = width
|
||||||
|
|
||||||
|
elif is_emote and height and not width:
|
||||||
|
el.attrib["width"] = height
|
||||||
|
|
||||||
|
elif not is_emote and (not width or not height):
|
||||||
el.tag = "a"
|
el.tag = "a"
|
||||||
el.attrib["href"] = el.attrib.pop("src", "")
|
el.attrib["href"] = el.attrib.pop("src", "")
|
||||||
el.text = el.attrib.pop("alt", None) or el.attrib["href"]
|
el.text = el.attrib.pop("alt", None) or el.attrib["href"]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user