From f7275e04e6d5aa07438760e51f1532fd165423df Mon Sep 17 00:00:00 2001 From: Robert Kozik Date: Fri, 19 Apr 2024 11:11:35 +0200 Subject: [PATCH 01/10] introduce OnyxAwareParser --- src/libs/OnyxAwareParser.ts | 39 +++++++++++++++++++ .../report/ContextMenu/ContextMenuActions.tsx | 4 +- 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/libs/OnyxAwareParser.ts diff --git a/src/libs/OnyxAwareParser.ts b/src/libs/OnyxAwareParser.ts new file mode 100644 index 000000000000..4a8d0045abe8 --- /dev/null +++ b/src/libs/OnyxAwareParser.ts @@ -0,0 +1,39 @@ +import ONYXKEYS from "@src/ONYXKEYS"; +import ExpensiMark from "expensify-common/lib/ExpensiMark"; +import Onyx from "react-native-onyx"; + +const parser = new ExpensiMark(); + +const reportIDToNameMap: Record = {}; +const accountIDToNameMap: Record = {}; + +Onyx.connect({ + key: ONYXKEYS.COLLECTION.REPORT, + callback: (report) => { + if (!report) { + return; + } + + reportIDToNameMap[report.reportID] = report.reportName ?? ''; + }, +}) + +Onyx.connect({ + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + callback: (personalDetailsList) => { + Object.values(personalDetailsList ?? {}).forEach((personalDetails) => { + if (!personalDetails) { + return; + } + + accountIDToNameMap[personalDetails.accountID] = personalDetails.displayName ?? ''; + }); + }, +}) + + +function parseHtmlToMarkdown(html: string): string { + return parser.htmlToMarkdown(html, {reportIdToName: reportIDToNameMap, accountIDToName: accountIDToNameMap}); +}; + +export default parseHtmlToMarkdown; diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index b5cb9d911ef5..efe728148887 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -30,6 +30,7 @@ import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import type {Beta, ReportAction, ReportActionReactions, Transaction} from '@src/types/onyx'; import type IconAsset from '@src/types/utils/IconAsset'; +import parseHtmlToMarkdown from '@libs/OnyxAwareParser'; import type {ContextMenuAnchor} from './ReportActionContextMenu'; import {hideContextMenu, showDeleteModal} from './ReportActionContextMenu'; @@ -232,8 +233,7 @@ const ContextMenuActions: ContextMenuAction[] = [ } const editAction = () => { if (!draftMessage) { - const parser = new ExpensiMark(); - Report.saveReportActionDraft(reportID, reportAction, parser.htmlToMarkdown(getActionHtml(reportAction))); + Report.saveReportActionDraft(reportID, reportAction, parseHtmlToMarkdown(getActionHtml(reportAction))); } else { Report.deleteReportActionDraft(reportID, reportAction); } From 7b3fe65b72567ec3bb7f516f531263b57a5914f8 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 19 Apr 2024 15:06:04 +0200 Subject: [PATCH 02/10] `parser.htmlTo` -> `parseHtmlTo` --- package-lock.json | 6 +++--- package.json | 2 +- src/hooks/useCopySelectionHelper.ts | 7 +++---- src/hooks/useHtmlPaste/index.ts | 5 ++--- src/libs/OnyxAwareParser.ts | 19 +++++++++++-------- src/libs/ReportUtils.ts | 10 ++++------ src/libs/actions/Report.ts | 5 +++-- .../PrivateNotes/PrivateNotesEditPage.tsx | 7 +++---- src/pages/RoomDescriptionPage.tsx | 5 ++--- .../report/ContextMenu/ContextMenuActions.tsx | 8 +++----- .../ComposerWithSuggestions.tsx | 5 ++--- .../report/ReportActionItemMessageEdit.tsx | 5 ++--- src/pages/tasks/NewTaskDescriptionPage.tsx | 3 ++- src/pages/tasks/NewTaskDetailsPage.tsx | 5 +++-- src/pages/tasks/TaskDescriptionPage.tsx | 5 +++-- .../workspace/WorkspaceInviteMessagePage.tsx | 3 ++- .../WorkspaceProfileDescriptionPage.tsx | 3 ++- src/pages/workspace/taxes/NamePage.tsx | 6 ++---- 18 files changed, 53 insertions(+), 56 deletions(-) diff --git a/package-lock.json b/package-lock.json index 52a975e3a83e..80484c07a6fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,7 +57,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#c0f7f3b6558fbeda0527c80d68460d418afef219", + "expensify-common": "git+ssh://git@github.com:software-mansion-labs/expensify-common.git#7596ae07c9cd5a6b5265897034898b4526d681dc", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", @@ -20213,8 +20213,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#c0f7f3b6558fbeda0527c80d68460d418afef219", - "integrity": "sha512-zz0/y0apISP1orxXEQOgn+Uod45O4wVypwwtaqcDPV4dH1tC3i4L98NoLSZvLn7Y17EcceSkfN6QCEsscgFTDQ==", + "resolved": "git+ssh://git@github.com/software-mansion-labs/expensify-common.git#7596ae07c9cd5a6b5265897034898b4526d681dc", + "integrity": "sha512-Ns7qkMuJ4SeLj0lrj3i+KqHBzjlym8baDlS7CUIqq2tuNXkgxwO4D+5d6U3ooLOf0CyWb56KaGy5TOTFqpJDZA==", "license": "MIT", "dependencies": { "classnames": "2.5.0", diff --git a/package.json b/package.json index 1cef7d94fcba..50029f0e22c3 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#c0f7f3b6558fbeda0527c80d68460d418afef219", + "expensify-common": "git+ssh://git@github.com:software-mansion-labs/expensify-common.git#7596ae07c9cd5a6b5265897034898b4526d681dc", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", diff --git a/src/hooks/useCopySelectionHelper.ts b/src/hooks/useCopySelectionHelper.ts index be7830dc6170..ed379bfcf2e6 100644 --- a/src/hooks/useCopySelectionHelper.ts +++ b/src/hooks/useCopySelectionHelper.ts @@ -1,7 +1,7 @@ -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import {useEffect} from 'react'; import Clipboard from '@libs/Clipboard'; import KeyboardShortcut from '@libs/KeyboardShortcut'; +import {parseHtmlToMarkdown, parseHtmlToText} from '@libs/OnyxAwareParser'; import SelectionScraper from '@libs/SelectionScraper'; import CONST from '@src/CONST'; @@ -10,12 +10,11 @@ function copySelectionToClipboard() { if (!selection) { return; } - const parser = new ExpensiMark(); if (!Clipboard.canSetHtml()) { - Clipboard.setString(parser.htmlToMarkdown(selection)); + Clipboard.setString(parseHtmlToMarkdown(selection)); return; } - Clipboard.setHtml(selection, parser.htmlToText(selection)); + Clipboard.setHtml(selection, parseHtmlToText(selection)); } export default function useCopySelectionHelper() { diff --git a/src/hooks/useHtmlPaste/index.ts b/src/hooks/useHtmlPaste/index.ts index 925a3db518ae..82a52dbb0fef 100644 --- a/src/hooks/useHtmlPaste/index.ts +++ b/src/hooks/useHtmlPaste/index.ts @@ -1,6 +1,6 @@ import {useNavigation} from '@react-navigation/native'; -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import {useCallback, useEffect} from 'react'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import type UseHtmlPaste from './types'; const insertByCommand = (text: string) => { @@ -62,8 +62,7 @@ const useHtmlPaste: UseHtmlPaste = (textInputRef, preHtmlPasteCallback, removeLi */ const handlePastedHTML = useCallback( (html: string) => { - const parser = new ExpensiMark(); - paste(parser.htmlToMarkdown(html)); + paste(parseHtmlToMarkdown(html)); }, [paste], ); diff --git a/src/libs/OnyxAwareParser.ts b/src/libs/OnyxAwareParser.ts index 4a8d0045abe8..853f94d7189f 100644 --- a/src/libs/OnyxAwareParser.ts +++ b/src/libs/OnyxAwareParser.ts @@ -1,6 +1,6 @@ -import ONYXKEYS from "@src/ONYXKEYS"; -import ExpensiMark from "expensify-common/lib/ExpensiMark"; -import Onyx from "react-native-onyx"; +import ExpensiMark from 'expensify-common/lib/ExpensiMark'; +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '@src/ONYXKEYS'; const parser = new ExpensiMark(); @@ -16,7 +16,7 @@ Onyx.connect({ reportIDToNameMap[report.reportID] = report.reportName ?? ''; }, -}) +}); Onyx.connect({ key: ONYXKEYS.PERSONAL_DETAILS_LIST, @@ -29,11 +29,14 @@ Onyx.connect({ accountIDToNameMap[personalDetails.accountID] = personalDetails.displayName ?? ''; }); }, -}) - +}); function parseHtmlToMarkdown(html: string): string { return parser.htmlToMarkdown(html, {reportIdToName: reportIDToNameMap, accountIDToName: accountIDToNameMap}); -}; +} + +function parseHtmlToText(html: string): string { + return parser.htmlToText(html, {reportIdToName: reportIDToNameMap, accountIDToName: accountIDToNameMap}); +} -export default parseHtmlToMarkdown; +export {parseHtmlToMarkdown, parseHtmlToText}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index a15e1937dbe2..42c14c820f0d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -69,6 +69,7 @@ import ModifiedExpenseMessage from './ModifiedExpenseMessage'; import linkingConfig from './Navigation/linkingConfig'; import Navigation from './Navigation/Navigation'; import * as NumberUtils from './NumberUtils'; +import {parseHtmlToText} from './OnyxAwareParser'; import Permissions from './Permissions'; import * as PersonalDetailsUtils from './PersonalDetailsUtils'; import * as PhoneNumber from './PhoneNumber'; @@ -3174,8 +3175,7 @@ function getReportDescriptionText(report: Report): string { return ''; } - const parser = new ExpensiMark(); - return parser.htmlToText(report.description); + return parseHtmlToText(report.description); } function getPolicyDescriptionText(policy: OnyxEntry): string { @@ -3183,12 +3183,10 @@ function getPolicyDescriptionText(policy: OnyxEntry): string { return ''; } - const parser = new ExpensiMark(); - return parser.htmlToText(policy.description); + return parseHtmlToText(policy.description); } function buildOptimisticAddCommentReportAction(text?: string, file?: FileObject, actorAccountID?: number): OptimisticReportAction { - const parser = new ExpensiMark(); const commentText = getParsedComment(text ?? ''); const isAttachmentOnly = file && !text; const isTextOnly = text && !file; @@ -3200,7 +3198,7 @@ function buildOptimisticAddCommentReportAction(text?: string, file?: FileObject, textForNewComment = CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML; } else if (isTextOnly) { htmlForNewComment = commentText; - textForNewComment = parser.htmlToText(htmlForNewComment); + textForNewComment = parseHtmlToText(htmlForNewComment); } else { htmlForNewComment = `${commentText}\n${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; textForNewComment = `${commentText}\n${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index a4afff17d972..c4c140e0a85a 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -57,6 +57,7 @@ import * as ErrorUtils from '@libs/ErrorUtils'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import LocalNotification from '@libs/Notification/LocalNotification'; +import {parseHtmlToMarkdown, parseHtmlToText} from '@libs/OnyxAwareParser'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; import getPolicyEmployeeAccountIDs from '@libs/PolicyEmployeeListUtils'; @@ -1331,7 +1332,7 @@ function editReportComment(reportID: string, originalReportAction: OnyxEntry ReportActions.getDraftPrivateNote(report.reportID).trim() || parser.htmlToMarkdown(report?.privateNotes?.[Number(route.params.accountID)]?.note ?? '').trim(), + () => ReportActions.getDraftPrivateNote(report.reportID).trim() || parseHtmlToMarkdown(report?.privateNotes?.[Number(route.params.accountID)]?.note ?? '').trim(), ); /** @@ -93,7 +92,7 @@ function PrivateNotesEditPage({route, personalDetailsList, report}: PrivateNotes const originalNote = report?.privateNotes?.[Number(route.params.accountID)]?.note ?? ''; let editedNote = ''; if (privateNote.trim() !== originalNote.trim()) { - editedNote = ReportActions.handleUserDeletedLinksInHtml(privateNote.trim(), parser.htmlToMarkdown(originalNote).trim()); + editedNote = ReportActions.handleUserDeletedLinksInHtml(privateNote.trim(), parseHtmlToMarkdown(originalNote).trim()); ReportActions.updatePrivateNotes(report.reportID, Number(route.params.accountID), editedNote); } diff --git a/src/pages/RoomDescriptionPage.tsx b/src/pages/RoomDescriptionPage.tsx index 9d26de1da9f1..4641ed8c1c4f 100644 --- a/src/pages/RoomDescriptionPage.tsx +++ b/src/pages/RoomDescriptionPage.tsx @@ -1,5 +1,4 @@ import {useFocusEffect} from '@react-navigation/native'; -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import React, {useCallback, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxCollection} from 'react-native-onyx'; @@ -13,6 +12,7 @@ import TextInput from '@components/TextInput'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import * as ReportUtils from '@libs/ReportUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import * as Report from '@userActions/Report'; @@ -31,8 +31,7 @@ type RoomDescriptionPageProps = { function RoomDescriptionPage({report, policies}: RoomDescriptionPageProps) { const styles = useThemeStyles(); - const parser = new ExpensiMark(); - const [description, setDescription] = useState(() => parser.htmlToMarkdown(report?.description ?? '')); + const [description, setDescription] = useState(() => parseHtmlToMarkdown(report?.description ?? '')); const reportDescriptionInputRef = useRef(null); const focusTimeoutRef = useRef | null>(null); const {translate} = useLocalize(); diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index bd3bedb2a83c..db096e26cd30 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -1,4 +1,3 @@ -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import Str from 'expensify-common/lib/str'; import type {MutableRefObject} from 'react'; import React from 'react'; @@ -19,6 +18,7 @@ import getAttachmentDetails from '@libs/fileDownload/getAttachmentDetails'; import * as Localize from '@libs/Localize'; import ModifiedExpenseMessage from '@libs/ModifiedExpenseMessage'; import Navigation from '@libs/Navigation/Navigation'; +import {parseHtmlToMarkdown, parseHtmlToText} from '@libs/OnyxAwareParser'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -30,7 +30,6 @@ import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import type {Beta, ReportAction, ReportActionReactions, Transaction} from '@src/types/onyx'; import type IconAsset from '@src/types/utils/IconAsset'; -import parseHtmlToMarkdown from '@libs/OnyxAwareParser'; import type {ContextMenuAnchor} from './ReportActionContextMenu'; import {hideContextMenu, showDeleteModal} from './ReportActionContextMenu'; @@ -42,11 +41,10 @@ function getActionHtml(reportAction: OnyxEntry): string { /** Sets the HTML string to Clipboard */ function setClipboardMessage(content: string) { - const parser = new ExpensiMark(); if (!Clipboard.canSetHtml()) { - Clipboard.setString(parser.htmlToMarkdown(content)); + Clipboard.setString(parseHtmlToMarkdown(content)); } else { - const plainText = parser.htmlToText(content); + const plainText = parseHtmlToText(content); Clipboard.setHtml(content, plainText); } } diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 8f42da5a1575..6fc09fb1b15b 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -1,5 +1,4 @@ import {useIsFocused, useNavigation} from '@react-navigation/native'; -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import lodashDebounce from 'lodash/debounce'; import type {ForwardedRef, MutableRefObject, RefAttributes, RefObject} from 'react'; import React, {forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; @@ -35,6 +34,7 @@ import * as EmojiUtils from '@libs/EmojiUtils'; import focusComposerWithDelay from '@libs/focusComposerWithDelay'; import getPlatform from '@libs/getPlatform'; import * as KeyDownListener from '@libs/KeyboardShortcut/KeyDownPressListener'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; @@ -536,8 +536,7 @@ function ComposerWithSuggestions( ) { event.preventDefault(); if (lastReportAction) { - const parser = new ExpensiMark(); - Report.saveReportActionDraft(reportID, lastReportAction, parser.htmlToMarkdown(lastReportAction.message?.at(-1)?.html ?? '')); + Report.saveReportActionDraft(reportID, lastReportAction, parseHtmlToMarkdown(lastReportAction.message?.at(-1)?.html ?? '')); } } }, diff --git a/src/pages/home/report/ReportActionItemMessageEdit.tsx b/src/pages/home/report/ReportActionItemMessageEdit.tsx index fc3c92434fc4..cc1d2789a09a 100644 --- a/src/pages/home/report/ReportActionItemMessageEdit.tsx +++ b/src/pages/home/report/ReportActionItemMessageEdit.tsx @@ -1,4 +1,3 @@ -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import lodashDebounce from 'lodash/debounce'; import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useMemo, useRef, useState} from 'react'; @@ -28,6 +27,7 @@ import * as EmojiUtils from '@libs/EmojiUtils'; import focusComposerWithDelay from '@libs/focusComposerWithDelay'; import type {Selection} from '@libs/focusComposerWithDelay/types'; import focusEditAfterCancelDelete from '@libs/focusEditAfterCancelDelete'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import onyxSubscribe from '@libs/onyxSubscribe'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -117,8 +117,7 @@ function ReportActionItemMessageEdit( const isCommentPendingSaved = useRef(false); useEffect(() => { - const parser = new ExpensiMark(); - const originalMessage = parser.htmlToMarkdown(action.message?.[0]?.html ?? ''); + const originalMessage = parseHtmlToMarkdown(action.message?.[0]?.html ?? ''); if ( ReportActionsUtils.isDeletedAction(action) || Boolean(action.message && draftMessage === originalMessage) || diff --git a/src/pages/tasks/NewTaskDescriptionPage.tsx b/src/pages/tasks/NewTaskDescriptionPage.tsx index e33241c52f4a..4bca46213671 100644 --- a/src/pages/tasks/NewTaskDescriptionPage.tsx +++ b/src/pages/tasks/NewTaskDescriptionPage.tsx @@ -16,6 +16,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {NewTaskNavigatorParamList} from '@libs/Navigation/types'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import * as TaskActions from '@userActions/Task'; import CONST from '@src/CONST'; @@ -77,7 +78,7 @@ function NewTaskDescriptionPage({task}: NewTaskDescriptionPageProps) { { setTaskTitle(task?.title ?? ''); - setTaskDescription(parser.htmlToMarkdown(parser.replace(task?.description ?? ''))); + setTaskDescription(parseHtmlToMarkdown(parser.replace(task?.description ?? ''))); }, [task]); const validate = (values: FormOnyxValues): FormInputErrors => { @@ -132,7 +133,7 @@ function NewTaskDetailsPage({task}: NewTaskDetailsPageProps) { autoGrowHeight shouldSubmitForm containerStyles={styles.autoGrowHeightMultilineInput} - defaultValue={parser.htmlToMarkdown(parser.replace(taskDescription))} + defaultValue={parseHtmlToMarkdown(parser.replace(taskDescription))} value={taskDescription} onValueChange={setTaskDescription} isMarkdownEnabled diff --git a/src/pages/tasks/TaskDescriptionPage.tsx b/src/pages/tasks/TaskDescriptionPage.tsx index 9abe15a5bb80..63bff1073698 100644 --- a/src/pages/tasks/TaskDescriptionPage.tsx +++ b/src/pages/tasks/TaskDescriptionPage.tsx @@ -16,6 +16,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import * as ReportUtils from '@libs/ReportUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import withReportOrNotFound from '@pages/home/report/withReportOrNotFound'; @@ -46,7 +47,7 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti const submit = useCallback( (values: FormOnyxValues) => { - if (parser.htmlToMarkdown(parser.replace(values.description)) !== parser.htmlToMarkdown(parser.replace(report?.description ?? '')) && !isEmptyObject(report)) { + if (parseHtmlToMarkdown(parser.replace(values.description)) !== parseHtmlToMarkdown(parser.replace(report?.description ?? '')) && !isEmptyObject(report)) { // Set the description of the report in the store and then call EditTask API // to update the description of the report on the server Task.editTask(report, {description: values.description}); @@ -109,7 +110,7 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti name={INPUT_IDS.DESCRIPTION} label={translate('newTaskPage.descriptionOptional')} accessibilityLabel={translate('newTaskPage.descriptionOptional')} - defaultValue={parser.htmlToMarkdown((report && parser.replace(report?.description ?? '')) || '')} + defaultValue={parseHtmlToMarkdown((report && parser.replace(report?.description ?? '')) || '')} ref={(element: AnimatedTextInputRef) => { if (!element) { return; diff --git a/src/pages/workspace/WorkspaceInviteMessagePage.tsx b/src/pages/workspace/WorkspaceInviteMessagePage.tsx index 30d66662b996..56e2d5a2c257 100644 --- a/src/pages/workspace/WorkspaceInviteMessagePage.tsx +++ b/src/pages/workspace/WorkspaceInviteMessagePage.tsx @@ -23,6 +23,7 @@ import useAutoFocusInput from '@hooks/useAutoFocusInput'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; @@ -93,7 +94,7 @@ function WorkspaceInviteMessagePage({ useEffect(() => { if (!isEmptyObject(invitedEmailsToAccountIDsDraft)) { - setWelcomeNote(parser.htmlToMarkdown(getDefaultWelcomeNote())); + setWelcomeNote(parseHtmlToMarkdown(getDefaultWelcomeNote())); return; } Navigation.goBack(ROUTES.WORKSPACE_INVITE.getRoute(route.params.policyID), true); diff --git a/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx b/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx index 8086f2414e42..52066d8313d6 100644 --- a/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx +++ b/src/pages/workspace/WorkspaceProfileDescriptionPage.tsx @@ -12,6 +12,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import * as Policy from '@userActions/Policy'; import CONST from '@src/CONST'; @@ -27,7 +28,7 @@ function WorkspaceProfileDescriptionPage({policy}: Props) { const styles = useThemeStyles(); const {translate} = useLocalize(); const [description, setDescription] = useState(() => - parser.htmlToMarkdown( + parseHtmlToMarkdown( // policy?.description can be an empty string // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing policy?.description || diff --git a/src/pages/workspace/taxes/NamePage.tsx b/src/pages/workspace/taxes/NamePage.tsx index 5c77295a9664..3e5902b140ac 100644 --- a/src/pages/workspace/taxes/NamePage.tsx +++ b/src/pages/workspace/taxes/NamePage.tsx @@ -1,5 +1,4 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import React, {useCallback, useState} from 'react'; import {View} from 'react-native'; import FormProvider from '@components/Form/FormProvider'; @@ -14,6 +13,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import {renamePolicyTax, validateTaxName} from '@libs/actions/TaxRate'; import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; +import {parseHtmlToMarkdown} from '@libs/OnyxAwareParser'; import * as PolicyUtils from '@libs/PolicyUtils'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import AdminPolicyAccessOrNotFoundWrapper from '@pages/workspace/AdminPolicyAccessOrNotFoundWrapper'; @@ -29,8 +29,6 @@ import INPUT_IDS from '@src/types/form/WorkspaceTaxNameForm'; type NamePageProps = WithPolicyAndFullscreenLoadingProps & StackScreenProps; -const parser = new ExpensiMark(); - function NamePage({ route: { params: {policyID, taxID}, @@ -42,7 +40,7 @@ function NamePage({ const currentTaxRate = PolicyUtils.getTaxByID(policy, taxID); const {inputCallbackRef} = useAutoFocusInput(); - const [name, setName] = useState(() => parser.htmlToMarkdown(currentTaxRate?.name ?? '')); + const [name, setName] = useState(() => parseHtmlToMarkdown(currentTaxRate?.name ?? '')); const goBack = useCallback(() => Navigation.goBack(ROUTES.WORKSPACE_TAX_EDIT.getRoute(policyID ?? '', taxID)), [policyID, taxID]); From baf2a8c18cd41f58b7fdd098a48b53d022e074fa Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 19 Apr 2024 15:21:18 +0200 Subject: [PATCH 03/10] add fallback when displayName does not exist --- src/libs/OnyxAwareParser.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/OnyxAwareParser.ts b/src/libs/OnyxAwareParser.ts index 853f94d7189f..586b914216be 100644 --- a/src/libs/OnyxAwareParser.ts +++ b/src/libs/OnyxAwareParser.ts @@ -14,7 +14,7 @@ Onyx.connect({ return; } - reportIDToNameMap[report.reportID] = report.reportName ?? ''; + reportIDToNameMap[report.reportID] = report.reportName ?? report.displayName ?? report.reportID; }, }); @@ -26,7 +26,7 @@ Onyx.connect({ return; } - accountIDToNameMap[personalDetails.accountID] = personalDetails.displayName ?? ''; + accountIDToNameMap[personalDetails.accountID] = personalDetails.displayName ?? String(personalDetails.accountID); }); }, }); From 63a70982f9293675e1ce66070b9f1744b03d41b7 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 19 Apr 2024 15:25:32 +0200 Subject: [PATCH 04/10] bring back removed trim --- src/libs/actions/Report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index c4c140e0a85a..734078078126 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1332,7 +1332,7 @@ function editReportComment(reportID: string, originalReportAction: OnyxEntry Date: Tue, 23 Apr 2024 13:00:15 +0200 Subject: [PATCH 05/10] update expensify-common --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c30f6c1a74c..17bb60a22ef1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,7 +56,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com:software-mansion-labs/expensify-common.git#7596ae07c9cd5a6b5265897034898b4526d681dc", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#9a68635cdcef4c81593c0f816a007bc9c707d46a", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", @@ -20202,8 +20202,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/software-mansion-labs/expensify-common.git#7596ae07c9cd5a6b5265897034898b4526d681dc", - "integrity": "sha512-Ns7qkMuJ4SeLj0lrj3i+KqHBzjlym8baDlS7CUIqq2tuNXkgxwO4D+5d6U3ooLOf0CyWb56KaGy5TOTFqpJDZA==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#9a68635cdcef4c81593c0f816a007bc9c707d46a", + "integrity": "sha512-9BHjM3kZs7/dil0oykEQFkEhXjVD5liTttmO7ZYtPZkl4j6g97mubY2p9lYpWwpkWckUfvU7nGuZQjahw9xSFA==", "license": "MIT", "dependencies": { "classnames": "2.5.0", diff --git a/package.json b/package.json index 571b1638e266..39c6132711cc 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com:software-mansion-labs/expensify-common.git#7596ae07c9cd5a6b5265897034898b4526d681dc", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#9a68635cdcef4c81593c0f816a007bc9c707d46a", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", From 46a1f6e72cd3b3b069cdb1fcd72e845c63ee3716 Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 29 Apr 2024 14:04:57 +0200 Subject: [PATCH 06/10] fix failing typecheck --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index cb9f449c14f9..ad683903fd5c 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3324,7 +3324,7 @@ function buildOptimisticAddCommentReportAction(text?: string, file?: FileObject, textForNewComment = parseHtmlToText(htmlForNewComment); } else { htmlForNewComment = `${commentText}\n${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; - textForNewComment = `${parser.htmlToText(commentText)}\n${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; + textForNewComment = `${parseHtmlToText(commentText)}\n${CONST.ATTACHMENT_UPLOADING_MESSAGE_HTML}`; } const isAttachment = !text && file !== undefined; From 98c0acfaae9c511e2eb871b968023e7fe0c752da Mon Sep 17 00:00:00 2001 From: war-in Date: Mon, 13 May 2024 15:33:53 +0200 Subject: [PATCH 07/10] remove leftovers --- src/pages/tasks/TaskDescriptionPage.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/pages/tasks/TaskDescriptionPage.tsx b/src/pages/tasks/TaskDescriptionPage.tsx index 4a9a7f870230..7b3dd8813540 100644 --- a/src/pages/tasks/TaskDescriptionPage.tsx +++ b/src/pages/tasks/TaskDescriptionPage.tsx @@ -1,5 +1,4 @@ import {useFocusEffect} from '@react-navigation/native'; -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import React, {useCallback, useRef} from 'react'; import {View} from 'react-native'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -30,8 +29,6 @@ import {isEmptyObject} from '@src/types/utils/EmptyObject'; type TaskDescriptionPageProps = WithReportOrNotFoundProps & WithCurrentUserPersonalDetailsProps; -const parser = new ExpensiMark(); - function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescriptionPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -48,7 +45,7 @@ function TaskDescriptionPage({report, currentUserPersonalDetails}: TaskDescripti const submit = useCallback( (values: FormOnyxValues) => { - if (values.description !== parseHtmlToMarkdown(parser.replace(report?.description ?? '')) && !isEmptyObject(report)) { + if (values.description !== parseHtmlToMarkdown(report?.description ?? '') && !isEmptyObject(report)) { // Set the description of the report in the store and then call EditTask API // to update the description of the report on the server Task.editTask(report, {description: values.description}); From dafa5a4f22b9412b3f6ce64a69e796a427c3563d Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 14 May 2024 18:11:30 +0200 Subject: [PATCH 08/10] replace htmlToText in `OptionRowLHN` --- src/components/LHNOptionsList/OptionRowLHN.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index b665c305f5cf..fe234eb629a4 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -1,5 +1,4 @@ import {useFocusEffect} from '@react-navigation/native'; -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import React, {useCallback, useRef, useState} from 'react'; import type {GestureResponderEvent, ViewStyle} from 'react-native'; import {StyleSheet, View} from 'react-native'; @@ -20,6 +19,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import DateUtils from '@libs/DateUtils'; import DomUtils from '@libs/DomUtils'; +import {parseHtmlToText} from '@libs/OnyxAwareParser'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import Performance from '@libs/Performance'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; @@ -29,8 +29,6 @@ import CONST from '@src/CONST'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type {OptionRowLHNProps} from './types'; -const parser = new ExpensiMark(); - function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, optionItem, viewMode = 'default', style, onLayout = () => {}, hasDraftComment}: OptionRowLHNProps) { const theme = useTheme(); const styles = useThemeStyles(); @@ -228,7 +226,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti numberOfLines={1} accessibilityLabel={translate('accessibilityHints.lastChatMessagePreview')} > - {parser.htmlToText(optionItem.alternateText)} + {parseHtmlToText(optionItem.alternateText)} ) : null} From a8fbfa6ae5e5d11879015680fb9b9d3dc739df27 Mon Sep 17 00:00:00 2001 From: war-in Date: Tue, 4 Jun 2024 13:04:00 +0200 Subject: [PATCH 09/10] use `personalDetails.login` as account name --- src/libs/OnyxAwareParser.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/OnyxAwareParser.ts b/src/libs/OnyxAwareParser.ts index 586b914216be..3366de44e76c 100644 --- a/src/libs/OnyxAwareParser.ts +++ b/src/libs/OnyxAwareParser.ts @@ -26,16 +26,18 @@ Onyx.connect({ return; } - accountIDToNameMap[personalDetails.accountID] = personalDetails.displayName ?? String(personalDetails.accountID); + accountIDToNameMap[personalDetails.accountID] = personalDetails.login ?? String(personalDetails.accountID); }); }, }); function parseHtmlToMarkdown(html: string): string { + // TODO: change `reportIdToName` to `reportIDToName` (changes in expensify-common) return parser.htmlToMarkdown(html, {reportIdToName: reportIDToNameMap, accountIDToName: accountIDToNameMap}); } function parseHtmlToText(html: string): string { + // TODO: change `reportIdToName` to `reportIDToName` (changes in expensify-common) return parser.htmlToText(html, {reportIdToName: reportIDToNameMap, accountIDToName: accountIDToNameMap}); } From f0b59c07fbdc9b7ab9f72110f1aca1a92a1d9af4 Mon Sep 17 00:00:00 2001 From: war-in Date: Fri, 7 Jun 2024 11:16:36 +0200 Subject: [PATCH 10/10] allow passing custom extras to OnyxAwareParser --- src/libs/OnyxAwareParser.ts | 12 +++++------- src/libs/ReportUtils.ts | 3 +-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/libs/OnyxAwareParser.ts b/src/libs/OnyxAwareParser.ts index 3366de44e76c..a202118bdf5f 100644 --- a/src/libs/OnyxAwareParser.ts +++ b/src/libs/OnyxAwareParser.ts @@ -1,4 +1,4 @@ -import ExpensiMark from 'expensify-common/lib/ExpensiMark'; +import {ExpensiMark} from 'expensify-common'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -31,14 +31,12 @@ Onyx.connect({ }, }); -function parseHtmlToMarkdown(html: string): string { - // TODO: change `reportIdToName` to `reportIDToName` (changes in expensify-common) - return parser.htmlToMarkdown(html, {reportIdToName: reportIDToNameMap, accountIDToName: accountIDToNameMap}); +function parseHtmlToMarkdown(html: string, reportIDToName?: Record, accountIDToName?: Record): string { + return parser.htmlToMarkdown(html, {reportIDToName: reportIDToName ?? reportIDToNameMap, accountIDToName: accountIDToName ?? accountIDToNameMap}); } -function parseHtmlToText(html: string): string { - // TODO: change `reportIdToName` to `reportIDToName` (changes in expensify-common) - return parser.htmlToText(html, {reportIdToName: reportIDToNameMap, accountIDToName: accountIDToNameMap}); +function parseHtmlToText(html: string, reportIDToName?: Record, accountIDToName?: Record): string { + return parser.htmlToText(html, {reportIDToName: reportIDToName ?? reportIDToNameMap, accountIDToName: accountIDToName ?? accountIDToNameMap}); } export {parseHtmlToMarkdown, parseHtmlToText}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e7fdec5dadac..8ccef6e402c3 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -3187,8 +3187,7 @@ function parseReportActionHtmlToText(reportAction: OnyxEntry, repo const logins = PersonalDetailsUtils.getLoginsByAccountIDs(accountIDs); accountIDs.forEach((id, index) => (accountIDToName[id] = logins[index])); - const parser = new ExpensiMark(); - const textMessage = Str.removeSMSDomain(parser.htmlToText(html, {reportIDToName, accountIDToName})); + const textMessage = Str.removeSMSDomain(parseHtmlToText(html, reportIDToName, accountIDToName)); parsedReportActionMessageCache[key] = textMessage; return textMessage;