Skip to content

Conversation

@yellowtailfan
Copy link
Contributor

@yellowtailfan yellowtailfan commented May 2, 2025

Explanation of Change

Currently when a long HTML string is pasted into the App, the string is truncated before any parsing. However, some clipboard sources such as Microsoft Word create large headers that are bigger than the typical maxLength of 10K. This means the body element of the HTML is truncated and the HTML to Markdown parser attempt to parse the header producing nonsense codes.

This change moves the long string truncation into the Parser. The truncation happens after the body section is extracted but before any other parsing to preserve performance for long strings. The fix depends on Expensify/expensify-common#852.

The result is that HTML pastes are more reliable and preserve formatting such as bold and italics.

Multiple combinations of app platform + app browser host + clipboard source app were tested before and after the patch. In the combination reported (Windows), the patch fixes the reported issue. In other combinations, the behaviour was different from the reported issue (some cases were correct, others were not), and this patch makes no changes to that behaviour.

Fixed Issues

$ #57241
PROPOSAL: #57241 (comment)

Tests

  1. Copy text formatted with bold and italics in Word or other apps that copy HTML to the clipboard
  2. Paste into App chat
  3. Confirm that either formatted text or plain text appears (depending on the platform)
  4. Confirm that nonsense codes do not appear

Note that the bug was reported on Windows and the fix also applies to Windows. See the test results table below for the behaviour before and after this PR for all platforms.

Test: text with bold and italic formatting copied in Word (or equivalent) and pasted into Expensify

  • Small (S): 4 lines (bold, underline, italic, normal)
  • Medium (M): 2 pages
  • Extra Extra Large (L): 400 KB (181 pages)

Browsers used as an app host:

  • Chrome (CH)
  • Firefox (FF)
  • Safari (SF)

Medium and large pasted text was truncated by the Expensify app code (as expected) unless otherwise noted.

Platform OS Apps (copy source) Browser (app host) Test before fix (copy: paste) Test after fix (copy: paste) Screen cap
Web Win Word Chrome Firefox ❌SML: Code (CH)
❌SM: Code (FF)
❌L: 2 sec lag then code (FF)
✅SML: Formatted (CH)
✅SM: Formatted (FF)
✅L: Formatted + 2 sec lag (FF)
✅ (CH)
Web macOS Word Chrome Safari ❌SML: Image attachment (CH)
✅SM: Formatted (SF)
❌L: 2 sec lag then blank line (SF)
❌SML: Image attachment (CH)
✅SM: Formatted (SF)
❌L: 5 sec lag then blank line (SF)
✅ (SF)
Desktop macOS Word n/a ❌SM: Image attachment
❌L: 2 sec lag then image attachment
❌SM: Image attachment
❌L: 2 sec lag then image attachment
Native iOS Safari (iOS) n/a 🟠SML: Plain text 🟠SML: Plain text
mWeb iOS S: Safari (iOS)
ML: Word (macOS)
Safari ✅SM: Formatted
❌L: 2 sec lag then blank line
✅SM: Formatted
❌L: 2 sec lag then blank line
Native Android Google Docs
Chrome
n/a 🟠S (GD & CH): Plain text 🟠S (GD & CH): Plain text
mWeb Android Google Docs
Chrome
Chrome 🟠S (GD & CH): Plain text 🟠S (GD & CH): Plain text

Image copying was also tested on Windows with the Web version of Expensify:

  1. Create short Word document with a mix of formatted text and on image
  2. Copy the entire document to the clipboard
  3. Paste into Expensify chat
  4. Expensify pops a "Send attachment" modal showing just the image
  5. Clicking Send posts a chat message containing only the image

This happens both on the original and patched code.

The same test with Chrome as the source, and copying a mix of formatted text and an image produces a correctly formatted chat message including the image, both on the original and patched code.

  • Verify that no errors appear in the JS console

There was an alert related to the canBeMissing param for useOnyx but it occurred both in the main branch and patched code, so I assume it is an unrelated and unfixed issue on main.

Offline tests

Tested patched code works as expected on reported steps when browser is offline (Web on Windows).

QA Steps

// TODO: These must be filled out, or the issue title must include "[No QA]."

Same as tests

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
    • MacOS: Desktop
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
native-andoid-patched.webm
Android: mWeb Chrome
mweb-android-chrome-patched.webm
iOS: Native
native-ios-patched.mp4
iOS: mWeb Safari
mweb-ios-safari-patched.mp4
MacOS: Chrome / Safari
web-mac-safari-patched.mp4
MacOS: Desktop
desktop-mac-safari-patched.mp4
Windows: Chrome
web-win-chrome-patched.mp4

@github-actions
Copy link
Contributor

github-actions bot commented May 2, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@yellowtailfan
Copy link
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@github-actions
Copy link
Contributor

github-actions bot commented May 7, 2025

⚠️ This PR is possibly changing native code and/or updating libraries, it may cause problems with HybridApp. Please check if any patch updates are required in the HybridApp repo and run an AdHoc build to verify that HybridApp will not break. Ask Contributor Plus for help if you are not sure how to handle this. ⚠️

@yellowtailfan yellowtailfan changed the title [WIP] fix: move truncation of HTML paste into parser fix: move truncation of HTML paste into parser May 7, 2025
@yellowtailfan yellowtailfan marked this pull request as ready for review May 7, 2025 01:42
@yellowtailfan yellowtailfan requested a review from a team as a code owner May 7, 2025 01:42
@melvin-bot melvin-bot bot requested review from mananjadhav and removed request for a team May 7, 2025 01:42
@melvin-bot
Copy link

melvin-bot bot commented May 7, 2025

@mananjadhav Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@yellowtailfan
Copy link
Contributor Author

Waiting on high traffic account before I can complete the author checklist.

@yellowtailfan
Copy link
Contributor Author

@mananjadhav Not sure how to handle the HybridApp warning.

@mananjadhav
Copy link
Collaborator

@yellowtailfan I think the best way would be to trigger the adhoc build. The reason being we'll be able to test it like an end user and also large content.

@Gonals Can you please trigger adhoc build for this one.

@yellowtailfan
Copy link
Contributor Author

Tested on high-traffic account and staging API. Author checklist completed. ✅

@mananjadhav
Copy link
Collaborator

Thanks for constant communication on this one @yellowtailfan. I'll get to it today.

Copy link
Collaborator

@mananjadhav mananjadhav left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code change is fine. I don't have a Windows machine to test right now. Can we have an adhoc build @Gonals? I can then try to test this out.

@melvin-bot melvin-bot bot requested a review from Gonals May 13, 2025 06:31
Gonals
Gonals previously approved these changes May 14, 2025
@github-actions
Copy link
Contributor

🚧 @Gonals has triggered a test app build. You can view the workflow run here.

@github-actions
Copy link
Contributor

🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪

Android 🤖 iOS 🍎
Android 🤖🔄 iOS 🍎🔄
https://ad-hoc-expensify-cash.s3.amazonaws.com/android/61322-hybrid/index.html https://ad-hoc-expensify-cash.s3.amazonaws.com/ios/61322-hybrid/index.html
Android iOS
Desktop 💻 Web 🕸️
https://ad-hoc-expensify-cash.s3.amazonaws.com/desktop/61322/NewExpensify.dmg https://61322.pr-testing.expensify.com
Desktop Web

👀 View the workflow run that generated this build 👀

@yellowtailfan
Copy link
Contributor Author

@mananjadhav It looks like a lot of the automated checks failed, but in parts of the code that this PR doesn't change. I guess I forked off main when it was in a bad state? What's the best way to handle these failed checks?

I got a message with QR codes for an ad hoc build thanks @Gonals. @mananjadhav should I test the ad hoc build, or you, or both of us?

@mananjadhav
Copy link
Collaborator

You can test the adhoc build, I'll also be testing by Friday-Saturday. Meanwhile can you sync with the latest main?

@mananjadhav
Copy link
Collaborator

@yellowtailfan can we still fix these so that we can unblock the PR? Generally we try to fix the lint issues despite not a part of the PR. These are split amongst different PRs.

@yellowtailfan
Copy link
Contributor Author

yellowtailfan commented May 22, 2025

@mananjadhav Thanks for your guidance. I have fixed the lint issues. Some of them were also fixed upstream so I merged the fixes. The lint fixes were:

  1. Avoid namespace imports for @libs and @userActions
  2. Add canBeMissing to useOnyx() calls
  3. Avoid calling deprecated function getTransaction()

For canBeMissing I checked the usage of the return value to see if undefined was handled, which in all cases it was, so I set canBeMissing: true. However, other upstream changes have set some of these to false in which case I accepted the upstream change.

For the deprecated function, it was actually only used in the export so I added a comment to disable the lint check on that line.

To test the lint changes this is what I did:

  • Carefully review all changed lines in the commits
  • Local build and web
  • Test affected functions in the app (via Web)

I wasn't able to reach all of the affected functions in my app, e.g. I couldn't figure out how to access tasks. However, the ones I could reach all worked fine.

@yellowtailfan
Copy link
Contributor Author

A couple more lints. I can look at those tomorrow if you like.

@mananjadhav
Copy link
Collaborator

@yellowtailfan Can you merge the latest main?

@Gonals Should we rollback and skip the lint fixes? I can see several fixes which are not in the test path and could affect. If not can we atleast skip these new lint errors for this PR scope.

@mananjadhav
Copy link
Collaborator

Quick bump @Gonals

@Gonals
Copy link
Contributor

Gonals commented May 27, 2025

We managed to get past something this by coordinating merge/push times in this other PR

@MacroLens
Copy link
Contributor

The lint issues may be caused by a bug described in #62656.

@parasharrajat
Copy link
Member

parasharrajat commented May 27, 2025

@mananjadhav we need to update the e-common version to the latest to solve an error on main. have you tested and approved this PR?

I am going to merge the new version bump, then we won't need to do the same here in this PR. In case, you find any issues here, you will have to update the e-common again and version on this PR. Thus I can safely merge my PR.

@yellowtailfan
Copy link
Contributor Author

@parasharrajat Thanks for letting me know about the e-common version bump, I will resolve and test on the next merge. Please let me know which PR you are merging.

@Gonals Can you please trigger the workflows on this PR at 10 am EDT tomorrow (Wed)?

Before then I propose to do these steps:

  1. Rollback my lint fixes on files not originally changed in my PR (relating to useOnyx and import namespace) as they are out of scope for this PR and it was difficult for me to analyse and test all of them
  2. Merge the latest main, resolve the e-common version bump and retest
  3. Shortly before 10 am EDT, run another merge and manually simulate the workflows lint check

@parasharrajat
Copy link
Member

parasharrajat commented May 27, 2025

@yellowtailfan That PR is merged. During the conflict resolution, take the most recent version. #62873

@yellowtailfan
Copy link
Contributor Author

OK I've synchronised with upstream main and reverted my lint fixes on unrelated files. I tested my fix still works. I will resync shortly before 10 am EDT.

@yellowtailfan
Copy link
Contributor Author

yellowtailfan commented May 28, 2025

@Gonals I just did a sync and lint-changed is running fine for me. Can you please trigger the workflows?

If I don't hear from you in the next hour, I will do another sync just before 10 am EDT.

@Gonals Gonals merged commit 0b279f9 into Expensify:main May 28, 2025
16 checks passed
@OSBotify
Copy link
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@yellowtailfan yellowtailfan deleted the fix/57241 branch May 28, 2025 13:00
@github-actions
Copy link
Contributor

🚀 Deployed to staging by https://github.com/Gonals in version: 9.1.54-0 🚀

platform result
🖥 desktop 🖥 success ✅
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@github-actions
Copy link
Contributor

github-actions bot commented Jun 2, 2025

🚀 Deployed to production by https://github.com/roryabraham in version: 9.1.54-7 🚀

platform result
🖥 desktop 🖥 success ✅
🕸 web 🕸 success ✅
🤖 android 🤖 failure ❌
🍎 iOS 🍎 success ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants