From 1e2eff390a17b05c6d09d360937d65307d39ae39 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 24 Feb 2025 14:15:30 +1100 Subject: [PATCH] fix: memoize formatFullDate calls --- ts/components/conversation/Timestamp.tsx | 5 +++-- .../conversation/header/ConversationHeader.tsx | 5 ++++- .../message/message-content/MessageContent.tsx | 8 ++++---- .../conversation/message/message-item/DateBreak.tsx | 9 ++++----- ts/hooks/useFormatFullDate.tsx | 12 ++++++++++++ ts/localization/constants.ts | 1 - 6 files changed, 27 insertions(+), 13 deletions(-) create mode 100644 ts/hooks/useFormatFullDate.tsx diff --git a/ts/components/conversation/Timestamp.tsx b/ts/components/conversation/Timestamp.tsx index bd1b0b418..cdbad44f1 100644 --- a/ts/components/conversation/Timestamp.tsx +++ b/ts/components/conversation/Timestamp.tsx @@ -3,7 +3,7 @@ import useUpdate from 'react-use/lib/useUpdate'; import styled from 'styled-components'; import { CONVERSATION } from '../../session/constants'; import { getConversationItemString } from '../../util/i18n/formatting/conversationItemTimestamp'; -import { formatFullDate } from '../../util/i18n/formatting/generics'; +import { useFormatFullDate } from '../../hooks/useFormatFullDate'; type Props = { timestamp?: number; @@ -37,6 +37,7 @@ export const Timestamp = (props: Props) => { useInterval(update, UPDATE_FREQUENCY); const { timestamp, isConversationSearchResult } = props; + const formattedFullDate = useFormatFullDate(timestamp); if (timestamp === null || timestamp === undefined) { return null; @@ -48,7 +49,7 @@ export const Timestamp = (props: Props) => { if (timestamp !== CONVERSATION.LAST_JOINED_FALLBACK_TIMESTAMP) { dateString = getConversationItemString(new Date(timestamp)); - title = formatFullDate(new Date(timestamp)); + title = formattedFullDate; } if (isConversationSearchResult) { diff --git a/ts/components/conversation/header/ConversationHeader.tsx b/ts/components/conversation/header/ConversationHeader.tsx index 0cda95662..3544862d8 100644 --- a/ts/components/conversation/header/ConversationHeader.tsx +++ b/ts/components/conversation/header/ConversationHeader.tsx @@ -28,6 +28,7 @@ import { SessionButtonColor, SessionButton, SessionButtonType } from '../../basi import { useAreGroupsCreatedAsNewGroupsYet } from '../../../state/selectors/releasedFeatures'; import { ConvoHub } from '../../../session/conversations'; import { ConversationTypeEnum } from '../../../models/types'; +import { Constants } from '../../../session'; export const ConversationHeaderWithDetails = () => { const isSelectionMode = useIsMessageSelectionMode(); @@ -145,7 +146,9 @@ function RecreateGroupButton() { ConversationTypeEnum.PRIVATE ); if (!memberConvo.get('active_at')) { - memberConvo.set({ active_at: 1 }); + memberConvo.set({ + active_at: Constants.CONVERSATION.LAST_JOINED_FALLBACK_TIMESTAMP, + }); await memberConvo.commit(); } /* eslint-enable no-await-in-loop */ diff --git a/ts/components/conversation/message/message-content/MessageContent.tsx b/ts/components/conversation/message/message-content/MessageContent.tsx index 6878645e4..c3e19bcfa 100644 --- a/ts/components/conversation/message/message-content/MessageContent.tsx +++ b/ts/components/conversation/message/message-content/MessageContent.tsx @@ -26,7 +26,7 @@ import { MessageHighlighter } from './MessageHighlighter'; import { MessageLinkPreview } from './MessageLinkPreview'; import { MessageQuote } from './MessageQuote'; import { MessageText } from './MessageText'; -import { formatFullDate } from '../../../../util/i18n/formatting/generics'; +import { useFormatFullDate } from '../../../../hooks/useFormatFullDate'; export type MessageContentSelectorProps = Pick< MessageRenderingProps, @@ -125,16 +125,16 @@ export const MessageContent = (props: Props) => { shouldHighlightMessage, ]); + const toolTipTitle = useFormatFullDate(contentProps?.serverTimestamp || contentProps?.timestamp); + if (!contentProps) { return null; } - const { direction, text, timestamp, serverTimestamp, previews, quote } = contentProps; + const { direction, text, previews, quote } = contentProps; const hasContentBeforeAttachment = !isEmpty(previews) || !isEmpty(quote) || !isEmpty(text); - const toolTipTitle = formatFullDate(new Date(serverTimestamp || timestamp)); - return ( { const { timestamp, messageId } = props; + const formattedFullDate = useFormatFullDate(timestamp); // if less than 7 days, we display the "last Thursday at 4:10" syntax // otherwise, we display the date + time separately const text = Date.now() - timestamp <= DURATION.DAYS * 7 ? formatRelativeTimestampWithLocale(timestamp) - : formatFullDate(new Date(timestamp)); + : formattedFullDate; return ( diff --git a/ts/hooks/useFormatFullDate.tsx b/ts/hooks/useFormatFullDate.tsx new file mode 100644 index 000000000..32042720c --- /dev/null +++ b/ts/hooks/useFormatFullDate.tsx @@ -0,0 +1,12 @@ +import { useMemo } from 'react'; +import { formatFullDate } from '../util/i18n/formatting/generics'; +import { CONVERSATION } from '../session/constants'; + +export function useFormatFullDate(timestampMs?: number) { + return useMemo(() => { + if (!timestampMs || timestampMs === CONVERSATION.LAST_JOINED_FALLBACK_TIMESTAMP) { + return ''; + } + return formatFullDate(new Date(timestampMs)); + }, [timestampMs]); +} diff --git a/ts/localization/constants.ts b/ts/localization/constants.ts index b67623f10..b1c893c24 100644 --- a/ts/localization/constants.ts +++ b/ts/localization/constants.ts @@ -96,4 +96,3 @@ export type CrowdinLocale = (typeof crowdinLocales)[number]; export function isCrowdinLocale(locale: string): locale is CrowdinLocale { return crowdinLocales.includes(locale as CrowdinLocale); } -