Skip to content
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

Add clickable custom emoji support for onboarding task #55222

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
14 changes: 7 additions & 7 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const onboardingEmployerOrSubmitMessage: OnboardingMessage = {
'\n' +
'Here’s how to submit an expense:\n' +
'\n' +
'1. Click the green *+* button.\n' +
'1. Press the <custom-emoji emoji="action-menu-icon" /> button.\n' +
'2. Choose *Create expense*.\n' +
'3. Enter an amount or scan a receipt.\n' +
'4. Add your reimburser to the request.\n' +
Expand All @@ -144,7 +144,7 @@ const combinedTrackSubmitOnboardingEmployerOrSubmitMessage: OnboardingMessage =
'\n' +
'Here’s how to submit an expense:\n' +
'\n' +
'1. Click the green *+* button.\n' +
'1. Press the <custom-emoji emoji="action-menu-icon" /> button\n' +
'2. Choose *Create expense*.\n' +
'3. Enter an amount or scan a receipt.\n' +
'4. Add your reimburser to the request.\n' +
Expand Down Expand Up @@ -175,7 +175,7 @@ const onboardingPersonalSpendMessage: OnboardingMessage = {
'\n' +
'Here’s how to track an expense:\n' +
'\n' +
'1. Click the green *+* button.\n' +
'1. Press the <custom-emoji emoji="action-menu-icon" /> button.\n' +
'2. Choose *Track expense*.\n' +
'3. Enter an amount or scan a receipt.\n' +
'4. Click *Track*.\n' +
Expand All @@ -197,7 +197,7 @@ const combinedTrackSubmitOnboardingPersonalSpendMessage: OnboardingMessage = {
'\n' +
'Here’s how to track an expense:\n' +
'\n' +
'1. Click the green *+* button.\n' +
'1. Press the <custom-emoji emoji="action-menu-icon" /> button.\n' +
'2. Choose *Create expense*.\n' +
'3. Enter an amount or scan a receipt.\n' +
'4. Click "Just track it (don\'t submit it)".\n' +
Expand Down Expand Up @@ -5127,7 +5127,7 @@ const CONST = {
'\n' +
'Here’s how to start a chat:\n' +
'\n' +
'1. Click the green *+* button.\n' +
'1. Press the <custom-emoji emoji="action-menu-icon" /> button.\n' +
'2. Choose *Start chat*.\n' +
'3. Enter emails or phone numbers.\n' +
'\n' +
Expand All @@ -5144,7 +5144,7 @@ const CONST = {
'\n' +
'Here’s how to request money:\n' +
'\n' +
'1. Hit the green *+* button.\n' +
'1. Press the <custom-emoji emoji="action-menu-icon" /> button\n' +
'2. Choose *Start chat*.\n' +
'3. Enter any email, SMS, or name of who you want to split with.\n' +
'4. From within the chat, hit the *+* button on the message bar, and hit *Split expense*.\n' +
Expand Down Expand Up @@ -5194,7 +5194,7 @@ const CONST = {
'\n' +
'Here’s how to submit an expense:\n' +
'\n' +
'1. Click the green *+* button.\n' +
'1. Press the <custom-emoji emoji="action-menu-icon" /> button.\n' +
'2. Choose *Create expense*.\n' +
'3. Enter an amount or scan a receipt.\n' +
'4. Add your reimburser to the request.\n' +
Expand Down
72 changes: 45 additions & 27 deletions src/components/FloatingActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,12 @@ type FloatingActionButtonProps = {

/* An accessibility role for the button */
role: Role;

/* An accessibility render as emoji for the button */
isEmoji?: boolean;
};

function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: FloatingActionButtonProps, ref: ForwardedRef<HTMLDivElement | View | Text>) {
function FloatingActionButton({onPress, isActive, accessibilityLabel, role, isEmoji}: FloatingActionButtonProps, ref: ForwardedRef<HTMLDivElement | View | Text>) {
const {success, buttonDefaultBG, textLight, textDark} = useTheme();
const styles = useThemeStyles();
const borderRadius = styles.floatingActionButton.borderRadius;
Expand Down Expand Up @@ -117,6 +120,46 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo
onPress(event);
};

const floatingActionStyle = isEmoji ? styles.floatingActionEmoji : styles.floatingActionButton;
const iconSizeStyle = isEmoji ? variables.iconSizeExtraSmall : variables.iconSizeNormal;
const nativePositionFix = Platform.OS === 'web' ? [] : {height: '6%'};
const pressebleStyles = isEmoji ? [nativePositionFix] : [styles.h100, styles.bottomTabBarItem];
const animatedStyles = [floatingActionStyle, isEmoji ? {} : animatedStyle];

const button = (
<PressableWithoutFeedback
ref={(el) => {
fabPressable.current = el ?? null;
if (buttonRef && 'current' in buttonRef) {
buttonRef.current = el ?? null;
}
}}
style={pressebleStyles}
accessibilityLabel={accessibilityLabel}
onPress={toggleFabAction}
onLongPress={() => {}}
role={role}
shouldUseHapticsOnLongPress={false}
>
<Animated.View style={animatedStyles}>
<Svg
width={iconSizeStyle}
height={iconSizeStyle}
viewBox={`0 0 ${variables.iconSizeNormal} ${variables.iconSizeNormal}`}
>
<AnimatedPath
d="M12,3c0-1.1-0.9-2-2-2C8.9,1,8,1.9,8,3v5H3c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h5v5c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2v-5h5c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2h-5V3z"
animatedProps={animatedProps}
/>
</Svg>
</Animated.View>
</PressableWithoutFeedback>
);

if (isEmoji) {
return button;
}

return (
<EducationalTooltip
shouldRender={shouldShowProductTrainingTooltip}
Expand All @@ -129,32 +172,7 @@ function FloatingActionButton({onPress, isActive, accessibilityLabel, role}: Flo
wrapperStyle={styles.productTrainingTooltipWrapper}
shouldHideOnNavigate={false}
>
<PressableWithoutFeedback
ref={(el) => {
fabPressable.current = el ?? null;
if (buttonRef && 'current' in buttonRef) {
buttonRef.current = el ?? null;
}
}}
style={[styles.h100, styles.bottomTabBarItem]}
accessibilityLabel={accessibilityLabel}
onPress={toggleFabAction}
onLongPress={() => {}}
role={role}
shouldUseHapticsOnLongPress={false}
>
<Animated.View style={[styles.floatingActionButton, animatedStyle]}>
<Svg
width={variables.iconSizeNormal}
height={variables.iconSizeNormal}
>
<AnimatedPath
d="M12,3c0-1.1-0.9-2-2-2C8.9,1,8,1.9,8,3v5H3c-1.1,0-2,0.9-2,2c0,1.1,0.9,2,2,2h5v5c0,1.1,0.9,2,2,2c1.1,0,2-0.9,2-2v-5h5c1.1,0,2-0.9,2-2c0-1.1-0.9-2-2-2h-5V3z"
animatedProps={animatedProps}
/>
</Svg>
</Animated.View>
</PressableWithoutFeedback>
{button}
</EducationalTooltip>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ function BaseHTMLEngineProvider({textSelectable = false, children, enableExperim
'mention-user': HTMLElementModel.fromCustomModel({tagName: 'mention-user', contentModel: HTMLContentModel.textual}),
'mention-report': HTMLElementModel.fromCustomModel({tagName: 'mention-report', contentModel: HTMLContentModel.textual}),
'mention-here': HTMLElementModel.fromCustomModel({tagName: 'mention-here', contentModel: HTMLContentModel.textual}),
'custom-emoji': HTMLElementModel.fromCustomModel({tagName: 'custom-emoji', contentModel: HTMLContentModel.textual}),
'next-step': HTMLElementModel.fromCustomModel({
tagName: 'next-step',
mixedUAStyles: {...styles.textLabelSupporting, ...styles.lh16},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html';
import FloatingActionEmoji from '@pages/home/sidebar/SidebarScreen/FloatingActionEmoji';

function CustomEmojiRenderer({tnode}: CustomRendererProps<TText | TPhrasing>) {
if (tnode.attributes.emoji === 'action-menu-icon') {
return <FloatingActionEmoji />;
}

return '';
}

export default CustomEmojiRenderer;
carlosmiceli marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 2 additions & 0 deletions src/components/HTMLEngineProvider/HTMLRenderers/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type {CustomTagRendererRecord} from 'react-native-render-html';
import AnchorRenderer from './AnchorRenderer';
import CodeRenderer from './CodeRenderer';
import CustomEmojiRenderer from './CustomEmojiRenderer';
import EditedRenderer from './EditedRenderer';
import EmojiRenderer from './EmojiRenderer';
import ImageRenderer from './ImageRenderer';
Expand Down Expand Up @@ -28,6 +29,7 @@ const HTMLEngineProviderComponentList: CustomTagRendererRecord = {
'mention-user': MentionUserRenderer,
'mention-report': MentionReportRenderer,
'mention-here': MentionHereRenderer,
'custom-emoji': CustomEmojiRenderer,
emoji: EmojiRenderer,
'next-step-email': NextStepEmailRenderer,
/* eslint-enable @typescript-eslint/naming-convention */
Expand Down
18 changes: 13 additions & 5 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4522,7 +4522,7 @@ function completeShortMention(text: string): string {
* For comments shorter than or equal to 10k chars, convert the comment from MD into HTML because that's how it is stored in the database
* For longer comments, skip parsing, but still escape the text, and display plaintext for performance reasons. It takes over 40s to parse a 100k long string!!
*/
function getParsedComment(text: string, parsingDetails?: ParsingDetails): string {
function getParsedComment(text: string, parsingDetails?: ParsingDetails, isAllowCustomEmoji?: boolean): string {
let isGroupPolicyReport = false;
if (parsingDetails?.reportID) {
const currentReport = getReportOrDraftReport(parsingDetails?.reportID);
Expand All @@ -4538,9 +4538,16 @@ function getParsedComment(text: string, parsingDetails?: ParsingDetails): string

const textWithMention = completeShortMention(text);

return text.length <= CONST.MAX_MARKUP_LENGTH
? Parser.replace(textWithMention, {shouldEscapeText: parsingDetails?.shouldEscapeText, disabledRules: isGroupPolicyReport ? [] : ['reportMentions']})
: lodashEscape(text);
let result =
text.length <= CONST.MAX_MARKUP_LENGTH
? Parser.replace(textWithMention, {shouldEscapeText: parsingDetails?.shouldEscapeText, disabledRules: isGroupPolicyReport ? [] : ['reportMentions']})
: lodashEscape(text);

if (isAllowCustomEmoji) {
result = result.replace(/&lt;custom-emoji emoji=&quot;/g, '<custom-emoji emoji="').replace(/&quot; \/&gt;/g, '" />');
}

return result;
}

function getUploadingAttachmentHtml(file?: FileObject): string {
Expand Down Expand Up @@ -6342,6 +6349,7 @@ function buildOptimisticTaskReport(
description?: string,
policyID: string = CONST.POLICY.OWNER_EMAIL_FAKE,
notificationPreference: NotificationPreference = CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
isAllowCustomEmoji?: boolean,
): OptimisticTaskReport {
const participants: Participants = {
[ownerAccountID]: {
Expand All @@ -6356,7 +6364,7 @@ function buildOptimisticTaskReport(
return {
reportID: generateReportID(),
reportName: title,
description: getParsedComment(description ?? ''),
description: getParsedComment(description ?? '', undefined, isAllowCustomEmoji),
ownerAccountID,
participants,
managerID: assigneeAccountID,
Expand Down
1 change: 1 addition & 0 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3695,6 +3695,7 @@ function prepareOnboardingOptimisticData(
taskDescription,
targetChatPolicyID,
CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN,
true, // is Allow render custom emoji
);
const emailCreatingAction =
engagementChoice === CONST.ONBOARDING_CHOICES.MANAGE_TEAM ? allPersonalDetails?.[actorAccountID]?.login ?? CONST.EMAIL.CONCIERGE : CONST.EMAIL.CONCIERGE;
Expand Down
Loading
Loading