import { NDKSubscriptionCacheUsage } from '@nostr-dev-kit/ndk' import { FALLBACK_PROFILE_IMAGE } from '../../constants' import { useAppSelector, useLocalCache } from 'hooks' import { useProfile } from 'hooks/useProfile' import { Navigate, useActionData, useNavigation, useSubmit } from 'react-router-dom' import { appRoutes } from 'routes' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { adjustTextareaHeight, NOTE_DRAFT_CACHE_KEY } from 'utils' import { NotePreview } from './NotePreview' import { NoteSubmitActionResult, NoteSubmitForm } from 'types' import { InputError } from 'components/Inputs/Error' import { AlertPopup } from 'components/AlertPopup' interface NoteSubmitProps { initialContent?: string | undefined handleClose?: () => void | undefined } export const NoteSubmit = ({ initialContent, handleClose }: NoteSubmitProps) => { const navigation = useNavigation() const userState = useAppSelector((state) => state.user) const profile = useProfile(userState.user?.pubkey as string | undefined, { cacheUsage: NDKSubscriptionCacheUsage.PARALLEL }) const [cache, setCache] = useLocalCache(NOTE_DRAFT_CACHE_KEY) const [content, setContent] = useState(initialContent ?? cache?.content ?? '') const [nsfw, setNsfw] = useState(cache?.nsfw ?? false) const [showPreview, setShowPreview] = useState(!!initialContent) const image = useMemo( () => profile?.image || FALLBACK_PROFILE_IMAGE, [profile?.image] ) const ref = useRef(null) const submit = useSubmit() const actionData = useActionData() as NoteSubmitActionResult const formErrors = useMemo( () => actionData?.type === 'validation' ? actionData.formErrors : undefined, [actionData] ) useEffect(() => { if (ref.current && (!!initialContent || !!cache?.content)) { adjustTextareaHeight(ref.current) ref.current.focus() } }, [cache?.content, initialContent]) useEffect(() => { setCache({ content, nsfw }) }, [content, nsfw, setCache]) const [showTryAgainPopup, setShowTryAgainPopup] = useState(false) useEffect(() => { const isTimeout = actionData?.type === 'timeout' setShowTryAgainPopup(isTimeout) if (isTimeout && actionData.action.intent === 'submit') { setContent(actionData.action.data.content) setNsfw(actionData.action.data.nsfw) } }, [actionData]) const handleFormSubmit = useCallback( async (event?: React.FormEvent) => { event?.preventDefault() const formSubmit = { intent: 'submit', data: { content, nsfw } } // Reset form setContent('') setNsfw(false) submit(JSON.stringify(formSubmit), { method: 'post', encType: 'application/json', action: appRoutes.feed }) typeof handleClose === 'function' && handleClose() }, [content, handleClose, nsfw, submit] ) const handleTryAgainConfirm = useCallback( (confirm: boolean) => { setShowTryAgainPopup(false) // Cancel if not confirmed if (!confirm) return // Reset form setContent('') setNsfw(false) handleFormSubmit() }, [handleFormSubmit] ) const handleContentChange = ( event: React.ChangeEvent ) => { setContent(event.currentTarget.value) adjustTextareaHeight(event.currentTarget) } const handlePreviewToggle = () => { setShowPreview((prev) => !prev) } if (!userState.user?.pubkey) return return ( <>