From d3bbe51677933232566e33ef429f5c345d65da17 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Mon, 14 Feb 2022 18:23:50 -0300 Subject: [PATCH 1/4] Fix read receipts on first messages of the room --- app/models/server/models/Subscriptions.js | 3 --- imports/message-read-receipt/server/hooks.js | 2 +- .../server/lib/ReadReceipt.js | 25 ++++++++++--------- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/app/models/server/models/Subscriptions.js b/app/models/server/models/Subscriptions.js index deddc06afc5a..74e2176446ef 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/imports/message-read-receipt/server/hooks.js b/imports/message-read-receipt/server/hooks.js index 1fb4d35faae6..e8df9381de8b 100644 --- a/imports/message-read-receipt/server/hooks.js +++ b/imports/message-read-receipt/server/hooks.js @@ -16,7 +16,7 @@ callbacks.add( } // mark message as read as well - ReadReceipt.markMessageAsReadBySender(message, room._id, message.u._id); + ReadReceipt.markMessageAsReadBySender(message, room, message.u._id); return message; }, diff --git a/imports/message-read-receipt/server/lib/ReadReceipt.js b/imports/message-read-receipt/server/lib/ReadReceipt.js index cf43fca39587..fea03734da6e 100644 --- a/imports/message-read-receipt/server/lib/ReadReceipt.js +++ b/imports/message-read-receipt/server/lib/ReadReceipt.js @@ -22,7 +22,7 @@ const updateMessages = debounceByRoomId( Meteor.bindEnvironment(({ _id, lm }) => { // @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); }, From 799a6d6e5d54977e5e12007cdcdca4cae3ecd89f Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 15 Feb 2022 09:54:49 -0300 Subject: [PATCH 2/4] Use new hook to show seconds --- client/hooks/useFormatTimeWithSeconds.ts | 26 +++++++++++++++++++ .../ReadReceiptsModal/ReadReceiptRow.tsx | 4 +-- 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 client/hooks/useFormatTimeWithSeconds.ts diff --git a/client/hooks/useFormatTimeWithSeconds.ts b/client/hooks/useFormatTimeWithSeconds.ts new file mode 100644 index 000000000000..16a9daf5cb0e --- /dev/null +++ b/client/hooks/useFormatTimeWithSeconds.ts @@ -0,0 +1,26 @@ +import moment from 'moment'; +import { useCallback } from 'react'; + +import { useUserPreference } from '../contexts/UserContext'; + +const dayFormat = ['h:mm:ss A', 'H:mm:ss'] as const; +const format = 'L LTS'; + +export const useFormatTimeWithSeconds = (): ((input: moment.MomentInput) => string) => { + const clockMode = useUserPreference<1 | 2>('clockMode'); + const sameDay = clockMode !== undefined ? dayFormat[clockMode - 1] : format; + + return useCallback( + (time) => { + switch (clockMode) { + case 1: + case 2: + return moment(time).format(sameDay); + + default: + return moment(time).format(format); + } + }, + [clockMode, sameDay], + ); +}; diff --git a/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx b/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx index 0c26e718eb1a..6f1703e0c9ca 100644 --- a/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx +++ b/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx @@ -5,7 +5,7 @@ import React, { ReactElement } from 'react'; import type { ReadReceipt } from '../../../../../definition/ReadReceipt'; import UserAvatar from '../../../../components/avatar/UserAvatar'; -import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime'; +import { useFormatTimeWithSeconds } from '../../../../hooks/useFormatTimeWithSeconds'; import { useUserDisplayName } from '../../../../hooks/useUserDisplayName'; const hoverStyle = css` @@ -16,7 +16,7 @@ const hoverStyle = css` const ReadReceiptRow = ({ user, ts }: ReadReceipt): ReactElement => { const displayName = useUserDisplayName(user); - const formatDateAndTime = useFormatDateAndTime(); + const formatDateAndTime = useFormatTimeWithSeconds(); return ( Date: Tue, 15 Feb 2022 10:20:04 -0300 Subject: [PATCH 3/4] Add date to formats respecting clockMode --- client/hooks/useFormatTimeWithSeconds.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/hooks/useFormatTimeWithSeconds.ts b/client/hooks/useFormatTimeWithSeconds.ts index 16a9daf5cb0e..0f9cfb317232 100644 --- a/client/hooks/useFormatTimeWithSeconds.ts +++ b/client/hooks/useFormatTimeWithSeconds.ts @@ -3,7 +3,7 @@ import { useCallback } from 'react'; import { useUserPreference } from '../contexts/UserContext'; -const dayFormat = ['h:mm:ss A', 'H:mm:ss'] as const; +const dayFormat = ['L h:mm:ss A', 'L H:mm:ss'] as const; const format = 'L LTS'; export const useFormatTimeWithSeconds = (): ((input: moment.MomentInput) => string) => { From 810bed66f338213e41d95c68a4c3f2c8cb8dcdfd Mon Sep 17 00:00:00 2001 From: dougfabris Date: Tue, 15 Feb 2022 22:05:35 -0300 Subject: [PATCH 4/4] improve: add param to useFormatDateAndTime hook --- client/hooks/useFormatDateAndTime.js | 24 --------------- client/hooks/useFormatDateAndTime.ts | 29 +++++++++++++++++++ client/hooks/useFormatTimeWithSeconds.ts | 26 ----------------- .../views/account/tokens/AccountTokensRow.tsx | 3 +- .../ReadReceiptsModal/ReadReceiptRow.tsx | 4 +-- 5 files changed, 33 insertions(+), 53 deletions(-) delete mode 100644 client/hooks/useFormatDateAndTime.js create mode 100644 client/hooks/useFormatDateAndTime.ts delete mode 100644 client/hooks/useFormatTimeWithSeconds.ts diff --git a/client/hooks/useFormatDateAndTime.js b/client/hooks/useFormatDateAndTime.js deleted file mode 100644 index 900e832273ad..000000000000 --- 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 000000000000..0bda2b2350e4 --- /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/hooks/useFormatTimeWithSeconds.ts b/client/hooks/useFormatTimeWithSeconds.ts deleted file mode 100644 index 0f9cfb317232..000000000000 --- a/client/hooks/useFormatTimeWithSeconds.ts +++ /dev/null @@ -1,26 +0,0 @@ -import moment from 'moment'; -import { useCallback } from 'react'; - -import { useUserPreference } from '../contexts/UserContext'; - -const dayFormat = ['L h:mm:ss A', 'L H:mm:ss'] as const; -const format = 'L LTS'; - -export const useFormatTimeWithSeconds = (): ((input: moment.MomentInput) => string) => { - const clockMode = useUserPreference<1 | 2>('clockMode'); - const sameDay = clockMode !== undefined ? dayFormat[clockMode - 1] : format; - - return useCallback( - (time) => { - switch (clockMode) { - case 1: - case 2: - return moment(time).format(sameDay); - - default: - return moment(time).format(format); - } - }, - [clockMode, sameDay], - ); -}; diff --git a/client/views/account/tokens/AccountTokensRow.tsx b/client/views/account/tokens/AccountTokensRow.tsx index d64153d507f6..7f6f93bd0c25 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 6f1703e0c9ca..d06f8207e74c 100644 --- a/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx +++ b/client/views/room/modals/ReadReceiptsModal/ReadReceiptRow.tsx @@ -5,7 +5,7 @@ import React, { ReactElement } from 'react'; import type { ReadReceipt } from '../../../../../definition/ReadReceipt'; import UserAvatar from '../../../../components/avatar/UserAvatar'; -import { useFormatTimeWithSeconds } from '../../../../hooks/useFormatTimeWithSeconds'; +import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime'; import { useUserDisplayName } from '../../../../hooks/useUserDisplayName'; const hoverStyle = css` @@ -16,7 +16,7 @@ const hoverStyle = css` const ReadReceiptRow = ({ user, ts }: ReadReceipt): ReactElement => { const displayName = useUserDisplayName(user); - const formatDateAndTime = useFormatTimeWithSeconds(); + const formatDateAndTime = useFormatDateAndTime({ withSeconds: true }); return (