import { SmileOutlined } from '@ant-design/icons'; import { Button, Popover } from 'antd'; import React, { useState, useMemo, useRef, useEffect } from 'react'; import { useRecoilValue } from 'recoil'; import { Transforms, createEditor, Node, BaseEditor, Text } from 'slate'; import { Slate, Editable, withReact, ReactEditor } from 'slate-react'; import EmojiPicker from './EmojiPicker'; import WebsocketService from '../../../services/websocket-service'; import { websocketServiceAtom } from '../../stores/ClientConfigStore'; import { MessageType } from '../../../interfaces/socket-events'; import s from './ChatTextField.module.scss'; type CustomElement = { type: 'paragraph'; children: CustomText[] }; type CustomText = { text: string }; declare module 'slate' { interface CustomTypes { Editor: BaseEditor & ReactEditor; Element: CustomElement; Text: CustomText; } } interface Props { value?: string; } const Image = ({ element }) => ( emoji ); const insertImage = (editor, url) => { const text = { text: '' }; const image: ImageElement = { type: 'image', url, children: [text] }; Transforms.insertNodes(editor, image); }; const withImages = editor => { const { isVoid } = editor; editor.isVoid = element => (element.type === 'image' ? true : isVoid(element)); editor.isInline = element => element.type === 'image'; return editor; }; export type EmptyText = { text: string; }; type ImageElement = { type: 'image'; url: string; children: EmptyText[]; }; const Element = props => { const { attributes, children, element } = props; switch (element.type) { case 'image': return ; default: return

{children}

; } }; const serialize = node => { if (Text.isText(node)) { let string = node.text; if (node.bold) { string = `${string}`; } return string; } const children = node.children.map(n => serialize(n)).join(''); switch (node.type) { case 'paragraph': return `

${children}

`; case 'image': return `emoji`; default: return children; } }; export default function ChatTextField(props: Props) { const { value: originalValue } = props; const [showEmojis, setShowEmojis] = useState(false); const websocketService = useRecoilValue(websocketServiceAtom); const [editor] = useState(() => withImages(withReact(createEditor()))); const size = 'small'; const sendMessage = () => { if (!websocketService) { console.log('websocketService is not defined'); return; } const message = serialize(editor); websocketService.send({ type: MessageType.CHAT, body: message }); // Clear the editor. Transforms.select(editor, [0, editor.children.length - 1]); Transforms.delete(editor); }; const handleChange = e => {}; const handleEmojiSelect = emoji => { console.log(emoji); if (!emoji.native) { // Custom emoji const { src } = emoji; insertImage(editor, src); } else { // Native emoji const { native } = emoji; Transforms.insertText(editor, native); } }; const onKeyDown = e => { if (e.key === 'Enter') { e.preventDefault(); sendMessage(); } }; const initialValue = [ { type: 'paragraph', children: [{ text: originalValue }], }, ]; return (
} placeholder="Chat message goes here..." /> } trigger="click" onVisibleChange={visible => setShowEmojis(visible)} visible={showEmojis} placement="bottomLeft" />
); } ChatTextField.defaultProps = { value: '', };