feat: improve query message

This commit is contained in:
reya
2024-07-25 16:43:26 +07:00
parent 005cbeab72
commit 89a6883dbe
21 changed files with 313 additions and 280 deletions

View File

@@ -1,5 +1,5 @@
import { commands } from "@/commands";
import { cn, getReceivers, time } from "@/commons";
import { cn, getReceivers, time, useRelays } from "@/commons";
import { Spinner } from "@/components/spinner";
import { ArrowUp, CloudArrowUp, Paperclip } from "@phosphor-icons/react";
import * as ScrollArea from "@radix-ui/react-scroll-area";
@@ -23,14 +23,17 @@ export const Route = createLazyFileRoute("/$account/chats/$id")({
function Screen() {
const { id } = Route.useParams();
const { isLoading, data: relays } = useRelays(id);
useEffect(() => {
commands.subscribeTo(id).then(() => console.log("sub: ", id));
if (!isLoading && relays?.length)
commands.subscribeTo(id, relays).then(() => console.log("sub: ", id));
return () => {
commands.unsubscribe(id).then(() => console.log("unsub: ", id));
if (!isLoading && relays?.length)
commands.unsubscribe(id).then(() => console.log("unsub: ", id));
};
}, []);
}, [isLoading, relays]);
return (
<div className="size-full flex flex-col">
@@ -43,6 +46,7 @@ function Screen() {
function List() {
const { account, id } = Route.useParams();
const { isLoading: rl, isError: rE } = useRelays(id);
const { isLoading, isError, data } = useQuery({
queryKey: ["chats", id],
queryFn: async () => {
@@ -59,18 +63,20 @@ function List() {
throw new Error(res.error);
}
},
enabled: !rl && !rE,
refetchOnWindowFocus: false,
});
const queryClient = useQueryClient();
const ref = useRef<HTMLDivElement>(null);
const renderItem = useCallback(
(item: NostrEvent) => {
(item: NostrEvent, idx: number) => {
const self = account === item.pubkey;
return (
<div
key={item.id}
key={idx + item.id}
className="flex items-center justify-between gap-3 my-1.5 px-3 border-l-2 border-transparent hover:border-blue-400"
>
<div
@@ -139,12 +145,21 @@ function List() {
className="relative h-full py-2 [&>div]:!flex [&>div]:flex-col [&>div]:justify-end [&>div]:min-h-full"
>
<Virtualizer scrollRef={ref} shift>
{isLoading ? (
<p>Loading...</p>
) : isError || !data ? (
<p>Error</p>
{isLoading || !data ? (
<div className="w-full h-56 flex items-center justify-center">
<div className="flex items-center gap-1.5">
<Spinner />
Loading message...
</div>
</div>
) : isError ? (
<div className="w-full h-56 flex items-center justify-center">
<div className="flex items-center gap-1.5">
Cannot load message. Please try again later.
</div>
</div>
) : (
data.map((item) => renderItem(item))
data.map((item, idx) => renderItem(item, idx))
)}
</Virtualizer>
</ScrollArea.Viewport>
@@ -161,25 +176,7 @@ function List() {
function Form() {
const { id } = Route.useParams();
const {
isLoading,
isError,
data: relays,
} = useQuery({
queryKey: ["inboxes", id],
queryFn: async () => {
const res = await commands.getInboxes(id);
if (res.status === "ok") {
return res.data;
} else {
throw new Error(res.error);
}
},
refetchOnWindowFocus: false,
refetchOnMount: false,
refetchOnReconnect: false,
});
const { isLoading, isError, data: relays } = useRelays(id);
const [newMessage, setNewMessage] = useState("");
const [isPending, startTransition] = useTransition();

View File

@@ -80,27 +80,40 @@ function ChatList() {
throw new Error(res.error);
}
},
refetchOnWindowFocus: false,
});
const queryClient = useQueryClient();
useEffect(() => {
const unlisten = listen("synchronized", async () => {
await queryClient.refetchQueries({ queryKey: ["chats"] });
});
return () => {
unlisten.then((f) => f());
};
}, []);
useEffect(() => {
const unlisten = listen<Payload>("event", async (data) => {
const event: NostrEvent = JSON.parse(data.payload.event);
const chats: NostrEvent[] = await queryClient.getQueryData(["chats"]);
const exist = chats.find((ev) => ev.pubkey === event.pubkey);
if (!exist) {
await queryClient.setQueryData(
["chats"],
(prevEvents: NostrEvent[]) => {
if (!prevEvents) return prevEvents;
if (event.pubkey === account) return;
if (chats) {
const exist = chats.find((ev) => ev.pubkey === event.pubkey);
return [event, ...prevEvents];
// queryClient.invalidateQueries(['chats', id]);
},
);
if (!exist) {
await queryClient.setQueryData(
["chats"],
(prevEvents: NostrEvent[]) => {
if (!prevEvents) return prevEvents;
if (event.pubkey === account) return;
return [event, ...prevEvents];
},
);
}
}
});

View File

@@ -0,0 +1,14 @@
import { createLazyFileRoute } from "@tanstack/react-router";
import { CoopIcon } from "@/icons/coop";
export const Route = createLazyFileRoute("/$account/chats/new")({
component: Screen,
});
function Screen() {
return (
<div className="size-full flex items-center justify-center">
<CoopIcon className="size-10 text-neutral-200 dark:text-neutral-800" />
</div>
);
}

View File

@@ -82,7 +82,7 @@ function Screen() {
type="button"
onClick={() => submit()}
disabled={isPending}
className="inline-flex items-center justify-center w-full h-10 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50"
className="inline-flex items-center justify-center w-full h-9 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50"
>
{isPending ? <Spinner /> : "Continue"}
</button>

View File

@@ -90,7 +90,7 @@ function Screen() {
type="button"
onClick={() => submit()}
disabled={isPending}
className="inline-flex items-center justify-center w-full h-10 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50"
className="inline-flex items-center justify-center w-full h-9 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50"
>
{isPending ? <Spinner /> : "Continue"}
</button>

View File

@@ -49,7 +49,7 @@ function Screen() {
if (res.status === "ok") {
navigate({
to: "/$account/chats",
to: "/$account/chats/new",
params: { account: res.data },
replace: true,
});

View File

@@ -16,13 +16,13 @@ function Screen() {
<div className="flex flex-col gap-3">
<Link
to="/create-account"
className="w-full h-10 bg-blue-500 hover:bg-blue-600 text-white rounded-lg inline-flex items-center justify-center shadow"
className="w-full h-9 bg-blue-500 hover:bg-blue-600 text-white rounded-lg inline-flex items-center justify-center shadow"
>
Create a new identity
</Link>
<Link
to="/nostr-connect"
className="w-full h-10 bg-white hover:bg-neutral-100 dark:hover:bg-neutral-950 dark:bg-neutral-900 rounded-lg inline-flex items-center justify-center"
className="w-full h-9 bg-white hover:bg-neutral-100 dark:hover:bg-neutral-950 dark:bg-neutral-900 rounded-lg inline-flex items-center justify-center"
>
Login with Nostr Connect
</Link>

View File

@@ -76,7 +76,7 @@ function Screen() {
type="button"
onClick={() => submit()}
disabled={isPending}
className="inline-flex items-center justify-center w-full h-10 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50"
className="inline-flex items-center justify-center w-full h-9 text-sm font-semibold text-white bg-blue-500 rounded-lg shrink-0 hover:bg-blue-600 disabled:opacity-50"
>
{isPending ? <Spinner /> : "Continue"}
</button>