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)" ) - Quote links color in room subtitles (e.g. "> http://foo.orgA)" )
- UI - UI
- Standardize usage of punctuation
- Way to open context menus without a right mouse button - Way to open context menus without a right mouse button
- `smartVerticalFlick()` gradual acceleration - `smartVerticalFlick()` gradual acceleration
@ -184,6 +185,7 @@
- Live-reloading accounts.json - Live-reloading accounts.json
- nio - nio
- Dedicated error for invalid password on key import
- Running blocking DB function calls in executor - Running blocking DB function calls in executor
- `AsyncClient.share_group_session`: send device batches concurrently - `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) upload_item = Upload(path, total_size=size)
self.models[Upload, room_id][upload_item.uuid] = upload_item self.models[Upload, room_id][upload_item.uuid] = upload_item
url, mime, crypt_dict = await self.upload( try:
path, filename=path.name, encrypt=encrypt, 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 upload_item.status = UploadStatus.Caching
await Media.from_existing_file(self.backend.media_cache, url, path) await Media.from_existing_file(self.backend.media_cache, url, path)
@ -269,30 +275,35 @@ class MatrixClient(nio.AsyncClient):
else: else:
upload_item.status = UploadStatus.UploadingThumbnail upload_item.status = UploadStatus.UploadingThumbnail
thumb_url, _, thumb_crypt_dict = await self.upload( try:
thumb_data, thumb_url, _, thumb_crypt_dict = await self.upload(
filename = f"{path.stem}_sample{''.join(path.suffixes)}", thumb_data,
encrypt = encrypt, filename =
) f"{path.stem}_sample{''.join(path.suffixes)}",
encrypt = encrypt,
upload_item.status = UploadStatus.CachingThumbnail )
except MatrixError as err:
await Thumbnail.from_bytes( log.warning(f"Failed uploading thumbnail {path}: {err}")
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: 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": elif kind == "audio":
event_type = \ event_type = \

View File

@ -2,7 +2,7 @@ import re
from dataclasses import dataclass, field from dataclasses import dataclass, field
from datetime import datetime from datetime import datetime
from pathlib import Path 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 from uuid import uuid4
import lxml # nosec import lxml # nosec
@ -13,6 +13,8 @@ from ..html_filter import HTML_FILTER
from ..utils import AutoStrEnum, auto from ..utils import AutoStrEnum, auto
from .model_item import ModelItem from .model_item import ModelItem
OptionalExceptionType = Union[Type[None], Type[Exception]]
@dataclass @dataclass
class Account(ModelItem): class Account(ModelItem):
@ -106,15 +108,17 @@ class UploadStatus(AutoStrEnum):
Caching = auto() Caching = auto()
UploadingThumbnail = auto() UploadingThumbnail = auto()
CachingThumbnail = auto() CachingThumbnail = auto()
Failure = auto() Error = auto()
@dataclass @dataclass
class Upload(ModelItem): class Upload(ModelItem):
filepath: Path = field() filepath: Path = field()
status: UploadStatus = UploadStatus.Uploading status: UploadStatus = UploadStatus.Uploading
total_size: int = 0 total_size: int = 0
uploaded: int = 0 uploaded: int = 0
error: OptionalExceptionType = type(None)
error_args: Tuple[Any, ...] = ()
uuid: str = field(init=False, default_factory=lambda: str(uuid4())) uuid: str = field(init=False, default_factory=lambda: str(uuid4()))
start_date: datetime = field(init=False, default_factory=datetime.now) start_date: datetime = field(init=False, default_factory=datetime.now)

View File

@ -39,6 +39,10 @@ Rectangle {
HLabel { HLabel {
id: filenameLabel id: filenameLabel
elide: Text.ElideRight elide: Text.ElideRight
color: model.status === "Error" ?
theme.colors.errorText : theme.colors.text
text: text:
model.status === "Uploading" ? model.status === "Uploading" ?
qsTr("Uploading %1...").arg(fileName) : qsTr("Uploading %1...").arg(fileName) :
@ -47,13 +51,25 @@ Rectangle {
qsTr("Caching %1...").arg(fileName) : qsTr("Caching %1...").arg(fileName) :
model.status === "UploadingThumbnail" ? model.status === "UploadingThumbnail" ?
qsTr("Uploading %1 thumbnail...").arg(fileName) : qsTr("Uploading thumbnail for %1...").arg(fileName) :
model.status === "CachingThumbnail" ? model.status === "CachingThumbnail" ?
qsTr("Caching %1 thumbnail...").arg(fileName) : qsTr("Caching thumbnail for %1...").arg(fileName) :
model.status === "Failure" ? model.status === "Error" ? (
qsTr("Uploading %1 failed").arg(fileName) : 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") qsTr("Invalid status for %1: %2")
.arg(fileName).arg(model.status) .arg(fileName).arg(model.status)
@ -91,8 +107,18 @@ Rectangle {
HProgressBar { HProgressBar {
id: progressBar id: progressBar
visible: Layout.maximumHeight !== 0
indeterminate: true indeterminate: true
foregroundColor:
model.status === "Error" ?
theme.controls.progressBar.errorForeground :
theme.controls.progressBar.foreground
Layout.fillWidth: true 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 int borderWidth: 2
progressBar: progressBar:
int height: Math.max(2, spacing / 2) int height: Math.max(2, spacing / 2)
color background: colors.inputBackground color background: colors.inputBackground
color foreground: colors.accentBackground color foreground: colors.accentBackground
color errorForeground: colors.negativeBackground
circleProgressBar: circleProgressBar:
int thickness: Math.max(2, spacing / 2) int thickness: Math.max(2, spacing / 2)
color background: colors.inputBackground color background: colors.inputBackground
color foreground: colors.accentBackground color foreground: colors.accentBackground
color errorForeground: colors.negativeBackground
color text: colors.text color text: colors.text
real indeterminateSpan: 0.5 // 0-1 real indeterminateSpan: 0.5 // 0-1