From a97655e5ba9ef8d7166198a47506bedd5e88e68f Mon Sep 17 00:00:00 2001 From: doobry Date: Thu, 25 Apr 2024 18:31:11 +0200 Subject: [PATCH 1/3] feat: Add emoji picker to message form --- package.json | 3 ++ src/components/message/EmojiPickerModal.tsx | 31 +++++++++++++++++++++ src/components/message/MessageForm.tsx | 14 +++++++++- yarn.lock | 15 ++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/components/message/EmojiPickerModal.tsx diff --git a/package.json b/package.json index e76be825..5708c29f 100644 --- a/package.json +++ b/package.json @@ -6,6 +6,8 @@ "build": "webpack --config webpack.prod.config.ts" }, "dependencies": { + "@emoji-mart/data": "^1.1.2", + "@emoji-mart/react": "^1.1.1", "@emotion/react": "^11.11.0", "@emotion/styled": "^11.11.0", "@fontsource/roboto": "^5.0.2", @@ -17,6 +19,7 @@ "@mui/material": "^5.14.11", "@tanstack/react-query": "^4.10.3", "@tanstack/react-query-devtools": "^4.11.0", + "emoji-mart": "^5.5.2", "jwt-decode": "^4.0.0", "leaflet": "^1.9.4", "leaflet-draw": "^1.0.4", diff --git a/src/components/message/EmojiPickerModal.tsx b/src/components/message/EmojiPickerModal.tsx new file mode 100644 index 00000000..60264518 --- /dev/null +++ b/src/components/message/EmojiPickerModal.tsx @@ -0,0 +1,31 @@ +import React, { FC } from 'react' +import Modal from '../common/Modal' +import { Emoji } from 'emoji-mart' +import data from '@emoji-mart/data' +import Picker from '@emoji-mart/react' + +interface Props { + open: boolean + onClose: () => void + onChange: (emoji: Emoji) => void +} + +const EmojiPickerModal: FC = ({ open, onClose, onChange }) => { + const handleChange = (emoji: Emoji) => { + onChange(emoji) + onClose() + } + + return ( + + onClose } onEmojiSelect={handleChange}/> + + ) +} + +export default EmojiPickerModal diff --git a/src/components/message/MessageForm.tsx b/src/components/message/MessageForm.tsx index 280fe33a..70016f3b 100644 --- a/src/components/message/MessageForm.tsx +++ b/src/components/message/MessageForm.tsx @@ -8,12 +8,14 @@ import useAuth from '../useAuth' import { Upload } from '../../api/Upload' import UploadButton from './UploadButton' import AttachmentsPreview from './AttachmentsPreview' +import EmojiPickerModal from './EmojiPickerModal' import MessageMapModal from './MessageMapModal' import { FeatureCollection, Geometry } from 'geojson' import { Box, Button, FormGroup, IconButton, Stack, TextField } from '@mui/material' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faMapLocationDot, faPaperPlane } from '@fortawesome/free-solid-svg-icons' +import { faMapLocationDot, faPaperPlane, faSmile } from '@fortawesome/free-solid-svg-icons' import palette from '../../theme/palette' +import { Emoji } from 'emoji-mart' interface Props { ticker: Ticker @@ -30,6 +32,7 @@ const MessageForm: FC = ({ ticker }) => { reset, register, watch, + setValue, } = useForm({ mode: 'onSubmit' }) const { token } = useAuth() const { postMessage } = useMessageApi(token) @@ -37,6 +40,7 @@ const MessageForm: FC = ({ ticker }) => { const [isSubmitting, setIsSubmitting] = useState(false) const [attachments, setAttachments] = useState([]) const [mapDialogOpen, setMapDialogOpen] = useState(false) + const [emojiPickerOpen, setEmojiPickerOpen] = useState(false) const emptyMap: FeatureCollection = { type: 'FeatureCollection', features: [], @@ -78,6 +82,10 @@ const MessageForm: FC = ({ ticker }) => { [attachments] ) + const onSelectEmoji = (emoji: Emoji) => { + setValue('message', message.toString() + emoji.native + ' ') + } + const onMapUpdate = useCallback((featureGroups: FeatureCollection) => { setMap(featureGroups) }, []) @@ -126,11 +134,15 @@ const MessageForm: FC = ({ ticker }) => { + setEmojiPickerOpen(true)} style={{ marginRight: '8px' }}> + + setMapDialogOpen(true)}> setMapDialogOpen(false)} open={mapDialogOpen} ticker={ticker} /> + setEmojiPickerOpen(false)} open={emojiPickerOpen} /> diff --git a/yarn.lock b/yarn.lock index 4adad004..e14c3aa2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1238,6 +1238,16 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@emoji-mart/data@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@emoji-mart/data/-/data-1.1.2.tgz#777c976f8f143df47cbb23a7077c9ca9fe5fc513" + integrity sha512-1HP8BxD2azjqWJvxIaWAMyTySeZY0Osr83ukYjltPVkNXeJvTz7yDrPLBtnrD5uqJ3tg4CcLuuBW09wahqL/fg== + +"@emoji-mart/react@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@emoji-mart/react/-/react-1.1.1.tgz#ddad52f93a25baf31c5383c3e7e4c6e05554312a" + integrity sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g== + "@emotion/babel-plugin@^11.11.0": version "11.11.0" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c" @@ -4550,6 +4560,11 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== +emoji-mart@^5.5.2: + version "5.5.2" + resolved "https://registry.yarnpkg.com/emoji-mart/-/emoji-mart-5.5.2.tgz#3ddbaf053139cf4aa217650078bc1c50ca8381af" + integrity sha512-Sqc/nso4cjxhOwWJsp9xkVm8OF5c+mJLZJFoFfzRuKO+yWiN7K8c96xmtughYb0d/fZ8UC6cLIQ/p4BR6Pv3/A== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" From 4898c54d41dff6d1fc6891ad2d54578567b28aee Mon Sep 17 00:00:00 2001 From: louis Date: Thu, 25 Apr 2024 19:23:43 +0200 Subject: [PATCH 2/3] Use own interface for Emoji --- src/components/message/Emoji.ts | 3 +++ src/components/message/EmojiPickerModal.tsx | 11 +++-------- src/components/message/MessageForm.tsx | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) create mode 100644 src/components/message/Emoji.ts diff --git a/src/components/message/Emoji.ts b/src/components/message/Emoji.ts new file mode 100644 index 00000000..9020b212 --- /dev/null +++ b/src/components/message/Emoji.ts @@ -0,0 +1,3 @@ +export interface Emoji { + native: string +} diff --git a/src/components/message/EmojiPickerModal.tsx b/src/components/message/EmojiPickerModal.tsx index 60264518..9de43b12 100644 --- a/src/components/message/EmojiPickerModal.tsx +++ b/src/components/message/EmojiPickerModal.tsx @@ -1,8 +1,8 @@ import React, { FC } from 'react' import Modal from '../common/Modal' -import { Emoji } from 'emoji-mart' import data from '@emoji-mart/data' import Picker from '@emoji-mart/react' +import { Emoji } from './Emoji' interface Props { open: boolean @@ -17,13 +17,8 @@ const EmojiPickerModal: FC = ({ open, onClose, onChange }) => { } return ( - - onClose } onEmojiSelect={handleChange}/> + + onClose} onEmojiSelect={handleChange} /> ) } diff --git a/src/components/message/MessageForm.tsx b/src/components/message/MessageForm.tsx index 70016f3b..19996939 100644 --- a/src/components/message/MessageForm.tsx +++ b/src/components/message/MessageForm.tsx @@ -15,7 +15,7 @@ import { Box, Button, FormGroup, IconButton, Stack, TextField } from '@mui/mater import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faMapLocationDot, faPaperPlane, faSmile } from '@fortawesome/free-solid-svg-icons' import palette from '../../theme/palette' -import { Emoji } from 'emoji-mart' +import { Emoji } from './Emoji' interface Props { ticker: Ticker From 45455d29aa9a80571bc64d9cb24ea5c1d01aa998 Mon Sep 17 00:00:00 2001 From: louis Date: Thu, 25 Apr 2024 19:57:27 +0200 Subject: [PATCH 3/3] Use Popper instead of Modal --- src/components/message/EmojiPicker.tsx | 42 +++++++++++++++++++++ src/components/message/EmojiPickerModal.tsx | 26 ------------- src/components/message/MessageForm.tsx | 12 ++---- 3 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 src/components/message/EmojiPicker.tsx delete mode 100644 src/components/message/EmojiPickerModal.tsx diff --git a/src/components/message/EmojiPicker.tsx b/src/components/message/EmojiPicker.tsx new file mode 100644 index 00000000..14c9fde4 --- /dev/null +++ b/src/components/message/EmojiPicker.tsx @@ -0,0 +1,42 @@ +import React, { FC } from 'react' +import data from '@emoji-mart/data' +import Picker from '@emoji-mart/react' +import { Emoji } from './Emoji' +import { Box, IconButton, Popper } from '@mui/material' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faSmile } from '@fortawesome/free-solid-svg-icons' +import palette from '../../theme/palette' + +interface Props { + onChange: (emoji: Emoji) => void +} + +const EmojiPicker: FC = ({ onChange }) => { + const [anchorEl, setAnchorEl] = React.useState(null) + + const handleChange = (emoji: Emoji) => { + onChange(emoji) + setAnchorEl(null) + } + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(anchorEl ? null : event.currentTarget) + event.stopPropagation() + } + + const open = Boolean(anchorEl) + const id = open ? 'simple-popper' : undefined + + return ( + + + + + + setAnchorEl(null)} onEmojiSelect={handleChange} theme="light" /> + + + ) +} + +export default EmojiPicker diff --git a/src/components/message/EmojiPickerModal.tsx b/src/components/message/EmojiPickerModal.tsx deleted file mode 100644 index 9de43b12..00000000 --- a/src/components/message/EmojiPickerModal.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React, { FC } from 'react' -import Modal from '../common/Modal' -import data from '@emoji-mart/data' -import Picker from '@emoji-mart/react' -import { Emoji } from './Emoji' - -interface Props { - open: boolean - onClose: () => void - onChange: (emoji: Emoji) => void -} - -const EmojiPickerModal: FC = ({ open, onClose, onChange }) => { - const handleChange = (emoji: Emoji) => { - onChange(emoji) - onClose() - } - - return ( - - onClose} onEmojiSelect={handleChange} /> - - ) -} - -export default EmojiPickerModal diff --git a/src/components/message/MessageForm.tsx b/src/components/message/MessageForm.tsx index 19996939..31a05a14 100644 --- a/src/components/message/MessageForm.tsx +++ b/src/components/message/MessageForm.tsx @@ -8,12 +8,12 @@ import useAuth from '../useAuth' import { Upload } from '../../api/Upload' import UploadButton from './UploadButton' import AttachmentsPreview from './AttachmentsPreview' -import EmojiPickerModal from './EmojiPickerModal' +import EmojiPicker from './EmojiPicker' import MessageMapModal from './MessageMapModal' import { FeatureCollection, Geometry } from 'geojson' import { Box, Button, FormGroup, IconButton, Stack, TextField } from '@mui/material' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' -import { faMapLocationDot, faPaperPlane, faSmile } from '@fortawesome/free-solid-svg-icons' +import { faMapLocationDot, faPaperPlane } from '@fortawesome/free-solid-svg-icons' import palette from '../../theme/palette' import { Emoji } from './Emoji' @@ -40,7 +40,6 @@ const MessageForm: FC = ({ ticker }) => { const [isSubmitting, setIsSubmitting] = useState(false) const [attachments, setAttachments] = useState([]) const [mapDialogOpen, setMapDialogOpen] = useState(false) - const [emojiPickerOpen, setEmojiPickerOpen] = useState(false) const emptyMap: FeatureCollection = { type: 'FeatureCollection', features: [], @@ -130,19 +129,16 @@ const MessageForm: FC = ({ ticker }) => { /> - + - setEmojiPickerOpen(true)} style={{ marginRight: '8px' }}> - - + setMapDialogOpen(true)}> setMapDialogOpen(false)} open={mapDialogOpen} ticker={ticker} /> - setEmojiPickerOpen(false)} open={emojiPickerOpen} />