import Uploader from '@/components/PostEditor/Uploader' import ProfileBanner from '@/components/ProfileBanner' import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Textarea } from '@/components/ui/textarea' import { EMAIL_REGEX } from '@/constants' import SecondaryPageLayout from '@/layouts/SecondaryPageLayout' import { createProfileDraftEvent } from '@/lib/draft-event' import { generateImageByPubkey } from '@/lib/pubkey' import { useSecondaryPage } from '@/PageManager' import { useNostr } from '@/providers/NostrProvider' import { Loader, Upload } from 'lucide-react' import { forwardRef, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' const ProfileEditorPage = forwardRef(({ index }: { index?: number }, ref) => { const { t } = useTranslation() const { pop } = useSecondaryPage() const { account, profile, profileEvent, publish, updateProfileEvent } = useNostr() const [banner, setBanner] = useState('') const [avatar, setAvatar] = useState('') const [username, setUsername] = useState('') const [about, setAbout] = useState('') const [nip05, setNip05] = useState('') const [nip05Error, setNip05Error] = useState('') const [hasChanged, setHasChanged] = useState(false) const [saving, setSaving] = useState(false) const [uploadingBanner, setUploadingBanner] = useState(false) const [uploadingAvatar, setUploadingAvatar] = useState(false) const defaultImage = useMemo( () => (account ? generateImageByPubkey(account.pubkey) : undefined), [account] ) useEffect(() => { if (profile) { setBanner(profile.banner ?? '') setAvatar(profile.avatar ?? '') setUsername(profile.original_username ?? '') setAbout(profile.about ?? '') setNip05(profile.nip05 ?? '') } else { setBanner('') setAvatar('') setUsername('') setAbout('') setNip05('') } }, [profile]) if (!account || !profile) return null const save = async () => { if (nip05 && !EMAIL_REGEX.test(nip05)) { setNip05Error(t('Invalid NIP-05 address')) return } setSaving(true) setHasChanged(false) const oldProfileContent = profileEvent ? JSON.parse(profileEvent.content) : {} const newProfileContent = { ...oldProfileContent, display_name: username, displayName: username, name: oldProfileContent.name ?? username, about, nip05, banner, picture: avatar } const profileDraftEvent = createProfileDraftEvent( JSON.stringify(newProfileContent), profileEvent?.tags ) const newProfileEvent = await publish(profileDraftEvent) await updateProfileEvent(newProfileEvent) setSaving(false) pop() } const onBannerUploadSuccess = ({ url }: { url: string }) => { setBanner(url) setHasChanged(true) } const onAvatarUploadSuccess = ({ url }: { url: string }) => { setAvatar(url) setHasChanged(true) } const controls = (
) return (
setTimeout(() => setUploadingBanner(uploading), 50)} className="w-full relative cursor-pointer" >
{uploadingBanner ? ( ) : ( )}
setTimeout(() => setUploadingAvatar(uploading), 50)} className="w-24 h-24 absolute bottom-0 left-4 translate-y-1/2 border-4 border-background cursor-pointer rounded-full" >
{uploadingAvatar ? : }
{t('Display Name')} { setUsername(e.target.value) setHasChanged(true) }} /> {t('Bio')}