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()
|
await client.update_account_unread_counts()
|
||||||
|
|
||||||
if account.presence not in [
|
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)
|
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
|
# 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._presence = "online"
|
||||||
self.start_task = asyncio.ensure_future(self._start())
|
self.start_task = asyncio.ensure_future(self._start())
|
||||||
|
|
||||||
|
@ -327,9 +327,6 @@ class MatrixClient(nio.AsyncClient):
|
||||||
account = self.models["accounts"][user_id]
|
account = self.models["accounts"][user_id]
|
||||||
self._presence = "offline" if state == "invisible" else state
|
self._presence = "offline" if state == "invisible" else state
|
||||||
|
|
||||||
if state in ("online", "unavailable"):
|
|
||||||
state = f"echo_{state}"
|
|
||||||
|
|
||||||
account.set_fields(
|
account.set_fields(
|
||||||
presence=Presence.State(state), status_msg=status_msg,
|
presence=Presence.State(state), status_msg=status_msg,
|
||||||
)
|
)
|
||||||
|
@ -1386,7 +1383,6 @@ class MatrixClient(nio.AsyncClient):
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.models["accounts"][self.user_id].presence not in [
|
if self.models["accounts"][self.user_id].presence not in [
|
||||||
Presence.State.echo_invisible,
|
|
||||||
Presence.State.invisible,
|
Presence.State.invisible,
|
||||||
Presence.State.offline,
|
Presence.State.offline,
|
||||||
]:
|
]:
|
||||||
|
@ -1596,15 +1592,14 @@ class MatrixClient(nio.AsyncClient):
|
||||||
|
|
||||||
account = self.models["accounts"][self.user_id]
|
account = self.models["accounts"][self.user_id]
|
||||||
call_presence_api = True
|
call_presence_api = True
|
||||||
new_presence = presence
|
self._presence = "offline" if presence == "invisible" else presence
|
||||||
for_server = "offline" if presence == "invisible" else presence
|
|
||||||
|
|
||||||
if status_msg is None:
|
if status_msg is None:
|
||||||
status_msg = account.status_msg
|
status_msg = account.status_msg
|
||||||
|
|
||||||
# Starting/stopping client if current/new presence is offline
|
# Starting/stopping client if current/new presence is offline
|
||||||
|
|
||||||
if new_presence == "offline":
|
if presence == "offline":
|
||||||
if account.presence == Presence.State.offline:
|
if account.presence == Presence.State.offline:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -1620,7 +1615,6 @@ class MatrixClient(nio.AsyncClient):
|
||||||
# We might receive a recent status_msg set from another client on
|
# We might receive a recent status_msg set from another client on
|
||||||
# startup, so don't try to set a new one immediatly.
|
# startup, so don't try to set a new one immediatly.
|
||||||
# Presence though will be sent on first sync.
|
# Presence though will be sent on first sync.
|
||||||
self._presence = for_server
|
|
||||||
call_presence_api = False
|
call_presence_api = False
|
||||||
account.connecting = True
|
account.connecting = True
|
||||||
self.start_task = asyncio.ensure_future(self._start())
|
self.start_task = asyncio.ensure_future(self._start())
|
||||||
|
@ -1629,9 +1623,9 @@ class MatrixClient(nio.AsyncClient):
|
||||||
|
|
||||||
if (
|
if (
|
||||||
Presence.State(presence) != account.presence and
|
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
|
# Saving new details in accounts.json
|
||||||
|
|
||||||
|
@ -1639,7 +1633,7 @@ class MatrixClient(nio.AsyncClient):
|
||||||
account.save_presence = True
|
account.save_presence = True
|
||||||
|
|
||||||
await self.backend.saved_accounts.set(
|
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:
|
else:
|
||||||
account.save_presence = False
|
account.save_presence = False
|
||||||
|
@ -1648,7 +1642,7 @@ class MatrixClient(nio.AsyncClient):
|
||||||
|
|
||||||
if call_presence_api:
|
if call_presence_api:
|
||||||
account.status_msg = status_msg
|
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:
|
async def import_keys(self, infile: str, passphrase: str) -> None:
|
||||||
|
|
|
@ -870,20 +870,29 @@ class NioCallbacks:
|
||||||
async def onPresenceEvent(
|
async def onPresenceEvent(
|
||||||
self, ev: Union[nio.PresenceEvent, nio.PresenceGetResponse],
|
self, ev: Union[nio.PresenceEvent, nio.PresenceGetResponse],
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
# Servers that send presence events support presence
|
# Servers that send presence events support presence
|
||||||
self.models["accounts"][self.client.user_id].presence_support = True
|
self.models["accounts"][self.client.user_id].presence_support = True
|
||||||
|
|
||||||
account = self.models["accounts"].get(ev.user_id)
|
account = self.models["accounts"].get(ev.user_id)
|
||||||
presence = self.client.backend.presences.get(ev.user_id, Presence())
|
presence = self.client.backend.presences.get(ev.user_id, Presence())
|
||||||
|
invisible = False
|
||||||
|
|
||||||
if account:
|
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
|
# Synapse is stupid enough to return an older presence state on
|
||||||
# sync, which then causes a never-ending loop of presence cycling.
|
# sync, which then causes a never-ending loop of presence cycling.
|
||||||
# Let's hope they didn't screw up the get_presence API too:
|
# Let's hope they didn't screw up the get_presence API too:
|
||||||
ev = await client.get_presence(ev.user_id)
|
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":
|
if invisible and ev.presence == "offline":
|
||||||
presence.presence = Presence.State.invisible
|
presence.presence = Presence.State.invisible
|
||||||
|
@ -891,7 +900,15 @@ class NioCallbacks:
|
||||||
presence.presence = Presence.State(ev.presence)
|
presence.presence = Presence.State(ev.presence)
|
||||||
|
|
||||||
presence.currently_active = ev.currently_active or False
|
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:
|
if ev.last_active_ago:
|
||||||
presence.last_active_at = datetime.now() - timedelta(
|
presence.last_active_at = datetime.now() - timedelta(
|
||||||
|
@ -909,58 +926,21 @@ class NioCallbacks:
|
||||||
|
|
||||||
presence.update_members()
|
presence.update_members()
|
||||||
|
|
||||||
# If presence event represents a change for one of our account
|
if not 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:
|
|
||||||
self.client.backend.presences[ev.user_id] = presence
|
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] = {
|
ORDER: Dict[str, int] = {
|
||||||
"online": 0,
|
"online": 0,
|
||||||
"echo_online": 1,
|
"unavailable": 1,
|
||||||
"unavailable": 2,
|
"invisible": 2,
|
||||||
"echo_unavailable": 3,
|
"offline": 3,
|
||||||
"invisible": 4,
|
|
||||||
"echo_invisible": 5,
|
|
||||||
"offline": 6,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,10 +57,6 @@ class Presence:
|
||||||
online = auto()
|
online = auto()
|
||||||
invisible = auto()
|
invisible = auto()
|
||||||
|
|
||||||
echo_unavailable = auto()
|
|
||||||
echo_online = auto()
|
|
||||||
echo_invisible = auto()
|
|
||||||
|
|
||||||
def __lt__(self, other: "Presence.State") -> bool:
|
def __lt__(self, other: "Presence.State") -> bool:
|
||||||
return ORDER[self.value] < ORDER[other.value]
|
return ORDER[self.value] < ORDER[other.value]
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,7 @@ Rectangle {
|
||||||
|
|
||||||
implicitHeight: width
|
implicitHeight: width
|
||||||
radius: width / 2
|
radius: width / 2
|
||||||
opacity:
|
opacity: theme.controls.presence.opacity
|
||||||
theme.controls.presence.opacity * (presence.includes("echo") ? 0.5 : 1)
|
|
||||||
|
|
||||||
color:
|
color:
|
||||||
presence.includes("online") ?
|
presence.includes("online") ?
|
||||||
|
|
Loading…
Reference in New Issue
Block a user