@@ -190,6 +190,13 @@ interface IRoomProps extends RoomViewProps {
190190 * If true, hide the widgets
191191 */
192192 hideWidgets ?: boolean ;
193+
194+ /**
195+ * If true, enable sending read receipts and markers on user activity in the room view. When the user interacts with the room view, read receipts and markers are sent.
196+ * If false, the read receipts and markers are only send when the room view is focused. The user has to focus the room view in order to clear any unreads and to move the unread marker to the bottom of the view.
197+ * @default true
198+ */
199+ enableReadReceiptsAndMarkersOnActivity ?: boolean ;
193200}
194201
195202export { MainSplitContentType } ;
@@ -418,6 +425,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
418425 public static contextType = SDKContext ;
419426 declare public context : React . ContextType < typeof SDKContext > ;
420427
428+ public static readonly defaultProps = {
429+ enableReadReceiptsAndMarkersOnActivity : true ,
430+ } ;
431+
421432 public constructor ( props : IRoomProps , context : React . ContextType < typeof SDKContext > ) {
422433 super ( props , context ) ;
423434
@@ -2182,6 +2193,19 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
21822193 }
21832194 } ;
21842195
2196+ /**
2197+ * Handles the focus event on the RoomView component.
2198+ *
2199+ * Sends read receipts and updates the read marker if the
2200+ * disableReadReceiptsAndMarkersOnActivity prop is set.
2201+ */
2202+ private onFocus = ( ) : void => {
2203+ if ( this . props . enableReadReceiptsAndMarkersOnActivity ) return ;
2204+
2205+ this . messagePanel ?. sendReadReceipts ( ) ;
2206+ this . messagePanel ?. updateReadMarker ( ) ;
2207+ } ;
2208+
21852209 public render ( ) : ReactNode {
21862210 if ( ! this . context . client ) return null ;
21872211 const { isRoomEncrypted } = this . state ;
@@ -2539,7 +2563,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
25392563 timelineSet = { this . state . room . getUnfilteredTimelineSet ( ) }
25402564 showReadReceipts = { this . state . showReadReceipts }
25412565 manageReadReceipts = { ! this . state . isPeeking }
2542- sendReadReceiptOnLoad = { ! this . state . wasContextSwitch }
2566+ sendReadReceiptOnLoad = {
2567+ ! this . state . wasContextSwitch && this . props . enableReadReceiptsAndMarkersOnActivity
2568+ }
25432569 manageReadMarkers = { ! this . state . isPeeking }
25442570 hidden = { hideMessagePanel }
25452571 highlightedEventId = { highlightedEventId }
@@ -2556,6 +2582,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
25562582 showReactions = { true }
25572583 layout = { this . state . layout }
25582584 editState = { this . state . editState }
2585+ enableReadReceiptsAndMarkersOnActivity = { this . props . enableReadReceiptsAndMarkersOnActivity }
25592586 />
25602587 ) ;
25612588 }
@@ -2622,7 +2649,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
26222649 < Measured sensor = { this . roomViewBody } onMeasurement = { this . onMeasurement } />
26232650 { auxPanel }
26242651 { pinnedMessageBanner }
2625- < main className = { timelineClasses } >
2652+ < main className = { timelineClasses } data-testid = "timeline" >
26262653 < FileDropTarget
26272654 parent = { this . roomView . current }
26282655 onFileDrop = { this . onFileDrop }
@@ -2683,7 +2710,13 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
26832710
26842711 return (
26852712 < ScopedRoomContextProvider { ...this . state } roomViewStore = { this . roomViewStore } >
2686- < div className = { mainClasses } ref = { this . roomView } onKeyDown = { this . onReactKeyDown } >
2713+ < div
2714+ className = { mainClasses }
2715+ ref = { this . roomView }
2716+ onKeyDown = { this . onReactKeyDown }
2717+ onFocus = { this . onFocus }
2718+ tabIndex = { - 1 }
2719+ >
26872720 { showChatEffects && this . roomView . current && (
26882721 < EffectsOverlay roomWidth = { this . roomView . current . offsetWidth } />
26892722 ) }
0 commit comments