From 9fd4c04d74e40ddc8a875657353cc502d9a2a664 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 17 Feb 2022 17:19:41 -0300 Subject: [PATCH] [FIX] Read receipts showing first messages of the room as read even if not read by everyone (#24508) Co-authored-by: dougfabris --- app/models/server/models/Subscriptions.js | 3 -- client/hooks/useFormatDateAndTime.js | 24 --------------- client/hooks/useFormatDateAndTime.ts | 29 +++++++++++++++++++ .../views/account/tokens/AccountTokensRow.tsx | 3 +- .../ReadReceiptsModal/ReadReceiptRow.tsx | 2 +- imports/message-read-receipt/server/hooks.js | 2 +- .../server/lib/ReadReceipt.js | 25 ++++++++-------- 7 files changed, 46 insertions(+), 42 deletions(-) delete mode 100644 client/hooks/useFormatDateAndTime.js create mode 100644 client/hooks/useFormatDateAndTime.ts diff --git a/app/models/server/models/Subscriptions.js b/app/models/server/models/Subscriptions.js index deddc06afc5..74e2176446e 100644 --- a/app/models/server/models/Subscriptions.js +++ b/app/models/server/models/Subscriptions.js @@ -556,9 +556,6 @@ export class Subscriptions extends Base { return this.db.findOne( { rid, - ls: { - $exists: true, - }, }, { sort: { diff --git a/client/hooks/useFormatDateAndTime.js b/client/hooks/useFormatDateAndTime.js deleted file mode 100644 index 900e832273a..00000000000 --- a/client/hooks/useFormatDateAndTime.js +++ /dev/null @@ -1,24 +0,0 @@ -import moment from 'moment'; -import { useCallback } from 'react'; - -import { useSetting } from '../contexts/SettingsContext'; -import { useUserPreference } from '../contexts/UserContext'; - -export const useFormatDateAndTime = () => { - const clockMode = useUserPreference('clockMode', false); - const format = useSetting('Message_TimeAndDateFormat'); - - return useCallback( - (time) => { - switch (clockMode) { - case 1: - return moment(time).format('MMMM D, Y h:mm A'); - case 2: - return moment(time).format('MMMM D, Y H:mm'); - default: - return moment(time).format(format); - } - }, - [clockMode, format], - ); -}; diff --git a/client/hooks/useFormatDateAndTime.ts b/client/hooks/useFormatDateAndTime.ts new file mode 100644 index 00000000000..0bda2b2350e --- /dev/null +++ b/client/hooks/useFormatDateAndTime.ts @@ -0,0 +1,29 @@ +import moment, { MomentInput } from 'moment'; +import { useCallback } from 'react'; + +import { useSetting } from '../contexts/SettingsContext'; +import { useUserPreference } from '../contexts/UserContext'; + +type UseFormatDateAndTimeParams = { + withSeconds?: boolean; +}; + +export const useFormatDateAndTime = ({ withSeconds }: UseFormatDateAndTimeParams = {}): ((input: MomentInput) => string) => { + const clockMode = useUserPreference('clockMode'); + const format = useSetting('Message_TimeAndDateFormat') as string; + + return useCallback( + (time) => { + switch (clockMode) { + case 1: + return moment(time).format(withSeconds ? 'MMMM D, Y h:mm:ss A' : 'MMMM D, Y h:mm A'); + case 2: + return moment(time).format(withSeconds ? 'MMMM D, Y H:mm:ss' : 'MMMM D, Y H:mm'); + + default: + return moment(time).format(withSeconds ? 'L LTS' : format); + } + }, + [clockMode, format, withSeconds], + ); +}; diff --git a/client/views/account/tokens/AccountTokensRow.tsx b/client/views/account/tokens/AccountTokensRow.tsx index d64153d507f..7f6f93bd0c2 100644 --- a/client/views/account/tokens/AccountTokensRow.tsx +++ b/client/views/account/tokens/AccountTokensRow.tsx @@ -1,4 +1,5 @@ import { Button, ButtonGroup, Icon, Table } from '@rocket.chat/fuselage'; +import type { MomentInput } from 'moment'; import React, { useCallback, FC } from 'react'; import { useTranslation } from '../../../contexts/TranslationContext'; @@ -6,7 +7,7 @@ import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime'; type AccountTokensRowProps = { bypassTwoFactor: unknown; - createdAt: unknown; + createdAt: MomentInput; isMedium: boolean; lastTokenPart: string; name: string; diff --git a/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx b/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx index 0c26e718eb1..d06f8207e74 100644 --- a/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx +++ b/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx @@ -16,7 +16,7 @@ const hoverStyle = css` const ReadReceiptRow = ({ user, ts }: ReadReceipt): ReactElement => { const displayName = useUserDisplayName(user); - const formatDateAndTime = useFormatDateAndTime(); + const formatDateAndTime = useFormatDateAndTime({ withSeconds: true }); return ( { // @TODO maybe store firstSubscription in room object so we don't need to call the above update method const firstSubscription = Subscriptions.getMinimumLastSeenByRoomId(_id); - if (!firstSubscription) { + if (!firstSubscription || !firstSubscription.ls) { return; } @@ -42,31 +42,32 @@ export const ReadReceipt = { const room = Rooms.findOneById(roomId, { fields: { lm: 1 } }); - // if users last seen is greadebounceByRoomIdter than room's last message, it means the user already have this room marked as read + // if users last seen is greater than room's last message, it means the user already have this room marked as read if (userLastSeen > room.lm) { return; } - if (userLastSeen) { - this.storeReadReceipts(Messages.findUnreadMessagesByRoomAndDate(roomId, userLastSeen), roomId, userId); - } + this.storeReadReceipts(Messages.findUnreadMessagesByRoomAndDate(roomId, userLastSeen), roomId, userId); updateMessages(room); }, - markMessageAsReadBySender(message, roomId, userId) { + markMessageAsReadBySender(message, { _id: roomId, t }, userId) { if (!settings.get('Message_Read_Receipt_Enabled')) { return; } - // this will usually happens if the message sender is the only one on the room - const firstSubscription = Subscriptions.getMinimumLastSeenByRoomId(roomId); - if (firstSubscription && message.unread && message.ts < firstSubscription.ls) { - Messages.setAsReadById(message._id, firstSubscription.ls); + if (!message.unread) { + return; + } + + // mark message as read if the sender is the only one in the room + const isUserAlone = Subscriptions.findByRoomIdAndNotUserId(roomId, userId, { fields: { _id: 1 } }).count() === 0; + if (isUserAlone) { + Messages.setAsReadById(message._id); } - const room = Rooms.findOneById(roomId, { fields: { t: 1 } }); - const extraData = roomTypes.getConfig(room.t).getReadReceiptsExtraData(message); + const extraData = roomTypes.getConfig(t).getReadReceiptsExtraData(message); this.storeReadReceipts([{ _id: message._id }], roomId, userId, extraData); },