import JsonViewDialog from '@/components/JsonViewDialog' import { RefreshButton } from '@/components/RefreshButton' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/ui/dropdown-menu' import SecondaryPageLayout from '@/layouts/SecondaryPageLayout' import { usePrimaryNoteView } from '@/contexts/primary-note-view-context' import { buildAccountListRelayUrlsForMerge } from '@/lib/account-list-relay-urls' import { normalizeTopic } from '@/lib/discussion-topics' import { toNoteList } from '@/lib/link' import { fetchLatestReplaceableListEvent } from '@/lib/replaceable-list-latest' import { cn } from '@/lib/utils' import { useSmartHashtagNavigation } from '@/PageManager' import { useInterestList } from '@/providers/InterestListProvider' import { useNostr } from '@/providers/NostrProvider' import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider' import client from '@/services/client.service' import { Code, MoreVertical, Trash2 } from 'lucide-react' import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { toast } from 'sonner' import NotFoundPage from '../NotFoundPage' const INTEREST_LIST_KIND = 10015 const InterestListPage = forwardRef( ({ index, hideTitlebar = false }: { index?: number; hideTitlebar?: boolean }, ref) => { const { t } = useTranslation() const { registerPrimaryPanelRefresh } = usePrimaryNoteView() const { navigateToHashtag } = useSmartHashtagNavigation() const { profile, pubkey, interestListEvent, updateInterestListEvent } = useNostr() const { favoriteRelays, blockedRelays } = useFavoriteRelays() const { subscribedTopics, subscribe, unsubscribe, changing } = useInterestList() const [topicInput, setTopicInput] = useState('') const [jsonOpen, setJsonOpen] = useState(false) const [jsonPayload, setJsonPayload] = useState(null) const topicsSorted = useMemo( () => [...subscribedTopics].sort((a, b) => a.localeCompare(b)), [subscribedTopics] ) const refreshFromRelays = useCallback(async () => { if (!pubkey) return const comprehensiveRelays = await buildAccountListRelayUrlsForMerge({ accountPubkey: pubkey, favoriteRelays: favoriteRelays ?? [], blockedRelays }) let latest = (await fetchLatestReplaceableListEvent(pubkey, INTEREST_LIST_KIND, comprehensiveRelays)) ?? null if (!latest) { latest = (await client.fetchInterestListEvent(pubkey)) ?? null } if (latest) await updateInterestListEvent(latest) }, [pubkey, favoriteRelays, blockedRelays, updateInterestListEvent]) const openJson = useCallback(() => { setJsonPayload({ interestListEvent: interestListEvent ?? null, derivedTopics: topicsSorted, note: 'Interest list is kind 10015; subscribed topics are stored as `t` tags.' }) setJsonOpen(true) }, [interestListEvent, topicsSorted]) useEffect(() => { if (!hideTitlebar) { registerPrimaryPanelRefresh(null) return } registerPrimaryPanelRefresh(() => { void refreshFromRelays() }) return () => registerPrimaryPanelRefresh(null) }, [hideTitlebar, registerPrimaryPanelRefresh, refreshFromRelays]) const onAddTopic = async (e: React.FormEvent) => { e.preventDefault() const raw = topicInput.trim().replace(/^#+/u, '') const normalized = normalizeTopic(raw) if (!normalized) { toast.error(t('Interest topic invalid')) return } await subscribe(normalized) setTopicInput('') } if (!profile || !pubkey) { return } return ( void refreshFromRelays()} /> openJson()}> {t('View JSON')} ) } displayScrollToTopButton > setJsonOpen(false)} />

{t('Interests list section subtitle')}

void onAddTopic(ev)} className="flex flex-wrap items-center gap-2"> setTopicInput(ev.target.value)} placeholder={t('Interest topic placeholder')} className="min-w-[12rem] flex-1" disabled={changing} aria-label={t('Interest topic placeholder')} />
{topicsSorted.length === 0 ? (

{t('No interest topics in list')}

) : (
    {topicsSorted.map((topic) => (
  • ))}
)}
) } ) InterestListPage.displayName = 'InterestListPage' export default InterestListPage