From 6e202c3e271519fa2904152769e78d7c6ded0803 Mon Sep 17 00:00:00 2001 From: vslg Date: Wed, 1 Jul 2020 17:55:03 -0300 Subject: [PATCH] Fix outdated presence for lazy loaded members --- src/backend/backend.py | 7 ++- src/backend/matrix_client.py | 15 +++---- src/backend/models/items.py | 44 +++++++++++++------ src/backend/nio_callbacks.py | 18 +++----- src/gui/Base/HUserAvatar.qml | 2 +- .../RoomPane/MemberView/MemberDelegate.qml | 8 ++-- 6 files changed, 55 insertions(+), 39 deletions(-) diff --git a/src/backend/backend.py b/src/backend/backend.py index 4b497340..6d489d2b 100644 --- a/src/backend/backend.py +++ b/src/backend/backend.py @@ -6,7 +6,7 @@ import os import sys import traceback from pathlib import Path -from typing import Any, DefaultDict, Dict, List, Optional +from typing import TYPE_CHECKING, Any, DefaultDict, Dict, List, Optional from appdirs import AppDirs @@ -23,6 +23,9 @@ from .models.model import Model from .models.model_store import ModelStore from .user_files import Accounts, History, Theme, UISettings, UIState +if TYPE_CHECKING: + from .models.items import Presence + # Logging configuration log.getLogger().setLevel(log.INFO) nio.logger_group.level = nio.log.logbook.ERROR @@ -109,6 +112,8 @@ class Backend: self.media_cache: MediaCache = MediaCache(self, cache_dir) + self.presences: Dict[str, "Presence"] = {} + def __repr__(self) -> str: return f"{type(self).__name__}(clients={self.clients!r})" diff --git a/src/backend/matrix_client.py b/src/backend/matrix_client.py index ac400b17..4542cfa7 100644 --- a/src/backend/matrix_client.py +++ b/src/backend/matrix_client.py @@ -113,8 +113,6 @@ class MatrixClient(nio.AsyncClient): } low_limit_filter: ClassVar[Dict[str, Any]] = { - "presence": {"limit": 1}, - "room": { "ephemeral": {"limit": 1}, "timeline": { @@ -1565,7 +1563,8 @@ class MatrixClient(nio.AsyncClient): async def add_member(self, room: nio.MatrixRoom, user_id: str) -> None: """Register/update a room member into our models.""" - member = room.users[user_id] + member = room.users[user_id] + presence = self.backend.presences.get(user_id, Presence()) self.models[self.user_id, room.room_id, "members"][user_id] = Member( id = user_id, @@ -1576,12 +1575,10 @@ class MatrixClient(nio.AsyncClient): power_level = member.power_level, invited = member.invited, - last_active_ago = -1 if member.last_active_ago is None else - member.last_active_ago, - - currently_active = member.currently_active or False, - presence = member.presence or Presence.Offline, - status_message = member.status_msg or "", + presence = presence.presence, + last_active_ago = presence.last_active_ago, + status_msg = presence.status_msg, + currently_active = presence.currently_active, ) if member.display_name: diff --git a/src/backend/models/items.py b/src/backend/models/items.py index 46135897..45cb0755 100644 --- a/src/backend/models/items.py +++ b/src/backend/models/items.py @@ -29,10 +29,26 @@ class TypeSpecifier(AutoStrEnum): MembershipChange = auto() -class Presence(AutoStrEnum): - Offline = auto() # can mean offline, invisible or unknwon - Unavailable = auto() - Online = auto() +@dataclass +class Presence(): + class State(AutoStrEnum): + offline = auto() # can mean offline, invisible or unknwon + unavailable = auto() + online = auto() + + def __lt__(self, other: "Presence.State") -> bool: + order = [self.online, self.unavailable, self.offline] + + return ( + order.index(self) # type: ignore + ) < ( + order.index(other) # type: ignore + ) + + status_msg: str = "" + presence: State = State.offline + last_active_ago: int = -1 + currently_active: bool = False @dataclass @@ -169,7 +185,7 @@ class AccountOrRoom(Account, Room): @dataclass -class Member(ModelItem): +class Member(Presence, ModelItem): """A member in a matrix room.""" id: str = field() @@ -183,22 +199,22 @@ class Member(ModelItem): last_read_event: str = "" last_read_at: datetime = ZeroDate - last_active_ago: int = -1 - currently_active: bool = False - presence: Presence = Presence.Offline - status_message: str = "" - - def __lt__(self, other: "Member") -> bool: - """Sort by power level, then by display name/user ID.""" + """Sort by presence, power level, then by display name/user ID.""" name = self.display_name or self.id[1:] other_name = other.display_name or other.id[1:] return ( - self.invited, other.power_level, name.lower(), + self.presence, + self.invited, + other.power_level, + name.lower(), ) < ( - other.invited, self.power_level, other_name.lower(), + other.presence, + other.invited, + self.power_level, + other_name.lower(), ) diff --git a/src/backend/nio_callbacks.py b/src/backend/nio_callbacks.py index 2b90d84f..53595798 100644 --- a/src/backend/nio_callbacks.py +++ b/src/backend/nio_callbacks.py @@ -592,14 +592,10 @@ class NioCallbacks: # Presence event callbacks async def onPresenceEvent(self, ev: nio.PresenceEvent) -> None: - for room_id in self.models[self.user_id, "rooms"]: - member = \ - self.models[self.user_id, room_id, "members"].get(ev.user_id) - - if member: - member.last_active_ago = \ - -1 if ev.last_active_ago is None else ev.last_active_ago - - member.currently_active = ev.currently_active or False - member.presence = ev.presence or Presence.Offline - member.status_message = ev.status_msg or "" + self.client.backend.presences[ev.user_id] = Presence( + status_msg = ev.status_msg or "", + presence = Presence.State(ev.presence) if ev.presence + else Presence.State.offline, + last_active_ago = ev.last_active_ago or -1, + currently_active = ev.currently_active, + ) diff --git a/src/gui/Base/HUserAvatar.qml b/src/gui/Base/HUserAvatar.qml index f0f9072d..f04d343d 100644 --- a/src/gui/Base/HUserAvatar.qml +++ b/src/gui/Base/HUserAvatar.qml @@ -54,7 +54,7 @@ HAvatar { } HLoader { - active: presence + active: presence && presence !== "offline" anchors.bottom: parent.bottom anchors.right: parent.right anchors.bottomMargin: -diameter / 2 diff --git a/src/gui/Pages/Chat/RoomPane/MemberView/MemberDelegate.qml b/src/gui/Pages/Chat/RoomPane/MemberView/MemberDelegate.qml index de04882b..dc271132 100644 --- a/src/gui/Pages/Chat/RoomPane/MemberView/MemberDelegate.qml +++ b/src/gui/Pages/Chat/RoomPane/MemberView/MemberDelegate.qml @@ -46,8 +46,10 @@ HTile { text: model.presence === "offline" && model.last_active_ago !== -1 ? - "offline for " + - utils.formatRelativeTime(model.last_active_ago) : + "for " + + utils.formatRelativeTime( + model.last_active_ago + ) : "" } } @@ -55,7 +57,7 @@ HTile { SubtitleLabel { tile: member color: theme.chat.roomPane.listView.member.subtitle - text: model.status_message.trim() || model.id + text: model.status_msg.trim() || model.id } } }