From 7fb79f6ea62e03772eb41a8be1f2e963ef15ca97 Mon Sep 17 00:00:00 2001 From: Ajay Bura Date: Thu, 17 Mar 2022 13:11:14 +0530 Subject: [PATCH] Add notification mark as read action Signed-off-by: Ajay Bura --- .../molecules/room-options/RoomOptions.jsx | 5 ++-- src/app/organisms/room/Room.jsx | 2 +- src/app/organisms/room/RoomViewContent.jsx | 13 +++++----- src/app/organisms/room/RoomViewFloating.jsx | 3 ++- src/client/action/notifications.js | 26 +++++++++++++++++++ src/client/state/RoomTimeline.js | 21 +-------------- 6 files changed, 39 insertions(+), 31 deletions(-) create mode 100644 src/client/action/notifications.js diff --git a/src/app/molecules/room-options/RoomOptions.jsx b/src/app/molecules/room-options/RoomOptions.jsx index 734f93bd..85b2b5a5 100644 --- a/src/app/molecules/room-options/RoomOptions.jsx +++ b/src/app/molecules/room-options/RoomOptions.jsx @@ -6,6 +6,7 @@ import { twemojify } from '../../../util/twemojify'; import initMatrix from '../../../client/initMatrix'; import { openInviteUser } from '../../../client/action/navigation'; import * as roomActions from '../../../client/action/room'; +import { markAsRead } from '../../../client/action/notifications'; import { MenuHeader, MenuItem } from '../../atoms/context-menu/ContextMenu'; import RoomNotification from '../room-notification/RoomNotification'; @@ -20,10 +21,8 @@ function RoomOptions({ roomId, afterOptionSelect }) { const canInvite = room?.canInvite(mx.getUserId()); const handleMarkAsRead = () => { + markAsRead(roomId); afterOptionSelect(); - if (!room) return; - const events = room.getLiveTimeline().getEvents(); - mx.sendReadReceipt(events[events.length - 1]); }; const handleInviteClick = () => { diff --git a/src/app/organisms/room/Room.jsx b/src/app/organisms/room/Room.jsx index 015fb689..7c199bea 100644 --- a/src/app/organisms/room/Room.jsx +++ b/src/app/organisms/room/Room.jsx @@ -26,7 +26,7 @@ function Room() { roomInfo.roomTimeline?.removeInternalListeners(); if (mx.getRoom(rId)) { setRoomInfo({ - roomTimeline: new RoomTimeline(rId, initMatrix.notifications), + roomTimeline: new RoomTimeline(rId), eventId: eId ?? null, }); } else { diff --git a/src/app/organisms/room/RoomViewContent.jsx b/src/app/organisms/room/RoomViewContent.jsx index e3f2aba4..dd77e989 100644 --- a/src/app/organisms/room/RoomViewContent.jsx +++ b/src/app/organisms/room/RoomViewContent.jsx @@ -14,6 +14,7 @@ import cons from '../../../client/state/cons'; import navigation from '../../../client/state/navigation'; import { openProfileViewer } from '../../../client/action/navigation'; import { diffMinutes, isInSameDay, Throttle } from '../../../util/common'; +import { markAsRead } from '../../../client/action/notifications'; import Divider from '../../atoms/divider/Divider'; import ScrollView from '../../atoms/scroll/ScrollView'; @@ -253,7 +254,7 @@ function useHandleScroll( ); roomTimeline.emit(cons.events.roomTimeline.AT_BOTTOM, isAtBottom); if (isAtBottom && readUptoEvtStore.getItem()) { - requestAnimationFrame(() => roomTimeline.markAllAsRead()); + requestAnimationFrame(() => markAsRead(roomTimeline.roomId)); } }); autoPaginate(); @@ -263,7 +264,7 @@ function useHandleScroll( const timelineScroll = timelineScrollRef.current; const limit = eventLimitRef.current; if (readUptoEvtStore.getItem()) { - requestAnimationFrame(() => roomTimeline.markAllAsRead()); + requestAnimationFrame(() => markAsRead(roomTimeline.roomId)); } if (roomTimeline.isServingLiveTimeline()) { limit.setFrom(roomTimeline.timeline.length - limit.maxEvents); @@ -286,7 +287,7 @@ function useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, event const limit = eventLimitRef.current; const trySendReadReceipt = (event) => { if (myUserId === event.getSender()) { - requestAnimationFrame(() => roomTimeline.markAllAsRead()); + requestAnimationFrame(() => markAsRead(roomTimeline.roomId)); return; } const readUpToEvent = readUptoEvtStore.getItem(); @@ -295,7 +296,7 @@ function useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, event if (isUnread === false) { if (document.visibilityState === 'visible' && timelineScroll.bottom < 16) { - requestAnimationFrame(() => roomTimeline.markAllAsRead()); + requestAnimationFrame(() => markAsRead(roomTimeline.roomId)); } else { readUptoEvtStore.setItem(roomTimeline.findEventByIdInTimelineSet(readUpToId)); } @@ -305,7 +306,7 @@ function useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, event const { timeline } = roomTimeline; const unreadMsgIsLast = timeline[timeline.length - 2].getId() === readUpToId; if (unreadMsgIsLast) { - requestAnimationFrame(() => roomTimeline.markAllAsRead()); + requestAnimationFrame(() => markAsRead(roomTimeline.roomId)); } }; @@ -399,7 +400,7 @@ function RoomViewContent({ eventId, roomTimeline }) { if (timelineScroll.bottom < 16 && !roomTimeline.canPaginateForward()) { const readUpToId = roomTimeline.getReadUpToEventId(); if (readUptoEvtStore.getItem()?.getId() === readUpToId || readUpToId === null) { - requestAnimationFrame(() => roomTimeline.markAllAsRead()); + requestAnimationFrame(() => markAsRead(roomTimeline.roomId)); } } jumpToItemIndex = -1; diff --git a/src/app/organisms/room/RoomViewFloating.jsx b/src/app/organisms/room/RoomViewFloating.jsx index 9020ffff..f7fda8ed 100644 --- a/src/app/organisms/room/RoomViewFloating.jsx +++ b/src/app/organisms/room/RoomViewFloating.jsx @@ -5,6 +5,7 @@ import './RoomViewFloating.scss'; import initMatrix from '../../../client/initMatrix'; import cons from '../../../client/state/cons'; +import { markAsRead } from '../../../client/action/notifications'; import Text from '../../atoms/text/Text'; import Button from '../../atoms/button/Button'; @@ -24,7 +25,7 @@ function useJumpToEvent(roomTimeline) { }; const cancelJumpToEvent = () => { - roomTimeline.markAllAsRead(); + markAsRead(roomTimeline.roomId); setEventId(null); }; diff --git a/src/client/action/notifications.js b/src/client/action/notifications.js new file mode 100644 index 00000000..a869632a --- /dev/null +++ b/src/client/action/notifications.js @@ -0,0 +1,26 @@ +import initMatrix from '../initMatrix'; + +// eslint-disable-next-line import/prefer-default-export +export async function markAsRead(roomId) { + const mx = initMatrix.matrixClient; + const room = mx.getRoom(roomId); + if (!room) return; + initMatrix.notifications.deleteNoti(roomId); + + const timeline = room.getLiveTimeline().getEvents(); + const readEventId = room.getEventReadUpTo(mx.getUserId()); + + const getLatestValidEvent = () => { + for (let i = timeline.length - 1; i >= 0; i -= 1) { + const latestEvent = timeline[i]; + if (latestEvent.getId() === readEventId) return null; + if (!latestEvent.isSending()) return latestEvent; + } + return null; + }; + if (timeline.length === 0) return; + const latestEvent = getLatestValidEvent(); + if (latestEvent === null) return; + + await mx.sendReadReceipt(latestEvent); +} diff --git a/src/client/state/RoomTimeline.js b/src/client/state/RoomTimeline.js index 95a607db..57d91c14 100644 --- a/src/client/state/RoomTimeline.js +++ b/src/client/state/RoomTimeline.js @@ -77,7 +77,7 @@ function isTimelineLinked(tm1, tm2) { } class RoomTimeline extends EventEmitter { - constructor(roomId, notifications) { + constructor(roomId) { super(); // These are local timelines this.timeline = []; @@ -88,7 +88,6 @@ class RoomTimeline extends EventEmitter { this.matrixClient = initMatrix.matrixClient; this.roomId = roomId; this.room = this.matrixClient.getRoom(roomId); - this.notifications = notifications; this.liveTimeline = this.room.getLiveTimeline(); this.activeTimeline = this.liveTimeline; @@ -228,24 +227,6 @@ class RoomTimeline extends EventEmitter { return Promise.allSettled(decryptionPromises); } - markAllAsRead() { - const readEventId = this.getReadUpToEventId(); - const getLatestValidEvent = () => { - for (let i = this.timeline.length - 1; i >= 0; i -= 1) { - const latestEvent = this.timeline[i]; - if (latestEvent.getId() === readEventId) return null; - if (!latestEvent.isSending()) return latestEvent; - } - return null; - }; - this.notifications.deleteNoti(this.roomId); - if (this.timeline.length === 0) return; - const latestEvent = getLatestValidEvent(); - if (latestEvent === null) return; - if (readEventId === latestEvent.getId()) return; - this.matrixClient.sendReadReceipt(latestEvent); - } - hasEventInTimeline(eventId, timeline = this.activeTimeline) { const timelineSet = this.getUnfilteredTimelineSet(); const eventTimeline = timelineSet.getTimelineForEvent(eventId);