From 79bfe84b90fbb8c182bbab9bc61830e877a8ae56 Mon Sep 17 00:00:00 2001 From: Chris Heo Date: Tue, 4 Feb 2025 22:13:40 -0800 Subject: [PATCH] [CLNP-6260] forwardRef hook rule violation (#1308) // PR title (Required) [fix]: forwardRef hook rule violation bug-fix // Footer (Recommended) Fixes [CLNP-6260](https://sendbird.atlassian.net/browse/CLNP-6260) ### Changelogs - Fixed a bug with forwardRef Rules of Hooks violation ### Checklist Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If unsure, ask the members. This is a reminder of what we look for before merging your code. - [x] **All tests pass locally with my changes** - [ ] **I have added tests that prove my fix is effective or that my feature works** - [ ] **Public components / utils / props are appropriately exported** - [ ] I have added necessary documentation (if appropriate) ## External Contributions This project is not yet set up to accept pull requests from external contributors. If you have a pull request that you believe should be accepted, please contact the Developer Relations team with details and we'll evaluate if we can set up a [CLA](https://en.wikipedia.org/wiki/Contributor_License_Agreement) to allow for the contribution. [CLNP-6260]: https://sendbird.atlassian.net/browse/CLNP-6260?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ --- .../Channel/components/MessageList/index.tsx | 4 ++++ .../__test__/getMessagePartsInfo.spec.js | 8 ++++++++ .../MessageList/getMessagePartsInfo.ts | 7 +++++-- .../components/MessageList/index.tsx | 3 +++ .../components/OpenChannelMessageList/index.tsx | 4 +++- .../Thread/components/ThreadList/index.tsx | 3 +++ src/utils/messages.ts | 17 +++++++++-------- 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/modules/Channel/components/MessageList/index.tsx b/src/modules/Channel/components/MessageList/index.tsx index 3722f7ed2f..f0c7f5f63d 100644 --- a/src/modules/Channel/components/MessageList/index.tsx +++ b/src/modules/Channel/components/MessageList/index.tsx @@ -26,6 +26,7 @@ import { GroupChannelMessageListProps } from '../../../GroupChannel/components/M import { GroupChannelUIBasicProps } from '../../../GroupChannel/components/GroupChannelUI/GroupChannelUIView'; import { deleteNullish } from '../../../../utils/utils'; import { getHTMLTextDirection } from '../../../../utils'; +import { useLocalization } from '../../../../lib/LocalizationContext'; const SCROLL_BOTTOM_PADDING = 50; @@ -80,6 +81,7 @@ export const MessageList = (props: MessageListProps) => { } = useChannelContext(); const store = useSendbirdStateContext(); + const { stringSet } = useLocalization(); const allMessagesFiltered = typeof filterMessageList === 'function' ? allMessages.filter(filterMessageList) : allMessages; const markAsReadScheduler = store.config.markAsReadScheduler; @@ -205,6 +207,7 @@ export const MessageList = (props: MessageListProps) => { {allMessagesFiltered.map((m, idx) => { const { chainTop, chainBottom, hasSeparator } = getMessagePartsInfo({ allMessages: allMessagesFiltered, + stringSet, replyType, isMessageGroupingEnabled, currentIndex: idx, @@ -232,6 +235,7 @@ export const MessageList = (props: MessageListProps) => { {localMessages.map((m, idx) => { const { chainTop, chainBottom } = getMessagePartsInfo({ allMessages: allMessagesFiltered, + stringSet, replyType, isMessageGroupingEnabled, currentIndex: idx, diff --git a/src/modules/GroupChannel/components/MessageList/__test__/getMessagePartsInfo.spec.js b/src/modules/GroupChannel/components/MessageList/__test__/getMessagePartsInfo.spec.js index 90849893fb..2c9d0cf2ef 100644 --- a/src/modules/GroupChannel/components/MessageList/__test__/getMessagePartsInfo.spec.js +++ b/src/modules/GroupChannel/components/MessageList/__test__/getMessagePartsInfo.spec.js @@ -55,8 +55,10 @@ describe('getMessagePartsInfo', () => { }); }); it('should group messages that are sent at same time', () => { + const { stringSet } = useLocalization(); const defaultSetting = { allMessages: messageGroup1, + stringSet, isMessageGroupingEnabled: true, currentChannel: mockChannel, replyType: 'THREAD', @@ -88,8 +90,10 @@ describe('getMessagePartsInfo', () => { }); it('should not group messages if isMessageGroupingEnabled is false', () => { + const { stringSet } = useLocalization(); const defaultSetting = { allMessages: messageGroup1, + stringSet, isMessageGroupingEnabled: false, currentChannel: mockChannel, replyType: 'THREAD', @@ -121,8 +125,10 @@ describe('getMessagePartsInfo', () => { }); it('should not group messages if sent time are different', () => { + const { stringSet } = useLocalization(); const defaultSetting = { allMessages: messageGroup2, + stringSet, isMessageGroupingEnabled: true, currentChannel: mockChannel, replyType: 'THREAD', @@ -153,8 +159,10 @@ describe('getMessagePartsInfo', () => { expect(thirdGroupingInfo.hasSeparator).toBe(false); }); it('should not group messages if sender is different', () => { + const { stringSet } = useLocalization(); const defaultSetting = { allMessages: messageGroup3, + stringSet, isMessageGroupingEnabled: true, currentChannel: mockChannel, replyType: 'THREAD', diff --git a/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts b/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts index 282dd543ee..718e6cfac1 100644 --- a/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts +++ b/src/modules/GroupChannel/components/MessageList/getMessagePartsInfo.ts @@ -4,9 +4,11 @@ import isSameDay from 'date-fns/isSameDay'; import { compareMessagesForGrouping } from '../../../../utils/messages'; import { ReplyType } from '../../../../types'; import { CoreMessageType } from '../../../../utils'; +import { StringSet } from '../../../../ui/Label/stringSet'; export interface GetMessagePartsInfoProps { allMessages: Array; + stringSet: StringSet isMessageGroupingEnabled?: boolean; currentIndex: number; currentMessage: CoreMessageType; @@ -24,7 +26,8 @@ interface OutPuts { * exported, should be backward compatible */ export const getMessagePartsInfo = ({ - allMessages = [], + allMessages, + stringSet, isMessageGroupingEnabled = true, currentIndex = 0, currentMessage, @@ -34,7 +37,7 @@ export const getMessagePartsInfo = ({ const previousMessage = allMessages[currentIndex - 1]; const nextMessage = allMessages[currentIndex + 1]; const [chainTop, chainBottom] = isMessageGroupingEnabled - ? compareMessagesForGrouping(previousMessage, currentMessage, nextMessage, currentChannel, (replyType as ReplyType)) + ? compareMessagesForGrouping(previousMessage, currentMessage, nextMessage, stringSet, currentChannel, (replyType as ReplyType)) : [false, false]; const previousMessageCreatedAt = previousMessage?.createdAt; const currentCreatedAt = currentMessage.createdAt; diff --git a/src/modules/GroupChannel/components/MessageList/index.tsx b/src/modules/GroupChannel/components/MessageList/index.tsx index 66b5d6c1cc..86411554a4 100644 --- a/src/modules/GroupChannel/components/MessageList/index.tsx +++ b/src/modules/GroupChannel/components/MessageList/index.tsx @@ -21,6 +21,7 @@ import { getMessagePartsInfo } from './getMessagePartsInfo'; import { MessageProvider } from '../../../Message/context/MessageProvider'; import { getComponentKeyFromMessage, isContextMenuClosed } from '../../context/utils'; import { InfiniteList } from './InfiniteList'; +import { useLocalization } from '../../../../lib/LocalizationContext'; export interface GroupChannelMessageListProps { className?: string; @@ -88,6 +89,7 @@ export const MessageList = (props: GroupChannelMessageListProps) => { } = useGroupChannelContext(); const store = useSendbirdStateContext(); + const { stringSet } = useLocalization(); const [unreadSinceDate, setUnreadSinceDate] = useState(); @@ -185,6 +187,7 @@ export const MessageList = (props: GroupChannelMessageListProps) => { renderMessage={({ message, index }) => { const { chainTop, chainBottom, hasSeparator } = getMessagePartsInfo({ allMessages: messages as CoreMessageType[], + stringSet, replyType: replyType ?? 'NONE', isMessageGroupingEnabled: isMessageGroupingEnabled ?? false, currentIndex: index, diff --git a/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx b/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx index ef60cc5da8..6bded14160 100644 --- a/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx +++ b/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx @@ -14,6 +14,7 @@ import { MessageProvider } from '../../../Message/context/MessageProvider'; import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext'; import { useHandleOnScrollCallback } from '../../../../hooks/useHandleOnScrollCallback'; import { compareMessagesForGrouping } from '../../../../utils/messages'; +import { useLocalization } from '../../../../lib/LocalizationContext'; export type OpenChannelMessageListProps = { renderMessage?: (props: RenderMessageProps) => React.ReactElement; @@ -31,6 +32,7 @@ function OpenChannelMessageList(props: OpenChannelMessageListProps, ref: React.F onScroll, } = useOpenChannelContext(); const store = useSendbirdStateContext(); + const { stringSet } = useLocalization(); const userId = store.config.userId; const localRef = useRef(null); const scrollRef = ref || localRef; @@ -65,7 +67,7 @@ function OpenChannelMessageList(props: OpenChannelMessageListProps, ref: React.F )); const [chainTop, chainBottom] = isMessageGroupingEnabled - ? compareMessagesForGrouping(previousMessage, message, nextMessage) + ? compareMessagesForGrouping(previousMessage, message, nextMessage, stringSet) : [false, false]; const isByMe = (message as UserMessage)?.sender?.userId === userId; const key = message?.messageId || (message as UserMessage)?.reqId; diff --git a/src/modules/Thread/components/ThreadList/index.tsx b/src/modules/Thread/components/ThreadList/index.tsx index 9d7fab7569..92a8b193ca 100644 --- a/src/modules/Thread/components/ThreadList/index.tsx +++ b/src/modules/Thread/components/ThreadList/index.tsx @@ -11,6 +11,7 @@ import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext'; import { isSameDay } from 'date-fns'; import { MessageProvider } from '../../../Message/context/MessageProvider'; import { getCaseResolvedReplyType } from '../../../../lib/utils/resolvedReplyType'; +import { useLocalization } from '../../../../lib/LocalizationContext'; export interface ThreadListProps { className?: string; @@ -28,6 +29,7 @@ export default function ThreadList({ scrollBottom, }: ThreadListProps): React.ReactElement { const { config } = useSendbirdStateContext(); + const { stringSet } = useLocalization(); const { userId } = config; const { currentChannel, @@ -47,6 +49,7 @@ export default function ThreadList({ prevMessage as SendableMessageType, message as SendableMessageType, nextMessage as SendableMessageType, + stringSet, currentChannel, getCaseResolvedReplyType(config.groupChannel.replyType).upperCase, ) diff --git a/src/utils/messages.ts b/src/utils/messages.ts index d4f0e121fb..78e1f95765 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -5,7 +5,7 @@ import format from 'date-fns/format'; import { ReplyType } from '../types'; import type { CoreMessageType } from '.'; import { isReadMessage } from '.'; -import { useLocalization } from '../lib/LocalizationContext'; +import { StringSet } from '../ui/Label/stringSet'; /** * exported, should be backward compatible @@ -15,13 +15,14 @@ export const compareMessagesForGrouping = ( prevMessage: CoreMessageType, currMessage: CoreMessageType, nextMessage: CoreMessageType, + stringSet: StringSet, currentChannel?: GroupChannel | null, replyType?: ReplyType, ) => { if (!currentChannel || (currentChannel as GroupChannel).channelType !== 'group') { return [ - isSameGroup(prevMessage, currMessage), - isSameGroup(currMessage, nextMessage), + isSameGroup(prevMessage, currMessage, stringSet), + isSameGroup(currMessage, nextMessage, stringSet), ]; } @@ -31,19 +32,19 @@ export const compareMessagesForGrouping = ( const sendingStatus = (currMessage as UserMessage)?.sendingStatus || ''; const isAcceptable = sendingStatus !== 'pending' && sendingStatus !== 'failed'; return [ - isSameGroup(prevMessage, currMessage, currentChannel) && isAcceptable, - isSameGroup(currMessage, nextMessage, currentChannel) && isAcceptable, + isSameGroup(prevMessage, currMessage, stringSet, currentChannel) && isAcceptable, + isSameGroup(currMessage, nextMessage, stringSet, currentChannel) && isAcceptable, ]; }; -export const getMessageCreatedAt = (message: BaseMessage) => { - const { stringSet } = useLocalization(); +export const getMessageCreatedAt = (message: BaseMessage, stringSet: StringSet) => { return format(message.createdAt, stringSet.DATE_FORMAT__MESSAGE_CREATED_AT); }; export const isSameGroup = ( message: CoreMessageType, comparingMessage: CoreMessageType, + stringSet: StringSet, currentChannel?: GroupChannel, ) => { if ( @@ -67,7 +68,7 @@ export const isSameGroup = ( return ( message?.sendingStatus === comparingMessage?.sendingStatus && message?.sender?.userId === comparingMessage?.sender?.userId - && getMessageCreatedAt(message) === getMessageCreatedAt(comparingMessage) + && getMessageCreatedAt(message, stringSet) === getMessageCreatedAt(comparingMessage, stringSet) ) && ( currentChannel ? isReadMessage(currentChannel, message) === isReadMessage(currentChannel, comparingMessage) : true );