[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>
This commit is contained in:
parent
8ab5eb6583
commit
6487a87542
10 changed files with 136 additions and 12 deletions
|
|
@ -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,9 +134,22 @@ 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
|
||||
blur: () => {}, // TODO
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue