Files
Compass/web/components/messaging/send-message-button.tsx
2026-02-12 17:14:40 +01:00

143 lines
4.8 KiB
TypeScript

import clsx from 'clsx'
import {User} from 'common/user'
import {Button} from 'web/components/buttons/button'
import {useRouter} from 'next/router'
import {BiEnvelope} from 'react-icons/bi'
import {useSortedPrivateMessageMemberships} from 'web/hooks/use-private-messages'
import {usePrivateUser} from 'web/hooks/use-user'
import {findKey} from 'lodash'
import {useEffect, useState} from 'react'
import {Modal, MODAL_CLASS} from 'web/components/layout/modal'
import {Col} from 'web/components/layout/col'
import {api} from 'web/lib/api'
import {useTextEditor} from 'web/components/widgets/editor'
import {MAX_COMMENT_LENGTH} from 'common/comment'
import {CommentInputTextArea} from 'web/components/comments/comment-input'
import {Title} from 'web/components/widgets/title'
import {Row} from 'web/components/layout/row'
import {auth, firebaseLogin} from 'web/lib/firebase/users'
import {useT} from 'web/lib/locale'
import {Tooltip} from "web/components/widgets/tooltip";
import {EmailVerificationPrompt} from 'web/components/messaging/email-verification-prompt'
export const SendMessageButton = (props: {
toUser: User
currentUser: User | undefined | null
includeLabel?: boolean
circleButton?: boolean
}) => {
const {toUser, currentUser, includeLabel, circleButton} = props
const firebaseUser = auth.currentUser
const router = useRouter()
const privateUser = usePrivateUser()
const channelMemberships = useSortedPrivateMessageMemberships(currentUser?.id)
const {memberIdsByChannelId} = channelMemberships
const t = useT()
const [openComposeModal, setOpenComposeModal] = useState(false)
const [error, setError] = useState('')
const [submitting, setSubmitting] = useState(false)
const messageButtonClicked = async () => {
if (!currentUser) return firebaseLogin()
const previousDirectMessageChannel = findKey(
memberIdsByChannelId,
(dm) => dm.includes(toUser.id) && dm.length === 1
)
const previousChannelId =
previousDirectMessageChannel !== undefined
? previousDirectMessageChannel
: undefined
if (previousChannelId) router.push(`/messages/${previousChannelId}`)
else setOpenComposeModal(true)
}
const editor = useTextEditor({
key: `compose-new-message-${toUser.id}`,
size: 'sm',
max: MAX_COMMENT_LENGTH,
// placeholder: t('send_message.placeholder', '...'),
})
useEffect(() => {
if (openComposeModal && editor) {
// Focus the editor after a short delay to ensure the modal is fully rendered
setTimeout(() => {
editor.commands.focus()
}, 100)
}
}, [openComposeModal, editor])
const sendMessage = async () => {
if (!editor) return
setSubmitting(true)
const res = await api('create-private-user-message-channel', {
userIds: [toUser.id],
}).catch((e) => {
setError(e.message)
setSubmitting(false)
return
})
if (!res) return
const msgRes = await api('create-private-user-message', {
channelId: res.channelId,
content: editor.getJSON(),
}).catch((e: any) => {
setError(e.message)
setSubmitting(false)
return
})
if (!msgRes) return
router.push(`/messages/${res.channelId}`)
}
if (privateUser?.blockedByUserIds.includes(toUser.id)) return null
return (
<>
<Tooltip text={t('send_message.button_label', 'Message')} noTap>
{circleButton ? (
<button
className="bg-primary-900 hover:bg-primary-600 h-7 w-7 rounded-full transition-colors"
onClick={messageButtonClicked}
>
<BiEnvelope
className={clsx(
'm-auto h-5 w-5 text-white drop-shadow',
includeLabel && 'mr-2'
)}
/>
</button>
) : (
<Button size={'sm'} onClick={messageButtonClicked} color={'none'}
className='bg-canvas-200 hover:bg-canvas-300'>
<BiEnvelope className={clsx('h-5 w-5', includeLabel && 'mr-2')}/>{' '}
{includeLabel && <>{t('send_message.button_label', 'Message')}</>}
</Button>
)}
</Tooltip>
<Modal open={openComposeModal} setOpen={setOpenComposeModal}>
<Col className={MODAL_CLASS}>
<Row className={'w-full'}>
<Title className={'!mb-2'}>{t('send_message.title', 'Message')} {toUser.name}</Title>
</Row>
{firebaseUser?.emailVerified ? <CommentInputTextArea
editor={editor}
user={currentUser}
submit={sendMessage}
isSubmitting={!editor || submitting}
submitOnEnter={false}
/> :
<EmailVerificationPrompt firebaseUser={firebaseUser} t={t} className='max-w-xl'/>
}
<span className={'text-red-500'}>{error}</span>
</Col>
</Modal>
</>
)
}