import { Dialog, Transition } from '@headlessui/react'; import { NDKEvent } from '@nostr-dev-kit/ndk'; import { useQueryClient } from '@tanstack/react-query'; import { fetch } from '@tauri-apps/plugin-http'; import { Fragment, useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { AvatarUploader } from '@shared/avatarUploader'; import { BannerUploader } from '@shared/bannerUploader'; import { CancelIcon, CheckCircleIcon, LoaderIcon, UnverifiedIcon } from '@shared/icons'; import { Image } from '@shared/image'; import { DEFAULT_AVATAR } from '@stores/constants'; import { useAccount } from '@utils/hooks/useAccount'; import { useNostr } from '@utils/hooks/useNostr'; export function EditProfileModal() { const queryClient = useQueryClient(); const [isOpen, setIsOpen] = useState(false); const [loading, setLoading] = useState(false); const [picture, setPicture] = useState(DEFAULT_AVATAR); const [banner, setBanner] = useState(''); const [nip05, setNIP05] = useState({ verified: false, text: '' }); const { publish } = useNostr(); const { account } = useAccount(); const { register, handleSubmit, reset, setError, formState: { isValid, errors }, } = useForm({ defaultValues: async () => { const res: any = queryClient.getQueryData(['user', account.pubkey]); if (res.image) { setPicture(res.image); } if (res.banner) { setBanner(res.banner); } if (res.nip05) { setNIP05((prev) => ({ ...prev, text: res.nip05 })); } return res; }, }); const closeModal = () => { setIsOpen(false); }; const openModal = () => { setIsOpen(true); }; const verifyNIP05 = async (data: string) => { if (data) { const url = data.split('@'); const username = url[0]; const service = url[1]; const verifyURL = `https://${service}/.well-known/nostr.json?name=${username}`; const res: any = await fetch(verifyURL, { method: 'GET', headers: { 'Content-Type': 'application/json; charset=utf-8', }, }); if (!res.ok) return false; if (res.data.names[username] === account.pubkey) { setNIP05((prev) => ({ ...prev, verified: true })); return true; } else { return false; } } }; const onSubmit = async (data: any) => { // start loading setLoading(true); let event: NDKEvent; const content = { ...data, username: data.name, display_name: data.name, bio: data.about, image: data.picture, }; if (data.nip05) { const verify = await verifyNIP05(data.nip05); if (verify) { event = await publish({ content: JSON.stringify({ ...content, nip05: data.nip05 }), kind: 0, tags: [], }); } else { setNIP05((prev) => ({ ...prev, verified: false })); setError('nip05', { type: 'manual', message: "Can't verify your Lume ID / NIP-05, please check again", }); } } else { event = await publish({ content: JSON.stringify(content), kind: 0, tags: [], }); } if (event.id) { setTimeout(() => { // invalid cache queryClient.invalidateQueries(['user', account.pubkey]); // reset form reset(); // reset state setLoading(false); setIsOpen(false); setPicture(DEFAULT_AVATAR); setBanner(null); }, 1200); } else { setLoading(false); } }; useEffect(() => { if (!nip05.verified && /\S+@\S+\.\S+/.test(nip05.text)) { verifyNIP05(nip05.text); } }, [nip05.text]); return ( <> openModal()} className="inline-flex h-10 w-36 items-center justify-center rounded-md bg-white/10 text-sm font-medium hover:bg-fuchsia-500" > Edit profile Edit profile Name Lume ID / NIP-05 {nip05.verified ? ( Verified ) : ( Unverified )} {errors.nip05 && ( {errors.nip05.message.toString()} )} Bio Website Lightning address {loading ? ( ) : ( 'Update' )} > ); }
{errors.nip05.message.toString()}