Room context menu: notification setting checkmark

Indicate which notification override setting is currently active
This commit is contained in:
miruka 2021-02-28 09:52:51 -04:00
parent af321d8eae
commit 0017a1562c
4 changed files with 85 additions and 14 deletions

View File

@ -41,8 +41,8 @@ from .errors import (
from .html_markdown import HTML_PROCESSOR as HTML
from .media_cache import Media, Thumbnail
from .models.items import (
ZERO_DATE, Account, Event, Member, PushRule, Room, Transfer,
TransferStatus, TypeSpecifier,
ZERO_DATE, Account, Event, Member, PushRule, Room,
RoomNotificationOverride, Transfer, TransferStatus, TypeSpecifier,
)
from .models.model_store import ModelStore
from .nio_callbacks import NioCallbacks
@ -1919,13 +1919,25 @@ class MatrixClient(nio.AsyncClient):
await self.delete_pushrule("global", kind, rule_id)
def _rule_overrides_room(self, rule: PushRule) -> Optional[str]:
override = rule.kind is nio.PushRuleKind.override
one_cnd = len(rule.conditions) == 1
if not one_cnd:
return None
cnd = nio.PushCondition.from_dict(rule.conditions[0])
ev_match = isinstance(cnd, nio.PushEventMatch)
if override and ev_match and cnd.key == "room_id":
return cnd.pattern
return None
async def _remove_room_override_rule(self, room_id: str) -> None:
for rule in self.models[self.user_id, "pushrules"].values():
override_kind = rule.kind is nio.PushRuleKind.override
this_room_cnd = nio.PushEventMatch("room_id", room_id).as_value
if (override_kind and rule.conditions == [this_room_cnd]):
print(rule)
if self._rule_overrides_room(rule) == room_id:
await self.remove_pushrule(rule.kind, rule.rule_id)
@ -2015,7 +2027,6 @@ class MatrixClient(nio.AsyncClient):
) -> None:
"""Register/update a `nio.MatrixRoom` as a `models.items.Room`."""
# Add room
inviter = getattr(room, "inviter", "") or ""
levels = room.power_levels
can_send_state = partial(levels.can_user_send_state, self.user_id)
@ -2044,7 +2055,28 @@ class MatrixClient(nio.AsyncClient):
)
unverified_devices = registered.unverified_devices
notification_setting = RoomNotificationOverride.UseDefaultSettings
for rule in self.models[self.user_id, "pushrules"].values():
overrides = self._rule_overrides_room(rule) == room.room_id
is_room_kind = rule.kind is nio.PushRuleKind.room
room_kind_match = is_room_kind and rule.rule_id == room.room_id
if overrides and not rule.actions:
notification_setting = RoomNotificationOverride.IgnoreEvents
break
elif overrides:
notification_setting = RoomNotificationOverride.AllEvents
break
elif room_kind_match and not rule.actions:
notification_setting = RoomNotificationOverride.HighlightsOnly
break
elif room_kind_match:
notification_setting = RoomNotificationOverride.AllEvents
break
pinned = self.backend.settings.RoomList.Pinned
room_item = Room(
id = room.room_id,
for_account = self.user_id,
@ -2085,9 +2117,10 @@ class MatrixClient(nio.AsyncClient):
last_event_date = last_event_date,
unreads = room.unread_notifications,
highlights = room.unread_highlights,
local_unreads = local_unreads,
unreads = room.unread_notifications,
highlights = room.unread_highlights,
local_unreads = local_unreads,
notification_setting = notification_setting,
lexical_sorting = self.backend.settings.RoomList.lexical_sort,
pinned = room.room_id in pinned.get(self.user_id, []),

View File

@ -38,6 +38,16 @@ class PingStatus(AutoStrEnum):
Failed = auto()
class RoomNotificationOverride(AutoStrEnum):
"""Possible per-room notification override settings, as displayed in the
left sidepane's context menu when right-clicking a room.
"""
UseDefaultSettings = auto()
AllEvents = auto()
HighlightsOnly = auto()
IgnoreEvents = auto()
@dataclass(eq=False)
class Homeserver(ModelItem):
"""A homeserver we can connect to. The `id` field is the server's URL."""
@ -170,6 +180,9 @@ class Room(ModelItem):
highlights: int = 0
local_unreads: bool = False
notification_setting: RoomNotificationOverride = \
RoomNotificationOverride.UseDefaultSettings
lexical_sorting: bool = False
pinned: bool = False
@ -229,6 +242,12 @@ class Room(ModelItem):
@dataclass(eq=False)
class AccountOrRoom(Account, Room):
"""The left sidepane in the GUI lists a mixture of accounts and rooms
giving a tree view illusion. Since all items in a QML ListView must have
the same available properties, this class inherits both
`Account` and `Room` to fulfill that purpose.
"""
type: Union[Type[Account], Type[Room]] = Account
account_order: int = -1

View File

@ -4,7 +4,7 @@
import asyncio
import json
import logging as log
from dataclasses import asdict, dataclass, field
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from html import escape
from pathlib import Path
@ -783,6 +783,18 @@ class NioCallbacks:
# Account data callbacks
async def onPushRulesEvent(self, ev: nio.PushRulesEvent) -> None:
async def update_affected_room(rule: PushRule) -> None:
affects_room: Optional[str]
if rule.kind == nio.PushRuleKind.room:
affects_room = rule.rule_id
else:
affects_room = self.client._rule_overrides_room(rule)
if affects_room in self.client.rooms:
nio_room = self.client.rooms[affects_room]
await self.client.register_nio_room(nio_room)
model = self.models[self.user_id, "pushrules"]
kinds: Dict[nio.PushRuleKind, List[nio.PushRule]] = {
@ -800,9 +812,10 @@ class NioCallbacks:
new_keys.add((kind.value, rule.id))
with model.batch_remove():
for key in tuple(model):
for key, rule in list(model.items()):
if key not in new_keys:
del model[key]
await update_affected_room(rule)
# Then, add new rules/modify changed existing ones
@ -825,7 +838,7 @@ class NioCallbacks:
sound = str(tweaks.get("sound") or "")
hint = tweaks.get("urgency_hint", bool(sound)) is not False
model[kind.value, rule.id] = PushRule(
rule_item = PushRule(
id = (kind.value, rule.id),
kind = kind,
rule_id = rule.id,
@ -841,6 +854,8 @@ class NioCallbacks:
sound = sound,
urgency_hint = hint,
)
model[kind.value, rule.id] = rule_item
await update_affected_room(rule_item)
self.client.push_rules = ev

View File

@ -152,6 +152,7 @@ HTile {
HMenuItem {
text: qsTr("Use default account settings")
checked: model.notification_setting === "UseDefaultSettings"
onTriggered: py.callClientCoro(
model.for_account, "room_pushrule_use_default", [model.id],
)
@ -159,6 +160,7 @@ HTile {
HMenuItem {
text: qsTr("All new messages")
checked: model.notification_setting === "AllEvents"
onTriggered: py.callClientCoro(
model.for_account, "room_pushrule_all_events", [model.id],
)
@ -166,6 +168,7 @@ HTile {
HMenuItem {
text: qsTr("Highlights only (replies, keywords...)")
checked: model.notification_setting === "HighlightsOnly"
onTriggered: py.callClientCoro(
model.for_account,
"room_pushrule_highlights_only",
@ -175,6 +178,7 @@ HTile {
HMenuItem {
text: qsTr("Ignore new messages")
checked: model.notification_setting === "IgnoreEvents"
onTriggered: py.callClientCoro(
model.for_account, "room_pushrule_ignore_all", [model.id],
)