Add ability to cancel uploads
This commit is contained in:
parent
ae009c7412
commit
3919b964ca
1
TODO.md
1
TODO.md
|
@ -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
|
||||||
|
- Make theme error/etc text colors more like name colors
|
||||||
- Standardize usage of punctuation
|
- 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
|
||||||
|
|
|
@ -12,7 +12,7 @@ from typing import (
|
||||||
Any, DefaultDict, Dict, NamedTuple, Optional, Set, Tuple, Type, Union,
|
Any, DefaultDict, Dict, NamedTuple, Optional, Set, Tuple, Type, Union,
|
||||||
)
|
)
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from uuid import uuid4
|
from uuid import UUID, uuid4
|
||||||
|
|
||||||
import cairosvg
|
import cairosvg
|
||||||
from PIL import Image as PILImage
|
from PIL import Image as PILImage
|
||||||
|
@ -211,17 +211,28 @@ class MatrixClient(nio.AsyncClient):
|
||||||
|
|
||||||
|
|
||||||
async def send_file(self, room_id: str, path: Union[Path, str]) -> None:
|
async def send_file(self, room_id: str, path: Union[Path, str]) -> None:
|
||||||
|
item_uuid = uuid4()
|
||||||
|
|
||||||
|
try:
|
||||||
|
await self._send_file(item_uuid, room_id, path)
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
del self.models[Upload, room_id][item_uuid]
|
||||||
|
|
||||||
|
|
||||||
|
async def _send_file(
|
||||||
|
self, item_uuid: UUID, room_id: str, path: Union[Path, str],
|
||||||
|
) -> None:
|
||||||
from .media_cache import Media, Thumbnail
|
from .media_cache import Media, Thumbnail
|
||||||
|
|
||||||
path = Path(path)
|
path = Path(path)
|
||||||
size = path.resolve().stat().st_size
|
size = path.resolve().stat().st_size
|
||||||
encrypt = room_id in self.encrypted_rooms
|
encrypt = room_id in self.encrypted_rooms
|
||||||
|
|
||||||
upload_item = Upload(path, total_size=size)
|
task = asyncio.Task.current_task()
|
||||||
|
upload_item = Upload(item_uuid, task, path, total_size=size)
|
||||||
self.models[Upload, room_id][upload_item.uuid] = upload_item
|
self.models[Upload, room_id][upload_item.uuid] = upload_item
|
||||||
|
|
||||||
try:
|
try:
|
||||||
raise MatrixError(111, "Ooops!")
|
|
||||||
url, mime, crypt_dict = await self.upload(
|
url, mime, crypt_dict = await self.upload(
|
||||||
path, filename=path.name, encrypt=encrypt,
|
path, filename=path.name, encrypt=encrypt,
|
||||||
)
|
)
|
||||||
|
@ -229,7 +240,10 @@ class MatrixClient(nio.AsyncClient):
|
||||||
upload_item.status = UploadStatus.Error
|
upload_item.status = UploadStatus.Error
|
||||||
upload_item.error = type(err)
|
upload_item.error = type(err)
|
||||||
upload_item.error_args = err.args
|
upload_item.error_args = err.args
|
||||||
return
|
|
||||||
|
# Wait for cancellation, see parent send_file() method
|
||||||
|
while True:
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
import asyncio
|
||||||
import re
|
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, Tuple, Type, Union
|
from typing import Any, Dict, List, Optional, Tuple, Type, Union
|
||||||
from uuid import uuid4
|
from uuid import UUID
|
||||||
|
|
||||||
import lxml # nosec
|
import lxml # nosec
|
||||||
|
|
||||||
|
@ -113,6 +114,8 @@ class UploadStatus(AutoStrEnum):
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Upload(ModelItem):
|
class Upload(ModelItem):
|
||||||
|
uuid: UUID = field()
|
||||||
|
task: asyncio.Task = field()
|
||||||
filepath: Path = field()
|
filepath: Path = field()
|
||||||
status: UploadStatus = UploadStatus.Uploading
|
status: UploadStatus = UploadStatus.Uploading
|
||||||
total_size: int = 0
|
total_size: int = 0
|
||||||
|
@ -120,7 +123,6 @@ class Upload(ModelItem):
|
||||||
error: OptionalExceptionType = type(None)
|
error: OptionalExceptionType = type(None)
|
||||||
error_args: Tuple[Any, ...] = ()
|
error_args: Tuple[Any, ...] = ()
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,34 @@ Rectangle {
|
||||||
id: delegate
|
id: delegate
|
||||||
width: uploadsList.width
|
width: uploadsList.width
|
||||||
|
|
||||||
|
Behavior on height { HNumberAnimation {} }
|
||||||
|
|
||||||
|
Binding {
|
||||||
|
id: hideBind
|
||||||
|
target: delegate
|
||||||
|
property: "height"
|
||||||
|
value: 0
|
||||||
|
when: false
|
||||||
|
}
|
||||||
|
|
||||||
HRowLayout {
|
HRowLayout {
|
||||||
|
HButton {
|
||||||
|
icon.name: "cancel"
|
||||||
|
icon.color: theme.colors.negativeBackground
|
||||||
|
padded: false
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
// Python might take a sec to cancel, but we want
|
||||||
|
// immediate visual feedback
|
||||||
|
hideBind.when = true
|
||||||
|
// Python will delete this model item on cancel
|
||||||
|
py.call(py.getattr(model.task, "cancel"))
|
||||||
|
}
|
||||||
|
|
||||||
|
Layout.preferredWidth: theme.baseElementsHeight
|
||||||
|
Layout.preferredHeight: Layout.preferredWidth
|
||||||
|
}
|
||||||
|
|
||||||
HLabel {
|
HLabel {
|
||||||
id: statusLabel
|
id: statusLabel
|
||||||
elide: expand ? Text.ElideNone : Text.ElideRight
|
elide: expand ? Text.ElideNone : Text.ElideRight
|
||||||
|
@ -108,7 +135,8 @@ Rectangle {
|
||||||
}
|
}
|
||||||
|
|
||||||
TapHandler {
|
TapHandler {
|
||||||
onTapped: statusLabel.expand = ! statusLabel.expand
|
onTapped: if (model.status !== "Error")
|
||||||
|
statusLabel.expand = ! statusLabel.expand
|
||||||
}
|
}
|
||||||
|
|
||||||
HoverHandler { id: infoRowHover }
|
HoverHandler { id: infoRowHover }
|
||||||
|
|
Loading…
Reference in New Issue
Block a user