diff --git a/src/components/BottomNav.tsx b/src/components/BottomNav.tsx index 650f0463..ac6ddfb6 100644 --- a/src/components/BottomNav.tsx +++ b/src/components/BottomNav.tsx @@ -5,8 +5,8 @@ import { Button } from '@/components/ui/button'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useUnreadNotificationCount } from '@/hooks/useNotifications'; import { useSubdomainNavigate } from '@/hooks/useSubdomainNavigate'; +import { buildProfileLinkPath } from '@/lib/profileLinks'; import { cn } from '@/lib/utils'; -import { nip19 } from 'nostr-tools'; export function BottomNav() { const navigate = useSubdomainNavigate(); @@ -17,8 +17,10 @@ export function BottomNav() { const getUserProfilePath = () => { if (!user?.pubkey) return '/'; - const npub = nip19.npubEncode(user.pubkey); - return `/profile/${npub}`; + return buildProfileLinkPath({ + pubkey: user.pubkey, + fallbackRoute: 'profile', + }); }; const isActive = (path: string) => location.pathname === path; diff --git a/src/components/ClassicVinersRow.tsx b/src/components/ClassicVinersRow.tsx index 6ee7acef..82cf574f 100644 --- a/src/components/ClassicVinersRow.tsx +++ b/src/components/ClassicVinersRow.tsx @@ -8,7 +8,7 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Star } from '@phosphor-icons/react'; import { CLASSIC_VINERS, CLASSIC_VINER_AVATARS, type StaticViner } from '@/data/classicViners'; import { getSafeProfileImage } from '@/lib/imageUtils'; -import { nip19 } from 'nostr-tools'; +import { buildProfileLinkPath } from '@/lib/profileLinks'; /** * Single viner avatar item @@ -17,14 +17,7 @@ function VinerItem({ viner }: { viner: StaticViner }) { const displayName = viner.name; const picture = getSafeProfileImage(viner.picture) || '/user-avatar.png'; - // Use npub for URL - let profilePath = `/profile/${viner.pubkey}`; - try { - const npub = nip19.npubEncode(viner.pubkey); - profilePath = `/${npub}`; - } catch { - // Fall back to hex pubkey - } + const profilePath = buildProfileLinkPath({ pubkey: viner.pubkey }); return ( { if (notification.type === 'follow') { - const npub = nip19.npubEncode(notification.actorPubkey); - navigate(`/profile/${npub}`); + navigate(buildProfileLinkPath({ + pubkey: notification.actorPubkey, + nip05: metadata?.nip05, + fallbackRoute: 'profile', + })); } else if (notification.targetEventId) { navigate(`/video/${notification.targetEventId}`); } diff --git a/src/components/UserListDialog.tsx b/src/components/UserListDialog.tsx index 1d73721b..176f37be 100644 --- a/src/components/UserListDialog.tsx +++ b/src/components/UserListDialog.tsx @@ -2,7 +2,6 @@ // ABOUTME: Uses virtual scrolling for performance with large lists (500+ users) import { memo, useCallback, useRef, useEffect, useMemo } from 'react'; -import { nip19 } from 'nostr-tools'; import type { NostrMetadata } from '@nostrify/nostrify'; import { useVirtualizer } from '@tanstack/react-virtual'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; @@ -19,6 +18,7 @@ import { useSubdomainNavigate } from '@/hooks/useSubdomainNavigate'; import { getSafeProfileImage } from '@/lib/imageUtils'; import { genUserName } from '@/lib/genUserName'; import { Sentry } from '@/lib/sentry'; +import { buildProfileLinkPath } from '@/lib/profileLinks'; const ESTIMATED_ROW_HEIGHT = 56; @@ -35,7 +35,7 @@ interface UserListDialogProps { interface UserRowProps { pubkey: string; metadata?: NostrMetadata; - onNavigate: (pubkey: string) => void; + onNavigate: (pubkey: string, nip05?: string) => void; } const UserRow = memo(function UserRow({ pubkey, metadata, onNavigate }: UserRowProps) { @@ -45,7 +45,7 @@ const UserRow = memo(function UserRow({ pubkey, metadata, onNavigate }: UserRowP return (