Visual unread mentions counter

This commit is contained in:
miruka 2020-03-22 23:55:48 -04:00
parent 367fff8f4a
commit ef2504ecae
6 changed files with 71 additions and 20 deletions

View File

@ -7,6 +7,7 @@ from typing import DefaultDict, Dict
from urllib.parse import unquote from urllib.parse import unquote
import html_sanitizer.sanitizer as sanitizer import html_sanitizer.sanitizer as sanitizer
import lxml.html # nosec
import mistune import mistune
from html_sanitizer.sanitizer import Sanitizer from html_sanitizer.sanitizer import Sanitizer
from lxml.html import HtmlElement, etree # nosec from lxml.html import HtmlElement, etree # nosec
@ -173,6 +174,19 @@ class HTMLProcessor:
] ]
def user_id_link_in_html(self, html: str, user_id: str) -> bool:
if not html.strip():
return False
regex = re.compile(rf"https?://matrix.to/#/{user_id}", re.IGNORECASE)
for _, _, href, _ in lxml.html.iterlinks(html):
if regex.match(unquote(href.strip())):
return True
return False
def from_markdown( def from_markdown(
self, self,
text: str, text: str,

View File

@ -1073,9 +1073,11 @@ class MatrixClient(nio.AsyncClient):
registered = self.models[self.user_id, "rooms"][room.room_id] registered = self.models[self.user_id, "rooms"][room.room_id]
last_event_date = registered.last_event_date last_event_date = registered.last_event_date
typing_members = registered.typing_members typing_members = registered.typing_members
mentions = registered.mentions
except KeyError: except KeyError:
last_event_date = datetime.fromtimestamp(0) last_event_date = datetime.fromtimestamp(0)
typing_members = [] typing_members = []
mentions = 0
self.models[self.user_id, "rooms"][room.room_id] = Room( self.models[self.user_id, "rooms"][room.room_id] = Room(
id = room.room_id, id = room.room_id,
@ -1108,6 +1110,7 @@ class MatrixClient(nio.AsyncClient):
can_set_guest_access = can_send_state("m.room.guest_access"), can_set_guest_access = can_send_state("m.room.guest_access"),
last_event_date = last_event_date, last_event_date = last_event_date,
mentions = mentions,
) )

View File

@ -80,6 +80,8 @@ class Room(ModelItem):
last_event_date: datetime = ZeroDate last_event_date: datetime = ZeroDate
mentions: int = 0
def __lt__(self, other: "Room") -> bool: def __lt__(self, other: "Room") -> bool:
"""Sort by join state, then descending last event date, then name. """Sort by join state, then descending last event date, then name.

View File

@ -100,6 +100,11 @@ class NioCallbacks:
room_id = room.room_id, room_id = room.room_id,
) )
if HTML_PROCESSOR.user_id_link_in_html(co, self.client.user_id):
rooms = self.client.models[self.client.user_id, "rooms"]
rooms[room.room_id].mentions += 1
await self.client.register_nio_event(room, ev, content=co) await self.client.register_nio_event(room, ev, content=co)

View File

@ -6,6 +6,7 @@ import QtQuick.Layouts 1.12
HButton { HButton {
id: tile id: tile
signal leftClicked() signal leftClicked()
signal rightClicked() signal rightClicked()
@ -24,6 +25,7 @@ HButton {
property Component image property Component image
contentItem: HRowLayout { contentItem: HRowLayout {
id: contentItem id: contentItem
spacing: tile.spacing spacing: tile.spacing
@ -50,34 +52,37 @@ HButton {
Layout.fillHeight: true Layout.fillHeight: true
} }
HLabel {
id: rightInfo
font.pixelSize: theme.fontSize.small
verticalAlignment: Qt.AlignVCenter
color: theme.colors.halfDimText
visible: Layout.maximumWidth > 0
Layout.fillHeight: true
Layout.maximumWidth:
text && tile.width >= 200 * theme.uiScale ?
implicitWidth : 0
Behavior on Layout.maximumWidth { HNumberAnimation {} }
}
HRowLayout { HRowLayout {
id: additionalInfo id: additionalInfo
visible: visibleChildren.length > 0 visible: visibleChildren.length > 0
} }
HLabel {
id: rightInfo
font.pixelSize: theme.fontSize.small
color: theme.colors.halfDimText
visible: Layout.maximumWidth > 0
Layout.fillHeight: true
Layout.maximumWidth:
text && tile.width >= 160 * theme.uiScale ?
implicitWidth : 0
Behavior on Layout.maximumWidth { HNumberAnimation {} }
}
} }
HRichLabel { HRichLabel {
id: subtitle id: subtitle
textFormat: Text.StyledText textFormat: Text.StyledText
font.pixelSize: theme.fontSize.small font.pixelSize: theme.fontSize.small
verticalAlignment: Qt.AlignVCenter
elide: Text.ElideRight elide: Text.ElideRight
color: theme.colors.dimText color: theme.colors.dimText
visible: Layout.maximumHeight > 0 visible: Layout.maximumHeight > 0
Layout.maximumHeight: ! compact && text ? implicitHeight : 0 Layout.maximumHeight: ! compact && text ? implicitHeight : 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true

View File

@ -33,14 +33,36 @@ HTileDelegate {
title.color: theme.mainPane.listView.room.name title.color: theme.mainPane.listView.room.name
title.text: model.display_name || qsTr("Empty room") title.text: model.display_name || qsTr("Empty room")
additionalInfo.children: HIcon { additionalInfo.children: [
HLabel {
text: model.mentions
font.pixelSize: theme.fontSize.small
verticalAlignment: Qt.AlignVCenter
leftPadding: theme.spacing / 4
rightPadding: leftPadding
scale: model.mentions === 0 ? 0 : 1
visible: scale > 0
background: Rectangle {
color: theme.colors.alertBackground
radius: theme.radius / 4
}
Behavior on scale { HNumberAnimation {} }
},
HIcon {
svgName: "invite-received" svgName: "invite-received"
colorize: theme.colors.alertBackground colorize: theme.colors.alertBackground
small: room.compact
visible: invited
Layout.maximumWidth: invited ? implicitWidth : 0 Layout.maximumWidth: invited ? implicitWidth : 0
Behavior on Layout.maximumWidth { HNumberAnimation {} } Behavior on Layout.maximumWidth { HNumberAnimation {} }
} }
]
subtitle.color: theme.mainPane.listView.room.subtitle subtitle.color: theme.mainPane.listView.room.subtitle
subtitle.textFormat: Text.StyledText subtitle.textFormat: Text.StyledText