Skip to content

Commit 469310e

Browse files
authored
Merge pull request #58555 from Krishna2323/krishna2323/issue/58194
fix: title image rendering in task preview and task view.
2 parents 58b8887 + 726c35b commit 469310e

File tree

13 files changed

+49
-17
lines changed

13 files changed

+49
-17
lines changed

src/CONST.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ const CONST = {
363363
BILLABLE: 'billable',
364364
NON_BILLABLE: 'nonBillable',
365365
},
366-
366+
TASK_TITLE_DISABLED_RULES: ['image'],
367367
// Note: Group and Self-DM excluded as these are not tied to a Workspace
368368
WORKSPACE_ROOM_TYPES: [chatTypes.POLICY_ADMINS, chatTypes.POLICY_ANNOUNCE, chatTypes.DOMAIN_ALL, chatTypes.POLICY_ROOM, chatTypes.POLICY_EXPENSE_CHAT, chatTypes.INVOICE],
369369
ANDROID_PACKAGE_NAME,

src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,15 @@ function AnchorRenderer({tnode, style, key}: AnchorRendererProps) {
7272
// eslint-disable-next-line react/jsx-props-no-multi-spaces
7373
target={htmlAttribs.target || '_blank'}
7474
rel={htmlAttribs.rel || 'noopener noreferrer'}
75-
style={[style, parentStyle, textDecorationLineStyle, styles.textUnderlinePositionUnder, styles.textDecorationSkipInkNone, isChildOfTaskTitle && styles.taskTitleMenuItem]}
75+
style={[
76+
style,
77+
parentStyle,
78+
textDecorationLineStyle,
79+
styles.textUnderlinePositionUnder,
80+
styles.textDecorationSkipInkNone,
81+
isChildOfTaskTitle && styles.taskTitleMenuItem,
82+
styles.dInlineFlex,
83+
]}
7684
key={key}
7785
// Only pass the press handler for internal links. For public links or whitelisted internal links fallback to default link handling
7886
onPress={internalNewExpensifyPath || internalExpensifyPath ? () => openLink(attrHref, environmentURL, isAttachment) : undefined}
@@ -88,7 +96,14 @@ function AnchorRenderer({tnode, style, key}: AnchorRendererProps) {
8896
return (
8997
<Text
9098
key={props.key}
91-
style={[props.childTnode.getNativeStyles(), parentStyle, textDecorationLineStyle, styles.textUnderlinePositionUnder, styles.textDecorationSkipInkNone]}
99+
style={[
100+
props.childTnode.getNativeStyles(),
101+
parentStyle,
102+
textDecorationLineStyle,
103+
styles.textUnderlinePositionUnder,
104+
styles.textDecorationSkipInkNone,
105+
styles.dInlineFlex,
106+
]}
92107
>
93108
{props.childTnode.data}
94109
</Text>

src/components/ReportActionItem/TaskPreview.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import ControlSelection from '@libs/ControlSelection';
2424
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
2525
import getButtonState from '@libs/getButtonState';
2626
import Navigation from '@libs/Navigation/Navigation';
27+
import Parser from '@libs/Parser';
2728
import {isCanceledTaskReport, isOpenTaskReport, isReportManager} from '@libs/ReportUtils';
2829
import type {ContextMenuAnchor} from '@pages/home/report/ContextMenu/ReportActionContextMenu';
2930
import CONST from '@src/CONST';
@@ -64,6 +65,9 @@ function TaskPreview({taskReportID, action, contextMenuAnchor, chatReportID, che
6465
const {translate} = useLocalize();
6566
const theme = useTheme();
6667
const [taskReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${taskReportID}`);
68+
const taskTitle = action?.childReportName ?? taskReport?.reportName ?? '';
69+
70+
const taskTitleWithoutImage = Parser.replace(Parser.htmlToMarkdown(taskTitle), {disabledRules: [...CONST.TASK_TITLE_DISABLED_RULES]});
6771

6872
// The reportAction might not contain details regarding the taskReport
6973
// Only the direct parent reportAction will contain details about the taskReport
@@ -127,7 +131,7 @@ function TaskPreview({taskReportID, action, contextMenuAnchor, chatReportID, che
127131
</UserDetailsTooltip>
128132
)}
129133
<View style={[styles.alignSelfCenter, styles.flex1]}>
130-
<RenderHTML html={`<comment>${taskReport?.reportName ?? action?.childReportName ?? ''}</comment>`} />
134+
<RenderHTML html={`<comment>${taskTitleWithoutImage}</comment>`} />
131135
</View>
132136
</View>
133137
{shouldShowGreenDotIndicator && (

src/components/ReportActionItem/TaskView.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import convertToLTR from '@libs/convertToLTR';
2222
import getButtonState from '@libs/getButtonState';
2323
import Navigation from '@libs/Navigation/Navigation';
2424
import {getAvatarsForAccountIDs, getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils';
25+
import Parser from '@libs/Parser';
2526
import {getDisplayNameForParticipant, getDisplayNamesWithTooltips, isCompletedTaskReport, isOpenTaskReport} from '@libs/ReportUtils';
2627
import {isActiveTaskEditRoute} from '@libs/TaskUtils';
2728
import {callFunctionIfActionIsAllowed} from '@userActions/Session';
@@ -44,7 +45,8 @@ function TaskView({report}: TaskViewProps) {
4445
useEffect(() => {
4546
setTaskReport(report);
4647
}, [report]);
47-
const taskTitle = `<task-title>${convertToLTR(report?.reportName ?? '')}</task-title>`;
48+
const titleWithoutImage = Parser.replace(Parser.htmlToMarkdown(report?.reportName ?? ''), {disabledRules: [...CONST.TASK_TITLE_DISABLED_RULES]});
49+
const taskTitle = `<task-title>${convertToLTR(titleWithoutImage)}</task-title>`;
4850
const assigneeTooltipDetails = getDisplayNamesWithTooltips(getPersonalDetailsForAccountIDs(report?.managerID ? [report?.managerID] : [], personalDetails), false);
4951

5052
const isOpen = isOpenTaskReport(report);

src/components/Search/SearchAutocompleteList.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {
3535
parseForAutocomplete,
3636
} from '@libs/SearchAutocompleteUtils';
3737
import {buildSearchQueryJSON, buildUserReadableQueryString, sanitizeSearchValue} from '@libs/SearchQueryUtils';
38+
import StringUtils from '@libs/StringUtils';
3839
import Timing from '@userActions/Timing';
3940
import CONST from '@src/CONST';
4041
import ONYXKEYS from '@src/ONYXKEYS';
@@ -479,7 +480,12 @@ function SearchAutocompleteList(
479480
sections.push({title: translate('search.recentSearches'), data: recentSearchesData});
480481
}
481482

482-
const styledRecentReports = recentReportsOptions.map((item) => ({...item, pressableStyle: styles.br2, wrapperStyle: [styles.pr3, styles.pl3]}));
483+
const styledRecentReports = recentReportsOptions.map((item) => ({
484+
...item,
485+
pressableStyle: styles.br2,
486+
text: StringUtils.lineBreaksToSpaces(item.text),
487+
wrapperStyle: [styles.pr3, styles.pl3],
488+
}));
483489
sections.push({title: autocompleteQueryValue.trim() === '' ? translate('search.recentChats') : undefined, data: styledRecentReports});
484490

485491
if (autocompleteSuggestions.length > 0) {

src/components/Search/SearchRouter/SearchRouter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret}: SearchRouterProps,
145145
{
146146
data: [
147147
{
148-
text: `${translate('search.searchIn')} ${reportForContextualSearch.text ?? reportForContextualSearch.alternateText}`,
148+
text: StringUtils.lineBreaksToSpaces(`${translate('search.searchIn')} ${reportForContextualSearch.text ?? reportForContextualSearch.alternateText}`),
149149
singleIcon: Expensicons.MagnifyingGlass,
150150
searchQuery: reportQueryValue,
151151
autocompleteID,

src/libs/ReportUtils.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4933,7 +4933,7 @@ function completeShortMention(text: string): string {
49334933
* 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
49344934
* 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!!
49354935
*/
4936-
function getParsedComment(text: string, parsingDetails?: ParsingDetails, mediaAttributes?: Record<string, string>): string {
4936+
function getParsedComment(text: string, parsingDetails?: ParsingDetails, mediaAttributes?: Record<string, string>, disabledRules?: string[]): string {
49374937
let isGroupPolicyReport = false;
49384938
if (parsingDetails?.reportID) {
49394939
const currentReport = getReportOrDraftReport(parsingDetails?.reportID);
@@ -4948,11 +4948,12 @@ function getParsedComment(text: string, parsingDetails?: ParsingDetails, mediaAt
49484948
}
49494949

49504950
const textWithMention = completeShortMention(text);
4951+
const rules = disabledRules ?? [];
49514952

49524953
return text.length <= CONST.MAX_MARKUP_LENGTH
49534954
? Parser.replace(textWithMention, {
49544955
shouldEscapeText: parsingDetails?.shouldEscapeText,
4955-
disabledRules: isGroupPolicyReport ? [] : ['reportMentions'],
4956+
disabledRules: isGroupPolicyReport ? [...rules] : ['reportMentions', ...rules],
49564957
extras: {mediaAttributeCache: mediaAttributes},
49574958
})
49584959
: lodashEscape(text);
@@ -6578,7 +6579,7 @@ function buildOptimisticEditedTaskFieldReportAction({title, description}: Task):
65786579
{
65796580
type: CONST.REPORT.MESSAGE.TYPE.COMMENT,
65806581
text: changelog,
6581-
html: getParsedComment(changelog),
6582+
html: getParsedComment(changelog, undefined, undefined, title !== undefined ? [...CONST.TASK_TITLE_DISABLED_RULES] : undefined),
65826583
},
65836584
],
65846585
person: [
@@ -6923,7 +6924,7 @@ function buildOptimisticTaskReport(
69236924

69246925
return {
69256926
reportID: generateReportID(),
6926-
reportName: getParsedComment(title ?? ''),
6927+
reportName: getParsedComment(title ?? '', undefined, undefined, [...CONST.TASK_TITLE_DISABLED_RULES]),
69276928
description: getParsedComment(description ?? '', {}, mediaAttributes),
69286929
ownerAccountID,
69296930
participants,

src/libs/actions/Task.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ function editTask(report: OnyxTypes.Report, {title, description}: OnyxTypes.Task
550550

551551
// Ensure title is defined before parsing it with getParsedComment. If title is undefined, fall back to reportName from report.
552552
// Trim the final parsed title for consistency.
553-
const reportName = title ? ReportUtils.getParsedComment(title) : report?.reportName ?? '';
553+
const reportName = title ? ReportUtils.getParsedComment(title, undefined, undefined, [...CONST.TASK_TITLE_DISABLED_RULES]) : report?.reportName ?? '';
554554
const parsedTitle = (reportName ?? '').trim();
555555

556556
// Description can be unset, so we default to an empty string if so

src/pages/tasks/NewTaskPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ function NewTaskPage({route}: NewTaskPageProps) {
139139
shouldShowRightIcon
140140
rightLabel={translate('common.required')}
141141
shouldParseTitle
142+
excludedMarkdownRules={[...CONST.TASK_TITLE_DISABLED_RULES]}
142143
/>
143144
<MenuItemWithTopDescription
144145
description={translate('task.description')}

src/pages/tasks/TaskTitlePage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps)
4141
({title}: FormOnyxValues<typeof ONYXKEYS.FORMS.EDIT_TASK_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.EDIT_TASK_FORM> => {
4242
const errors: FormInputErrors<typeof ONYXKEYS.FORMS.EDIT_TASK_FORM> = {};
4343

44-
const parsedTitle = getParsedComment(title);
44+
const parsedTitle = getParsedComment(title, undefined, undefined, [...CONST.TASK_TITLE_DISABLED_RULES]);
4545
const parsedTitleLength = getCommentLength(parsedTitle);
4646

4747
if (!parsedTitle) {
@@ -110,7 +110,7 @@ function TaskTitlePage({report, currentUserPersonalDetails}: TaskTitlePageProps)
110110
name={INPUT_IDS.TITLE}
111111
label={translate('task.title')}
112112
accessibilityLabel={translate('task.title')}
113-
defaultValue={Parser.htmlToMarkdown(report?.reportName ?? '')}
113+
defaultValue={Parser.htmlToMarkdown(report?.reportName ?? '', {})}
114114
ref={(element: AnimatedTextInputRef) => {
115115
if (!element) {
116116
return;

src/styles/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4313,18 +4313,20 @@ const styles = (theme: ThemeColors) =>
43134313
...writingDirection.ltr,
43144314
...headlineFont,
43154315
fontSize: variables.fontSizeXLarge,
4316-
lineHeight: variables.lineHeightSizeh2,
4316+
lineHeight: variables.lineHeighTaskTitle,
43174317
maxWidth: '100%',
43184318
...wordBreak.breakWord,
4319+
textUnderlineOffset: -1,
43194320
},
43204321

43214322
taskTitleMenuItemItalic: {
43224323
...writingDirection.ltr,
43234324
...headlineItalicFont,
43244325
fontSize: variables.fontSizeXLarge,
4325-
lineHeight: variables.lineHeightSizeh2,
4326+
lineHeight: variables.lineHeighTaskTitle,
43264327
maxWidth: '100%',
43274328
...wordBreak.breakWord,
4329+
textUnderlineOffset: -1,
43284330
},
43294331

43304332
taskDescriptionMenuItem: {

src/styles/utils/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ function getCodeFontSize(isInsideH1: boolean, isInsideTaskTitle?: boolean) {
635635
return 15;
636636
}
637637
if (isInsideTaskTitle) {
638-
return 19;
638+
return 18;
639639
}
640640
return 13;
641641
}

src/styles/variables.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ export default {
114114
lineHeightXXXLarge: getValueUsingPixelRatio(32, 37),
115115
lineHeightSizeh1: getValueUsingPixelRatio(28, 32),
116116
lineHeightSizeh2: getValueUsingPixelRatio(24, 28),
117+
lineHeighTaskTitle: getValueUsingPixelRatio(26, 30),
117118
lineHeightSignInHeroXSmall: getValueUsingPixelRatio(32, 37),
118119
inputHeight: getValueUsingPixelRatio(52, 72),
119120
inputHeightSmall: 28,

0 commit comments

Comments
 (0)