Fix new message not appearing (#391)
authorAjay Bura <32841439+ajbura@users.noreply.github.com>
Thu, 17 Mar 2022 02:46:49 +0000 (08:16 +0530)
committerGitHub <noreply@github.com>
Thu, 17 Mar 2022 02:46:49 +0000 (08:16 +0530)
* Fix new message no appearing

Signed-off-by: Ajay Bura <ajbura@gmail.com>
* Fix room not marking as read

Signed-off-by: Ajay Bura <ajbura@gmail.com>
* Fix room automatically gets mark as read

Signed-off-by: Ajay Bura <ajbura@gmail.com>
* Fix sending wrong read recipt

Signed-off-by: Ajay Bura <ajbura@gmail.com>
* Fix sending message not mark as read

Signed-off-by: Ajay Bura <ajbura@gmail.com>
src/app/organisms/room/Room.jsx
src/app/organisms/room/RoomViewContent.jsx
src/client/state/RoomTimeline.js

index b8972d61efc04e0507d1836d7f67c0862d7b551d..015fb689d7000343a573ca6451bef8dce19dc7da 100644 (file)
@@ -13,33 +13,46 @@ import RoomSettings from './RoomSettings';
 import PeopleDrawer from './PeopleDrawer';
 
 function Room() {
-  const [roomTimeline, setRoomTimeline] = useState(null);
-  const [eventId, setEventId] = useState(null);
+  const [roomInfo, setRoomInfo] = useState({
+    roomTimeline: null,
+    eventId: null,
+  });
   const [isDrawer, setIsDrawer] = useState(settings.isPeopleDrawer);
 
   const mx = initMatrix.matrixClient;
-  const handleRoomSelected = (rId, pRoomId, eId) => {
-    if (mx.getRoom(rId)) {
-      setRoomTimeline(new RoomTimeline(rId, initMatrix.notifications));
-      setEventId(eId);
-    } else {
-      // TODO: add ability to join room if roomId is invalid
-      setRoomTimeline(null);
-      setEventId(null);
-    }
-  };
-  const handleDrawerToggling = (visiblity) => setIsDrawer(visiblity);
 
   useEffect(() => {
+    const handleRoomSelected = (rId, pRoomId, eId) => {
+      roomInfo.roomTimeline?.removeInternalListeners();
+      if (mx.getRoom(rId)) {
+        setRoomInfo({
+          roomTimeline: new RoomTimeline(rId, initMatrix.notifications),
+          eventId: eId ?? null,
+        });
+      } else {
+        // TODO: add ability to join room if roomId is invalid
+        setRoomInfo({
+          roomTimeline: null,
+          eventId: null,
+        });
+      }
+    };
+
     navigation.on(cons.events.navigation.ROOM_SELECTED, handleRoomSelected);
-    settings.on(cons.events.settings.PEOPLE_DRAWER_TOGGLED, handleDrawerToggling);
     return () => {
       navigation.removeListener(cons.events.navigation.ROOM_SELECTED, handleRoomSelected);
+    };
+  }, [roomInfo]);
+
+  useEffect(() => {
+    const handleDrawerToggling = (visiblity) => setIsDrawer(visiblity);
+    settings.on(cons.events.settings.PEOPLE_DRAWER_TOGGLED, handleDrawerToggling);
+    return () => {
       settings.removeListener(cons.events.settings.PEOPLE_DRAWER_TOGGLED, handleDrawerToggling);
-      roomTimeline?.removeInternalListeners();
     };
   }, []);
 
+  const { roomTimeline, eventId } = roomInfo;
   if (roomTimeline === null) return <Welcome />;
 
   return (
index 751e83544e6215cbe713103f6b66cacd604f74e3..e3f2aba4cc06c413e8522fd8899b6c5ce219b59d 100644 (file)
@@ -145,13 +145,12 @@ function useTimeline(roomTimeline, eventId, readUptoEvtStore, eventLimitRef) {
 
       if (isSpecificEvent) {
         focusEventIndex = roomTimeline.getEventIndex(eId);
-      } else if (!readUptoEvtStore.getItem()) {
+      }
+      if (!readUptoEvtStore.getItem() && roomTimeline.hasEventInTimeline(readUpToId)) {
         // either opening live timeline or jump to unread.
-        focusEventIndex = roomTimeline.getUnreadEventIndex(readUpToId);
-        if (roomTimeline.hasEventInTimeline(readUpToId)) {
-          readUptoEvtStore.setItem(roomTimeline.findEventByIdInTimelineSet(readUpToId));
-        }
-      } else {
+        readUptoEvtStore.setItem(roomTimeline.findEventByIdInTimelineSet(readUpToId));
+      }
+      if (readUptoEvtStore.getItem() && !isSpecificEvent) {
         focusEventIndex = roomTimeline.getUnreadEventIndex(readUptoEvtStore.getItem().getId());
       }
 
@@ -167,7 +166,6 @@ function useTimeline(roomTimeline, eventId, readUptoEvtStore, eventLimitRef) {
     setEventTimeline(eventId);
     return () => {
       roomTimeline.removeListener(cons.events.roomTimeline.READY, initTimeline);
-      roomTimeline.removeInternalListeners();
       limit.setFrom(0);
     };
   }, [roomTimeline, eventId]);
@@ -286,44 +284,39 @@ function useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, event
   useEffect(() => {
     const timelineScroll = timelineScrollRef.current;
     const limit = eventLimitRef.current;
-    const sendReadReceipt = (event) => {
-      if (event.isSending()) return;
+    const trySendReadReceipt = (event) => {
       if (myUserId === event.getSender()) {
-        roomTimeline.markAllAsRead();
+        requestAnimationFrame(() => roomTimeline.markAllAsRead());
         return;
       }
       const readUpToEvent = readUptoEvtStore.getItem();
       const readUpToId = roomTimeline.getReadUpToEventId();
-      const isUnread = readUpToEvent?.getId() === readUpToId;
+      const isUnread = readUpToEvent ? readUpToEvent?.getId() === readUpToId : true;
 
-      // if user doesn't have focus on app don't mark messages as read.
-      if (document.visibilityState === 'hidden' || timelineScroll.bottom >= 16) {
-        if (isUnread) return;
-        readUptoEvtStore.setItem(roomTimeline.findEventByIdInTimelineSet(readUpToId));
+      if (isUnread === false) {
+        if (document.visibilityState === 'visible' && timelineScroll.bottom < 16) {
+          requestAnimationFrame(() => roomTimeline.markAllAsRead());
+        } else {
+          readUptoEvtStore.setItem(roomTimeline.findEventByIdInTimelineSet(readUpToId));
+        }
         return;
       }
 
-      // user has not mark room as read
-      if (!isUnread) {
-        roomTimeline.markAllAsRead();
-      }
       const { timeline } = roomTimeline;
-      const unreadMsgIsLast = timeline[timeline.length - 2].getId() === readUpToEvent?.getId();
+      const unreadMsgIsLast = timeline[timeline.length - 2].getId() === readUpToId;
       if (unreadMsgIsLast) {
-        roomTimeline.markAllAsRead();
+        requestAnimationFrame(() => roomTimeline.markAllAsRead());
       }
     };
 
     const handleEvent = (event) => {
       const tLength = roomTimeline.timeline.length;
-      const isUserViewingLive = (
-        roomTimeline.isServingLiveTimeline()
-        && limit.length >= tLength - 1
-        && timelineScroll.bottom < SCROLL_TRIGGER_POS
-      );
-      if (isUserViewingLive) {
+      const isViewingLive = roomTimeline.isServingLiveTimeline() && limit.length >= tLength - 1;
+      const isAttached = timelineScroll.bottom < SCROLL_TRIGGER_POS;
+
+      if (isViewingLive && isAttached) {
         limit.setFrom(tLength - limit.maxEvents);
-        sendReadReceipt(event);
+        trySendReadReceipt(event);
         setEvent(event);
         return;
       }
@@ -332,11 +325,8 @@ function useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, event
         setEvent(event);
         return;
       }
-      const isUserDitchedLive = (
-        roomTimeline.isServingLiveTimeline()
-        && limit.length >= tLength - 1
-      );
-      if (isUserDitchedLive) {
+
+      if (isViewingLive) {
         // This stateUpdate will help to put the
         // loading msg placeholder at bottom
         setEvent(event);
@@ -353,17 +343,7 @@ function useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, event
     };
   }, [roomTimeline]);
 
-  useEffect(() => {
-    const timelineScroll = timelineScrollRef.current;
-    if (!roomTimeline.initialized) return;
-    if (timelineScroll.bottom < 16
-      && !roomTimeline.canPaginateForward()
-      && document.visibilityState === 'visible') {
-      timelineScroll.scrollToBottom();
-    } else {
-      timelineScroll.tryRestoringScroll();
-    }
-  }, [newEvent, roomTimeline]);
+  return newEvent;
 }
 
 let jumpToItemIndex = -1;
@@ -394,7 +374,7 @@ function RoomViewContent({ eventId, roomTimeline }) {
     timelineScrollRef,
     eventLimitRef,
   );
-  useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, eventLimitRef);
+  const newEvent = useEventArrive(roomTimeline, readUptoEvtStore, timelineScrollRef, eventLimitRef);
 
   const { timeline } = roomTimeline;
 
@@ -448,6 +428,16 @@ function RoomViewContent({ eventId, roomTimeline }) {
     timelineScroll.tryRestoringScroll();
   }, [onLimitUpdate]);
 
+  useEffect(() => {
+    const timelineScroll = timelineScrollRef.current;
+    if (!roomTimeline.initialized) return;
+    if (timelineScroll.bottom < 16 && !roomTimeline.canPaginateForward() && document.visibilityState === 'visible') {
+      timelineScroll.scrollToBottom();
+    } else {
+      timelineScroll.tryRestoringScroll();
+    }
+  }, [newEvent]);
+
   const handleTimelineScroll = (event) => {
     const timelineScroll = timelineScrollRef.current;
     if (!event.target) return;
index f491186482b568ce57311e175d3c4545a2060e1c..bccb197d88e386acd27cfd3874eeaf0abd483442 100644 (file)
@@ -230,9 +230,18 @@ class RoomTimeline extends EventEmitter {
 
   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 = this.timeline[this.timeline.length - 1];
+    const latestEvent = getLatestValidEvent();
+    if (latestEvent === null) return;
     if (readEventId === latestEvent.getId()) return;
     this.matrixClient.sendReadReceipt(latestEvent);
     this.emit(cons.events.roomTimeline.MARKED_AS_READ, latestEvent);