feat: improve note details page
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
|
import { useSecondaryPage } from '@renderer/PageManager'
|
||||||
|
import { toNote } from '@renderer/lib/link'
|
||||||
import { formatTimestamp } from '@renderer/lib/timestamp'
|
import { formatTimestamp } from '@renderer/lib/timestamp'
|
||||||
import { Event } from 'nostr-tools'
|
import { Event } from 'nostr-tools'
|
||||||
import Content from '../Content'
|
import Content from '../Content'
|
||||||
|
import NoteStats from '../NoteStats'
|
||||||
import UserAvatar from '../UserAvatar'
|
import UserAvatar from '../UserAvatar'
|
||||||
import Username from '../Username'
|
import Username from '../Username'
|
||||||
import NoteStats from '../NoteStats'
|
|
||||||
|
|
||||||
export default function Note({
|
export default function Note({
|
||||||
event,
|
event,
|
||||||
@@ -33,7 +35,7 @@ export default function Note({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{parentEvent && (
|
{parentEvent && (
|
||||||
<div className="text-xs text-muted-foreground truncate mt-2">
|
<div className="text-muted-foreground truncate mt-2">
|
||||||
<ParentNote event={parentEvent} />
|
<ParentNote event={parentEvent} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -46,8 +48,16 @@ export default function Note({
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ParentNote({ event }: { event: Event }) {
|
function ParentNote({ event }: { event: Event }) {
|
||||||
|
const { push } = useSecondaryPage()
|
||||||
|
|
||||||
return (
|
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>
|
<div>reply to</div>
|
||||||
<UserAvatar userId={event.pubkey} size="tiny" />
|
<UserAvatar userId={event.pubkey} size="tiny" />
|
||||||
<div className="truncate">{event.content}</div>
|
<div className="truncate">{event.content}</div>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default function ShortTextNoteCard({
|
|||||||
className={className}
|
className={className}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
push(toNote(rootEvent ?? event))
|
push(toNote(event))
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Card
|
<Card
|
||||||
|
|||||||
24
src/renderer/src/components/ParentNote/index.tsx
Normal file
24
src/renderer/src/components/ParentNote/index.tsx
Normal 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>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ export default function ReplyNote({
|
|||||||
|
|
||||||
function ParentReplyNote({ event }: { event: Event }) {
|
function ParentReplyNote({ event }: { event: Event }) {
|
||||||
return (
|
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>
|
<div>reply to</div>
|
||||||
<UserAvatar userId={event.pubkey} size="tiny" />
|
<UserAvatar userId={event.pubkey} size="tiny" />
|
||||||
<div className="truncate">{event.content}</div>
|
<div className="truncate">{event.content}</div>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export default function ReplyNoteList({ event, className }: { event: Event; clas
|
|||||||
const onClickParent = (eventId: string) => {
|
const onClickParent = (eventId: string) => {
|
||||||
const ref = replyRefs.current[eventId]
|
const ref = replyRefs.current[eventId]
|
||||||
if (ref) {
|
if (ref) {
|
||||||
ref.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' })
|
ref.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
|
||||||
}
|
}
|
||||||
setHighlightReplyId(eventId)
|
setHighlightReplyId(eventId)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const UserAvatarSizeCnMap = {
|
|||||||
large: 'w-24 h-24',
|
large: 'w-24 h-24',
|
||||||
normal: 'w-10 h-10',
|
normal: 'w-10 h-10',
|
||||||
small: 'w-7 h-7',
|
small: 'w-7 h-7',
|
||||||
tiny: 'w-3 h-3'
|
tiny: 'w-4 h-4'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function UserAvatar({
|
export default function UserAvatar({
|
||||||
|
|||||||
@@ -9,15 +9,17 @@ export function isNsfwEvent(event: Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isReplyNoteEvent(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) {
|
export function getParentEventId(event?: Event) {
|
||||||
return event.tags.find(replyETag)?.[1]
|
return event?.tags.find(replyETag)?.[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRootEventId(event: Event) {
|
export function getRootEventId(event?: Event) {
|
||||||
return event.tags.find(rootETag)?.[1]
|
return event?.tags.find(rootETag)?.[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isReplaceable(kind: number) {
|
export function isReplaceable(kind: number) {
|
||||||
|
|||||||
@@ -1,19 +1,25 @@
|
|||||||
import Note from '@renderer/components/Note'
|
import Note from '@renderer/components/Note'
|
||||||
|
import ParentNote from '@renderer/components/ParentNote'
|
||||||
import ReplyNoteList from '@renderer/components/ReplyNoteList'
|
import ReplyNoteList from '@renderer/components/ReplyNoteList'
|
||||||
import { Separator } from '@renderer/components/ui/separator'
|
import { Separator } from '@renderer/components/ui/separator'
|
||||||
|
import { useFetchEventById } from '@renderer/hooks'
|
||||||
import SecondaryPageLayout from '@renderer/layouts/SecondaryPageLayout'
|
import SecondaryPageLayout from '@renderer/layouts/SecondaryPageLayout'
|
||||||
|
import { getParentEventId, getRootEventId } from '@renderer/lib/event'
|
||||||
import { Event } from 'nostr-tools'
|
import { Event } from 'nostr-tools'
|
||||||
|
|
||||||
export default function NotePage({ event }: { event?: Event }) {
|
export default function NotePage({ event }: { event?: Event }) {
|
||||||
|
const parentEvent = useFetchEventById(getParentEventId(event))
|
||||||
|
const rootEvent = useFetchEventById(getRootEventId(event))
|
||||||
|
|
||||||
|
if (!event) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SecondaryPageLayout titlebarContent="note">
|
<SecondaryPageLayout titlebarContent="note">
|
||||||
{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 />
|
<Note key={`note-${event.id}`} event={event} fetchNoteStats />
|
||||||
<Separator className="mt-2" />
|
<Separator className="my-2" />
|
||||||
<ReplyNoteList key={`reply-note-list-${event.id}`} event={event} />
|
<ReplyNoteList key={`reply-note-list-${event.id}`} event={event} />
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</SecondaryPageLayout>
|
</SecondaryPageLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user