fix: get replies function (#213)

This commit is contained in:
雨宮蓮 2024-06-19 21:02:33 +07:00 committed by GitHub
parent 6c26f8967b
commit f8280ec8ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 74 additions and 55 deletions

View File

@ -1,69 +1,82 @@
import { Note } from "@/components/note";
import { type LumeEvent, NostrQuery, useEvent } from "@lume/system";
import { type LumeEvent, NostrQuery } from "@lume/system";
import { Box, Container, Spinner } from "@lume/ui";
import { createFileRoute } from "@tanstack/react-router";
import { useEffect, useState } from "react";
import { WindowVirtualizer } from "virtua";
import { ReplyList } from "./-components/replyList";
import { Reply } from "./-components/reply";
export const Route = createFileRoute("/events/$eventId")({
beforeLoad: async () => {
const settings = await NostrQuery.getUserSettings();
return { settings };
},
loader: async ({ params }) => {
const event = await NostrQuery.getEvent(params.eventId);
return event;
},
component: Screen,
});
function Screen() {
const { eventId } = Route.useParams();
const { isLoading, isError, data } = useEvent(eventId);
const event = Route.useLoaderData();
if (isLoading) {
return (
<div className="flex items-center justify-center w-full h-full">
<Spinner className="size-5" />
</div>
);
}
const [reload, setReload] = useState(false);
const [replies, setReplies] = useState<LumeEvent[]>(null);
if (isError) {
<div className="flex items-center justify-center w-full h-full">
<p>Not found.</p>
</div>;
}
useEffect(() => {
let mounted = true;
if (event) {
event.getAllReplies().then((data) => {
if (mounted) setReplies(data);
});
}
return () => {
mounted = false;
};
}, [event]);
return (
<Container withDrag>
<Box className="scrollbar-none">
<WindowVirtualizer>
<MainNote data={data} />
{data ? (
<ReplyList eventId={eventId} />
) : (
<div className="flex items-center justify-center w-full h-full">
<Spinner className="size-5" />
<Note.Provider event={event}>
<Note.Root>
<div className="flex items-center justify-between px-3 h-14">
<Note.User />
<Note.Menu />
</div>
<Note.ContentLarge className="px-3" />
<div className="flex items-center justify-end gap-2 px-3 mt-4 h-11">
<Note.Reply large />
<Note.Repost large />
<Note.Zap large />
</div>
</Note.Root>
</Note.Provider>
<div className="flex flex-col">
<div className="flex items-center px-3 text-sm font-semibold border-t h-11 text-neutral-700 dark:text-neutral-300 border-neutral-100 dark:border-neutral-900">
Replies ({replies?.length ?? 0})
</div>
)}
{!replies ? (
<Spinner />
) : !replies.length ? (
<div className="flex items-center justify-center w-full">
<div className="flex flex-col items-center justify-center gap-2 py-6">
<h3 className="text-3xl">👋</h3>
<p className="leading-none text-neutral-600 dark:text-neutral-400">
Be the first to Reply!
</p>
</div>
</div>
) : (
replies.map((event) => <Reply key={event.id} event={event} />)
)}
</div>
</WindowVirtualizer>
</Box>
</Container>
);
}
function MainNote({ data }: { data: LumeEvent }) {
return (
<Note.Provider event={data}>
<Note.Root>
<div className="flex items-center justify-between px-3 h-14">
<Note.User />
<Note.Menu />
</div>
<Note.ContentLarge className="px-3" />
<div className="flex items-center justify-end gap-2 px-3 mt-4 h-11">
<Note.Reply large />
<Note.Repost large />
<Note.Zap large />
</div>
</Note.Root>
</Note.Provider>
);
}

View File

@ -1,18 +1,18 @@
import type { EventWithReplies } from "@lume/types";
import { Note } from "@/components/note";
import type { LumeEvent } from "@lume/system";
import { cn } from "@lume/utils";
import { SubReply } from "./subReply";
import { Note } from "@/components/note";
export function Reply({ event }: { event: EventWithReplies }) {
export function Reply({ event }: { event: LumeEvent }) {
return (
<Note.Provider event={event}>
<Note.Root className="border-t border-neutral-100 dark:border-neutral-900">
<div className="px-3 h-14 flex items-center justify-between">
<div className="flex items-center justify-between px-3 h-14">
<Note.User />
<Note.Menu />
</div>
<Note.ContentLarge className="px-3" />
<div className="mt-3 flex items-center gap-4 px-3 h-14">
<div className="flex items-center gap-4 px-3 mt-3 h-14">
<Note.Reply />
<Note.Repost />
<Note.Zap />

View File

@ -17,6 +17,7 @@ export class LumeEvent {
public sig: string;
public meta: Meta;
public relay?: string;
public replies?: LumeEvent[];
#raw: NostrEvent;
constructor(event: NostrEvent) {
@ -94,20 +95,22 @@ export class LumeEvent {
return { id, relayHint };
}
public async getReplies(id: string) {
const query = await commands.getReplies(id);
public async getAllReplies() {
const query = await commands.getReplies(this.id);
if (query.status === "ok") {
const events = query.data.map((item) => {
const raw = JSON.parse(item.raw) as EventWithReplies;
const nostrEvent: NostrEvent = JSON.parse(item.raw);
if (item.parsed) {
raw.meta = item.parsed;
nostrEvent.meta = item.parsed;
} else {
raw.meta = null;
nostrEvent.meta = null;
}
return raw;
const lumeEvent = new LumeEvent(nostrEvent);
return lumeEvent;
});
if (events.length > 0) {
@ -115,7 +118,7 @@ export class LumeEvent {
for (const event of events) {
const tags = event.tags.filter(
(el) => el[0] === "e" && el[1] !== id && el[3] !== "mention",
(el) => el[0] === "e" && el[1] !== this.id && el[3] !== "mention",
);
if (tags.length > 0) {
@ -141,6 +144,9 @@ export class LumeEvent {
}
return events;
} else {
console.error(query.error);
return [];
}
}

View File

@ -10,7 +10,7 @@ import { LumeEvent } from "./event";
export class NostrQuery {
static #toLumeEvents(richEvents: RichEvent[]) {
const events = richEvents.map((item) => {
const nostrEvent = JSON.parse(item.raw) as NostrEvent;
const nostrEvent: NostrEvent = JSON.parse(item.raw);
if (item.parsed) {
nostrEvent.meta = item.parsed;