import MessageView from '@/components/Inbox/MessageView' import UserAvatar from '@/components/UserAvatar' import { Button } from '@/components/ui/button' import { Titlebar } from '@/components/Titlebar' import { useSecondaryPage } from '@/PageManager' import { useDM } from '@/providers/DMProvider' import { useFollowList } from '@/providers/FollowListProvider' import client from '@/services/client.service' import { TPageRef, TProfile } from '@/types' import { ChevronLeft, MoreVertical, RefreshCw, Settings, Trash2, Undo2, Users, X } from 'lucide-react' import { nip19 } from 'nostr-tools' import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { cn } from '@/lib/utils' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu' import ConversationSettingsModal from '@/components/Inbox/ConversationSettingsModal' import indexedDb from '@/services/indexed-db.service' import { useNostr } from '@/providers/NostrProvider' interface DMConversationPageProps { pubkey?: string } const DMConversationPage = forwardRef(({ pubkey }, ref) => { const { t } = useTranslation() const layoutRef = useRef(null) const { pubkey: userPubkey } = useNostr() const { selectConversation, currentConversation, isLoadingConversation, isNewConversation, clearNewConversationFlag, reloadConversation, deleteAllInConversation, undeleteAllInConversation } = useDM() const { pop } = useSecondaryPage() const { followingSet } = useFollowList() const [profile, setProfile] = useState(null) const [settingsOpen, setSettingsOpen] = useState(false) const [selectedRelays, setSelectedRelays] = useState([]) const [showPulse, setShowPulse] = useState(false) // Decode npub to hex if needed const hexPubkey = useMemo(() => { if (!pubkey) return null if (pubkey.startsWith('npub')) { try { const decoded = nip19.decode(pubkey) return decoded.type === 'npub' ? decoded.data : null } catch { return null } } return pubkey }, [pubkey]) const isFollowing = hexPubkey ? followingSet.has(hexPubkey) : false useImperativeHandle(ref, () => layoutRef.current as TPageRef) // Select the conversation when this page mounts useEffect(() => { if (hexPubkey && hexPubkey !== currentConversation) { selectConversation(hexPubkey) } }, [hexPubkey, selectConversation, currentConversation]) // Clear conversation when page unmounts useEffect(() => { return () => { selectConversation(null) } }, []) // Fetch profile useEffect(() => { if (!hexPubkey) return const fetchProfileData = async () => { try { const profileData = await client.fetchProfile(hexPubkey) if (profileData) { setProfile(profileData) } } catch (error) { console.error('Failed to fetch profile:', error) } } fetchProfileData() }, [hexPubkey]) // Handle pulsing animation for new conversations useEffect(() => { if (isNewConversation) { setShowPulse(true) const timer = setTimeout(() => { setShowPulse(false) clearNewConversationFlag() }, 10000) return () => clearTimeout(timer) } }, [isNewConversation, clearNewConversationFlag]) // Load saved relay settings when conversation changes useEffect(() => { if (!hexPubkey || !userPubkey) return const loadRelaySettings = async () => { const saved = await indexedDb.getConversationRelaySettings(userPubkey, hexPubkey) setSelectedRelays(saved || []) } loadRelaySettings() }, [hexPubkey, userPubkey]) // Save relay settings when they change const handleRelaysChange = async (relays: string[]) => { setSelectedRelays(relays) if (userPubkey && hexPubkey) { await indexedDb.putConversationRelaySettings(userPubkey, hexPubkey, relays) } } const handleBack = () => { selectConversation(null) pop() } const displayName = profile?.username || (hexPubkey ? hexPubkey.slice(0, 8) + '...' : '') // Custom titlebar with user info const titlebar = (
{hexPubkey && ( <>
{displayName} {isFollowing && ( )}
{profile?.nip05 && ( {profile.nip05} )}
{t('Delete All')} {t('Undelete All')} )}
) return (
{titlebar}
{hexPubkey && ( )}
) }) DMConversationPage.displayName = 'DMConversationPage' export default DMConversationPage