refs #4653 Add emoji picker in compose

This commit is contained in:
AkiraFukushima 2023-12-10 23:55:41 +09:00
parent 39ff0563d8
commit 3c9f196df8
No known key found for this signature in database
GPG Key ID: B6E51BAC4DE1A957
4 changed files with 80 additions and 10 deletions

View File

@ -14,11 +14,13 @@
"thirdparty": "license-checker --production --json > thirdparty.json"
},
"dependencies": {
"@emoji-mart/react": "^1.1.1",
"blurhash": "^2.0.5",
"dayjs": "^1.11.10",
"dexie": "^3.2.4",
"electron-serve": "^1.1.0",
"electron-store": "^8.1.0",
"emoji-mart": "^5.5.2",
"flowbite": "^2.0.0",
"flowbite-react": "^0.6.4",
"megalodon": "^9.1.1",

View File

@ -1,9 +1,24 @@
import { Button, Checkbox, Dropdown, Label, Radio, Select, Spinner, TextInput, Textarea, ToggleSwitch } from 'flowbite-react'
import {
Button,
Checkbox,
CustomFlowbiteTheme,
Dropdown,
Flowbite,
Label,
Radio,
Select,
Spinner,
TextInput,
Textarea,
ToggleSwitch
} from 'flowbite-react'
import { ChangeEvent, Dispatch, SetStateAction, useEffect, useRef, useState } from 'react'
import { FormattedMessage, useIntl } from 'react-intl'
import { FaEnvelope, FaGlobe, FaListCheck, FaLock, FaLockOpen, FaPaperPlane, FaPaperclip, FaXmark } from 'react-icons/fa6'
import { FaEnvelope, FaFaceLaughBeam, FaGlobe, FaListCheck, FaLock, FaLockOpen, FaPaperPlane, FaPaperclip, FaXmark } from 'react-icons/fa6'
import { Entity, MegalodonInterface } from 'megalodon'
import { useToast } from '@/utils/toast'
import Picker from '@emoji-mart/react'
import { data } from '@/utils/emojiData'
type Props = {
client: MegalodonInterface
@ -16,6 +31,17 @@ type Poll = {
multiple: boolean
}
const customTheme: CustomFlowbiteTheme = {
dropdown: {
content: 'focus:outline-none',
floating: {
item: {
base: ''
}
}
}
}
export default function Compose(props: Props) {
const [body, setBody] = useState('')
const [visibility, setVisibility] = useState<'public' | 'unlisted' | 'private' | 'direct'>('public')
@ -128,6 +154,16 @@ export default function Compose(props: Props) {
}
}
const onEmojiSelect = emoji => {
const textarea = document.getElementById('body') as HTMLTextAreaElement
const cursor = textarea.selectionStart
if (emoji.native) {
setBody(current => `${current.slice(0, cursor)}${emoji.native} ${current.slice(cursor)}`)
} else if (emoji.shortcodes) {
setBody(current => `${current.slice(0, cursor)}${emoji.shortcodes} ${current.slice(cursor)}`)
}
}
return (
<div className="px-4 pb-4">
<form id="form">
@ -142,14 +178,31 @@ export default function Compose(props: Props) {
placeholder={formatMessage({ id: 'compose.spoiler.placeholder' })}
/>
)}
<Textarea
id="body"
className="resize-none focus:ring-0"
placeholder={formatMessage({ id: 'compose.placeholder' })}
rows={3}
value={body}
onChange={ev => setBody(ev.target.value)}
/>
<div className="relative">
<Textarea
id="body"
className="resize-none focus:ring-0"
placeholder={formatMessage({ id: 'compose.placeholder' })}
rows={3}
value={body}
onChange={ev => setBody(ev.target.value)}
/>
<Flowbite theme={{ theme: customTheme }}>
<Dropdown
label=""
dismissOnClick
renderTrigger={() => (
<span className="absolute top-1 right-1 text-gray-600 cursor-pointer">
<FaFaceLaughBeam />
</span>
)}
>
<Dropdown.Item>
<Picker data={data} onEmojiSelect={onEmojiSelect} previewPosition="none" set="native" perLine="7" theme="light" />
</Dropdown.Item>
</Dropdown>
</Flowbite>
</div>
</form>
{poll && <PollForm poll={poll} setPoll={setPoll} />}
<div className="attachments flex gap-2">

View File

@ -0,0 +1,5 @@
export const data = async () => {
const response = await fetch('https://cdn.jsdelivr.net/npm/@emoji-mart/data')
return response.json()
}

View File

@ -1092,6 +1092,11 @@
minimatch "^3.0.4"
plist "^3.0.4"
"@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==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
@ -2786,6 +2791,11 @@ electron@^27.0.0:
"@types/node" "^18.11.18"
extract-zip "^2.0.1"
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"