Fix SVG uploads, fix entire Upload model deleted
This commit is contained in:
parent
ace79a169c
commit
4c15b7dc62
1
TODO.md
1
TODO.md
@ -1,5 +1,4 @@
|
||||
- Media
|
||||
- SVG uploads
|
||||
- Uploading progress bar (+local echo)
|
||||
- Text bubbles theming
|
||||
- Directly create cache files for our uploads before actually uploading
|
||||
|
@ -1,6 +1,7 @@
|
||||
hsluv == 0.0.2
|
||||
Pillow >= 5.4.1, < 6
|
||||
pymediainfo >= 4.1, < 5
|
||||
cairosvg >= 2.4.2, < 3
|
||||
aiofiles >= 0.4.0, < 0.5
|
||||
appdirs >= 1.4.3, < 2
|
||||
filetype >= 1.0.5, < 2
|
||||
|
@ -18,6 +18,7 @@ from typing import (
|
||||
)
|
||||
from uuid import uuid4
|
||||
|
||||
import cairosvg
|
||||
from PIL import Image as PILImage
|
||||
from pymediainfo import MediaInfo
|
||||
|
||||
@ -252,18 +253,22 @@ class MatrixClient(nio.AsyncClient):
|
||||
content["url"] = url
|
||||
|
||||
if kind == "image":
|
||||
is_svg = mime == "image/svg+xml"
|
||||
|
||||
event_type = \
|
||||
nio.RoomEncryptedImage if encrypt else nio.RoomMessageImage
|
||||
|
||||
content["msgtype"] = "m.image"
|
||||
|
||||
content["info"]["w"], content["info"]["h"] = \
|
||||
content["info"]["w"], content["info"]["h"] = (
|
||||
utils.svg_dimensions(str(path)) if is_svg else
|
||||
PILImage.open(path).size
|
||||
)
|
||||
|
||||
try:
|
||||
thumb_url, thumb_info, thumb_crypt_dict = \
|
||||
await self.upload_thumbnail(
|
||||
path, upload_item, encrypt=encrypt,
|
||||
path, upload_item, is_svg=is_svg, encrypt=encrypt,
|
||||
)
|
||||
except (UneededThumbnail, UnthumbnailableError):
|
||||
pass
|
||||
@ -313,7 +318,7 @@ class MatrixClient(nio.AsyncClient):
|
||||
content["filename"] = path.name
|
||||
|
||||
upload_item.status = UploadStatus.Success
|
||||
del self.models[Upload, room_id]
|
||||
del self.models[Upload, room_id][upload_item.uuid]
|
||||
|
||||
uuid = str(uuid4())
|
||||
|
||||
@ -451,19 +456,31 @@ class MatrixClient(nio.AsyncClient):
|
||||
self,
|
||||
path: Union[Path, str],
|
||||
item: Optional[Upload] = None,
|
||||
is_svg: bool = False,
|
||||
encrypt: bool = False,
|
||||
) -> Tuple[str, Dict[str, Any], CryptDict]:
|
||||
|
||||
png_modes = ("1", "L", "P", "RGBA")
|
||||
|
||||
try:
|
||||
if is_svg:
|
||||
svg_width, svg_height = utils.svg_dimensions(str(path))
|
||||
|
||||
thumb = PILImage.open(io.BytesIO(
|
||||
cairosvg.svg2png(
|
||||
url = str(path),
|
||||
parent_width = svg_width,
|
||||
parent_height = svg_height,
|
||||
),
|
||||
))
|
||||
else:
|
||||
thumb = PILImage.open(path)
|
||||
|
||||
small = thumb.width <= 800 and thumb.height <= 600
|
||||
is_jpg_png = thumb.format in ("JPEG", "PNG")
|
||||
jpgable_png = thumb.format == "PNG" and thumb.mode not in png_modes
|
||||
|
||||
if small and is_jpg_png and not jpgable_png:
|
||||
if small and is_jpg_png and not jpgable_png and not is_svg:
|
||||
raise UneededThumbnail()
|
||||
|
||||
if item:
|
||||
|
@ -3,7 +3,7 @@ import html
|
||||
import xml.etree.cElementTree as xml_etree # FIXME: bandit warning
|
||||
from enum import Enum
|
||||
from enum import auto as autostr
|
||||
from typing import IO, Optional
|
||||
from typing import IO, Tuple, Union
|
||||
|
||||
import filetype
|
||||
|
||||
@ -26,7 +26,7 @@ def dict_update_recursive(dict1, dict2):
|
||||
dict1[k] = dict2[k]
|
||||
|
||||
|
||||
def is_svg(file: IO) -> bool:
|
||||
def is_svg(file: Union[IO, bytes, str]) -> bool:
|
||||
try:
|
||||
_, element = next(xml_etree.iterparse(file, ("start",)))
|
||||
return element.tag == "{http://www.w3.org/2000/svg}svg"
|
||||
@ -34,6 +34,22 @@ def is_svg(file: IO) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def svg_dimensions(file: Union[IO, bytes, str]) -> Tuple[int, int]:
|
||||
attrs = xml_etree.parse(file).getroot().attrib
|
||||
|
||||
try:
|
||||
width = round(float(attrs.get("width", attrs["viewBox"].split()[3])))
|
||||
except (KeyError, IndexError, ValueError, TypeError):
|
||||
width = 256
|
||||
|
||||
try:
|
||||
height = round(float(attrs.get("height", attrs["viewBox"].split()[4])))
|
||||
except (KeyError, IndexError, ValueError, TypeError):
|
||||
height = 256
|
||||
|
||||
return (width, height)
|
||||
|
||||
|
||||
def guess_mime(file: IO) -> str:
|
||||
if is_svg(file):
|
||||
return "image/svg+xml"
|
||||
|
Loading…
Reference in New Issue
Block a user