From 6487a875426d098432fa708dc493ce150385ce91 Mon Sep 17 00:00:00 2001
From: Ansh <anshnanda10@gmail.com>
Date: Wed, 23 Aug 2023 16:29:23 -0700
Subject: [APP-836] Emoji picker for web (#1254)

* add emoji-mart package for emoji dropdown picker

* remove emoji picker modal

* load emoji mart data not as part of the main bundle

* remove @emoji-mart/data

* setup emoji insertion with events

* get emoji data from local static assets

* close emoji picker after one emoji has been inserted

* Switch emoji picker trigger to an icon

* Update emoji-mart-data.js

* make grabbing emoji data work on more browsers

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
---
 src/view/com/composer/text-input/TextInput.web.tsx | 37 +++++++++++++++-------
 1 file changed, 25 insertions(+), 12 deletions(-)

(limited to 'src/view/com/composer/text-input/TextInput.web.tsx')

diff --git a/src/view/com/composer/text-input/TextInput.web.tsx b/src/view/com/composer/text-input/TextInput.web.tsx
index b7ebdd989..dfe1e26a1 100644
--- a/src/view/com/composer/text-input/TextInput.web.tsx
+++ b/src/view/com/composer/text-input/TextInput.web.tsx
@@ -16,6 +16,7 @@ import {UserAutocompleteModel} from 'state/models/discovery/user-autocomplete'
 import {createSuggestion} from './web/Autocomplete'
 import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
 import {isUriImage, blobToDataUri} from 'lib/media/util'
+import {Emoji} from './web/EmojiPicker.web'
 
 export interface TextInputRef {
   focus: () => void
@@ -34,6 +35,8 @@ interface TextInputProps {
   onError: (err: string) => void
 }
 
+export const textInputWebEmitter = new EventEmitter()
+
 export const TextInput = React.forwardRef(
   (
     {
@@ -54,21 +57,18 @@ export const TextInput = React.forwardRef(
       'ProseMirror-dark',
     )
 
-    // we use a memoized emitter to propagate events out of tiptap
-    // without triggering re-runs of the useEditor hook
-    const emitter = React.useMemo(() => new EventEmitter(), [])
     React.useEffect(() => {
-      emitter.addListener('publish', onPressPublish)
+      textInputWebEmitter.addListener('publish', onPressPublish)
       return () => {
-        emitter.removeListener('publish', onPressPublish)
+        textInputWebEmitter.removeListener('publish', onPressPublish)
       }
-    }, [emitter, onPressPublish])
+    }, [onPressPublish])
     React.useEffect(() => {
-      emitter.addListener('photo-pasted', onPhotoPasted)
+      textInputWebEmitter.addListener('photo-pasted', onPhotoPasted)
       return () => {
-        emitter.removeListener('photo-pasted', onPhotoPasted)
+        textInputWebEmitter.removeListener('photo-pasted', onPhotoPasted)
       }
-    }, [emitter, onPhotoPasted])
+    }, [onPhotoPasted])
 
     const editor = useEditor(
       {
@@ -105,12 +105,12 @@ export const TextInput = React.forwardRef(
             }
 
             getImageFromUri(items, (uri: string) => {
-              emitter.emit('photo-pasted', uri)
+              textInputWebEmitter.emit('photo-pasted', uri)
             })
           },
           handleKeyDown: (_, event) => {
             if ((event.metaKey || event.ctrlKey) && event.code === 'Enter') {
-              emitter.emit('publish')
+              textInputWebEmitter.emit('publish')
             }
           },
         },
@@ -134,8 +134,21 @@ export const TextInput = React.forwardRef(
           }
         },
       },
-      [modeClass, emitter],
+      [modeClass],
+    )
+
+    const onEmojiInserted = React.useCallback(
+      (emoji: Emoji) => {
+        editor?.chain().focus('end').insertContent(emoji.native).run()
+      },
+      [editor],
     )
+    React.useEffect(() => {
+      textInputWebEmitter.addListener('emoji-inserted', onEmojiInserted)
+      return () => {
+        textInputWebEmitter.removeListener('emoji-inserted', onEmojiInserted)
+      }
+    }, [onEmojiInserted])
 
     React.useImperativeHandle(ref, () => ({
       focus: () => {}, // TODO
-- 
cgit 1.4.1

