Handle upload errors

This commit is contained in:
miruka 2019-12-02 02:57:47 -04:00
parent 08694388dd
commit e4aa3b6572
5 changed files with 83 additions and 38 deletions

View File

@ -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

View File

@ -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 = \

View File

@ -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)

View File

@ -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 {} }
}
}
}

View File

@ -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