import NoteList, { type TNoteListRef } from '@/components/NoteList' import NoteCard from '@/components/NoteCard' import KindFilter from '@/components/KindFilter' import { RefreshButton } from '@/components/RefreshButton' import { Skeleton } from '@/components/ui/skeleton' import { ExtendedKind, PROFILE_FEED_KINDS, PROFILE_TIMELINE_REQ_LIMIT } from '@/constants' import { useProfileAuthorFeedSubRequests } from '@/hooks/useProfileAuthorFeedSubRequests' import { useProfilePins } from '@/hooks/useProfilePins' import { useKindFilterOrDefaults } from '@/providers/KindFilterProvider' import { useDeletedEvent } from '@/providers/DeletedEventProvider' import client from '@/services/client.service' import { nip19, kinds } from 'nostr-tools' import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' const profileFeedKinds = [...PROFILE_FEED_KINDS] const ProfileFeed = forwardRef<{ refresh: () => void }, { pubkey: string }>(({ pubkey }, ref) => { const { t } = useTranslation() const { isEventDeleted } = useDeletedEvent() const { showKinds, showKind1OPs, showKind1Replies, showKind1111, feedKindFilterBypass } = useKindFilterOrDefaults() const profileTimelineShowKinds = useMemo(() => { if (showKinds.includes(kinds.Repost) && showKinds.includes(ExtendedKind.GENERIC_REPOST)) { return showKinds } const next = [...showKinds] if (!next.includes(kinds.Repost)) next.push(kinds.Repost) if (!next.includes(ExtendedKind.GENERIC_REPOST)) next.push(ExtendedKind.GENERIC_REPOST) return next.sort((a, b) => a - b) }, [showKinds]) const [isRefreshing, setIsRefreshing] = useState(false) const noteListRef = useRef(null) const { pinEvents, loadingPins, refreshPins } = useProfilePins(pubkey) const { subRequests, followingFeedDeltaSubRequests, feedSubscriptionKey, refresh: refreshAuthorRelayLayers } = useProfileAuthorFeedSubRequests({ pubkey, kinds: profileFeedKinds, limit: PROFILE_TIMELINE_REQ_LIMIT }) const pinnedEventIds = useMemo( () => pinEvents.map((e) => nip19.neventEncode({ id: e.id, author: e.pubkey, kind: e.kind }) ), [pinEvents] ) const refreshAll = useCallback(() => { setIsRefreshing(true) refreshPins() refreshAuthorRelayLayers() noteListRef.current?.refresh() void client.fetchDeletionEventsForPubkey(pubkey) }, [refreshPins, refreshAuthorRelayLayers, pubkey]) useImperativeHandle(ref, () => ({ refresh: refreshAll }), [refreshAll]) useEffect(() => { if (!isRefreshing) return const id = window.setTimeout(() => setIsRefreshing(false), 600) return () => clearTimeout(id) }, [isRefreshing]) const handleShowKindsChange = useCallback(() => { noteListRef.current?.scrollToTop() }, []) const showPinsOnlySkeleton = pinEvents.length === 0 && loadingPins && subRequests.length === 0 if (showPinsOnlySkeleton) { return (
{Array.from({ length: 4 }).map((_, i) => ( ))}
) } if (!subRequests.length) { return (

{t('Nothing to load for this feed.')}

) } return (
{isRefreshing && (
{t('Refreshing posts...')}
)}
{pinEvents.filter((e) => !isEventDeleted(e)).length > 0 && (
{pinEvents .filter((e) => !isEventDeleted(e)) .map((event) => ( ))}
{t('Feed')}
)}
) }) ProfileFeed.displayName = 'ProfileFeed' export default ProfileFeed