Skip to content

Commit 17ce0c2

Browse files
authored
Merge pull request #30412 from aswin-s/fix/naitve-emoji-picker
feat: add whitespace after inserting emoji via native keyboard
2 parents 7a70056 + f2c1022 commit 17ce0c2

File tree

2 files changed

+75
-15
lines changed

2 files changed

+75
-15
lines changed

src/libs/ComposerUtils/index.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ function canSkipTriggerHotkeys(isSmallScreenWidth: boolean, isKeyboardShown: boo
3232
*/
3333
function getCommonSuffixLength(str1: string, str2: string): number {
3434
let i = 0;
35-
while (str1[str1.length - 1 - i] === str2[str2.length - 1 - i]) {
35+
if (str1.length === 0 || str2.length === 0) {
36+
return 0;
37+
}
38+
const minLen = Math.min(str1.length, str2.length);
39+
while (i < minLen && str1[str1.length - 1 - i] === str2[str2.length - 1 - i]) {
3640
i++;
3741
}
3842
return i;

src/pages/home/report/ReportActionCompose/ComposerWithSuggestions.js

+70-14
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ function ComposerWithSuggestions({
117117
return draft;
118118
});
119119
const commentRef = useRef(value);
120+
const lastTextRef = useRef(value);
120121

121122
const {isSmallScreenWidth} = useWindowDimensions();
122123
const maxComposerLines = isSmallScreenWidth ? CONST.COMPOSER.MAX_LINES_SMALL_SCREEN : CONST.COMPOSER.MAX_LINES;
@@ -196,6 +197,50 @@ function ComposerWithSuggestions({
196197
RNTextInputReset.resetKeyboardInput(findNodeHandle(textInputRef.current));
197198
}, [textInputRef]);
198199

200+
/**
201+
* Find the newly added characters between the previous text and the new text based on the selection.
202+
*
203+
* @param {string} prevText - The previous text.
204+
* @param {string} newText - The new text.
205+
* @returns {object} An object containing information about the newly added characters.
206+
* @property {number} startIndex - The start index of the newly added characters in the new text.
207+
* @property {number} endIndex - The end index of the newly added characters in the new text.
208+
* @property {string} diff - The newly added characters.
209+
*/
210+
const findNewlyAddedChars = useCallback(
211+
(prevText, newText) => {
212+
let startIndex = -1;
213+
let endIndex = -1;
214+
let currentIndex = 0;
215+
216+
// Find the first character mismatch with newText
217+
while (currentIndex < newText.length && prevText.charAt(currentIndex) === newText.charAt(currentIndex) && selection.start > currentIndex) {
218+
currentIndex++;
219+
}
220+
221+
if (currentIndex < newText.length) {
222+
startIndex = currentIndex;
223+
224+
// if text is getting pasted over find length of common suffix and subtract it from new text length
225+
if (selection.end - selection.start > 0) {
226+
const commonSuffixLength = ComposerUtils.getCommonSuffixLength(prevText, newText);
227+
endIndex = newText.length - commonSuffixLength;
228+
} else {
229+
endIndex = currentIndex + (newText.length - prevText.length);
230+
}
231+
}
232+
233+
return {
234+
startIndex,
235+
endIndex,
236+
diff: newText.substring(startIndex, endIndex),
237+
};
238+
},
239+
[selection.end, selection.start],
240+
);
241+
242+
const insertWhiteSpace = (text, index) => `${text.slice(0, index)} ${text.slice(index)}`;
243+
199244
const debouncedSaveReportComment = useMemo(
200245
() =>
201246
_.debounce((selectedReportID, newComment) => {
@@ -213,7 +258,14 @@ function ComposerWithSuggestions({
213258
const updateComment = useCallback(
214259
(commentValue, shouldDebounceSaveComment) => {
215260
raiseIsScrollLikelyLayoutTriggered();
216-
const {text: newComment, emojis} = EmojiUtils.replaceAndExtractEmojis(commentValue, preferredSkinTone, preferredLocale);
261+
const {startIndex, endIndex, diff} = findNewlyAddedChars(lastTextRef.current, commentValue);
262+
const isEmojiInserted = diff.length && endIndex > startIndex && EmojiUtils.containsOnlyEmojis(diff);
263+
const {text: newComment, emojis} = EmojiUtils.replaceAndExtractEmojis(
264+
isEmojiInserted ? insertWhiteSpace(commentValue, endIndex) : commentValue,
265+
preferredSkinTone,
266+
preferredLocale,
267+
);
268+
217269
if (!_.isEmpty(emojis)) {
218270
const newEmojis = EmojiUtils.getAddedEmojis(emojis, emojisPresentBefore.current);
219271
if (!_.isEmpty(newEmojis)) {
@@ -264,13 +316,14 @@ function ComposerWithSuggestions({
264316
}
265317
},
266318
[
267-
debouncedUpdateFrequentlyUsedEmojis,
268-
preferredLocale,
319+
raiseIsScrollLikelyLayoutTriggered,
320+
findNewlyAddedChars,
269321
preferredSkinTone,
270-
reportID,
322+
preferredLocale,
271323
setIsCommentEmpty,
324+
debouncedUpdateFrequentlyUsedEmojis,
272325
suggestionsRef,
273-
raiseIsScrollLikelyLayoutTriggered,
326+
reportID,
274327
debouncedSaveReportComment,
275328
],
276329
);
@@ -321,14 +374,8 @@ function ComposerWithSuggestions({
321374
* @param {Boolean} shouldAddTrailSpace
322375
*/
323376
const replaceSelectionWithText = useCallback(
324-
(text, shouldAddTrailSpace = true) => {
325-
const updatedText = shouldAddTrailSpace ? `${text} ` : text;
326-
const selectionSpaceLength = shouldAddTrailSpace ? CONST.SPACE_LENGTH : 0;
327-
updateComment(ComposerUtils.insertText(commentRef.current, selection, updatedText));
328-
setSelection((prevSelection) => ({
329-
start: prevSelection.start + text.length + selectionSpaceLength,
330-
end: prevSelection.start + text.length + selectionSpaceLength,
331-
}));
377+
(text) => {
378+
updateComment(ComposerUtils.insertText(commentRef.current, selection, text));
332379
},
333380
[selection, updateComment],
334381
);
@@ -452,7 +499,12 @@ function ComposerWithSuggestions({
452499
}
453500

454501
focus();
455-
replaceSelectionWithText(e.key, false);
502+
// Reset cursor to last known location
503+
setSelection((prevSelection) => ({
504+
start: prevSelection.start + 1,
505+
end: prevSelection.end + 1,
506+
}));
507+
replaceSelectionWithText(e.key);
456508
},
457509
[checkComposerVisibility, focus, replaceSelectionWithText],
458510
);
@@ -514,6 +566,10 @@ function ComposerWithSuggestions({
514566
// eslint-disable-next-line react-hooks/exhaustive-deps
515567
}, []);
516568

569+
useEffect(() => {
570+
lastTextRef.current = value;
571+
}, [value]);
572+
517573
useImperativeHandle(
518574
forwardedRef,
519575
() => ({

0 commit comments

Comments
 (0)