Handle upload errors
This commit is contained in:
parent
08694388dd
commit
e4aa3b6572
2
TODO.md
2
TODO.md
|
@ -57,6 +57,7 @@
|
|||
- Quote links color in room subtitles (e.g. "> http://foo.orgA)" )
|
||||
|
||||
- UI
|
||||
- Standardize usage of punctuation
|
||||
- Way to open context menus without a right mouse button
|
||||
- `smartVerticalFlick()` gradual acceleration
|
||||
|
||||
|
@ -184,6 +185,7 @@
|
|||
- Live-reloading accounts.json
|
||||
|
||||
- nio
|
||||
- Dedicated error for invalid password on key import
|
||||
- Running blocking DB function calls in executor
|
||||
- `AsyncClient.share_group_session`: send device batches concurrently
|
||||
|
||||
|
|
|
@ -220,9 +220,15 @@ class MatrixClient(nio.AsyncClient):
|
|||
upload_item = Upload(path, total_size=size)
|
||||
self.models[Upload, room_id][upload_item.uuid] = upload_item
|
||||
|
||||
url, mime, crypt_dict = await self.upload(
|
||||
path, filename=path.name, encrypt=encrypt,
|
||||
)
|
||||
try:
|
||||
url, mime, crypt_dict = await self.upload(
|
||||
path, filename=path.name, encrypt=encrypt,
|
||||
)
|
||||
except MatrixError as err:
|
||||
upload_item.status = UploadStatus.Error
|
||||
upload_item.error = type(err)
|
||||
upload_item.error_args = err.args
|
||||
return
|
||||
|
||||
upload_item.status = UploadStatus.Caching
|
||||
await Media.from_existing_file(self.backend.media_cache, url, path)
|
||||
|
@ -269,30 +275,35 @@ class MatrixClient(nio.AsyncClient):
|
|||
else:
|
||||
upload_item.status = UploadStatus.UploadingThumbnail
|
||||
|
||||
thumb_url, _, thumb_crypt_dict = await self.upload(
|
||||
thumb_data,
|
||||
filename = f"{path.stem}_sample{''.join(path.suffixes)}",
|
||||
encrypt = encrypt,
|
||||
)
|
||||
|
||||
upload_item.status = UploadStatus.CachingThumbnail
|
||||
|
||||
await Thumbnail.from_bytes(
|
||||
self.backend.media_cache,
|
||||
thumb_url,
|
||||
thumb_data,
|
||||
wanted_size = (content["info"]["w"], content["info"]["h"]),
|
||||
)
|
||||
|
||||
if encrypt:
|
||||
content["info"]["thumbnail_file"] = {
|
||||
"url": thumb_url,
|
||||
**thumb_crypt_dict,
|
||||
}
|
||||
try:
|
||||
thumb_url, _, thumb_crypt_dict = await self.upload(
|
||||
thumb_data,
|
||||
filename =
|
||||
f"{path.stem}_sample{''.join(path.suffixes)}",
|
||||
encrypt = encrypt,
|
||||
)
|
||||
except MatrixError as err:
|
||||
log.warning(f"Failed uploading thumbnail {path}: {err}")
|
||||
else:
|
||||
content["info"]["thumbnail_url"] = thumb_url
|
||||
upload_item.status = UploadStatus.CachingThumbnail
|
||||
|
||||
content["info"]["thumbnail_info"] = thumb_info._asdict()
|
||||
await Thumbnail.from_bytes(
|
||||
self.backend.media_cache,
|
||||
thumb_url,
|
||||
thumb_data,
|
||||
wanted_size = (content["info"]["w"],
|
||||
content["info"]["h"]),
|
||||
)
|
||||
|
||||
if encrypt:
|
||||
content["info"]["thumbnail_file"] = {
|
||||
"url": thumb_url,
|
||||
**thumb_crypt_dict,
|
||||
}
|
||||
else:
|
||||
content["info"]["thumbnail_url"] = thumb_url
|
||||
|
||||
content["info"]["thumbnail_info"] = thumb_info._asdict()
|
||||
|
||||
elif kind == "audio":
|
||||
event_type = \
|
||||
|
|
|
@ -2,7 +2,7 @@ import re
|
|||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Type
|
||||
from typing import Any, Dict, List, Optional, Tuple, Type, Union
|
||||
from uuid import uuid4
|
||||
|
||||
import lxml # nosec
|
||||
|
@ -13,6 +13,8 @@ from ..html_filter import HTML_FILTER
|
|||
from ..utils import AutoStrEnum, auto
|
||||
from .model_item import ModelItem
|
||||
|
||||
OptionalExceptionType = Union[Type[None], Type[Exception]]
|
||||
|
||||
|
||||
@dataclass
|
||||
class Account(ModelItem):
|
||||
|
@ -106,15 +108,17 @@ class UploadStatus(AutoStrEnum):
|
|||
Caching = auto()
|
||||
UploadingThumbnail = auto()
|
||||
CachingThumbnail = auto()
|
||||
Failure = auto()
|
||||
Error = auto()
|
||||
|
||||
|
||||
@dataclass
|
||||
class Upload(ModelItem):
|
||||
filepath: Path = field()
|
||||
status: UploadStatus = UploadStatus.Uploading
|
||||
total_size: int = 0
|
||||
uploaded: int = 0
|
||||
filepath: Path = field()
|
||||
status: UploadStatus = UploadStatus.Uploading
|
||||
total_size: int = 0
|
||||
uploaded: int = 0
|
||||
error: OptionalExceptionType = type(None)
|
||||
error_args: Tuple[Any, ...] = ()
|
||||
|
||||
uuid: str = field(init=False, default_factory=lambda: str(uuid4()))
|
||||
start_date: datetime = field(init=False, default_factory=datetime.now)
|
||||
|
|
|
@ -39,6 +39,10 @@ Rectangle {
|
|||
HLabel {
|
||||
id: filenameLabel
|
||||
elide: Text.ElideRight
|
||||
|
||||
color: model.status === "Error" ?
|
||||
theme.colors.errorText : theme.colors.text
|
||||
|
||||
text:
|
||||
model.status === "Uploading" ?
|
||||
qsTr("Uploading %1...").arg(fileName) :
|
||||
|
@ -47,13 +51,25 @@ Rectangle {
|
|||
qsTr("Caching %1...").arg(fileName) :
|
||||
|
||||
model.status === "UploadingThumbnail" ?
|
||||
qsTr("Uploading %1 thumbnail...").arg(fileName) :
|
||||
qsTr("Uploading thumbnail for %1...").arg(fileName) :
|
||||
|
||||
model.status === "CachingThumbnail" ?
|
||||
qsTr("Caching %1 thumbnail...").arg(fileName) :
|
||||
qsTr("Caching thumbnail for %1...").arg(fileName) :
|
||||
|
||||
model.status === "Failure" ?
|
||||
qsTr("Uploading %1 failed").arg(fileName) :
|
||||
model.status === "Error" ? (
|
||||
model.error === "MatrixForbidden" ?
|
||||
qsTr("Forbidden file type or quota exceeded: %1")
|
||||
.arg(fileName) :
|
||||
|
||||
model.error === "MatrixTooLarge" ?
|
||||
qsTr("Too large for this server: %1")
|
||||
.arg(fileName) :
|
||||
|
||||
qsTr("Unknown error for %1: %2 - %3")
|
||||
.arg(fileName)
|
||||
.arg(model.error)
|
||||
.arg(model.error_args)
|
||||
) :
|
||||
|
||||
qsTr("Invalid status for %1: %2")
|
||||
.arg(fileName).arg(model.status)
|
||||
|
@ -91,8 +107,18 @@ Rectangle {
|
|||
|
||||
HProgressBar {
|
||||
id: progressBar
|
||||
visible: Layout.maximumHeight !== 0
|
||||
indeterminate: true
|
||||
foregroundColor:
|
||||
model.status === "Error" ?
|
||||
theme.controls.progressBar.errorForeground :
|
||||
theme.controls.progressBar.foreground
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumHeight:
|
||||
model.status === "Error" && indeterminate ? 0 : -1
|
||||
|
||||
Behavior on Layout.maximumHeight { HNumberAnimation {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,14 +183,16 @@ controls:
|
|||
int borderWidth: 2
|
||||
|
||||
progressBar:
|
||||
int height: Math.max(2, spacing / 2)
|
||||
color background: colors.inputBackground
|
||||
color foreground: colors.accentBackground
|
||||
int height: Math.max(2, spacing / 2)
|
||||
color background: colors.inputBackground
|
||||
color foreground: colors.accentBackground
|
||||
color errorForeground: colors.negativeBackground
|
||||
|
||||
circleProgressBar:
|
||||
int thickness: Math.max(2, spacing / 2)
|
||||
color background: colors.inputBackground
|
||||
color foreground: colors.accentBackground
|
||||
color errorForeground: colors.negativeBackground
|
||||
color text: colors.text
|
||||
real indeterminateSpan: 0.5 // 0-1
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user