import { useSmartNoteNavigation } from '@/PageManager' import { ExtendedKind } from '@/constants' import { Button } from '@/components/ui/button' import { Skeleton } from '@/components/ui/skeleton' import { notificationReactionSummaryKey, useNotificationReactionDisplay } from '@/hooks/useNotificationReactionDisplay' import { DISCUSSION_DOWNVOTE_DISPLAY, DISCUSSION_UPVOTE_DISPLAY } from '@/lib/discussion-votes' import { getZapInfoFromEvent } from '@/lib/event-metadata' import { isMentioningMutedUsers, isNip25ReactionKind } from '@/lib/event' import { getWebExternalReactionTargetUrl } from '@/lib/rss-article' import { toNote } from '@/lib/link' import { useContentPolicy } from '@/providers/ContentPolicyProvider' import { useMuteList } from '@/contexts/mute-list-context' import { useScreenSize } from '@/providers/ScreenSizeProvider' import { Event, kinds } from 'nostr-tools' import { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import ClientTag from '../ClientTag' import Collapsible from '../Collapsible' import MarkdownArticle from '../Note/MarkdownArticle/MarkdownArticle' import ReactionEmojiDisplay from '../Note/ReactionEmojiDisplay' import { FormattedTimestamp } from '../FormattedTimestamp' import Nip05 from '../Nip05' import NoteOptions from '../NoteOptions' import NoteStats from '../NoteStats' import ParentNotePreview from '../ParentNotePreview' import WebPreview from '../WebPreview' import UserAvatar from '../UserAvatar' import Username from '../Username' import NoteKindLabel from '../Note/NoteKindLabel' import Zap from '../Note/Zap' export default function ReplyNote({ event, parentEventId, onClickParent = () => {}, onClickReply, highlight = false, duplicateWebPreviewCleanedUrlHints }: { event: Event parentEventId?: string onClickParent?: () => void onClickReply?: (event: Event) => void highlight?: boolean duplicateWebPreviewCleanedUrlHints?: string[] }) { const { t } = useTranslation() const { isSmallScreen } = useScreenSize() const { navigateToNote } = useSmartNoteNavigation() const { mutePubkeySet } = useMuteList() const { hideContentMentioningMutedUsers } = useContentPolicy() const [showMuted, setShowMuted] = useState(false) const reactionDisplay = useNotificationReactionDisplay(event) const webReactionParentUrl = useMemo( () => event.kind === ExtendedKind.EXTERNAL_REACTION ? getWebExternalReactionTargetUrl(event) : undefined, [event] ) const headerUserId = useMemo(() => { if (event.kind !== kinds.Zap) return event.pubkey const info = getZapInfoFromEvent(event) return info?.senderPubkey ?? event.pubkey }, [event]) const show = useMemo(() => { if (showMuted) { return true } if (mutePubkeySet.has(event.pubkey)) { return false } if (hideContentMentioningMutedUsers && isMentioningMutedUsers(event, mutePubkeySet)) { return false } return true }, [showMuted, mutePubkeySet, event, hideContentMentioningMutedUsers]) return (
{ // Don't navigate if clicking on interactive elements const target = e.target as HTMLElement if (target.closest('button') || target.closest('[role="button"]') || target.closest('a') || target.closest('[data-parent-note-preview]')) { return } if (onClickReply) { onClickReply(event) } else { navigateToNote(toNote(event), event) } }} >
{webReactionParentUrl ? (
) : parentEventId ? ( { e.stopPropagation() onClickParent() }} /> ) : null} {show ? ( isNip25ReactionKind(event.kind) ? (
{reactionDisplay.status === 'pending' ? ( ) : reactionDisplay.status === 'vote_up' ? ( {DISCUSSION_UPVOTE_DISPLAY} ) : reactionDisplay.status === 'vote_down' ? ( {DISCUSSION_DOWNVOTE_DISPLAY} ) : ( )} {t(notificationReactionSummaryKey(reactionDisplay))}
) : event.kind === kinds.Zap ? ( ) : ( ) ) : ( )}
{show && !isNip25ReactionKind(event.kind) && ( )}
) } export function ReplyNoteSkeleton() { return (
) }