diff --git a/src/backend/matrix_client.py b/src/backend/matrix_client.py
index 7aca3d98..279019ce 100644
--- a/src/backend/matrix_client.py
+++ b/src/backend/matrix_client.py
@@ -2078,6 +2078,7 @@ class MatrixClient(nio.AsyncClient):
target_avatar = target_avatar,
links = Event.parse_links(content),
last_read_by = last_read_by,
+ read_by_count = len(last_read_by),
fetch_profile =
(must_fetch_sender or must_fetch_target)
diff --git a/src/backend/models/items.py b/src/backend/models/items.py
index c7be827a..53d42a71 100644
--- a/src/backend/models/items.py
+++ b/src/backend/models/items.py
@@ -332,6 +332,7 @@ class Event(ModelItem):
# {user_id: server_timestamp} - QML can't parse dates from JSONified dicts
last_read_by: Dict[str, int] = field(default_factory=dict)
+ read_by_count: int = 0
is_local_echo: bool = False
source: Optional[nio.Event] = None
diff --git a/src/backend/nio_callbacks.py b/src/backend/nio_callbacks.py
index 97ce1a50..e79c2a23 100644
--- a/src/backend/nio_callbacks.py
+++ b/src/backend/nio_callbacks.py
@@ -734,6 +734,7 @@ class NioCallbacks:
event_model = self.models[self.user_id, room.room_id, "events"]
unassigned_mems = self.client.unassigned_member_last_read_event
unassigned_evs = self.client.unassigned_event_last_read_by
+ recount_markers = []
for receipt in ev.receipts:
if receipt.user_id in self.client.backend.clients:
@@ -747,6 +748,7 @@ class NioCallbacks:
timestamp = receipt.timestamp
if read_event:
+ recount_markers.append(read_event)
read_event.last_read_by[receipt.user_id] = timestamp
read_event.notify_change("last_read_by")
else:
@@ -764,11 +766,15 @@ class NioCallbacks:
if previous_read_event:
# Remove the read marker from the previous last read event
+ recount_markers.append(previous_read_event)
previous_read_event.last_read_by.pop(receipt.user_id, None)
previous_read_event.notify_change("last_read_by")
member.last_read_event = echo_id or receipt.event_id
+ for ev in recount_markers:
+ ev.read_by_count = len(ev.last_read_by)
+
# Presence event callbacks
diff --git a/src/gui/Pages/Chat/Timeline/EventContent.qml b/src/gui/Pages/Chat/Timeline/EventContent.qml
index 0eb321b6..2867118e 100644
--- a/src/gui/Pages/Chat/Timeline/EventContent.qml
+++ b/src/gui/Pages/Chat/Timeline/EventContent.qml
@@ -34,10 +34,14 @@ HRowLayout {
)
property string contentText: utils.processedEventText(model)
readonly property string timeText: utils.formatTime(model.date, false)
- readonly property string localEchoText:
- model.is_local_echo ?
- ` ⏳` :
- ""
+
+ readonly property string readInfoText:
+ `` + (
+ model.is_local_echo ? ` ⏳` :
+ model.read_by_count ? ` ⦿ ${model.read_by_count}` :
+ ""
+ ) + ""
readonly property bool pureMedia: ! contentText && linksRepeater.count
@@ -166,9 +170,7 @@ HRowLayout {
timeText +
"" +
- // Local echo icon
- (model.is_local_echo ?
- ` ⏳` : "")
+ readInfoText
transform: Translate { x: xOffset }
@@ -315,7 +317,7 @@ HRowLayout {
mediaUrl: modelData
showSender: pureMedia ? senderText : ""
showDate: pureMedia ? timeText : ""
- showLocalEcho: pureMedia ? localEchoText : ""
+ showLocalEcho: pureMedia ? readInfoText : ""
transform: Translate { x: xOffset }