Skip to content

Commit

Permalink
fix: apply LRM,RLM properly for mention direction
Browse files Browse the repository at this point in the history
  • Loading branch information
bang9 committed Nov 21, 2024
1 parent d3c76d5 commit 7c7a751
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import { I18nManager, Text as RNText, TextProps as RNTextProps, StyleSheet, TextStyle } from 'react-native';

import { isStartsWithRTL } from '@sendbird/uikit-utils';

import useUIKitTheme from '../../theme/useUIKitTheme';
import type { TypoName, UIKitTheme } from '../../types';
import { isStartsWithRTL } from './isStartsWithRTL';

export interface RTLTextAlignSupportProps {
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import { I18nManager, TextInput as RNTextInput, StyleSheet, TextInputProps, TextStyle } from 'react-native';

import { isStartsWithRTL } from '@sendbird/uikit-utils';

import createStyleSheet from '../../styles/createStyleSheet';
import useUIKitTheme from '../../theme/useUIKitTheme';
import type { UIKitTheme } from '../../types';
import { RTLTextAlignSupportProps } from '../Text';
import { isStartsWithRTL } from '../Text/isStartsWithRTL';

type Props = {
variant?: keyof UIKitTheme['colors']['ui']['input'];
Expand Down
20 changes: 11 additions & 9 deletions packages/uikit-react-native/src/libs/MentionManager.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React from 'react';
import { I18nManager } from 'react-native';

import { Text, createStyleSheet } from '@sendbird/uikit-react-native-foundation';
import type { SendbirdFileMessage, SendbirdUser, SendbirdUserMessage } from '@sendbird/uikit-utils';
import { createMentionTemplateRegex, replaceWithRegex } from '@sendbird/uikit-utils';
import { createMentionTemplateRegex, isEndsWithRTL, replaceWithRegex } from '@sendbird/uikit-utils';

import type { MentionedUser, Range } from '../types';
import type { MentionConfigInterface } from './MentionConfig';
Expand All @@ -22,14 +21,17 @@ class MentionManager {
this._templateRegex = createMentionTemplateRegex(this.config.trigger);
}

// Note: When the input starts in LTR and a mentioned user's name is in RTL, it appears as "Hello @{cibarA}."
// Note: When the input starts in LTR and the mentioned user's name is in RTL, it appears as "Hello @{cibarA}."
// If typing continues in RTL, the mention is rendered as: "Hello @{txeTlanoitiddA}{cibarA}."
//
// This appears natural in RTL, but the mention syntax becomes unclear.
// To address this, if RTL is active, we reset subsequent spans using the LRM(Left-To-Right-Mark) Unicode character.
// By applying this trick, the result will be "Hello @{cibarA} {txeTlanoitiddA}," where the mention block remains distinct.
getDirectionOfNextSpan = () => {
return I18nManager.isRTL ? SPAN_DIRECTION.LRM : '';
// Conversely, if the input starts in RTL and the mentioned user's name is in LTR, it appears as "{Eng}@ cibarA."
// If typing continues, it is rendered as: "{Eng}{AdditionalText}@ cibarA."
//
// While this follows the natural text direction, it can make mentions harder to distinguish.
// To address this, we use the RLM or LRM Unicode characters to reset subsequent spans based on the last text string of the user's name.
// By applying this trick, the result will be displayed as "Hello @{cibarA} {txeTlanoitiddA}" or "{AdditionalText} {Eng}@ cibarA," ensuring the mention block remains clearly distinguishable.
getDirectionOfNextSpan = (name: string) => {
return isEndsWithRTL(name) ? SPAN_DIRECTION.LRM : SPAN_DIRECTION.RLM;
};

public rangeHelpers = {
Expand Down Expand Up @@ -136,7 +138,7 @@ class MentionManager {
public asMentionedMessageText = (user: SendbirdUser, delimiter = false) => {
const prefix = '';
const content = `${this.config.trigger}${user.nickname}`;
const postfix = this.getDirectionOfNextSpan() + (delimiter ? this.config.delimiter : '');
const postfix = this.getDirectionOfNextSpan(user.nickname) + (delimiter ? this.config.delimiter : '');

return prefix + content + postfix;
};
Expand Down
1 change: 1 addition & 0 deletions packages/uikit-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export { default as arrayToMap, arrayToMapWithGetter } from './shared/arrayToMap
export * from './shared/regex';
export * from './shared/bufferedRequest';
export * from './shared/file';
export * from './shared/rtl';
export * from './shared';

export * from './hooks';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const isStartsWithRTL = (str?: string): boolean => {
const isRTLString = (dir: 'start' | 'end', str?: string) => {
if (!str || str.length === 0) {
return false;
}
Expand All @@ -8,15 +8,23 @@ export const isStartsWithRTL = (str?: string): boolean => {
return false;
}

const firstChar = Array.from(trimmedStr)[0];
const point = firstChar.codePointAt(0);
const char = dir === 'start' ? Array.from(trimmedStr)[0] : Array.from(trimmedStr).pop();
const point = char?.codePointAt(0);
if (point === undefined) {
return false;
}

return isRTLCodePoint(point);
};

export const isStartsWithRTL = (str?: string): boolean => {
return isRTLString('start', str);
};

export const isEndsWithRTL = (str?: string): boolean => {
return isRTLString('end', str);
};

const isRTLCodePoint = (codePoint: number) => {
for (const [start, end] of rtlCodePointRanges) {
if (codePoint >= start && codePoint <= end) {
Expand Down

0 comments on commit 7c7a751

Please sign in to comment.