From 8116d12c15495fa192e92f5bfb75cb561bb16402 Mon Sep 17 00:00:00 2001
From: Eric Bailey <git@esb.lol>
Date: Fri, 20 Dec 2024 13:59:33 -0600
Subject: Fix Emoji picker focus (#7217)

* Only portal the emoji picker where needed

* Add optional portal prop to emoji picker

* Use FocusScope to our advantage

* Pare back, add guards, fix focus trap

* Don't return focus to emoji button

* Set DM input position on emoji insert

* Let the caller determine next focus node

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
---
 .../Messages/components/MessageInput.web.tsx       | 28 +++++++++++++++++-----
 1 file changed, 22 insertions(+), 6 deletions(-)

(limited to 'src/screens/Messages/components/MessageInput.web.tsx')

diff --git a/src/screens/Messages/components/MessageInput.web.tsx b/src/screens/Messages/components/MessageInput.web.tsx
index 72e0382a9..bac163685 100644
--- a/src/screens/Messages/components/MessageInput.web.tsx
+++ b/src/screens/Messages/components/MessageInput.web.tsx
@@ -3,6 +3,7 @@ import {Pressable, StyleSheet, View} from 'react-native'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import Graphemer from 'graphemer'
+import {flushSync} from 'react-dom'
 import TextareaAutosize from 'react-textarea-autosize'
 
 import {isSafari, isTouchDevice} from '#/lib/browser'
@@ -106,11 +107,19 @@ export function MessageInput({
 
   const onEmojiInserted = React.useCallback(
     (emoji: Emoji) => {
-      const position = textAreaRef.current?.selectionStart ?? 0
-      setMessage(
-        message =>
-          message.slice(0, position) + emoji.native + message.slice(position),
-      )
+      if (!textAreaRef.current) {
+        return
+      }
+      const position = textAreaRef.current.selectionStart ?? 0
+      textAreaRef.current.focus()
+      flushSync(() => {
+        setMessage(
+          message =>
+            message.slice(0, position) + emoji.native + message.slice(position),
+        )
+      })
+      textAreaRef.current.selectionStart = position + emoji.native.length
+      textAreaRef.current.selectionEnd = position + emoji.native.length
     },
     [setMessage],
   )
@@ -148,7 +157,14 @@ export function MessageInput({
         <Button
           onPress={e => {
             e.currentTarget.measure((_fx, _fy, _width, _height, px, py) => {
-              openEmojiPicker?.({top: py, left: px, right: px, bottom: py})
+              openEmojiPicker?.({
+                top: py,
+                left: px,
+                right: px,
+                bottom: py,
+                nextFocusRef:
+                  textAreaRef as unknown as React.MutableRefObject<HTMLElement>,
+              })
             })
           }}
           style={[
-- 
cgit 1.4.1

