feat: improve note details page

This commit is contained in:
codytseng
2024-11-08 18:22:41 +08:00
parent 3a3cf6d256
commit 5b0abcf380
8 changed files with 61 additions and 19 deletions

View File

@@ -1,9 +1,11 @@
import { useSecondaryPage } from '@renderer/PageManager'
import { toNote } from '@renderer/lib/link'
import { formatTimestamp } from '@renderer/lib/timestamp'
import { Event } from 'nostr-tools'
import Content from '../Content'
import NoteStats from '../NoteStats'
import UserAvatar from '../UserAvatar'
import Username from '../Username'
import NoteStats from '../NoteStats'
export default function Note({
event,
@@ -33,7 +35,7 @@ export default function Note({
</div>
</div>
{parentEvent && (
<div className="text-xs text-muted-foreground truncate mt-2">
<div className="text-muted-foreground truncate mt-2">
<ParentNote event={parentEvent} />
</div>
)}
@@ -46,8 +48,16 @@ export default function Note({
}
function ParentNote({ event }: { event: Event }) {
const { push } = useSecondaryPage()
return (
<div className="flex space-x-1 items-center text-xs rounded-lg border px-1 bg-muted w-fit max-w-full">
<div
className="flex space-x-1 items-center text-xs rounded-lg px-2 bg-muted w-fit max-w-full hover:text-foreground cursor-pointer"
onClick={(e) => {
e.stopPropagation()
push(toNote(event))
}}
>
<div>reply to</div>
<UserAvatar userId={event.pubkey} size="tiny" />
<div className="truncate">{event.content}</div>

View File

@@ -26,7 +26,7 @@ export default function ShortTextNoteCard({
className={className}
onClick={(e) => {
e.stopPropagation()
push(toNote(rootEvent ?? event))
push(toNote(event))
}}
>
<Card

View File

@@ -0,0 +1,24 @@
import { useSecondaryPage } from '@renderer/PageManager'
import { Card } from '@renderer/components/ui/card'
import { toNote } from '@renderer/lib/link'
import { Event } from 'nostr-tools'
import UserAvatar from '../UserAvatar'
import Username from '../Username'
export default function ParentNote({ event }: { event: Event }) {
const { push } = useSecondaryPage()
return (
<div>
<Card
className="flex space-x-1 p-1 items-center hover:bg-muted/50 cursor-pointer text-xs text-muted-foreground hover:text-foreground"
onClick={() => push(toNote(event))}
>
<UserAvatar userId={event.pubkey} size="tiny" />
<Username userId={event.pubkey} className="font-semibold" />
<div className="truncate">{event.content}</div>
</Card>
<div className="ml-5 w-px h-2 bg-border" />
</div>
)
}

View File

@@ -48,7 +48,7 @@ export default function ReplyNote({
function ParentReplyNote({ event }: { event: Event }) {
return (
<div className="flex space-x-1 items-center text-xs border rounded-lg w-fit px-1 bg-muted max-w-full">
<div className="flex space-x-1 items-center text-xs rounded-lg w-fit px-2 bg-muted max-w-full">
<div>reply to</div>
<UserAvatar userId={event.pubkey} size="tiny" />
<div className="truncate">{event.content}</div>

View File

@@ -56,7 +56,7 @@ export default function ReplyNoteList({ event, className }: { event: Event; clas
const onClickParent = (eventId: string) => {
const ref = replyRefs.current[eventId]
if (ref) {
ref.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' })
ref.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
}
setHighlightReplyId(eventId)
setTimeout(() => {

View File

@@ -13,7 +13,7 @@ const UserAvatarSizeCnMap = {
large: 'w-24 h-24',
normal: 'w-10 h-10',
small: 'w-7 h-7',
tiny: 'w-3 h-3'
tiny: 'w-4 h-4'
}
export default function UserAvatar({

View File

@@ -9,15 +9,17 @@ export function isNsfwEvent(event: Event) {
}
export function isReplyNoteEvent(event: Event) {
return event.kind === kinds.ShortTextNote && event.tags.some(rootETag)
return (
event.kind === kinds.ShortTextNote && event.tags.some((tag) => replyETag(tag) || rootETag(tag))
)
}
export function getParentEventId(event: Event) {
return event.tags.find(replyETag)?.[1]
export function getParentEventId(event?: Event) {
return event?.tags.find(replyETag)?.[1]
}
export function getRootEventId(event: Event) {
return event.tags.find(rootETag)?.[1]
export function getRootEventId(event?: Event) {
return event?.tags.find(rootETag)?.[1]
}
export function isReplaceable(kind: number) {

View File

@@ -1,19 +1,25 @@
import Note from '@renderer/components/Note'
import ParentNote from '@renderer/components/ParentNote'
import ReplyNoteList from '@renderer/components/ReplyNoteList'
import { Separator } from '@renderer/components/ui/separator'
import { useFetchEventById } from '@renderer/hooks'
import SecondaryPageLayout from '@renderer/layouts/SecondaryPageLayout'
import { getParentEventId, getRootEventId } from '@renderer/lib/event'
import { Event } from 'nostr-tools'
export default function NotePage({ event }: { event?: Event }) {
const parentEvent = useFetchEventById(getParentEventId(event))
const rootEvent = useFetchEventById(getRootEventId(event))
if (!event) return null
return (
<SecondaryPageLayout titlebarContent="note">
{event && (
<>
<Note key={`note-${event.id}`} event={event} fetchNoteStats />
<Separator className="mt-2" />
<ReplyNoteList key={`reply-note-list-${event.id}`} event={event} />
</>
)}
{rootEvent && <ParentNote key={`root-note-${event.id}`} event={rootEvent} />}
{parentEvent && <ParentNote key={`parent-note-${event.id}`} event={parentEvent} />}
<Note key={`note-${event.id}`} event={event} fetchNoteStats />
<Separator className="my-2" />
<ReplyNoteList key={`reply-note-list-${event.id}`} event={event} />
</SecondaryPageLayout>
)
}