Add a batch set_fields method to Model
This commit is contained in:
parent
5476e00b9b
commit
4752abf6e5
|
@ -301,13 +301,14 @@ class Backend:
|
|||
|
||||
async def update(client: MatrixClient) -> None:
|
||||
room = self.models[client.user_id, "rooms"].get(room_id)
|
||||
local = room.local_unreads or room.local_highlights
|
||||
|
||||
if room and (room.unreads or room.highlights or local):
|
||||
room.unreads = 0
|
||||
room.highlights = 0
|
||||
room.local_unreads = False
|
||||
room.local_highlights = False
|
||||
if room:
|
||||
room.set_fields(
|
||||
unreads = 0,
|
||||
highlights = 0,
|
||||
local_unreads = False,
|
||||
local_highlights = False,
|
||||
)
|
||||
await client.update_account_unread_counts()
|
||||
await client.update_receipt_marker(room_id, event_id)
|
||||
|
||||
|
|
|
@ -354,9 +354,11 @@ class MatrixClient(nio.AsyncClient):
|
|||
resp = await self.backend.get_profile(self.user_id, use_cache=False)
|
||||
|
||||
account = self.models["accounts"][self.user_id]
|
||||
account.profile_updated = datetime.now()
|
||||
account.display_name = resp.displayname or ""
|
||||
account.avatar_url = resp.avatar_url or ""
|
||||
account.set_fields(
|
||||
profile_updated = datetime.now(),
|
||||
display_name = resp.displayname or "",
|
||||
avatar_url = resp.avatar_url or "",
|
||||
)
|
||||
|
||||
|
||||
async def get_server_config(self) -> int:
|
||||
|
@ -528,8 +530,10 @@ class MatrixClient(nio.AsyncClient):
|
|||
upload_item.uploaded = transferred
|
||||
|
||||
def on_speed_changed(speed: float) -> None:
|
||||
upload_item.speed = speed
|
||||
upload_item.time_left = monitor.remaining_time or timedelta(0)
|
||||
upload_item.set_fields(
|
||||
speed = speed,
|
||||
time_left = monitor.remaining_time or timedelta(0),
|
||||
)
|
||||
|
||||
monitor.on_transferred = on_transferred
|
||||
monitor.on_speed_changed = on_speed_changed
|
||||
|
@ -548,9 +552,11 @@ class MatrixClient(nio.AsyncClient):
|
|||
raise nio.TransferCancelledError()
|
||||
|
||||
except (MatrixError, OSError) as err:
|
||||
upload_item.status = UploadStatus.Error
|
||||
upload_item.error = type(err)
|
||||
upload_item.error_args = err.args
|
||||
upload_item.set_fields(
|
||||
status = UploadStatus.Error,
|
||||
error = type(err),
|
||||
error_args = err.args,
|
||||
)
|
||||
|
||||
# Wait for cancellation from UI, see parent send_file() method
|
||||
while True:
|
||||
|
@ -605,9 +611,11 @@ class MatrixClient(nio.AsyncClient):
|
|||
thumb_ext = "png" if thumb_info.mime == "image/png" else "jpg"
|
||||
thumb_name = f"{path.stem}_thumbnail.{thumb_ext}"
|
||||
|
||||
upload_item.status = UploadStatus.Uploading
|
||||
upload_item.filepath = Path(thumb_name)
|
||||
upload_item.total_size = len(thumb_data)
|
||||
upload_item.set_fields(
|
||||
status = UploadStatus.Uploading,
|
||||
filepath = Path(thumb_name),
|
||||
total_size = len(thumb_data),
|
||||
)
|
||||
|
||||
try:
|
||||
upload_item.total_size = thumb_info.size
|
||||
|
@ -1385,10 +1393,12 @@ class MatrixClient(nio.AsyncClient):
|
|||
local_highlights = True
|
||||
|
||||
account = self.models["accounts"][self.user_id]
|
||||
account.total_unread = unreads
|
||||
account.total_highlights = highlights
|
||||
account.local_unreads = local_unreads
|
||||
account.local_highlights = local_highlights
|
||||
account.set_fields(
|
||||
total_unread = unreads,
|
||||
total_highlights = highlights,
|
||||
local_unreads = local_unreads,
|
||||
local_highlights = local_highlights,
|
||||
)
|
||||
|
||||
|
||||
async def event_is_past(self, ev: Union[nio.Event, Event]) -> bool:
|
||||
|
@ -1552,13 +1562,11 @@ class MatrixClient(nio.AsyncClient):
|
|||
|
||||
if not ev.sender_name and not ev.sender_avatar:
|
||||
sender_name, sender_avatar, _ = await get_profile(ev.sender_id)
|
||||
ev.sender_name = sender_name
|
||||
ev.sender_avatar = sender_avatar
|
||||
ev.set_fields(sender_name=sender_name, sender_avatar=sender_avatar)
|
||||
|
||||
if ev.target_id and not ev.target_name and not ev.target_avatar:
|
||||
target_name, target_avatar, _ = await get_profile(ev.target_id)
|
||||
ev.target_name = target_name
|
||||
ev.target_avatar = target_avatar
|
||||
ev.set_fields(target_name=target_name, target_avatar=target_avatar)
|
||||
|
||||
if ev.redacter_id and not ev.redacter_name:
|
||||
redacter_name, _, _ = await get_profile(ev.target_id)
|
||||
|
|
|
@ -33,32 +33,34 @@ class ModelItem:
|
|||
def __setattr__(self, name: str, value) -> None:
|
||||
"""If this item is in a `Model`, alert it of attribute changes."""
|
||||
|
||||
if name == "parent_model" or not self.parent_model:
|
||||
if (
|
||||
name == "parent_model" or
|
||||
not self.parent_model or
|
||||
getattr(self, name) == value
|
||||
):
|
||||
super().__setattr__(name, value)
|
||||
return
|
||||
|
||||
if getattr(self, name) == value:
|
||||
return
|
||||
|
||||
super().__setattr__(name, value)
|
||||
self._notify_parent_model({name: self.serialize_field(name)})
|
||||
|
||||
|
||||
def _notify_parent_model(self, changed_fields: Dict[str, Any]) -> None:
|
||||
parent = self.parent_model
|
||||
|
||||
if not parent.sync_id:
|
||||
if not parent or not parent.sync_id or not changed_fields:
|
||||
return
|
||||
|
||||
fields = {name: self.serialize_field(name)}
|
||||
|
||||
with parent.write_lock:
|
||||
index_then = parent._sorted_data.index(self)
|
||||
parent._sorted_data.sort()
|
||||
index_now = parent._sorted_data.index(self)
|
||||
|
||||
ModelItemSet(parent.sync_id, index_then, index_now, fields)
|
||||
ModelItemSet(parent.sync_id, index_then, index_now, changed_fields)
|
||||
|
||||
for sync_id, proxy in parent.proxies.items():
|
||||
if sync_id != parent.sync_id:
|
||||
proxy.source_item_set(parent, self.id, self, fields)
|
||||
proxy.source_item_set(parent, self.id, self, changed_fields)
|
||||
|
||||
|
||||
def __delattr__(self, name: str) -> None:
|
||||
|
@ -82,3 +84,20 @@ class ModelItem:
|
|||
name.startswith("_") or name in ("parent_model", "serialized")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
def set_fields(self, **fields: Any) -> None:
|
||||
"""Set multiple fields's values at once.
|
||||
|
||||
The parent model will be resorted only once, and one `ModelItemSet`
|
||||
event will be sent informing QML of all the changed fields.
|
||||
"""
|
||||
|
||||
for name, value in fields.copy().items():
|
||||
if getattr(self, name) == value:
|
||||
del fields[name]
|
||||
else:
|
||||
super().__setattr__(name, value)
|
||||
fields[name] = self.serialize_field(name)
|
||||
|
||||
self._notify_parent_model(fields)
|
||||
|
|
|
@ -388,9 +388,11 @@ class NioCallbacks:
|
|||
account = self.models["accounts"][self.user_id]
|
||||
|
||||
if account.profile_updated < ev_date:
|
||||
account.profile_updated = ev_date
|
||||
account.display_name = now.get("displayname") or ""
|
||||
account.avatar_url = now.get("avatar_url") or ""
|
||||
account.set_fields(
|
||||
profile_updated = ev_date,
|
||||
display_name = now.get("displayname") or "",
|
||||
avatar_url = now.get("avatar_url") or "",
|
||||
)
|
||||
|
||||
if self.client.backend.ui_settings["hideProfileChangeEvents"]:
|
||||
return None
|
||||
|
@ -568,6 +570,8 @@ class NioCallbacks:
|
|||
member = model.get(receipt.user_id)
|
||||
|
||||
if member:
|
||||
member.last_read_event = receipt.event_id
|
||||
timestamp = receipt.timestamp / 1000
|
||||
member.last_read_at = datetime.fromtimestamp(timestamp)
|
||||
member.set_fields(
|
||||
last_read_event = receipt.event_id,
|
||||
last_read_at = datetime.fromtimestamp(timestamp),
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue
Block a user