From 9d49418a1f81d3b368bba8e8454d33a9ee588770 Mon Sep 17 00:00:00 2001 From: Andrew Murphy Date: Sat, 14 Feb 2026 17:32:10 +1100 Subject: [PATCH] Set m.fully_read marker when marking rooms as read (#2587) Previously markAsRead() only sent m.read receipts via sendReadReceipt(). This meant the read position was not persisted across page refreshes, especially noticeable in bridged rooms. Now uses setRoomReadMarkers() which sets both: - m.fully_read marker (persistent read position) - m.read receipt Fixes issue where rooms would still show as unread after refresh. --- src/app/utils/notifications.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/app/utils/notifications.ts b/src/app/utils/notifications.ts index a23bd1a4..edab9196 100644 --- a/src/app/utils/notifications.ts +++ b/src/app/utils/notifications.ts @@ -1,6 +1,6 @@ import { MatrixClient, ReceiptType } from 'matrix-js-sdk'; -export async function markAsRead(mx: MatrixClient, roomId: string, privateReceipt: boolean) { +export async function markAsRead(mx: MatrixClient, roomId: string, privateReceipt?: boolean) { const room = mx.getRoom(roomId); if (!room) return; @@ -19,8 +19,15 @@ export async function markAsRead(mx: MatrixClient, roomId: string, privateReceip const latestEvent = getLatestValidEvent(); if (latestEvent === null) return; - await mx.sendReadReceipt( - latestEvent, - privateReceipt ? ReceiptType.ReadPrivate : ReceiptType.Read + const latestEventId = latestEvent.getId(); + if (!latestEventId) return; + + // Set both the read receipt AND the fully_read marker + // The fully_read marker is what persists your read position across sessions + await mx.setRoomReadMarkers( + roomId, + latestEventId, // m.fully_read marker + latestEvent, // m.read receipt event + privateReceipt ? { receiptType: ReceiptType.ReadPrivate } : undefined ); }