feat: add more buttons to reply

This commit is contained in:
codytseng
2025-02-06 11:06:22 +08:00
parent 760f4bcccb
commit 6ffa180812
4 changed files with 36 additions and 47 deletions

View File

@@ -11,11 +11,9 @@ import { formatCount } from './utils'
export default function LikeButton({ export default function LikeButton({
event, event,
variant = 'normal',
canFetch = false canFetch = false
}: { }: {
event: Event event: Event
variant?: 'normal' | 'reply'
canFetch?: boolean canFetch?: boolean
}) { }) {
const { t } = useTranslation() const { t } = useTranslation()
@@ -70,8 +68,7 @@ export default function LikeButton({
return ( return (
<button <button
className={cn( className={cn(
'flex items-center enabled:hover:text-red-400', 'flex items-center enabled:hover:text-red-400 gap-1',
variant === 'normal' ? 'gap-1' : 'flex-col',
hasLiked ? 'text-red-400' : 'text-muted-foreground' hasLiked ? 'text-red-400' : 'text-muted-foreground'
)} )}
onClick={like} onClick={like}

View File

@@ -7,11 +7,20 @@ import { useTranslation } from 'react-i18next'
import PostEditor from '../PostEditor' import PostEditor from '../PostEditor'
import { formatCount } from './utils' import { formatCount } from './utils'
export default function ReplyButton({ event }: { event: Event }) { export default function ReplyButton({
event,
variant = 'note'
}: {
event: Event
variant?: 'note' | 'reply'
}) {
const { t } = useTranslation() const { t } = useTranslation()
const { checkLogin } = useNostr() const { checkLogin } = useNostr()
const { noteStatsMap } = useNoteStats() const { noteStatsMap } = useNoteStats()
const { replyCount } = useMemo(() => noteStatsMap.get(event.id) ?? {}, [noteStatsMap, event.id]) const { replyCount } = useMemo(
() => (variant === 'reply' ? {} : (noteStatsMap.get(event.id) ?? {})),
[noteStatsMap, event.id, variant]
)
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
return ( return (
@@ -27,7 +36,9 @@ export default function ReplyButton({ event }: { event: Event }) {
title={t('Reply')} title={t('Reply')}
> >
<MessageCircle size={16} /> <MessageCircle size={16} />
{!!replyCount && <div className="text-sm">{formatCount(replyCount)}</div>} {variant !== 'reply' && !!replyCount && (
<div className="text-sm">{formatCount(replyCount)}</div>
)}
</button> </button>
<PostEditor parentEvent={event} open={open} setOpen={setOpen} /> <PostEditor parentEvent={event} open={open} setOpen={setOpen} />
</> </>

View File

@@ -8,16 +8,18 @@ import RepostButton from './RepostButton'
export default function NoteStats({ export default function NoteStats({
event, event,
className, className,
fetchIfNotExisting = false fetchIfNotExisting = false,
variant = 'note'
}: { }: {
event: Event event: Event
className?: string className?: string
fetchIfNotExisting?: boolean fetchIfNotExisting?: boolean
variant?: 'note' | 'reply'
}) { }) {
return ( return (
<div className={cn('flex justify-between', className)}> <div className={cn('flex justify-between', className)}>
<div className="flex gap-4 h-4 items-center" onClick={(e) => e.stopPropagation()}> <div className="flex gap-5 h-4 items-center" onClick={(e) => e.stopPropagation()}>
<ReplyButton event={event} /> <ReplyButton event={event} variant={variant} />
<RepostButton event={event} canFetch={fetchIfNotExisting} /> <RepostButton event={event} canFetch={fetchIfNotExisting} />
<LikeButton event={event} canFetch={fetchIfNotExisting} /> <LikeButton event={event} canFetch={fetchIfNotExisting} />
</div> </div>

View File

@@ -1,14 +1,8 @@
import { useSecondaryPage } from '@/PageManager'
import { toNote } from '@/lib/link'
import { useNostr } from '@/providers/NostrProvider'
import { Event } from 'nostr-tools' import { Event } from 'nostr-tools'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import Content from '../Content' import Content from '../Content'
import { FormattedTimestamp } from '../FormattedTimestamp' import { FormattedTimestamp } from '../FormattedTimestamp'
import LikeButton from '../NoteStats/LikeButton' import NoteStats from '../NoteStats'
import ParentNotePreview from '../ParentNotePreview' import ParentNotePreview from '../ParentNotePreview'
import PostEditor from '../PostEditor'
import UserAvatar from '../UserAvatar' import UserAvatar from '../UserAvatar'
import Username from '../Username' import Username from '../Username'
@@ -23,25 +17,25 @@ export default function ReplyNote({
onClickParent?: (eventId: string) => void onClickParent?: (eventId: string) => void
highlight?: boolean highlight?: boolean
}) { }) {
const { t } = useTranslation()
const { checkLogin } = useNostr()
const { push } = useSecondaryPage()
const [isPostDialogOpen, setIsPostDialogOpen] = useState(false)
return ( return (
<div <div
className={`flex space-x-2 items-start rounded-lg p-2 transition-colors duration-500 clickable ${highlight ? 'bg-highlight/50' : ''}`} className={`flex space-x-2 items-start rounded-lg p-2 transition-colors duration-500 ${highlight ? 'bg-highlight/50' : ''}`}
onClick={() => push(toNote(event.id))}
> >
<UserAvatar userId={event.pubkey} size="small" className="shrink-0" /> <UserAvatar userId={event.pubkey} size="small" className="shrink-0" />
<div className="w-full overflow-hidden space-y-1"> <div className="w-full overflow-hidden">
<div className="flex gap-2 items-center">
<Username <Username
userId={event.pubkey} userId={event.pubkey}
className="text-sm font-semibold text-muted-foreground hover:text-foreground truncate" className="text-sm font-semibold text-muted-foreground hover:text-foreground truncate"
skeletonClassName="h-3" skeletonClassName="h-3"
/> />
<div className="text-xs text-muted-foreground">
<FormattedTimestamp timestamp={event.created_at} />
</div>
</div>
{parentEvent && ( {parentEvent && (
<ParentNotePreview <ParentNotePreview
className="mt-1"
event={parentEvent} event={parentEvent}
onClick={(e) => { onClick={(e) => {
e.stopPropagation() e.stopPropagation()
@@ -49,24 +43,9 @@ export default function ReplyNote({
}} }}
/> />
)} )}
<Content event={event} size="small" /> <Content className="mt-1" event={event} size="small" />
<div className="flex gap-2 text-xs"> <NoteStats className="mt-2" event={event} variant="reply" />
<div className="text-muted-foreground/60">
<FormattedTimestamp timestamp={event.created_at} />
</div> </div>
<div
className="text-muted-foreground hover:text-primary cursor-pointer"
onClick={(e) => {
e.stopPropagation()
checkLogin(() => setIsPostDialogOpen(true))
}}
>
{t('reply')}
</div>
</div>
</div>
<LikeButton event={event} variant="reply" />
<PostEditor parentEvent={event} open={isPostDialogOpen} setOpen={setIsPostDialogOpen} />
</div> </div>
) )
} }