import { SendOutlined, SmileOutlined } from '@ant-design/icons'; import { Button, Popover } from 'antd'; import React, { useState } from 'react'; import { useRecoilValue } from 'recoil'; import { Transforms, createEditor, 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' | 'span'; children: CustomText[] }; type CustomText = { text: string }; declare module 'slate' { interface CustomTypes { Editor: BaseEditor & ReactEditor; Element: CustomElement; Text: CustomText; } } interface Props { value?: string; } // eslint-disable-next-line react/prop-types const Image = ({ element }) => ( emoji ); // eslint-disable-next-line @typescript-eslint/no-unused-vars 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; // eslint-disable-next-line no-param-reassign editor.isVoid = element => (element.type === 'image' ? true : isVoid(element)); // eslint-disable-next-line no-param-reassign editor.isInline = element => element.type === 'image'; return editor; }; export type EmptyText = { text: string; }; // type ImageElement = { // type: 'image'; // url: string; // children: EmptyText[]; // }; const Element = (props: any) => { const { attributes, children, element } = props; switch (element.type) { case 'image': return ; default: return

{children}

; } }; const serialize = node => { if (Text.isText(node)) { const 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; } }; // eslint-disable-next-line @typescript-eslint/no-unused-vars 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 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 = () => {}; const handleEmojiSelect = (e: any) => { ReactEditor.focus(editor); if (e.url) { // Custom emoji const { url } = e; insertImage(editor, url); } else { // Native emoji const { emoji } = e; Transforms.insertText(editor, emoji); } }; const onKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { e.preventDefault(); sendMessage(); } }; return (
} placeholder="Chat message goes here..." style={{ width: '100%' }} autoFocus /> } trigger="click" onVisibleChange={visible => setShowEmojis(visible)} visible={showEmojis} />
); } ChatTextField.defaultProps = { value: '', };