Skip to content

Commit 86de371

Browse files
committed
Render custom emoji
1 parent 53e26da commit 86de371

1 file changed

Lines changed: 61 additions & 16 deletions

File tree

app/containers/markdown/components/Preview.tsx

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { themes } from '../../../lib/constants/colors';
55
import { useTheme } from '../../../theme';
66
import usePreviewFormatText from '../../../lib/hooks/usePreviewFormatText';
77
import styles from '../styles';
8+
import { useSelector } from 'react-redux';
9+
import { IApplicationState } from '../../../definitions';
10+
import CustomEmoji from '../../EmojiPicker/CustomEmoji';
811

912
interface IMarkdownPreview {
1013
msg?: string;
@@ -14,22 +17,64 @@ interface IMarkdownPreview {
1417
}
1518

1619
const MarkdownPreview = ({ msg, numberOfLines = 1, style = [], testID }: IMarkdownPreview) => {
17-
const { theme } = useTheme();
18-
const formattedText = usePreviewFormatText(msg ?? '');
19-
20-
if (!msg) {
21-
return null;
22-
}
23-
const m = formattedText;
24-
return (
25-
<Text
26-
accessibilityLabel={m}
27-
style={[styles.text, { color: themes[theme].fontDefault, lineHeight: undefined }, ...style]}
28-
numberOfLines={numberOfLines}
29-
testID={testID || `markdown-preview-${m}`}>
30-
{m}
31-
</Text>
32-
);
20+
const { theme } = useTheme();
21+
const formattedText = usePreviewFormatText(msg ?? '');
22+
const customEmojis = useSelector((state: IApplicationState) => state.customEmojis);
23+
24+
if (!msg) {
25+
return null;
26+
}
27+
28+
function getCustomEmoji(name: string) {
29+
const emoji = customEmojis[name];
30+
return emoji ?? null;
31+
}
32+
33+
function parseText(input: string) {
34+
const emojiPattern = /(:[a-zA-Z0-9_+-]+:)/g;
35+
const emojiRegex = /:[a-zA-Z0-9_+-]+:/;
36+
37+
const parts = input.split(emojiPattern).filter(Boolean);
38+
39+
const tokens = parts.map(p => {
40+
const isEmoji = emojiRegex.test(p);
41+
42+
return {
43+
type: isEmoji ? "emoji" : "text",
44+
value: isEmoji ? getCustomEmoji(p.replace(/:/g, '')) : p
45+
}
46+
});
47+
48+
return tokens.reduce((acc: any[], curr: any) => {
49+
const last = acc[acc.length - 1];
50+
if (last && last.type === "text" && curr.type === "text") {
51+
last.value += curr.value;
52+
} else {
53+
acc.push(curr);
54+
}
55+
return acc;
56+
}, []);
57+
}
58+
59+
const m = parseText(formattedText);
60+
61+
return (
62+
<Text
63+
accessibilityLabel={formattedText}
64+
style={[styles.text, { color: themes[theme].fontDefault, lineHeight: undefined }, ...style]}
65+
numberOfLines={numberOfLines}
66+
testID={testID || `markdown-preview-${formattedText}`}
67+
>
68+
{m.map((token, i) => {
69+
if (token.type === 'emoji' && token.value) {
70+
return <CustomEmoji key={i} emoji={token.value} style={{ width: 15, height: 15 }} />
71+
}
72+
return (
73+
<Text key={i}>{token.value}</Text>
74+
);
75+
})}
76+
</Text>
77+
);
3378
};
3479

3580
export default MarkdownPreview;

0 commit comments

Comments
 (0)