Add emoji picker to chat composer (#5196)
Co-authored-by: surfdude29 <149612116+surfdude29@users.noreply.github.com> Co-authored-by: Adrov Igor <nucleartux@gmail.com>
This commit is contained in:
parent
30d2ab8dd3
commit
543be17674
9 changed files with 119 additions and 14 deletions
|
|
@ -133,7 +133,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
quote: initQuote,
|
||||
quoteCount,
|
||||
mention: initMention,
|
||||
openPicker,
|
||||
openEmojiPicker,
|
||||
text: initText,
|
||||
imageUris: initImageUris,
|
||||
cancelRef,
|
||||
|
|
@ -520,8 +520,8 @@ export const ComposePost = observer(function ComposePost({
|
|||
gallery.size > 0 || Boolean(extLink) || Boolean(videoUploadState.video)
|
||||
|
||||
const onEmojiButtonPress = useCallback(() => {
|
||||
openPicker?.(textInput.current?.getCursorPosition())
|
||||
}, [openPicker])
|
||||
openEmojiPicker?.(textInput.current?.getCursorPosition())
|
||||
}, [openEmojiPicker])
|
||||
|
||||
const focusTextInput = useCallback(() => {
|
||||
textInput.current?.focus()
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ import {Placeholder} from '@tiptap/extension-placeholder'
|
|||
import {Text as TiptapText} from '@tiptap/extension-text'
|
||||
import {generateJSON} from '@tiptap/html'
|
||||
import {EditorContent, JSONContent, useEditor} from '@tiptap/react'
|
||||
import EventEmitter from 'eventemitter3'
|
||||
|
||||
import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {useActorAutocompleteFn} from '#/state/queries/actor-autocomplete'
|
||||
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||
import {blobToDataUri, isUriImage} from 'lib/media/util'
|
||||
import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEmitter'
|
||||
import {
|
||||
LinkFacetMatch,
|
||||
suggestLinkCardUri,
|
||||
|
|
@ -46,8 +46,6 @@ interface TextInputProps {
|
|||
onError: (err: string) => void
|
||||
}
|
||||
|
||||
export const textInputWebEmitter = new EventEmitter()
|
||||
|
||||
export const TextInput = React.forwardRef(function TextInputImpl(
|
||||
{
|
||||
richtext,
|
||||
|
|
|
|||
3
src/view/com/composer/text-input/textInputWebEmitter.ts
Normal file
3
src/view/com/composer/text-input/textInputWebEmitter.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import EventEmitter from 'eventemitter3'
|
||||
|
||||
export const textInputWebEmitter = new EventEmitter()
|
||||
|
|
@ -7,8 +7,8 @@ import {
|
|||
} from 'react-native'
|
||||
import Picker from '@emoji-mart/react'
|
||||
|
||||
import {textInputWebEmitter} from '#/view/com/composer/text-input/textInputWebEmitter'
|
||||
import {atoms as a} from '#/alf'
|
||||
import {textInputWebEmitter} from '../TextInput.web'
|
||||
|
||||
const HEIGHT_OFFSET = 40
|
||||
const WIDTH_OFFSET = 100
|
||||
|
|
@ -26,22 +26,41 @@ export type Emoji = {
|
|||
unified: string
|
||||
}
|
||||
|
||||
export interface EmojiPickerPosition {
|
||||
top: number
|
||||
left: number
|
||||
right: number
|
||||
bottom: number
|
||||
}
|
||||
|
||||
export interface EmojiPickerState {
|
||||
isOpen: boolean
|
||||
pos: {top: number; left: number; right: number; bottom: number}
|
||||
pos: EmojiPickerPosition
|
||||
}
|
||||
|
||||
interface IProps {
|
||||
state: EmojiPickerState
|
||||
close: () => void
|
||||
/**
|
||||
* If `true`, overrides position and ensures picker is pinned to the top of
|
||||
* the target element.
|
||||
*/
|
||||
pinToTop?: boolean
|
||||
}
|
||||
|
||||
export function EmojiPicker({state, close}: IProps) {
|
||||
export function EmojiPicker({state, close, pinToTop}: IProps) {
|
||||
const {height, width} = useWindowDimensions()
|
||||
|
||||
const isShiftDown = React.useRef(false)
|
||||
|
||||
const position = React.useMemo(() => {
|
||||
if (pinToTop) {
|
||||
return {
|
||||
top: state.pos.top - PICKER_HEIGHT + HEIGHT_OFFSET - 10,
|
||||
left: state.pos.left,
|
||||
}
|
||||
}
|
||||
|
||||
const fitsBelow = state.pos.top + PICKER_HEIGHT < height
|
||||
const fitsAbove = PICKER_HEIGHT < state.pos.top
|
||||
const placeOnLeft = PICKER_WIDTH < state.pos.left
|
||||
|
|
@ -64,7 +83,7 @@ export function EmojiPicker({state, close}: IProps) {
|
|||
: undefined,
|
||||
}
|
||||
}
|
||||
}, [state.pos, height, width])
|
||||
}, [state.pos, height, width, pinToTop])
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!state.isOpen) return
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ export function Composer({}: {winHeight: number}) {
|
|||
quoteCount={state?.quoteCount}
|
||||
onPost={state.onPost}
|
||||
mention={state.mention}
|
||||
openPicker={onOpenPicker}
|
||||
openEmojiPicker={onOpenPicker}
|
||||
text={state.text}
|
||||
/>
|
||||
</View>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue