'use client'; import React, { useEffect, useState } from 'react'; import { Button } from "@/components/ui/button" import { Input } from "@/components/ui/input" import { nip19 } from "nostr-tools" import { Label } from "./ui/label" import { Textarea } from "@/components/ui/textarea" import { verifyEvent } from 'nostr-tools/pure' import { hexToBytes } from '@noble/hashes/utils' import { useNostr, useProfile } from 'nostr-react'; import { signEvent } from '@/utils/utils'; import { Card, CardContent } from "@/components/ui/card"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Loader2, Globe, Image, ImageIcon, BadgeCheck, Zap } from "lucide-react"; import { Skeleton } from "@/components/ui/skeleton"; export function UpdateProfileForm() { const { publish } = useNostr(); const [isSubmitting, setIsSubmitting] = useState(false); const [isSaved, setIsSaved] = useState(false); const [isDataLoaded, setIsDataLoaded] = useState(false); let npub = ''; let pubkey = ''; let loginType = ''; let nsec: Uint8Array; if (typeof window !== 'undefined') { pubkey = window.localStorage.getItem("pubkey") ?? ''; const nsecHex = window.localStorage.getItem("nsec"); loginType = window.localStorage.getItem("loginType") ?? ''; if (pubkey && pubkey.length > 0) { npub = nip19.npubEncode(pubkey); } if (nsecHex && nsecHex.length > 0) { nsec = hexToBytes(nsecHex); } } const { data: userData, isLoading: isUserDataLoading } = useProfile({ pubkey, }); const [username, setUsername] = useState(''); const [displayName, setDisplayName] = useState(''); const [bio, setBio] = useState(''); const [picture, setPicture] = useState(''); const [banner, setBanner] = useState(''); const [nip05, setNip05] = useState(''); const [lud16, setLud16] = useState(''); const [website, setWebsite] = useState(''); // Update form data when userData changes useEffect(() => { if (userData && !isDataLoaded) { setUsername(userData.name); setDisplayName(userData.display_name); setBio(userData.about); setPicture(userData.picture); setBanner(userData.banner); setNip05(userData.nip05); setLud16(userData.lud16); setWebsite(userData.website); setIsDataLoaded(true); } }, [userData, isDataLoaded]); // Field change handlers const handleUsernameChange = (event: React.ChangeEvent) => { setUsername(event.target.value); setIsSaved(false); }; const handleDisplayNameChange = (event: React.ChangeEvent) => { setDisplayName(event.target.value); setIsSaved(false); }; const handleBioChange = (event: React.ChangeEvent) => { setBio(event.target.value); setIsSaved(false); }; const handlePictureChange = (event: React.ChangeEvent) => { setPicture(event.target.value); setIsSaved(false); }; const handleBannerChange = (event: React.ChangeEvent) => { setBanner(event.target.value); setIsSaved(false); }; const handleNip05Change = (event: React.ChangeEvent) => { setNip05(event.target.value); setIsSaved(false); }; const handleLud16Change = (event: React.ChangeEvent) => { setLud16(event.target.value); setIsSaved(false); }; const handleWebsiteChange = (event: React.ChangeEvent) => { setWebsite(event.target.value); setIsSaved(false); }; async function handleProfileUpdate() { setIsSubmitting(true); setIsSaved(false); if (loginType) { try { let event = { kind: 0, created_at: Math.floor(Date.now() / 1000), tags: [], content: JSON.stringify({ name: username, display_name: displayName, about: bio, picture: picture, banner: banner, nip05: nip05, lud16: lud16, website: website, }), pubkey: pubkey, id: "", sig: "", }; let signedEvent = await signEvent(loginType, event); if (signedEvent === null) { throw new Error('Failed to sign the event'); } let isGood = verifyEvent(signedEvent); if (isGood) { publish(signedEvent); setIsSaved(true); setTimeout(() => { window.location.href = `/profile/${npub}`; }, 1000); } } catch (error) { console.error("Error updating profile:", error); alert('Failed to update profile. Please check your connection and try again.'); } finally { setIsSubmitting(false); } } } if (isUserDataLoading && !isDataLoaded) { return (
); } return (
{username?.charAt(0) || "U"}

{displayName || username || "Your Profile"}

{nip05 || npub}

Your public identity on the Nostr network

Your unique username on the network

How your name appears to others