Make desktop notifications follow push rules
This commit is contained in:
parent
2ef1edb3dc
commit
3dd12691b8
|
@ -4,17 +4,22 @@
|
|||
- PCN error handling
|
||||
- Change docs linking to dev branch back to master
|
||||
|
||||
- Implement fallback QML notifications, usable if dbus isn't available
|
||||
- profiles missing in notifications
|
||||
- option to use plaintext notifications
|
||||
- Notification urgency level (plyer)?
|
||||
- Rename the alertOn(Mention/Message)ForMsec options, default Message to non-0
|
||||
- Make local unread counter an optional turned off by default
|
||||
|
||||
- fix DeviceSection padding
|
||||
- Implement fallback QML notifications, usable if dbus isn't available
|
||||
- annoying tooltips when menu open
|
||||
- profiles missing in notifications
|
||||
|
||||
- add http_proxy support
|
||||
- image viewer: can't expand image in reduced window layout
|
||||
- Encrypted rooms don't show invites in member list after Mirage restart
|
||||
- Room display name not updated when someone removes theirs
|
||||
- Fix right margin of own `<image url>\n<image url>` messages
|
||||
- option to use plaintext notifications
|
||||
- warn on ambiguously activated shortcut
|
||||
|
||||
- SSO device delete?
|
||||
|
|
|
@ -209,8 +209,7 @@ class MatrixClient(nio.AsyncClient):
|
|||
self.unassigned_event_last_read_by: DefaultDict[str, Dict[str, int]] =\
|
||||
DefaultDict(dict)
|
||||
|
||||
self.previous_server_unreads: Dict[str, int] = {}
|
||||
self.previous_server_highlights: Dict[str, int] = {}
|
||||
self.push_rules: nio.PushRulesEvent = nio.PushRulesEvent()
|
||||
|
||||
# {room_id: event}
|
||||
self.power_level_events: Dict[str, nio.PowerLevelsEvent] = {}
|
||||
|
@ -2247,55 +2246,52 @@ class MatrixClient(nio.AsyncClient):
|
|||
await self.update_account_unread_counts()
|
||||
return item
|
||||
|
||||
self.models[self.user_id, "rooms"][room.room_id].local_unreads = True
|
||||
await self.update_account_unread_counts()
|
||||
|
||||
# Alerts & notifications
|
||||
|
||||
room_item = self.models[self.user_id, "rooms"][room.room_id]
|
||||
name = self.models["accounts"][self.user_id].display_name
|
||||
nio_rule = self.push_rules.global_rules.matching_rule(ev, room, name)
|
||||
|
||||
unread = \
|
||||
room_item.unreads and \
|
||||
room_item.unreads != \
|
||||
self.previous_server_unreads.get(room.room_id, 0)
|
||||
if not nio_rule:
|
||||
return item
|
||||
|
||||
highlight = \
|
||||
room_item.highlights and \
|
||||
room_item.highlights != \
|
||||
self.previous_server_highlights.get(room.room_id, 0)
|
||||
model = self.models[self.user_id, "pushrules"]
|
||||
rule = model[nio_rule.kind.value, nio_rule.id]
|
||||
|
||||
self.previous_server_unreads[room.room_id] = room_item.unreads
|
||||
self.previous_server_highlights[room.room_id] = room_item.highlights
|
||||
if not rule.notify and not rule.highlight:
|
||||
return item
|
||||
|
||||
room_item.local_unreads = True
|
||||
sender = item.sender_name or item.sender_id
|
||||
|
||||
if unread or highlight:
|
||||
members = self.models[self.user_id, room.room_id, "members"]
|
||||
room_name = room.display_name
|
||||
sender = item.sender_name or item.sender_id
|
||||
|
||||
if isinstance(ev, nio.RoomMessageEmote):
|
||||
body = f"<i>{sender} {item.inline_content}</i>"
|
||||
elif not isinstance(ev, nio.RoomMessage):
|
||||
body = item.inline_content.replace(
|
||||
"%1", item.sender_name or item.sender_id,
|
||||
).replace(
|
||||
"%2", item.target_name or item.target_id,
|
||||
)
|
||||
elif len(members) == 2 and room_name == sender:
|
||||
body = item.inline_content
|
||||
else:
|
||||
body = f"{sender}: {item.inline_content}"
|
||||
|
||||
NotificationRequested(
|
||||
id = item.id,
|
||||
high_importance = highlight,
|
||||
title = room_name,
|
||||
|
||||
body = body.replace(" ⏎ ", "<br>")
|
||||
.replace(" ⏎⏎ ", f"<br>{'─' * 24}<br>"),
|
||||
|
||||
image = await self.get_notification_avatar(
|
||||
mxc=item.sender_avatar, user_id=item.sender_id,
|
||||
) if item.sender_avatar else "",
|
||||
if isinstance(ev, nio.RoomMessageEmote):
|
||||
body = f"<i>{sender} {item.inline_content}</i>"
|
||||
elif not isinstance(ev, nio.RoomMessage):
|
||||
body = item.inline_content.replace(
|
||||
"%1", item.sender_name or item.sender_id,
|
||||
).replace(
|
||||
"%2", item.target_name or item.target_id,
|
||||
)
|
||||
elif room.member_count == 2 and room.display_name == sender:
|
||||
body = item.inline_content
|
||||
else:
|
||||
body = f"{sender}: {item.inline_content}"
|
||||
|
||||
NotificationRequested(
|
||||
id = item.id,
|
||||
critical = rule.highlight,
|
||||
bubble = rule.bubble,
|
||||
sound = rule.sound,
|
||||
urgency_hint = rule.urgency_hint,
|
||||
|
||||
title = room.display_name,
|
||||
body = body.replace(" ⏎ ", "<br>")
|
||||
.replace(" ⏎⏎ ", f"<br>{'─' * 24}<br>"),
|
||||
|
||||
image = await self.get_notification_avatar(
|
||||
mxc=item.sender_avatar, user_id=item.sender_id,
|
||||
) if item.sender_avatar else "",
|
||||
)
|
||||
|
||||
await self.update_account_unread_counts()
|
||||
return item
|
||||
|
|
|
@ -839,6 +839,8 @@ class NioCallbacks:
|
|||
urgency_hint = hint,
|
||||
)
|
||||
|
||||
self.client.push_rules = ev
|
||||
|
||||
|
||||
# Presence event callbacks
|
||||
|
||||
|
|
|
@ -31,17 +31,22 @@ class PyOtherSideEvent:
|
|||
|
||||
@dataclass
|
||||
class NotificationRequested(PyOtherSideEvent):
|
||||
"""Request a notification and window manager alert to be shown.
|
||||
"""Request a notification bubble, sound or window urgency hint.
|
||||
|
||||
Alerts set the urgency hint for compliant X11/Wayland window managers or
|
||||
flash the program's taskbar icon on Windows.
|
||||
Urgency hints usually flash or highlight the program's icon in a taskbar,
|
||||
dock or panel.
|
||||
"""
|
||||
|
||||
id: str = field()
|
||||
title: str = field()
|
||||
body: str = ""
|
||||
image: Union[Path, str] = ""
|
||||
high_importance: bool = False
|
||||
id: str = field()
|
||||
critical: bool = False
|
||||
bubble: bool = False
|
||||
sound: bool = False
|
||||
urgency_hint: bool = False
|
||||
|
||||
# Bubble parameters
|
||||
title: str = ""
|
||||
body: str = ""
|
||||
image: Union[Path, str] = ""
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
@ -8,26 +8,33 @@ import ".."
|
|||
QtObject {
|
||||
signal deviceUpdateSignal(string forAccount)
|
||||
|
||||
function onNotificationRequested(id, title, body, image, highImportance) {
|
||||
function onNotificationRequested(
|
||||
id, critical, bubble, sound, urgencyHint, title, body, image,
|
||||
) {
|
||||
const level = window.notificationLevel
|
||||
|
||||
if (level === Window.NotificationLevel.None) return
|
||||
if (level === Window.MentionsKeywords && ! highImportance) return
|
||||
if (level === Window.MentionsKeywords && ! critical) return
|
||||
if (window.notifiedIds.has(id)) return
|
||||
|
||||
window.notifiedIds.add(id)
|
||||
window.notifiedIdsChanged()
|
||||
|
||||
if (Qt.application.state === Qt.ApplicationActive) return
|
||||
if (Qt.application.state === Qt.ApplicationActive)
|
||||
return
|
||||
|
||||
py.callCoro("desktop_notify", [title, body, image])
|
||||
if (bubble)
|
||||
py.callCoro("desktop_notify", [title, body, image])
|
||||
|
||||
const msec =
|
||||
highImportance ?
|
||||
window.settings.Notifications.urgent_alert_time * 1000 :
|
||||
window.settings.Notifications.alert_time * 1000
|
||||
if (urgencyHint) {
|
||||
const msec =
|
||||
critical ?
|
||||
window.settings.Notifications.urgent_alert_time * 1000 :
|
||||
window.settings.Notifications.alert_time * 1000
|
||||
|
||||
if (msec) window.alert(msec === -1 ? 0 : msec) // -1 → 0 = no time out
|
||||
// -1 ? 0 for no time out : msec
|
||||
if (msec !== 0) window.alert(msec === -1 ? 0 : msec)
|
||||
}
|
||||
}
|
||||
|
||||
function onCoroutineDone(uuid, result, error, traceback) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user