Fix presence loop with unavailable/offline
Yes, again. Also removes echo presence states to simplify things.
This commit is contained in:
parent
47cfd7c7b0
commit
94bf41dc3e
|
@ -388,9 +388,7 @@ class Backend:
|
|||
await client.update_account_unread_counts()
|
||||
|
||||
if account.presence not in [
|
||||
Presence.State.echo_invisible,
|
||||
Presence.State.invisible,
|
||||
Presence.State.offline,
|
||||
Presence.State.invisible, Presence.State.offline,
|
||||
]:
|
||||
await client.update_receipt_marker(room_id, event_id)
|
||||
|
||||
|
|
|
@ -307,7 +307,7 @@ class MatrixClient(nio.AsyncClient):
|
|||
)
|
||||
|
||||
# TODO: be able to set presence before logging in
|
||||
item.set_fields(presence=Presence.State.echo_online, connecting=True)
|
||||
item.set_fields(presence=Presence.State.online, connecting=True)
|
||||
self._presence = "online"
|
||||
self.start_task = asyncio.ensure_future(self._start())
|
||||
|
||||
|
@ -327,9 +327,6 @@ class MatrixClient(nio.AsyncClient):
|
|||
account = self.models["accounts"][user_id]
|
||||
self._presence = "offline" if state == "invisible" else state
|
||||
|
||||
if state in ("online", "unavailable"):
|
||||
state = f"echo_{state}"
|
||||
|
||||
account.set_fields(
|
||||
presence=Presence.State(state), status_msg=status_msg,
|
||||
)
|
||||
|
@ -1386,7 +1383,6 @@ class MatrixClient(nio.AsyncClient):
|
|||
return
|
||||
|
||||
if self.models["accounts"][self.user_id].presence not in [
|
||||
Presence.State.echo_invisible,
|
||||
Presence.State.invisible,
|
||||
Presence.State.offline,
|
||||
]:
|
||||
|
@ -1596,15 +1592,14 @@ class MatrixClient(nio.AsyncClient):
|
|||
|
||||
account = self.models["accounts"][self.user_id]
|
||||
call_presence_api = True
|
||||
new_presence = presence
|
||||
for_server = "offline" if presence == "invisible" else presence
|
||||
self._presence = "offline" if presence == "invisible" else presence
|
||||
|
||||
if status_msg is None:
|
||||
status_msg = account.status_msg
|
||||
|
||||
# Starting/stopping client if current/new presence is offline
|
||||
|
||||
if new_presence == "offline":
|
||||
if presence == "offline":
|
||||
if account.presence == Presence.State.offline:
|
||||
return
|
||||
|
||||
|
@ -1620,7 +1615,6 @@ class MatrixClient(nio.AsyncClient):
|
|||
# We might receive a recent status_msg set from another client on
|
||||
# startup, so don't try to set a new one immediatly.
|
||||
# Presence though will be sent on first sync.
|
||||
self._presence = for_server
|
||||
call_presence_api = False
|
||||
account.connecting = True
|
||||
self.start_task = asyncio.ensure_future(self._start())
|
||||
|
@ -1629,9 +1623,9 @@ class MatrixClient(nio.AsyncClient):
|
|||
|
||||
if (
|
||||
Presence.State(presence) != account.presence and
|
||||
new_presence != "offline"
|
||||
presence != "offline"
|
||||
):
|
||||
account.presence = Presence.State("echo_" + new_presence)
|
||||
account.presence = Presence.State(presence)
|
||||
|
||||
# Saving new details in accounts.json
|
||||
|
||||
|
@ -1639,7 +1633,7 @@ class MatrixClient(nio.AsyncClient):
|
|||
account.save_presence = True
|
||||
|
||||
await self.backend.saved_accounts.set(
|
||||
self.user_id, presence=new_presence, status_msg=status_msg,
|
||||
self.user_id, presence=presence, status_msg=status_msg,
|
||||
)
|
||||
else:
|
||||
account.save_presence = False
|
||||
|
@ -1648,7 +1642,7 @@ class MatrixClient(nio.AsyncClient):
|
|||
|
||||
if call_presence_api:
|
||||
account.status_msg = status_msg
|
||||
await super().set_presence(for_server, status_msg)
|
||||
await super().set_presence(self._presence, status_msg)
|
||||
|
||||
|
||||
async def import_keys(self, infile: str, passphrase: str) -> None:
|
||||
|
|
|
@ -870,20 +870,29 @@ class NioCallbacks:
|
|||
async def onPresenceEvent(
|
||||
self, ev: Union[nio.PresenceEvent, nio.PresenceGetResponse],
|
||||
) -> None:
|
||||
|
||||
# Servers that send presence events support presence
|
||||
self.models["accounts"][self.client.user_id].presence_support = True
|
||||
|
||||
account = self.models["accounts"].get(ev.user_id)
|
||||
presence = self.client.backend.presences.get(ev.user_id, Presence())
|
||||
invisible = False
|
||||
|
||||
if account:
|
||||
client = self.client.backend.clients[ev.user_id]
|
||||
invisible = account.presence == Presence.State.invisible
|
||||
client = self.client.backend.clients[ev.user_id]
|
||||
|
||||
# Synapse is stupid enough to return an older presence state on
|
||||
# sync, which then causes a never-ending loop of presence cycling.
|
||||
# Let's hope they didn't screw up the get_presence API too:
|
||||
ev = await client.get_presence(ev.user_id)
|
||||
|
||||
invisible = account and "invisible" in account.presence.value
|
||||
if ev.presence == "offline" and not invisible:
|
||||
to_set = account.presence.value
|
||||
await client.set_presence(to_set, account.status_msg)
|
||||
return
|
||||
elif not (invisible and ev.presence != "offline"):
|
||||
client._presence = ev.presence
|
||||
|
||||
if invisible and ev.presence == "offline":
|
||||
presence.presence = Presence.State.invisible
|
||||
|
@ -891,7 +900,15 @@ class NioCallbacks:
|
|||
presence.presence = Presence.State(ev.presence)
|
||||
|
||||
presence.currently_active = ev.currently_active or False
|
||||
presence.status_msg = ev.status_msg or ""
|
||||
|
||||
# Restore status msg lost from server due to e.g. getting offline
|
||||
if account and account.status_msg and not ev.status_msg:
|
||||
if invisible:
|
||||
presence.status_msg = account.status_msg
|
||||
else:
|
||||
await client.set_presence(ev.presence, account.status_msg)
|
||||
else:
|
||||
presence.status_msg = ev.status_msg or ""
|
||||
|
||||
if ev.last_active_ago:
|
||||
presence.last_active_at = datetime.now() - timedelta(
|
||||
|
@ -909,58 +926,21 @@ class NioCallbacks:
|
|||
|
||||
presence.update_members()
|
||||
|
||||
# If presence event represents a change for one of our account
|
||||
if account and account.presence != Presence.State.offline:
|
||||
client = self.client.backend.clients[ev.user_id]
|
||||
|
||||
# Ignore cases where we send a new presence to the server, but it
|
||||
# returns an older state that doesn't match due to lag:
|
||||
if (
|
||||
account.presence == Presence.State.echo_invisible and
|
||||
ev.presence != Presence.State.offline.value
|
||||
) or (
|
||||
account.presence == Presence.State.echo_unavailable and
|
||||
ev.presence != Presence.State.unavailable.value
|
||||
) or (
|
||||
account.presence == Presence.State.echo_online and
|
||||
ev.presence != Presence.State.online.value
|
||||
):
|
||||
return
|
||||
|
||||
# Do not fight back presence from other clients, unless server says
|
||||
# we're offline, which happens if another client disconnected or we
|
||||
# had a long connection issue. Note that this makes invisibility
|
||||
# only possible if we're the only client using the account, or the
|
||||
# other clients are invisible/offline themselves.
|
||||
if ev.presence != Presence.State.offline.value:
|
||||
client._presence = ev.presence
|
||||
|
||||
# Restore status msg lost from server due to e.g. getting offline
|
||||
if not ev.status_msg and account.status_msg:
|
||||
if invisible:
|
||||
presence.status_msg = account.status_msg
|
||||
else:
|
||||
await client.set_presence(ev.presence, account.status_msg)
|
||||
|
||||
# Save the presence to be restored next time we restart application
|
||||
if account.save_presence:
|
||||
status_msg = presence.status_msg
|
||||
state = presence.presence
|
||||
|
||||
if account.presence == Presence.State.echo_invisible:
|
||||
status_msg = account.status_msg
|
||||
state = Presence.State.invisible
|
||||
elif state == Presence.State.echo_online:
|
||||
state = Presence.State.online
|
||||
elif state == Presence.State.echo_unavailable:
|
||||
state = Presence.State.unavailable
|
||||
|
||||
await self.client.backend.saved_accounts.set(
|
||||
user_id = ev.user_id,
|
||||
status_msg = status_msg,
|
||||
presence = state.value,
|
||||
)
|
||||
|
||||
presence.update_account()
|
||||
else:
|
||||
if not account:
|
||||
self.client.backend.presences[ev.user_id] = presence
|
||||
return
|
||||
|
||||
client = self.client.backend.clients[ev.user_id]
|
||||
|
||||
# Save the presence to be restored next time we restart application
|
||||
if account.save_presence:
|
||||
status_msg = presence.status_msg
|
||||
state = presence.presence
|
||||
|
||||
await self.client.backend.saved_accounts.set(
|
||||
user_id = ev.user_id,
|
||||
status_msg = status_msg,
|
||||
presence = state.value,
|
||||
)
|
||||
|
||||
presence.update_account()
|
||||
|
|
|
@ -12,12 +12,9 @@ if TYPE_CHECKING:
|
|||
|
||||
ORDER: Dict[str, int] = {
|
||||
"online": 0,
|
||||
"echo_online": 1,
|
||||
"unavailable": 2,
|
||||
"echo_unavailable": 3,
|
||||
"invisible": 4,
|
||||
"echo_invisible": 5,
|
||||
"offline": 6,
|
||||
"unavailable": 1,
|
||||
"invisible": 2,
|
||||
"offline": 3,
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,10 +57,6 @@ class Presence:
|
|||
online = auto()
|
||||
invisible = auto()
|
||||
|
||||
echo_unavailable = auto()
|
||||
echo_online = auto()
|
||||
echo_invisible = auto()
|
||||
|
||||
def __lt__(self, other: "Presence.State") -> bool:
|
||||
return ORDER[self.value] < ORDER[other.value]
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@ Rectangle {
|
|||
|
||||
implicitHeight: width
|
||||
radius: width / 2
|
||||
opacity:
|
||||
theme.controls.presence.opacity * (presence.includes("echo") ? 0.5 : 1)
|
||||
opacity: theme.controls.presence.opacity
|
||||
|
||||
color:
|
||||
presence.includes("online") ?
|
||||
|
|
Loading…
Reference in New Issue
Block a user