mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-29 16:30:55 +00:00
fix: get replies function (#213)
This commit is contained in:
parent
6c26f8967b
commit
f8280ec8ee
@ -1,57 +1,48 @@
|
|||||||
import { Note } from "@/components/note";
|
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 { Box, Container, Spinner } from "@lume/ui";
|
||||||
import { createFileRoute } from "@tanstack/react-router";
|
import { createFileRoute } from "@tanstack/react-router";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
import { WindowVirtualizer } from "virtua";
|
import { WindowVirtualizer } from "virtua";
|
||||||
import { ReplyList } from "./-components/replyList";
|
import { Reply } from "./-components/reply";
|
||||||
|
|
||||||
export const Route = createFileRoute("/events/$eventId")({
|
export const Route = createFileRoute("/events/$eventId")({
|
||||||
beforeLoad: async () => {
|
beforeLoad: async () => {
|
||||||
const settings = await NostrQuery.getUserSettings();
|
const settings = await NostrQuery.getUserSettings();
|
||||||
return { settings };
|
return { settings };
|
||||||
},
|
},
|
||||||
|
loader: async ({ params }) => {
|
||||||
|
const event = await NostrQuery.getEvent(params.eventId);
|
||||||
|
return event;
|
||||||
|
},
|
||||||
component: Screen,
|
component: Screen,
|
||||||
});
|
});
|
||||||
|
|
||||||
function Screen() {
|
function Screen() {
|
||||||
const { eventId } = Route.useParams();
|
const event = Route.useLoaderData();
|
||||||
const { isLoading, isError, data } = useEvent(eventId);
|
|
||||||
|
|
||||||
if (isLoading) {
|
const [reload, setReload] = useState(false);
|
||||||
return (
|
const [replies, setReplies] = useState<LumeEvent[]>(null);
|
||||||
<div className="flex items-center justify-center w-full h-full">
|
|
||||||
<Spinner className="size-5" />
|
useEffect(() => {
|
||||||
</div>
|
let mounted = true;
|
||||||
);
|
|
||||||
|
if (event) {
|
||||||
|
event.getAllReplies().then((data) => {
|
||||||
|
if (mounted) setReplies(data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isError) {
|
return () => {
|
||||||
<div className="flex items-center justify-center w-full h-full">
|
mounted = false;
|
||||||
<p>Not found.</p>
|
};
|
||||||
</div>;
|
}, [event]);
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container withDrag>
|
<Container withDrag>
|
||||||
<Box className="scrollbar-none">
|
<Box className="scrollbar-none">
|
||||||
<WindowVirtualizer>
|
<WindowVirtualizer>
|
||||||
<MainNote data={data} />
|
<Note.Provider event={event}>
|
||||||
{data ? (
|
|
||||||
<ReplyList eventId={eventId} />
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center justify-center w-full h-full">
|
|
||||||
<Spinner className="size-5" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</WindowVirtualizer>
|
|
||||||
</Box>
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function MainNote({ data }: { data: LumeEvent }) {
|
|
||||||
return (
|
|
||||||
<Note.Provider event={data}>
|
|
||||||
<Note.Root>
|
<Note.Root>
|
||||||
<div className="flex items-center justify-between px-3 h-14">
|
<div className="flex items-center justify-between px-3 h-14">
|
||||||
<Note.User />
|
<Note.User />
|
||||||
@ -65,5 +56,27 @@ function MainNote({ data }: { data: LumeEvent }) {
|
|||||||
</div>
|
</div>
|
||||||
</Note.Root>
|
</Note.Root>
|
||||||
</Note.Provider>
|
</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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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 { cn } from "@lume/utils";
|
||||||
import { SubReply } from "./subReply";
|
import { SubReply } from "./subReply";
|
||||||
import { Note } from "@/components/note";
|
|
||||||
|
|
||||||
export function Reply({ event }: { event: EventWithReplies }) {
|
export function Reply({ event }: { event: LumeEvent }) {
|
||||||
return (
|
return (
|
||||||
<Note.Provider event={event}>
|
<Note.Provider event={event}>
|
||||||
<Note.Root className="border-t border-neutral-100 dark:border-neutral-900">
|
<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.User />
|
||||||
<Note.Menu />
|
<Note.Menu />
|
||||||
</div>
|
</div>
|
||||||
<Note.ContentLarge className="px-3" />
|
<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.Reply />
|
||||||
<Note.Repost />
|
<Note.Repost />
|
||||||
<Note.Zap />
|
<Note.Zap />
|
||||||
|
@ -17,6 +17,7 @@ export class LumeEvent {
|
|||||||
public sig: string;
|
public sig: string;
|
||||||
public meta: Meta;
|
public meta: Meta;
|
||||||
public relay?: string;
|
public relay?: string;
|
||||||
|
public replies?: LumeEvent[];
|
||||||
#raw: NostrEvent;
|
#raw: NostrEvent;
|
||||||
|
|
||||||
constructor(event: NostrEvent) {
|
constructor(event: NostrEvent) {
|
||||||
@ -94,20 +95,22 @@ export class LumeEvent {
|
|||||||
return { id, relayHint };
|
return { id, relayHint };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getReplies(id: string) {
|
public async getAllReplies() {
|
||||||
const query = await commands.getReplies(id);
|
const query = await commands.getReplies(this.id);
|
||||||
|
|
||||||
if (query.status === "ok") {
|
if (query.status === "ok") {
|
||||||
const events = query.data.map((item) => {
|
const events = query.data.map((item) => {
|
||||||
const raw = JSON.parse(item.raw) as EventWithReplies;
|
const nostrEvent: NostrEvent = JSON.parse(item.raw);
|
||||||
|
|
||||||
if (item.parsed) {
|
if (item.parsed) {
|
||||||
raw.meta = item.parsed;
|
nostrEvent.meta = item.parsed;
|
||||||
} else {
|
} else {
|
||||||
raw.meta = null;
|
nostrEvent.meta = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return raw;
|
const lumeEvent = new LumeEvent(nostrEvent);
|
||||||
|
|
||||||
|
return lumeEvent;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (events.length > 0) {
|
if (events.length > 0) {
|
||||||
@ -115,7 +118,7 @@ export class LumeEvent {
|
|||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
const tags = event.tags.filter(
|
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) {
|
if (tags.length > 0) {
|
||||||
@ -141,6 +144,9 @@ export class LumeEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return events;
|
return events;
|
||||||
|
} else {
|
||||||
|
console.error(query.error);
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import { LumeEvent } from "./event";
|
|||||||
export class NostrQuery {
|
export class NostrQuery {
|
||||||
static #toLumeEvents(richEvents: RichEvent[]) {
|
static #toLumeEvents(richEvents: RichEvent[]) {
|
||||||
const events = richEvents.map((item) => {
|
const events = richEvents.map((item) => {
|
||||||
const nostrEvent = JSON.parse(item.raw) as NostrEvent;
|
const nostrEvent: NostrEvent = JSON.parse(item.raw);
|
||||||
|
|
||||||
if (item.parsed) {
|
if (item.parsed) {
|
||||||
nostrEvent.meta = item.parsed;
|
nostrEvent.meta = item.parsed;
|
||||||
|
Loading…
Reference in New Issue
Block a user