Immediatly show UI transfer for clipboard paste
Create an Upload model item before compressing the image and writing it to disk
This commit is contained in:
parent
bceafd7bbd
commit
5cc1c55d95
|
@ -18,8 +18,8 @@ from functools import partial
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import NamedTemporaryFile
|
from tempfile import NamedTemporaryFile
|
||||||
from typing import (
|
from typing import (
|
||||||
TYPE_CHECKING, Any, ClassVar, Dict, List, NamedTuple, Optional, Set, Tuple,
|
TYPE_CHECKING, Any, Callable, ClassVar, Coroutine, Dict, List, NamedTuple,
|
||||||
Type, Union,
|
Optional, Set, Tuple, Type, Union,
|
||||||
)
|
)
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
from uuid import UUID, uuid4
|
from uuid import UUID, uuid4
|
||||||
|
@ -56,7 +56,10 @@ if sys.version_info >= (3, 7):
|
||||||
else:
|
else:
|
||||||
current_task = asyncio.Task.current_task
|
current_task = asyncio.Task.current_task
|
||||||
|
|
||||||
CryptDict = Dict[str, Any]
|
CryptDict = Dict[str, Any]
|
||||||
|
PathCallable = Union[
|
||||||
|
str, Path, Callable[[], Coroutine[None, None, Union[str, Path]]],
|
||||||
|
]
|
||||||
|
|
||||||
REPLY_FALLBACK = (
|
REPLY_FALLBACK = (
|
||||||
"<mx-reply>"
|
"<mx-reply>"
|
||||||
|
@ -565,13 +568,20 @@ class MatrixClient(nio.AsyncClient):
|
||||||
prefix = datetime.now().strftime("%Y%m%d-%H%M%S.")
|
prefix = datetime.now().strftime("%Y%m%d-%H%M%S.")
|
||||||
|
|
||||||
with NamedTemporaryFile(prefix=prefix, suffix=".png") as temp:
|
with NamedTemporaryFile(prefix=prefix, suffix=".png") as temp:
|
||||||
async with aiofiles.open(temp.name, "wb") as file:
|
|
||||||
await file.write(image)
|
|
||||||
|
|
||||||
await self.send_file(room_id, temp.name)
|
async def get_path() -> Path:
|
||||||
|
with io.BytesIO(image) as inp, io.BytesIO() as buffer:
|
||||||
|
PILImage.open(inp).save(buffer, "PNG", optimize=True)
|
||||||
|
|
||||||
|
async with aiofiles.open(temp.name, "wb") as file:
|
||||||
|
await file.write(buffer.getvalue())
|
||||||
|
|
||||||
|
return Path(temp.name)
|
||||||
|
|
||||||
|
await self.send_file(room_id, get_path)
|
||||||
|
|
||||||
|
|
||||||
async def send_file(self, room_id: str, path: Union[Path, str]) -> None:
|
async def send_file(self, room_id: str, path: PathCallable) -> None:
|
||||||
"""Send a `m.file`, `m.image`, `m.audio` or `m.video` message."""
|
"""Send a `m.file`, `m.image`, `m.audio` or `m.video` message."""
|
||||||
|
|
||||||
item_uuid = uuid4()
|
item_uuid = uuid4()
|
||||||
|
@ -579,22 +589,26 @@ class MatrixClient(nio.AsyncClient):
|
||||||
try:
|
try:
|
||||||
await self._send_file(item_uuid, room_id, path)
|
await self._send_file(item_uuid, room_id, path)
|
||||||
except (nio.TransferCancelledError, asyncio.CancelledError):
|
except (nio.TransferCancelledError, asyncio.CancelledError):
|
||||||
log.info("Deleting item for cancelled upload %s", item_uuid)
|
self.upload_monitors.pop(item_uuid, None)
|
||||||
del self.upload_monitors[item_uuid]
|
self.upload_tasks.pop(item_uuid, None)
|
||||||
del self.upload_tasks[item_uuid]
|
self.models[room_id, "uploads"].pop(str(item_uuid), None)
|
||||||
del self.models[room_id, "uploads"][str(item_uuid)]
|
|
||||||
|
|
||||||
|
|
||||||
async def _send_file(
|
async def _send_file(
|
||||||
self, item_uuid: UUID, room_id: str, path: Union[Path, str],
|
self, item_uuid: UUID, room_id: str, path: PathCallable,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Upload and monitor a file + thumbnail and send the built event."""
|
"""Upload and monitor a file + thumbnail and send the built event."""
|
||||||
|
|
||||||
# TODO: this function is way too complex, and most of it should be
|
# TODO: this function is way too complex, and most of it should be
|
||||||
# refactored into nio.
|
# refactored into nio.
|
||||||
|
|
||||||
|
self.upload_tasks[item_uuid] = current_task() # type: ignore
|
||||||
|
|
||||||
|
upload_item = Upload(item_uuid)
|
||||||
|
self.models[room_id, "uploads"][str(item_uuid)] = upload_item
|
||||||
|
|
||||||
transaction_id = uuid4()
|
transaction_id = uuid4()
|
||||||
path = Path(path)
|
path = Path(await path() if callable(path) else path)
|
||||||
encrypt = room_id in self.encrypted_rooms
|
encrypt = room_id in self.encrypted_rooms
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -603,13 +617,12 @@ class MatrixClient(nio.AsyncClient):
|
||||||
# This error will be caught again by the try block later below
|
# This error will be caught again by the try block later below
|
||||||
size = 0
|
size = 0
|
||||||
|
|
||||||
monitor = nio.TransferMonitor(size)
|
upload_item.set_fields(
|
||||||
upload_item = Upload(item_uuid, path, total_size=size)
|
status=UploadStatus.Uploading, filepath=path, total_size=size,
|
||||||
|
)
|
||||||
self.models[room_id, "uploads"][str(item_uuid)] = upload_item
|
|
||||||
|
|
||||||
|
monitor = nio.TransferMonitor(size)
|
||||||
self.upload_monitors[item_uuid] = monitor
|
self.upload_monitors[item_uuid] = monitor
|
||||||
self.upload_tasks[item_uuid] = current_task() # type: ignore
|
|
||||||
|
|
||||||
def on_transferred(transferred: int) -> None:
|
def on_transferred(transferred: int) -> None:
|
||||||
upload_item.uploaded = transferred
|
upload_item.uploaded = transferred
|
||||||
|
|
|
@ -311,6 +311,7 @@ class Member(ModelItem):
|
||||||
class UploadStatus(AutoStrEnum):
|
class UploadStatus(AutoStrEnum):
|
||||||
"""Enum describing the status of an upload operation."""
|
"""Enum describing the status of an upload operation."""
|
||||||
|
|
||||||
|
Preparing = auto()
|
||||||
Uploading = auto()
|
Uploading = auto()
|
||||||
Caching = auto()
|
Caching = auto()
|
||||||
Error = auto()
|
Error = auto()
|
||||||
|
@ -321,7 +322,7 @@ class Upload(ModelItem):
|
||||||
"""Represent a running or failed file upload operation."""
|
"""Represent a running or failed file upload operation."""
|
||||||
|
|
||||||
id: UUID = field()
|
id: UUID = field()
|
||||||
filepath: Path = field()
|
filepath: Path = Path("-")
|
||||||
|
|
||||||
total_size: int = 0
|
total_size: int = 0
|
||||||
uploaded: int = 0
|
uploaded: int = 0
|
||||||
|
@ -329,7 +330,7 @@ class Upload(ModelItem):
|
||||||
time_left: timedelta = timedelta(0)
|
time_left: timedelta = timedelta(0)
|
||||||
paused: bool = False
|
paused: bool = False
|
||||||
|
|
||||||
status: UploadStatus = UploadStatus.Uploading
|
status: UploadStatus = UploadStatus.Preparing
|
||||||
error: OptionalExceptionType = type(None)
|
error: OptionalExceptionType = type(None)
|
||||||
error_args: Tuple[Any, ...] = ()
|
error_args: Tuple[Any, ...] = ()
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,9 @@ HColumnLayout {
|
||||||
cancelPending ?
|
cancelPending ?
|
||||||
qsTr("Cancelling...") :
|
qsTr("Cancelling...") :
|
||||||
|
|
||||||
|
status === "Preparing" ?
|
||||||
|
qsTr("Preparing file...") :
|
||||||
|
|
||||||
status === "Uploading" ?
|
status === "Uploading" ?
|
||||||
fileName :
|
fileName :
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user