Downloaded files: include title + ext in filename

This commit is contained in:
miruka 2020-03-09 11:46:08 -04:00
parent bd7b45cc7a
commit 7ee83c5fe4
11 changed files with 45 additions and 13 deletions

View File

@ -47,20 +47,30 @@ class MediaCache:
self.downloads_dir.mkdir(parents=True, exist_ok=True) self.downloads_dir.mkdir(parents=True, exist_ok=True)
async def get_media(self, mxc: str, crypt_dict: CryptDict = None) -> Path: async def get_media(
self,
mxc: str,
title: str,
crypt_dict: CryptDict = None,
) -> Path:
"""Return a `Media` object. Method intended for QML convenience.""" """Return a `Media` object. Method intended for QML convenience."""
return await Media(self, mxc, crypt_dict).get() return await Media(self, mxc, title, crypt_dict).get()
async def get_thumbnail( async def get_thumbnail(
self, mxc: str, width: int, height: int, crypt_dict: CryptDict = None, self,
mxc: str,
title: str,
width: int,
height: int,
crypt_dict: CryptDict = None,
) -> Path: ) -> Path:
"""Return a `Thumbnail` object. Method intended for QML convenience.""" """Return a `Thumbnail` object. Method intended for QML convenience."""
thumb = Thumbnail( thumb = Thumbnail(
# QML sometimes pass float sizes, which matrix API doesn't like. # QML sometimes pass float sizes, which matrix API doesn't like.
self, mxc, crypt_dict, (round(width), round(height)), self, mxc, title, crypt_dict, (round(width), round(height)),
) )
return await thumb.get() return await thumb.get()
@ -71,6 +81,7 @@ class Media:
cache: "MediaCache" = field() cache: "MediaCache" = field()
mxc: str = field() mxc: str = field()
title: str = field()
crypt_dict: CryptDict = field(repr=False) crypt_dict: CryptDict = field(repr=False)
@ -85,9 +96,11 @@ class Media:
def local_path(self) -> Path: def local_path(self) -> Path:
"""The path where the file either exists or should be downloaded.""" """The path where the file either exists or should be downloaded."""
parsed = urlparse(self.mxc) parsed = urlparse(self.mxc)
name = parsed.path.lstrip("/") mxc_id = parsed.path.lstrip("/")
return self.cache.downloads_dir / parsed.netloc / name title = Path(self.title)
filename = f"{title.stem}_{mxc_id}{title.suffix}"
return self.cache.downloads_dir / parsed.netloc / filename
async def get(self) -> Path: async def get(self) -> Path:
@ -165,7 +178,7 @@ class Media:
) -> "Media": ) -> "Media":
"""Copy an existing file to cache and return a `Media` for it.""" """Copy an existing file to cache and return a `Media` for it."""
media = cls(cache, mxc, {}, **kwargs) # type: ignore media = cls(cache, mxc, existing.name, {}, **kwargs) # type: ignore
media.local_path.parent.mkdir(parents=True, exist_ok=True) media.local_path.parent.mkdir(parents=True, exist_ok=True)
if not media.local_path.exists() or overwrite: if not media.local_path.exists() or overwrite:
@ -202,6 +215,7 @@ class Thumbnail(Media):
cache: "MediaCache" = field() cache: "MediaCache" = field()
mxc: str = field() mxc: str = field()
title: str = field()
crypt_dict: CryptDict = field(repr=False) crypt_dict: CryptDict = field(repr=False)
wanted_size: Size = field() wanted_size: Size = field()
@ -244,11 +258,15 @@ class Thumbnail(Media):
e.g. `~/.cache/appname/thumbnails/matrix.org/32x32/Hm24ar11i768b0el`. e.g. `~/.cache/appname/thumbnails/matrix.org/32x32/Hm24ar11i768b0el`.
""" """
parsed = urlparse(self.mxc) size = self.normalize_size(self.server_size or self.wanted_size)
size = self.normalize_size(self.server_size or self.wanted_size) size_dir = f"{size[0]}x{size[1]}"
name = "%dx%d/%s" % (size[0], size[1], parsed.path.lstrip("/"))
return self.cache.thumbs_dir / parsed.netloc / name parsed = urlparse(self.mxc)
mxc_id = parsed.path.lstrip("/")
title = Path(self.title)
filename = f"{title.stem}_{mxc_id}{title.suffix}"
return self.cache.thumbs_dir / parsed.netloc / size_dir / filename
async def _get_local_existing_file(self) -> Path: async def _get_local_existing_file(self) -> Path:

View File

@ -18,6 +18,7 @@ Rectangle {
property string name property string name
property alias mxc: avatarImage.mxc property alias mxc: avatarImage.mxc
property alias title: avatarImage.title
property alias toolTipMxc: avatarToolTipImage.mxc property alias toolTipMxc: avatarToolTipImage.mxc
property alias sourceOverride: avatarImage.sourceOverride property alias sourceOverride: avatarImage.sourceOverride
@ -77,6 +78,7 @@ Rectangle {
id: avatarToolTipImage id: avatarToolTipImage
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
mxc: avatarImage.mxc mxc: avatarImage.mxc
title: avatarImage.title
sourceSize.width: avatarToolTip.dimension sourceSize.width: avatarToolTip.dimension
sourceSize.height: avatarToolTip.dimension sourceSize.height: avatarToolTip.dimension

View File

@ -13,6 +13,7 @@ HImage {
property string mxc property string mxc
property string title
property string sourceOverride: "" property string sourceOverride: ""
property bool thumbnail: true property bool thumbnail: true
property var cryptDict: ({}) property var cryptDict: ({})
@ -41,7 +42,8 @@ HImage {
const method = image.thumbnail ? "get_thumbnail" : "get_media" const method = image.thumbnail ? "get_thumbnail" : "get_media"
const args = image.thumbnail ? const args = image.thumbnail ?
[image.mxc, w, h, cryptDict] : [image.mxc, cryptDict] [image.mxc, image.title, w, h, cryptDict] :
[image.mxc, image.title, cryptDict]
py.callCoro("media_cache." + method, args, path => { py.callCoro("media_cache." + method, args, path => {
if (! image) return if (! image) return

View File

@ -7,6 +7,9 @@ HAvatar {
displayName.substring(1) : displayName.substring(1) :
displayName displayName
title: "room_" + roomId + ".avatar"
property string roomId
property string displayName property string displayName
} }

View File

@ -4,6 +4,7 @@ import QtQuick 2.12
HAvatar { HAvatar {
name: displayName || userId.substring(1) // no leading @ name: displayName || userId.substring(1) // no leading @
title: "user_" + userId + ".avatar"
property string userId property string userId

View File

@ -12,6 +12,7 @@ HTileDelegate {
opacity: model.left ? theme.mainPane.room.leftRoomOpacity : 1 opacity: model.left ? theme.mainPane.room.leftRoomOpacity : 1
image: HRoomAvatar { image: HRoomAvatar {
roomId: model.id
displayName: model.display_name displayName: model.display_name
mxc: model.avatar_url mxc: model.avatar_url
} }

View File

@ -56,6 +56,7 @@ HBox {
HRoomAvatar { HRoomAvatar {
id: avatar id: avatar
roomId: ""
displayName: nameField.text displayName: nameField.text
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter

View File

@ -14,6 +14,7 @@ Rectangle {
HRoomAvatar { HRoomAvatar {
id: avatar id: avatar
roomId: chat.roomId
displayName: chat.roomInfo.display_name displayName: chat.roomInfo.display_name
mxc: chat.roomInfo.avatar_url mxc: chat.roomInfo.avatar_url
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop

View File

@ -55,6 +55,7 @@ HBox {
HRoomAvatar { HRoomAvatar {
id: avatar id: avatar
roomId: chat.roomId
displayName: chat.roomInfo.display_name displayName: chat.roomInfo.display_name
mxc: chat.roomInfo.avatar_url mxc: chat.roomInfo.avatar_url
// enabled: chat.roomInfo.can_set_avatar # put this in "change avatar" // enabled: chat.roomInfo.can_set_avatar # put this in "change avatar"

View File

@ -9,6 +9,7 @@ HMxcImage {
height: fitSize.height height: fitSize.height
horizontalAlignment: Image.AlignLeft horizontalAlignment: Image.AlignLeft
title: loader.title
animated: loader.singleMediaInfo.media_mime === "image/gif" || animated: loader.singleMediaInfo.media_mime === "image/gif" ||
utils.urlExtension(loader.mediaUrl).toLowerCase() === "gif" utils.urlExtension(loader.mediaUrl).toLowerCase() === "gif"
thumbnail: ! animated && loader.thumbnailMxc thumbnail: ! animated && loader.thumbnailMxc

View File

@ -85,6 +85,7 @@ HLoader {
const args = [ const args = [
loader.mediaUrl, loader.mediaUrl,
loader.title,
JSON.parse(loader.singleMediaInfo.media_crypt_dict) JSON.parse(loader.singleMediaInfo.media_crypt_dict)
] ]