Skip to content

Commit 197e037

Browse files
authored
[CLNP-5549] fix: Improve message layout direction hook reliability (#1242)
Aim to fix https://sendbird.atlassian.net/browse/SBISSUE-17616 ## Description Fixed an issue where the `dir` attribute was not being properly applied to message containers. Instead of using DOM manipulation through `useMessageLayoutDirection` hook, implemented a more React-friendly solution by directly setting the `dir` attribute on the message container component. ### Changes - Removed `useMessageLayoutDirection` hook - Updated `MessageList` component to directly handle text direction through the `dir` attribute - Simplified the implementation while maintaining the same functionality - Ensures proper text direction propagation to child elements ### Testing Please test the following scenarios: - Verify text direction changes properly when switching between LTR and RTL by changing the value of `forceLeftToRightMessageLayout` / `hTMLTextDirection` - Check message alignment in both directions - Confirm direction changes are properly propagated to child elements ### Note This change simplifies our approach to handling text direction while maintaining full compatibility with our RTL support system.
1 parent 4fdc83f commit 197e037

File tree

8 files changed

+25
-46
lines changed

8 files changed

+25
-46
lines changed

src/hooks/useHTMLTextDirection.tsx

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,4 @@ const useHTMLTextDirection = (direction: HTMLTextDirection) => {
1515
}, [direction]);
1616
};
1717

18-
export const useMessageLayoutDirection = (direction: HTMLTextDirection, forceLeftToRightMessageLayout: boolean, loading: boolean) => {
19-
useEffect(() => {
20-
if (loading) return;
21-
const messageListElements = document.getElementsByClassName('sendbird-conversation__messages');
22-
if (messageListElements.length > 0) {
23-
Array.from(messageListElements).forEach((elem: HTMLElement) => {
24-
elem.dir = forceLeftToRightMessageLayout
25-
? 'ltr'
26-
: direction;
27-
});
28-
}
29-
}, [direction, forceLeftToRightMessageLayout, loading]);
30-
};
31-
3218
export default useHTMLTextDirection;

src/modules/Channel/components/MessageList/index.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { getMessagePartsInfo } from '../../../GroupChannel/components/MessageLis
2525
import { GroupChannelMessageListProps } from '../../../GroupChannel/components/MessageList';
2626
import { GroupChannelUIBasicProps } from '../../../GroupChannel/components/GroupChannelUI/GroupChannelUIView';
2727
import { deleteNullish } from '../../../../utils/utils';
28+
import { getHTMLTextDirection } from '../../../../utils';
2829

2930
const SCROLL_BOTTOM_PADDING = 50;
3031

@@ -175,7 +176,13 @@ export const MessageList = (props: MessageListProps) => {
175176
return (
176177
<>
177178
{!isScrolled && <PlaceHolder type={PlaceHolderTypes.LOADING} />}
178-
<div className={`sendbird-conversation__messages ${className}`}>
179+
<div
180+
className={`sendbird-conversation__messages ${className}`}
181+
dir={getHTMLTextDirection(
182+
store?.config?.htmlTextDirection,
183+
store?.config?.forceLeftToRightMessageLayout,
184+
)}
185+
>
179186
<div className="sendbird-conversation__scroll-container">
180187
<div className="sendbird-conversation__padding" />
181188
<div

src/modules/Channel/context/ChannelProvider.tsx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ import { useSendMultipleFilesMessage } from './hooks/useSendMultipleFilesMessage
5151
import { useHandleChannelPubsubEvents } from './hooks/useHandleChannelPubsubEvents';
5252
import { PublishingModuleType } from '../../internalInterfaces';
5353
import { ChannelActionTypes } from './dux/actionTypes';
54-
import { useMessageLayoutDirection } from '../../../hooks/useHTMLTextDirection';
5554

5655
export { ThreadReplySelectType } from './const'; // export for external usage
5756

@@ -212,8 +211,6 @@ const ChannelProvider = (props: ChannelContextProps) => {
212211
imageCompression,
213212
markAsReadScheduler,
214213
groupChannel,
215-
htmlTextDirection,
216-
forceLeftToRightMessageLayout,
217214
} = config;
218215
const sdk = globalStore?.stores?.sdkStore?.sdk;
219216
const sdkInit = globalStore?.stores?.sdkStore?.initialized;
@@ -381,12 +378,6 @@ const ChannelProvider = (props: ChannelContextProps) => {
381378
markAsReadScheduler,
382379
});
383380

384-
useMessageLayoutDirection(
385-
htmlTextDirection,
386-
forceLeftToRightMessageLayout,
387-
loading,
388-
);
389-
390381
// callbacks for Message CURD actions
391382
const deleteMessage = useDeleteMessageCallback(
392383
{ currentGroupChannel, messagesDispatcher },

src/modules/GroupChannel/components/MessageList/index.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
33
import type { Member } from '@sendbird/chat/groupChannel';
44
import { useGroupChannelHandler } from '@sendbird/uikit-tools';
55

6-
import { CoreMessageType, isSendableMessage } from '../../../../utils';
6+
import { CoreMessageType, isSendableMessage, getHTMLTextDirection } from '../../../../utils';
77
import { EveryMessage, RenderMessageParamsType, TypingIndicatorType } from '../../../../types';
88

99
import PlaceHolder, { PlaceHolderTypes } from '../../../../ui/PlaceHolder';
@@ -160,7 +160,13 @@ export const MessageList = (props: GroupChannelMessageListProps) => {
160160

161161
return (
162162
<>
163-
<div className={`sendbird-conversation__messages ${className}`}>
163+
<div
164+
className={`sendbird-conversation__messages ${className}`}
165+
dir={getHTMLTextDirection(
166+
store?.config?.htmlTextDirection,
167+
store?.config?.forceLeftToRightMessageLayout,
168+
)}
169+
>
164170
<InfiniteList
165171
ref={scrollRef}
166172
initDeps={[channelUrl]}

src/modules/GroupChannel/context/GroupChannelProvider.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import PUBSUB_TOPICS, { PubSubSendMessagePayload } from '../../../lib/pubSub/top
2626
import { PubSubTypes } from '../../../lib/pubSub';
2727
import { useMessageActions } from './hooks/useMessageActions';
2828
import { getIsReactionEnabled } from '../../../utils/getIsReactionEnabled';
29-
import { useMessageLayoutDirection } from '../../../hooks/useHTMLTextDirection';
3029

3130
export { ThreadReplySelectType } from './const'; // export for external usage
3231

@@ -146,7 +145,7 @@ export const GroupChannelProvider = (props: GroupChannelProviderProps) => {
146145
const { config, stores } = useSendbirdStateContext();
147146

148147
const { sdkStore } = stores;
149-
const { markAsReadScheduler, logger, htmlTextDirection, forceLeftToRightMessageLayout } = config;
148+
const { markAsReadScheduler, logger } = config;
150149

151150
// State
152151
const [quoteMessage, setQuoteMessage] = useState<SendableMessageType | null>(null);
@@ -262,12 +261,6 @@ export const GroupChannelProvider = (props: GroupChannelProviderProps) => {
262261
if (_animatedMessageId) setAnimatedMessageId(_animatedMessageId);
263262
}, [_animatedMessageId]);
264263

265-
useMessageLayoutDirection(
266-
htmlTextDirection,
267-
forceLeftToRightMessageLayout,
268-
messageDataSource.loading,
269-
);
270-
271264
const scrollToBottom = usePreservedCallback(async (animated?: boolean) => {
272265
if (!scrollRef.current) return;
273266

src/modules/Thread/components/ThreadUI/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import useMemorizedThreadList from './useMemorizedThreadList';
1717
import Label, { LabelTypography, LabelColors } from '../../../../ui/Label';
1818
import { isAboutSame } from '../../context/utils';
1919
import { MessageProvider } from '../../../Message/context/MessageProvider';
20-
import { SendableMessageType } from '../../../../utils';
20+
import { SendableMessageType, getHTMLTextDirection } from '../../../../utils';
2121
import { classnames } from '../../../../utils/utils';
2222

2323
export interface ThreadUIProps {
@@ -52,6 +52,7 @@ const ThreadUI: React.FC<ThreadUIProps> = ({
5252
}: ThreadUIProps): React.ReactElement => {
5353
const {
5454
stores,
55+
config,
5556
} = useSendbirdStateContext();
5657
const currentUserId = stores?.sdkStore?.sdk?.currentUser?.userId;
5758
const {
@@ -152,6 +153,7 @@ const ThreadUI: React.FC<ThreadUIProps> = ({
152153
className={classnames('sendbird-thread-ui--scroll', 'sendbird-conversation__messages')}
153154
ref={scrollRef}
154155
onScroll={onScroll}
156+
dir={getHTMLTextDirection(config?.htmlTextDirection, config?.forceLeftToRightMessageLayout)}
155157
>
156158
<MessageProvider message={parentMessage} isByMe={isByMe}>
157159
{MemorizedParentMessageInfo}

src/modules/Thread/context/ThreadProvider.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@ import useSendVoiceMessageCallback from './hooks/useSendVoiceMessageCallback';
3333
import { PublishingModuleType, useSendMultipleFilesMessage } from './hooks/useSendMultipleFilesMessage';
3434
import { SendableMessageType } from '../../../utils';
3535
import { useThreadFetchers } from './hooks/useThreadFetchers';
36-
import { useMessageLayoutDirection } from '../../../hooks/useHTMLTextDirection';
37-
import { ChannelStateTypes, ParentMessageStateTypes, ThreadListStateTypes } from '../types';
3836

3937
export interface ThreadProviderProps extends
4038
Pick<UserProfileProviderProps, 'disableUserProfile' | 'renderUserProfile'> {
@@ -92,7 +90,7 @@ export const ThreadProvider = (props: ThreadProviderProps) => {
9290
const { user } = userStore;
9391
const sdkInit = sdkStore?.initialized;
9492
// // config
95-
const { logger, pubSub, htmlTextDirection, forceLeftToRightMessageLayout } = config;
93+
const { logger, pubSub } = config;
9694

9795
const isMentionEnabled = config.groupChannel.enableMention;
9896
const isReactionEnabled = config.groupChannel.enableReactions;
@@ -166,14 +164,6 @@ export const ThreadProvider = (props: ThreadProviderProps) => {
166164
}
167165
}, [stores.sdkStore.initialized, config.isOnline, initialize]);
168166

169-
useMessageLayoutDirection(
170-
htmlTextDirection,
171-
forceLeftToRightMessageLayout,
172-
channelState === ChannelStateTypes.LOADING
173-
|| threadListState === ThreadListStateTypes.LOADING
174-
|| parentMessageState === ParentMessageStateTypes.LOADING,
175-
);
176-
177167
const toggleReaction = useToggleReactionCallback({ currentChannel }, { logger });
178168

179169
// Send Message Hooks

src/utils/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,3 +990,7 @@ export const isSendableMessage = (message?: BaseMessage | null): message is Send
990990
export const isChannelJustCreated = (channel: GroupChannel): boolean => {
991991
return isSameSecond(channel.createdAt, channel.invitedAt) && !channel.lastMessage;
992992
};
993+
994+
export const getHTMLTextDirection = (direction: HTMLTextDirection, forceLeftToRightMessageLayout: boolean): string => {
995+
return forceLeftToRightMessageLayout ? 'ltr' : direction;
996+
};

0 commit comments

Comments
 (0)