-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Replace double newlines with a single newline #13739
Conversation
@sobitneupane @robertjchen One of you needs to 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] |
src/components/Composer/index.js
Outdated
@@ -265,7 +265,9 @@ class Composer extends React.Component { | |||
return; | |||
} | |||
|
|||
const plainText = event.clipboardData.getData('text/plain'); | |||
// The regex replace is there because when doing a "paste without formatting", there are extra line breaks added to the content (I do not know why). To fix the problem, anytime | |||
// there is a double set of newline characters, they are replaced with a single newline. This preserves the same number of newlines between pasting with and without formatting. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// there is a double set of newline characters, they are replaced with a single newline. This preserves the same number of newlines between pasting with and without formatting. | |
// there is a double set of newline characters, they are replaced with a single newline. This preserves the same number of new lines between pasting with and without formatting. |
Testing .... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we select the text and copy it with Ctl+C, it works as expected. But if we copy the text with "Copy to Clipboard" option from context menu and paste with Ctrl+Shift+V, new lines get removed.
Steps to reproduce:
- Right click on the sent message and select Copy to clipboard
- Paste the message with Ctrl+Shift+V
- Expected new lines get removed.
Screen.Recording.2022-12-21.at.20.34.23.mov
Thanks for reporting that! I've updated this branch so that the context menu and CTRL+c will have consistent behaviors for browsers. |
@tgolen When I copy the text from Github and paste it with "Ctrl+Shift+V", newlines get removed. Steps to Reproduce:
Screen.Recording.2022-12-29.at.23.37.05.mov |
Copy the text with Ctrl+C from expensify and paste with with "Ctrl + Shift + V", new lines get added.
trimmed.mov |
I might be wrong here, but I think I remember seeing a discussion about this and since GitHub formats its code blocks differently, we weren't going to bother with trying to preserve them perfectly. I'm having trouble finding the conversation, but do you feel that issue is in scope of the original GH?
I am not able to reproduce this one. Any pointers on what I'm doing differently? 2022-12-29_11-49-30.mp4 |
So, I believe this issue is reproducible when the message contains link Can you try sending something like
|
OK, I'll test it out with a link, but that is sure weird why a link would matter. I wonder if that's messing up a regex somewhere... |
All right, I tried it with the link, and I still can't reproduce it 🤔 This video shows me pasting twice. The first time is a normal paste with formatting, the second time is a paste without formatting. In both cases, the newlines are the same (you can see the link is treated a little differently though which is expected). 2023-01-02_09-22-31.mp4 |
@tgolen I can still reproduce the issue on my end. Steps to reproduce:
Screen.Recording.2023-01-03.at.21.19.45.mov |
OK, I see in that video you are copying the message by using the context menu. That is different then from when you previously reported it, right? Can you verify if there is a difference between using the context menu and using CTRL+C to copy the message? |
There is no difference. Both context menu "Copy to clipboard" and CTRL+C has the same result. Screen.Recording.2023-01-03.at.21.57.08.mov |
OK, since I am not able to reproduce it, are there any changes to the code you would suggest? Any idea why you can reproduce it but I can't? |
I just tested it again this morning and I can reproduce the problem 🤦 sorry about that! I'll keep digging |
All right, I found a different place to double the newlines for the context menu which seems to work better and fix the issue. Can you please test again? Thanks for your persistence on this! |
@tgolen It solves the above issue. But with following steps, newlines are still getting added.
Screen.Recording.2023-01-04.at.13.18.34.mov |
OK, that is unfortunate. I will need to think about how to fix that 🤔 |
All right, I pushed an update to fix what happens when you copy (or cut) stuff from inside the composer input |
I also added that to the list of tests |
Screenshots/VideosWebScreen.Recording.2023-01-06.at.20.14.09.movMobile Web - ChromeScreen.Recording.2023-01-06.at.21.01.46.movMobile Web - SafariDesktopScreen.Recording.2023-01-06.at.20.21.28.moviOSRPReplay_Final1673017424.MP4AndroidScreen.Recording.2023-01-06.at.20.38.07.mov |
@tgolen It looks like #13739 (comment) issue is not present in staging. But when copied from other sources(notes, docs) and pasted in app (and vice versa), there are inconsistencies in staging as well. |
@sobitneupane Thanks! I am going to go out on a limb and say that the mobile web issue is OK for now. I don't think that platform provides a very good UX for copy/pasting text within the composer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewer Checklist
- I have verified the author checklist is complete (all boxes are checked off).
- I verified the correct issue is linked in the
### Fixed Issues
section above - I verified testing steps are clear and they cover the changes made in this PR
- I verified the steps for local testing are in the
Tests
section - I verified the steps for Staging and/or Production testing are in the
QA steps
section - I verified the steps cover any possible 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 verified the steps for local testing are in the
- I checked that screenshots or videos are included for tests on all platforms
- I included screenshots or videos for tests on all platforms
- I verified tests pass on all platforms & I tested again on:
- Android / native
- Android / Chrome
- iOS / native
- iOS / Safari
- MacOS / Chrome / Safari
- MacOS / Desktop
- If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
- I verified proper code patterns were followed (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 notonIconClick
). - 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 - 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 correct English and approved by marketing by adding the
Waiting for Copy
label for a copy review on the original GH to get the correct copy. - 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
- 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.
- If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
- I verified that this PR follows the guidelines as stated in the Review Guidelines
- I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like
Avatar
, I verified the components usingAvatar
have been tested & I retested again) - 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.js or at the top of the file that uses the constant) are defined as such
- If a new component is created I verified that:
- A similar component doesn't exist in the codebase
- All props are defined accurately and each prop has a
/** comment above it */
- The file is named correctly
- The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
- The only data being stored in the state is data necessary for rendering and nothing else
- For Class Components, any internal methods passed to components event handlers are bound to
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor) - Any internal methods bound to
this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
) - All JSX used for rendering exists in the render method
- The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
- 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(themeColors.componentBG
)
- 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 thatAvatar
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 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 have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM and tests well. Thanks for all the comments - it made reviewing the PR really easy and I'm sure it will help others who come across these lines too!
all yours @robertjchen! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code/Comments look great and it tests well on my end as well, this is good to go! 👍
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by @robertjchen in version: 1.2.52-0 🚀
|
🚀 Deployed to production by @Julesssss in version: 1.2.52-4 🚀
|
Hi!! Coming from this issue #14243 where the PR is introducing the regression specifically on this code Thank you! |
The PR introduces this regression. Steps To Reproduce:
The regression is now fixed by #16464 |
The same issue is happening when you copy highlighted text using ctrl/cmd+c, this has been resolved in #16473 |
if (!event.metaKey || (event.key !== 'c' && event.key !== 'x')) { | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tgolen Here we are only checking for the metaKey
modifier which is only available on macOS. I'm not sure if this is intended but I think we should also check for ctrlKey
to have same behaviour on other OS (Windows & Linux).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds fine to me, but it's very low value since we don't officially support those platforms. Just my thoughts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed Issues
$ #12769
Tests
Use the following text for the test (it has 4 newlines):
Web/Desktop
Native and mobile web
Native platforms do not have a paste without formatting feature, so just do basic regression testing to ensure pasting functions normally
Offline tests
n/a this feature doesn't change or is impacted by offline mode
QA Steps
Same as above
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
properly so there are no scoping issues (i.e. foronClick={this.submit}
the methodthis.submit
should be bound tothis
in the constructor)this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.Screenshots/Videos
Web
2022-12-20_14-06-50.mp4
Mobile Web - Chrome
2022-12-20_14-08-19.mp4
Mobile Web - Safari
2022-12-20_14-11-50.mp4
Desktop
2022-12-20_14-10-15.mp4
iOS
2022-12-20_14-11-13.mp4
Android
2022-12-20_14-09-15.mp4