Skip to content

Handle emoji tooltip #35838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b930ed4
implement tooltip for emoji
dukenv0307 Jan 18, 2024
7385bf2
Merge branch 'main' into fix/34307
dukenv0307 Jan 24, 2024
925d6c3
implement tooltip for emoji
dukenv0307 Jan 24, 2024
ff81b72
write new file in typescript
dukenv0307 Jan 24, 2024
b6ecd0f
merge main
dukenv0307 Feb 5, 2024
21d6337
Merge branch 'main' into fix/34307
dukenv0307 Feb 5, 2024
d5f99a0
Merge branch 'main' into fix/34307
dukenv0307 Feb 5, 2024
ab0f57b
fix edge case
dukenv0307 Feb 5, 2024
54a21ae
write new page on ts
dukenv0307 Feb 5, 2024
046522e
revert local change
dukenv0307 Feb 6, 2024
47e78b6
disable tooltip for native
dukenv0307 Feb 6, 2024
a0f72ef
Merge branch 'main' into fix/34307
dukenv0307 Feb 6, 2024
4a9f29e
bump version of expensify-common
dukenv0307 Feb 6, 2024
2b5ec33
Merge branch 'main' into fix/34307
dukenv0307 Feb 7, 2024
1de60ab
Update src/styles/index.ts
dukenv0307 Feb 10, 2024
5a6a291
Merge branch 'main' into fix/34307
dukenv0307 Feb 10, 2024
2755f34
merge main
dukenv0307 Feb 10, 2024
a9bd9b4
fix ts error
dukenv0307 Feb 10, 2024
a0e43e0
merge main
dukenv0307 Feb 13, 2024
05c9b28
Merge branch 'main' into fix/34307
dukenv0307 Feb 13, 2024
0501a41
merge main
dukenv0307 Feb 15, 2024
439e629
fix the case emoji that is made up by some different emojis
dukenv0307 Feb 19, 2024
cf36e9b
Merge branch 'main' into fix/34307
dukenv0307 Feb 22, 2024
d622078
update version expesify-common
dukenv0307 Feb 22, 2024
7a65924
Merge branch 'main' into fix/34307
dukenv0307 Feb 22, 2024
db43ff1
Merge branch 'main' into fix/34307
dukenv0307 Feb 26, 2024
7eedaf3
add new attribute for emoji tag if contain only emoji
dukenv0307 Feb 26, 2024
5382c13
Merge branch 'main' into fix/34307
dukenv0307 Feb 27, 2024
62d558d
add check shouldRenderAsText for seprate platform
dukenv0307 Feb 27, 2024
1a34f6b
merge main
dukenv0307 Feb 28, 2024
a37188a
fix case delete emoji
dukenv0307 Feb 28, 2024
4cad935
merge main
dukenv0307 Mar 1, 2024
2a292da
Merge branch 'main' into fix/34307
dukenv0307 Mar 4, 2024
5f599ae
fix test
dukenv0307 Mar 4, 2024
bcb3510
fix lint
dukenv0307 Mar 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
"date-fns-tz": "^2.0.0",
"dom-serializer": "^0.2.2",
"domhandler": "^4.3.0",
"expensify-common": "git+ssh://[email protected]/Expensify/expensify-common.git#a8ed0f8e1be3a1e09016e07a74cfd13c85bbc167",
"expensify-common": "git+ssh://[email protected]/Expensify/expensify-common.git#45d3b61bb38b4f9a19ddf573ce1e212369b242db",
"expo": "^50.0.3",
"expo-av": "~13.10.4",
"expo-image": "1.10.1",
Expand Down
10 changes: 10 additions & 0 deletions src/components/EmojiWithTooltip/index.native.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Text from '@components/Text';
import type EmojiWithTooltipProps from './types';

function EmojiWithTooltip({emojiCode, style = {}}: EmojiWithTooltipProps) {
return <Text style={style}>{emojiCode}</Text>;
}

EmojiWithTooltip.displayName = 'EmojiWithTooltip';

export default EmojiWithTooltip;
40 changes: 40 additions & 0 deletions src/components/EmojiWithTooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, {useCallback} from 'react';
import {View} from 'react-native';
import Text from '@components/Text';
import Tooltip from '@components/Tooltip';
import useThemeStyles from '@hooks/useThemeStyles';
import * as EmojiUtils from '@libs/EmojiUtils';
import type EmojiWithTooltipProps from './types';

function EmojiWithTooltip({emojiCode, style = {}}: EmojiWithTooltipProps) {
const styles = useThemeStyles();
const emoji = EmojiUtils.findEmojiByCode(emojiCode);
const emojiName = EmojiUtils.getEmojiName(emoji);

const emojiTooltipContent = useCallback(
() => (
<View style={[styles.alignItemsCenter, styles.ph2]}>
<View style={[styles.flexRow, styles.emojiTooltipWrapper]}>
<Text
key={emojiCode}
style={styles.onlyEmojisText}
>
{emojiCode}
</Text>
</View>
<Text style={[styles.textMicro, styles.fontColorReactionLabel]}>{`:${emojiName}:`}</Text>
</View>
),
[emojiCode, emojiName, styles.alignItemsCenter, styles.ph2, styles.flexRow, styles.emojiTooltipWrapper, styles.fontColorReactionLabel, styles.onlyEmojisText, styles.textMicro],
);

return (
<Tooltip renderTooltipContent={emojiTooltipContent}>
<Text style={[style, styles.cursorDefault]}>{emojiCode}</Text>
</Tooltip>
);
}

EmojiWithTooltip.displayName = 'EmojiWithTooltip';

export default EmojiWithTooltip;
8 changes: 8 additions & 0 deletions src/components/EmojiWithTooltip/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type {StyleProp, TextStyle} from 'react-native';

type EmojiWithTooltipProps = {
emojiCode: string;
style?: StyleProp<TextStyle>;
};

export default EmojiWithTooltipProps;
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
mixedUAStyles: {whiteSpace: 'pre'},
contentModel: HTMLContentModel.block,
}),
emoji: HTMLElementModel.fromCustomModel({tagName: 'emoji', contentModel: HTMLContentModel.textual}),
}),
[styles.colorMuted, styles.formError, styles.mb0, styles.textLabelSupporting, styles.lh16],
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html';
import EmojiWithTooltip from '@components/EmojiWithTooltip';
import useThemeStyles from '@hooks/useThemeStyles';

function EmojiRenderer({tnode}: CustomRendererProps<TText | TPhrasing>) {
const styles = useThemeStyles();
const style = 'islarge' in tnode.attributes ? styles.onlyEmojisText : {};
return (
<EmojiWithTooltip
style={[style, styles.cursorDefault]}
emojiCode={'data' in tnode ? tnode.data : ''}
/>
);
}

EmojiRenderer.displayName = 'EmojiRenderer';

export default EmojiRenderer;
2 changes: 2 additions & 0 deletions src/components/HTMLEngineProvider/HTMLRenderers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type {CustomTagRendererRecord} from 'react-native-render-html';
import AnchorRenderer from './AnchorRenderer';
import CodeRenderer from './CodeRenderer';
import EditedRenderer from './EditedRenderer';
import EmojiRenderer from './EmojiRenderer';
import ImageRenderer from './ImageRenderer';
import MentionHereRenderer from './MentionHereRenderer';
import MentionUserRenderer from './MentionUserRenderer';
Expand All @@ -25,6 +26,7 @@ const HTMLEngineProviderComponentList: CustomTagRendererRecord = {
/* eslint-disable @typescript-eslint/naming-convention */
'mention-user': MentionUserRenderer,
'mention-here': MentionHereRenderer,
emoji: EmojiRenderer,
'next-step-email': NextStepEmailRenderer,
/* eslint-enable @typescript-eslint/naming-convention */
};
Expand Down
3 changes: 3 additions & 0 deletions src/libs/EmojiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const findEmojiByName = (name: string): Emoji => Emojis.emojiNameTable[name];
const findEmojiByCode = (code: string): Emoji => Emojis.emojiCodeTableWithSkinTones[code];

const getEmojiName = (emoji: Emoji, lang: 'en' | 'es' = CONST.LOCALES.DEFAULT): string => {
if (!emoji) {
return '';
}
if (lang === CONST.LOCALES.DEFAULT) {
return emoji.name;
}
Expand Down
18 changes: 9 additions & 9 deletions src/pages/home/report/comment/TextCommentFragment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import CONST from '@src/CONST';
import type {OriginalMessageSource} from '@src/types/onyx/OriginalMessage';
import type {Message} from '@src/types/onyx/ReportAction';
import RenderCommentHTML from './RenderCommentHTML';
import shouldRenderAsText from './shouldRenderAsText';

type TextCommentFragmentProps = {
/** The reportAction's source */
Expand Down Expand Up @@ -44,15 +45,15 @@ function TextCommentFragment({fragment, styleAsDeleted, source, style, displayAs
const {translate} = useLocalize();
const {isSmallScreenWidth} = useWindowDimensions();

// If the only difference between fragment.text and fragment.html is <br /> tags
// we render it as text, not as html.
// This is done to render emojis with line breaks between them as text.
const differByLineBreaksOnly = Str.replaceAll(html, '<br />', '\n') === text;

// Only render HTML if we have html in the fragment
if (!differByLineBreaksOnly) {
// If the only difference between fragment.text and fragment.html is <br /> tags and emoji tag
// on native, we render it as text, not as html
// on other device, only render it as text if the only difference is <br /> tag
const containsOnlyEmojis = EmojiUtils.containsOnlyEmojis(text);
if (!shouldRenderAsText(html, text) && !(containsOnlyEmojis && styleAsDeleted)) {
const editedTag = fragment.isEdited ? `<edited ${styleAsDeleted ? 'deleted' : ''}></edited>` : '';
const htmlContent = styleAsDeleted ? `<del>${html}</del>` : html;
const htmlWithDeletedTag = styleAsDeleted ? `<del>${html}</del>` : html;

const htmlContent = containsOnlyEmojis ? Str.replaceAll(htmlWithDeletedTag, '<emoji>', '<emoji islarge>') : htmlWithDeletedTag;

const htmlWithTag = editedTag ? `${htmlContent}${editedTag}` : htmlContent;

Expand All @@ -64,7 +65,6 @@ function TextCommentFragment({fragment, styleAsDeleted, source, style, displayAs
);
}

const containsOnlyEmojis = EmojiUtils.containsOnlyEmojis(text);
const message = isEmpty(iouMessage) ? text : iouMessage;

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Str from 'expensify-common/lib/str';

/**
* Whether to render the report action as text
*/
export default function shouldRenderAsText(html: string, text: string): boolean {
// On native, we render emoji as text to prevent the large emoji is cut off when the action is edited.
// More info: https://github.com/Expensify/App/pull/35838#issuecomment-1964839350
const htmlWithoutLineBreak = Str.replaceAll(html, '<br />', '\n');
const htmlWithoutEmojiOpenTag = Str.replaceAll(htmlWithoutLineBreak, '<emoji>', '');
return Str.replaceAll(htmlWithoutEmojiOpenTag, '</emoji>', '') === text;
}
8 changes: 8 additions & 0 deletions src/pages/home/report/comment/shouldRenderAsText/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Str from 'expensify-common/lib/str';

/**
* Whether to render the report action as text
*/
export default function shouldRenderAsText(html: string, text: string): boolean {
return Str.replaceAll(html, '<br />', '\n') === text;
}
4 changes: 4 additions & 0 deletions src/styles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ const styles = (theme: ThemeColors) =>
...wordBreak.breakWord,
...spacing.pr4,
},
emojiTooltipWrapper: {
...spacing.p2,
borderRadius: 8,
},

mentionSuggestionsAvatarContainer: {
width: 24,
Expand Down