Skip to content

Commit

Permalink
[CLNP-6260] forwardRef hook rule violation (#1308)
Browse files Browse the repository at this point in the history
// 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 <[email protected]> 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
  • Loading branch information
chrisallo authored Feb 5, 2025
1 parent f30922e commit 79bfe84
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 11 deletions.
4 changes: 4 additions & 0 deletions src/modules/Channel/components/MessageList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -232,6 +235,7 @@ export const MessageList = (props: MessageListProps) => {
{localMessages.map((m, idx) => {
const { chainTop, chainBottom } = getMessagePartsInfo({
allMessages: allMessagesFiltered,
stringSet,
replyType,
isMessageGroupingEnabled,
currentIndex: idx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<CoreMessageType>;
stringSet: StringSet
isMessageGroupingEnabled?: boolean;
currentIndex: number;
currentMessage: CoreMessageType;
Expand All @@ -24,7 +26,8 @@ interface OutPuts {
* exported, should be backward compatible
*/
export const getMessagePartsInfo = ({
allMessages = [],
allMessages,
stringSet,
isMessageGroupingEnabled = true,
currentIndex = 0,
currentMessage,
Expand All @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/modules/GroupChannel/components/MessageList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -88,6 +89,7 @@ export const MessageList = (props: GroupChannelMessageListProps) => {
} = useGroupChannelContext();

const store = useSendbirdStateContext();
const { stringSet } = useLocalization();

const [unreadSinceDate, setUnreadSinceDate] = useState<Date>();

Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<HTMLDivElement>(null);
const scrollRef = ref || localRef;
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions src/modules/Thread/components/ThreadList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -28,6 +29,7 @@ export default function ThreadList({
scrollBottom,
}: ThreadListProps): React.ReactElement {
const { config } = useSendbirdStateContext();
const { stringSet } = useLocalization();
const { userId } = config;
const {
currentChannel,
Expand All @@ -47,6 +49,7 @@ export default function ThreadList({
prevMessage as SendableMessageType,
message as SendableMessageType,
nextMessage as SendableMessageType,
stringSet,
currentChannel,
getCaseResolvedReplyType(config.groupChannel.replyType).upperCase,
)
Expand Down
17 changes: 9 additions & 8 deletions src/utils/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
];
}

Expand All @@ -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 (
Expand All @@ -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
);
Expand Down

0 comments on commit 79bfe84

Please sign in to comment.