-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
[HOLD for payment 2022-11-29] [$250] Cursor moves to the end of the message when inserting an emoji in between the words reported by @adeel0202 #12325
Comments
Triggered auto assignment to @laurenreidexpensify ( |
Current assignee @laurenreidexpensify is eligible for the External assigner, not assigning anyone new. |
Triggered auto assignment to Contributor-plus team member for initial proposal review - @rushatgabhane ( |
Triggered auto assignment to @ctkochan22 ( |
Proposal function replaceEmojis(text) {
+ let latestIconPosition = -1;
let newText = text;
const emojiData = text.match(CONST.REGEX.EMOJI_NAME);
if (!emojiData || emojiData.length === 0) {
- return text
+ return {
+ newComment: newText,
+ latestIconPosition,
};
}
for (let i = 0; i < emojiData.length; i++) {
const checkEmoji = emojisTrie.search(emojiData[i].slice(1, -1));
if (checkEmoji && checkEmoji.metaData.code) {
newText = newText.replace(emojiData[i], checkEmoji.metaData.code);
+ latestIconPosition = text.indexOf(emojiData[i]) + checkEmoji.metaData.code.length;
}
}
- return newText
+ return {
+ newComment: newText,
+ latestIconPosition,
};
} After that update + const {newComment, latestIconPosition} = EmojiUtils.replaceEmojis(comment);
this.setState({
isCommentEmpty: !!newComment.match(/^(\s|`)*$/),
value: newComment,
- }
+ }, () => {
+ if (latestIconPosition !== -1) {
+ this.textInput.selectionEnd = latestIconPosition;
+ }
}); We are also using replaceEmojis inside updateDraft(draft) {
- const newDraft = EmojiUtils.replaceEmojis(draft);
+ const { newComment: newDraft, latestIconPosition } = EmojiUtils.replaceEmojis(draft);
- this.setState({draft: newDraft});
+ this.setState({draft: newDraft}, () => {
+ if (latestIconPosition !== -1) {
+ this.textInput.selectionEnd = latestIconPosition;
+ }
+ })
// This component is rendered only when draft is set to a non-empty string. In order to prevent component
// unmount when user deletes content of textarea, we set previous message instead of empty string.
if (newDraft.trim().length > 0) {
this.debouncedSaveDraft(newDraft);
} else {
this.debouncedSaveDraft(this.props.action.message[0].html);
}
} Updated paste(text) {
try {
document.execCommand('insertText', false, text);
this.updateNumberOfLines();
// Pointer will go out of sight when a large paragraph is pasted on the web. Refocusing the input keeps the cursor in view.
this.textInput.blur();
this.textInput.focus();
+ this.textInput.selectionStart = text.length;
+ this.textInput.selectionEnd = text.length;
} catch (e) {}
} Here's the result when texting: Here's the result when editing: Screen.Recording.2022-11-02.at.00.35.50.movResult for pasting: Screen.Recording.2022-11-02.at.09.52.50.mov |
this should have been closed by now, the proposal @hungvu193 has provided works. |
Proposal My proposed solution is, when the emoji is replaced, to get the cursor position from previous state and set the selection value in the new state. In the const newComment = EmojiUtils.replaceEmojis(comment);
+ this.setState((prevState) => {
+ let newState = {
+ isCommentEmpty: !!newComment.match(/^(\s|`)*$/),
+ value: newComment
+ }
+
+ if(comment !== newComment) {
+ const remainder = prevState.value.slice(prevState.selection.end).length
+ newState.selection = {
+ start: newComment.length - remainder,
+ end: newComment.length - remainder
+ }
+ }
+
+ return newState
}); In the const newDraft = EmojiUtils.replaceEmojis(draft);
+ this.setState((prevState) => {
+ let newState = {draft: newDraft}
+
+ if(draft !== newDraft) {
+ const remainder = prevState.draft.slice(prevState.selection.end).length
+ newState.selection = {
+ start: newDraft.length - remainder,
+ end: newDraft.length - remainder
+ }
+ }
+
+ return newState
+ }); Here's a video of this code taking effect: bugfix.mov |
@rushatgabhane bump ^^ |
I'm quite confused maybe someone from the engineering team might enlighten me. |
@hungvu193 question: does modifying the selection using it's ref work on all platforms? (especially iOS and iOS safari) suggestion: we already are passing selection as a prop to TextInput. Maybe we should use that? |
We're adding selection logic to |
@rushatgabhane yeah, it worked on all platforms, I tested them all. |
@hungvu193 If I'm not wrong, @AndreasBBS's proposal uses selection prop, and also addresses seperation of concerns. |
yeah, that's right. If I use selection props, it will look like: this.setState(() => {
const newState = {
isCommentEmpty: !!newComment.match(/^(\s|`)*$/),
value: newComment,
};
if (latestIconPosition !== -1) {
newState.selection = {
start: latestIconPosition,
end: latestIconPosition,
};
}
return newState;
}); |
Really appreciate your proposal! @hungvu193 I'm gonna recommend @AndreasBBS' proposal to @ctkochan22 because it was using the existing selection prop, and had better separation of concerns. 🎀 👀 🎀 C+ reviewed |
@hungvu193 Both our approaches work the same when writing an emoji, the big difference is how the paste is handled.
|
@ctkochan22, @rushatgabhane, @laurenreidexpensify Whoops! This issue is 2 days overdue. Let's get this updated quick! |
@ctkochan22 bump here 👍 for this solution Thanks |
Hi. I'm writing here trying to get an update. I already submitted the proposal on Upwork. Is there something on my side holding up? It's my first time contributing to this project, if there's anything on my side that needs to be done just let me know 😃 |
@ctkochan22 gentle bump to review @AndreasBBS's proposal #12325 (comment) |
Man, hard to keep track of so many of these. Good work here everyone! @rushatgabhane I'm good with your recommendation. @AndreasBBS 's solution looks good. @laurenreidexpensify lets hire and move forward
Second @AndreasBBS , we no longer use the |
📣 @AndreasBBS You have been assigned to this job by @laurenreidexpensify! |
@AndreasBBS I've hired you in Upwork now, if you can let us know when you're aiming to have the PR up? Feel free to ask any questions in Slack as you go : ) |
@laurenreidexpensify I just pushed the fix to my branch. I'm gonna now record the videos of it working on the different platforms. I'm aiming to submit the PR still today. |
I just discovered a strange behavior in the Android app that I'm trying to understand if it was causes by my changes. It's why it's taking me a while to make the PR. I want to make sure I don't create another problem trying to solve. Thanks for your patience. |
@laurenreidexpensify this got closed without issuing payments. |
@laurenreidexpensify friendly bump |
Everyone has been paid now, apols! |
If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!
Action Performed:
Expected Result:
The cursor is positioned at the end of the emoji
Actual Result:
The cursor is positioned at the end of the message
Workaround:
unknown
Platform:
Where is this issue occurring?
Version Number: 1.2.22-1
Reproducible in staging?: y
Reproducible in production?: y
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos:
https://user-images.githubusercontent.com/43996225/199127521-33318600-d63e-4c04-a751-30c2dc7c57e3.mp4
https://user-images.githubusercontent.com/43996225/199127573-9bac7276-3186-4e2e-8401-5c148d47b9eb.mov
Expensify/Expensify Issue URL:
Issue reported by: @adeel0202
Slack conversation: https://expensify.slack.com/archives/C01GTK53T8Q/p1667226062750359
View all open jobs on GitHub
The text was updated successfully, but these errors were encountered: