import { PaperAirplaneIcon } from '@heroicons/react/solid' import { Editor } from '@tiptap/react' import clsx from 'clsx' import { User } from 'common/user' import { useEffect, useState } from 'react' import { useUser } from 'web/hooks/use-user' import { MAX_COMMENT_LENGTH } from 'common/comment' import { Avatar } from '../widgets/avatar' import { TextEditor, useTextEditor } from '../widgets/editor' import { ReplyToUserInfo } from 'common/comment' import { Row } from '../layout/row' import { LoadingIndicator } from '../widgets/loading-indicator' import { safeLocalStorage } from 'web/lib/util/local' import toast from 'react-hot-toast' import { BiRepost } from 'react-icons/bi' import { Tooltip } from 'web/components/widgets/tooltip' import { track } from 'web/lib/service/analytics' import { firebaseLogin } from 'web/lib/firebase/users' import { useEvent } from 'web/hooks/use-event' import {useT} from "web/lib/locale"; export function CommentInput(props: { replyToUserInfo?: ReplyToUserInfo // Reply to another comment parentCommentId?: string onSubmitComment: (editor: Editor, type: CommentType) => Promise // unique id for autosave pageId: string className?: string blocked?: boolean placeholder?: string commentTypes: CommentType[] onClearInput?: () => void }) { const { parentCommentId, replyToUserInfo, onSubmitComment, pageId, className, blocked, placeholder = 'Write a comment...', commentTypes, onClearInput, } = props const user = useUser() const key = `comment ${pageId} ${parentCommentId ?? ''}` const [isSubmitting, setIsSubmitting] = useState(false) const editor = useTextEditor({ key, size: 'sm', max: MAX_COMMENT_LENGTH, placeholder, className: isSubmitting ? '!text-ink-400' : '', }) const submitComment = useEvent(async (type: CommentType) => { if (!editor || editor.isEmpty || isSubmitting) return setIsSubmitting(true) if (!user) { track('sign in to comment') await firebaseLogin() setIsSubmitting(false) return } editor.commands.focus('end') // if last item is text, try to linkify it by adding and deleting a space if (editor.state.selection.empty) { editor.commands.insertContent(' ') const endPos = editor.state.selection.from editor.commands.deleteRange({ from: endPos - 1, to: endPos }) } try { await onSubmitComment?.(editor, type) editor.commands.clearContent(true) // force clear save, because it can fail if editor unrenders safeLocalStorage?.removeItem(`text ${key}`) onClearInput?.() } catch (e) { console.error(e) toast.error('Error submitting. Try again?') } finally { setIsSubmitting(false) } }) if (user?.isBannedFromPosting) return <> return blocked ? (
You blocked the creator or they blocked you, so you can't comment.
) : ( ) } const emojiMenuActive = (view: { state: any }) => { const regex = /^emoji\$.*$/ // emoji$ can have random numbers following it....❤️ tiptap let active = false for (const key in view.state) { if (regex.test(key)) { active = (view.state as any)[key].active if (active) break } } return active } export type CommentType = 'comment' | 'repost' export function CommentInputTextArea(props: { user: User | undefined | null replyTo?: { id: string; username: string } editor: Editor | null submit?: (type: CommentType) => void cancelEditing?: () => void isSubmitting: boolean submitOnEnter?: boolean isEditing?: boolean commentTypes?: CommentType[] }) { const { user, submitOnEnter, editor, submit, isSubmitting, isEditing, replyTo, commentTypes = ['comment'], cancelEditing, } = props const t = useT() useEffect(() => { editor?.setEditable(!isSubmitting) }, [isSubmitting, editor]) useEffect(() => { if (!editor) return // Submit on ctrl+enter or mod+enter key editor.setOptions({ editorProps: { handleKeyDown: (view, event) => { if ( event.key === 'Enter' && !event.shiftKey && (!submitOnEnter ? event.ctrlKey || event.metaKey : true) && // mention list is closed !(view.state as any).mention$.active && // emoji list is closed !emojiMenuActive(view) ) { // console.log('handleKeyDown') submit?.(commentTypes[0]) event.preventDefault() return true } return false }, }, }) }, [editor, submit, submitOnEnter, commentTypes]) useEffect(() => { if (!editor) return // insert at mention and focus if (replyTo && editor.isEmpty) { editor .chain() .setContent({ type: 'mention', attrs: { label: replyTo.username, id: replyTo.id }, }) .insertContent(' ') .focus(undefined, { scrollIntoView: false }) .run() } }, [replyTo, editor]) return ( {user && !isSubmitting && submit && commentTypes.includes('repost') && ( )} {isEditing && ( {/*Editing message*/} )} {!isSubmitting && submit && commentTypes.includes('comment') && ( )} {submit && isSubmitting && ( )} ) }