-
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
fix: scroll to right position on text insertion #9062
Conversation
CLA Assistant Lite bot All contributors have signed the CLA ✍️ ✅ |
I have read the CLA Document and I hereby sign the CLA |
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.
Thanks for the detailed PR.
@@ -244,6 +244,8 @@ class Composer extends React.Component { | |||
try { | |||
document.execCommand('insertText', false, markdownText); | |||
this.updateNumberOfLines(); | |||
this.textInput.blur(); |
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.
A comment will be useful.
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.
Comment added.
The review of this PR will be delayed. I need to run a few tests. The current solution is also a hack to fix the cursor. I will try to find a better solution to the problem. |
@parasharrajat I agree with you, if we use a hack to fix one issue at the current moment, it may lead to another issue in the future. Always find the root cause. First I thought it was related to react-native-web, but after some digging, it may be problem with Chrome. I write snippets with basic JS to show how document.execCommand('insertText') works: If you run with Chrome, when you paste a large paragraph, the text insertion point goes out of sight. But if you run the example with Firefox, everything works fine. |
Thanks for waiting. I will try to steal some time from my schedule to do some research on this issue. |
No update yet. But I will share some update very soon. On my main list. |
@b1tjoy Thank you for your patience. I was looking into your other proposals. And it seems that this #8663 (comment) could be the next potential solution. You mentioned that this is working fine. Was there any issues with it? |
@parasharrajat When we select text from bottom to top, then paste the content copy from html page, the text insertion point moves out of sight. Screencast.from.06-11-2022.11.49.27.PM.mp4 |
Ok, I am trying to determine the expected behavior when we paste text in textArea. There are a few case possible for pasting. I will try to list them down and test your solution over it. |
@parasharrajat Possible cases for pasting I thought of:
I don't want to be bothersome and I know you are pretty busy, could you please take some time to review this PR for me? As a new contributor, I am not allowed to work on other issues for now, although I have submitted good proposal. Thanks a lot! :) |
Sorry for the delay. I just kind of lost this one. Adding it to my list now. I will get to the bottom of it in a day or two. Anyways, you should be good for new tasks. You can ping again on the same issue. |
Ok, I tested your #8663 (comment) proposal and it seems to be working. Could you do the following and run a few tests? Otherwise, I can go with the existing solution.
const heightToBottom = this.textInput.scrollHeight - paddingTopAndBottom - this.textInput.scrollTop;
this.textInput.scrollTop = this.textInput.scrollHeight - paddingTopAndBottom - heightToBottom; Now run your tests. |
Also, please merge main. |
I don't think it's going to work. The main idea of #8663 (comment) is to store the height from the insertion point to the last line of textArea before document.execCommand('insertText'), after text insertion we can calculate scrollTop by the stored value and manually scroll the textArea to the appropriate position. This works fine for the following cases:
If we have 40 lines text for example, line height is 20, Before insert:
scrollHeight = 800
selection lines (select from top to bottom) = [11, 30]
insertion point line = 30
visible area lines = [15, 30]
upper lines not visible = [1, 14]
lower lines not visible = [31, 40]
scrollTop = 14 * 20 = 280
heightToBottom = 800 - 280 = 520
After insert:
scrollHeight = 1000
scrollTop = 1000 - 520 = 480 = 24 * 20
upper lines not visible = [1, 24]
visible area lines = [25, 40]
lower lines not visible = [41, 50]
insertion point line = 40 (because we replace line 11-30 with 30 lines text) Insertion point is in the visible area and everything works fine. But in some edge case it doesn't work:
If we have 40 lines text for example, line height is 20, Before insert:
scrollHeight = 800
selection lines (select from bottom to top) = [30, 11]
insertion point line = 30
visible area lines = [11, 26]
upper lines not visible = [1, 10]
lower lines not visible = [27, 40]
scrollTop = 10 * 20 = 200
heightToBottom = 800 - 200 = 600
After insert:
scrollHeight = 1000
scrollTop = 1000 - 600 = 400 = 20 * 20
upper lines not visible = [1, 20]
visible area lines = [21, 36]
lower lines not visible = [37, 50]
insertion point line = 40 (because we replace line 11-30 with 30 lines text) Insertion point is not in the visible area. I think we can combine these two proposals, use the calculation one to handle regular case, and use blur() & focus() one to handle select backward case. We can add a variable to track if user scroll backward, if user scroll backward and selection is not empty, call blur() & focus() to keep insertion point insight, otherwise calculate scrollTop and manually scroll to appropriate position. How about that? |
A slight difference from your proposal is that I am not tracking the scroll before paste. Instead, I am relying on the reset of Anyways, I see your analysis. Testing the current solution in this PR. I would say that if are not able to set a manual scroll position then this solution is fine. I will open the discussion on slack to get more eyes before moving ahead with the PR. It would be done by tomorrow. |
Meanwhile please merge main into this PR. |
@parasharrajat After run a few tests, I think that reset |
Yeah, I saw that the current solution of the PR has better results. I will open the discussion today. |
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.
@b1tjoy Please merge main into this.
src/components/Composer/index.js
Outdated
@@ -239,6 +239,10 @@ class Composer extends React.Component { | |||
try { | |||
document.execCommand('insertText', false, markdownText); | |||
this.updateNumberOfLines(); | |||
// Manually make text input scroll to appropriate position, otherwise the text insertion | |||
// point will goes out of sight when we paste a large paragraph on Chrome or Desktop |
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.
// point will goes out of sight when we paste a large paragraph on Chrome or Desktop | |
// Pointer will go out of sight when a large paragraph is pasted on the web. Refocusing the input keeps the cursor in view. |
src/components/Composer/index.js
Outdated
@@ -239,6 +239,10 @@ class Composer extends React.Component { | |||
try { | |||
document.execCommand('insertText', false, markdownText); | |||
this.updateNumberOfLines(); | |||
// Manually make text input scroll to appropriate position, otherwise the text insertion |
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.
// Manually make text input scroll to appropriate position, otherwise the text insertion |
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.
cc: @pecanoro
PR Reviewer Checklist
- I verified the PR has a small number of commits behind
main
- 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 testing environment is mentioned in the test steps
- I verified testing steps cover success & fail scenarios (if applicable)
- I checked that screenshots or videos are included for tests on all platforms
- I verified tests pass on all platforms & I tested again on:
- iOS / native
- Android / native
- iOS / Safari
- Android / Chrome
- MacOS / Chrome
- MacOS / Desktop
- I verified there are no console errors related to changes in this PR
- I verified proper code patterns were followed (see Reviewing the code)
- I verified comments were added when the code was not self explanatory
- I verified any copy / text shown in the product was added in all
src/languages/*
files (if applicable) - I verified proper naming convention for platform-specific files was followed (if applicable)
- I verified style guidelines were followed
- I verified the JSDocs style guidelines (in
STYLE.md
) were followed
- I verified that this PR follows the guidelines as stated in the Review Guidelines
- I verified other components are not impacted by changes in this PR (i.e. if the PR modifies a shared library or component like
Avatar
, I verified the components usingAvatar
are working as expected) - I verified the UI performance was not affected (the performance is the same than
main
branch) - If a new component is created I verified that a similar component doesn't exist in the codebase
✋ 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 production by @roryabraham in version: 1.1.82-5 🚀
|
Details
Text Insertion point goes out of the sight on typing in the middle of the paragraph. This PR fix the issue. And in order to fix #8663, we have to delete one line of code, which was add to fix #7351 previous, so this PR alse fix that one.
Why move textInput.blur() and textInput.focus() from ReportActionCompose.js to Composer/index.js?
Because these two lines was add to fix #7351, but the issue only affects Web, mWeb and Desktop platform, and only in pasting text copied from HTML page scenario, if we keep the code in ReportActionCompose.js, it will cause other issues, such as:
So I moved these codes to Composer/index.js:handlePasteHTML().
Fixed Issues
$ #8663
Tests
Test case for #8663:
Test case for #7351:
Test case for paste on selection, a more complex scenario:
PR Review Checklist
Contributor (PR Author) Checklist
### Fixed Issues
section aboveTests
sectionQA steps
sectiontoggleReport
and notonIconClick
)src/languages/*
filesSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
displayName
propertythis
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)PR Reviewer Checklist
### Fixed Issues
section aboveTests
sectionQA steps
sectiontoggleReport
and notonIconClick
).src/languages/*
filesSTYLE.md
) were followed/** comment above it */
displayName
propertythis
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)QA Steps
Test case for #8663:
Test case for #7351:
Test case for paste on selection, a more complex scenario:
Screenshots
Web
Test case for #8663
Screen.Recording.2022-05-22.at.10.49.11-MacOS-Chrome-1.mp4
Test case for #7351
Screen.Recording.2022-05-22.at.10.50.23-MacOS-Chrome-2.mp4
Test case for paste on selection, a more complex scenario
Screen.Recording.2022-05-22.at.10.52.02-MacOS-Chrome-3.mp4
Mobile Web
Test case for #8663 Android/Chrome
Screenshot-8663-Android-chrome-1.mp4
Test case for #7351 Android/Chrome
Screenshot-8663-Android-chrome-2.mp4
Test case for paste on selection, a more complex scenario Android/Chrome
Screenshot-8663-Android-chrome-3.mp4
Test case for #8663 iOS/Safari
Simulator.Screen.Recording.-.iPhone.13.-.2022-05-22.at.11.37.26-iOS-safari-1.mp4
Test case for #7351 iOS/Safari
Simulator.Screen.Recording.-.iPhone.13.-.2022-05-22.at.11.39.18-iOS-safari-2.mp4
Test case for paste on selection, a more complex scenario iOS/Safari
Simulator.Screen.Recording.-.iPhone.13.-.2022-05-22.at.11.40.46-iOS-safari-3.mp4
Desktop
Test case for #8663
Screen.Recording.2022-05-22.at.10.55.34-MacOS-Desktop-1.mp4
Test case for #7351
Screen.Recording.2022-05-22.at.10.58.01-MacOS-Desktop-2.mp4
Test case for paste on selection, a more complex scenario
Screen.Recording.2022-05-22.at.10.59.00-MacOS-Desktop-3.mp4
iOS
Test case for #8663
Simulator.Screen.Recording.-.iPhone.13.-.2022-05-22.at.11.06.48-iOS-native-1.mp4
Test case for #7351
Simulator.Screen.Recording.-.iPhone.13.-.2022-05-22.at.11.10.35-iOS-native-2.mp4
Test case for paste on selection, a more complex scenario
Simulator.Screen.Recording.-.iPhone.13.-.2022-05-22.at.11.12.47-iOS-native-3.mp4
Android
Test case for #8663
Screenshot-20220522084200-Android-native-1.mp4
Test case for #7351
Screenshot-20220522084700-Android-native-2.mp4
Test case for paste on selection, a more complex scenario
Screenshot-20220522085300-Android-native-3.mp4