diff --git a/src/app/chats/chat.tsx b/src/app/chats/chat.tsx index 243cbae9..4767cc6f 100644 --- a/src/app/chats/chat.tsx +++ b/src/app/chats/chat.tsx @@ -1,5 +1,5 @@ import { NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk'; -import { useQuery } from '@tanstack/react-query'; +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { useCallback, useEffect, useRef } from 'react'; import { useParams } from 'react-router-dom'; import { VList, VListHandle } from 'virtua'; @@ -16,8 +16,6 @@ import { User } from '@shared/user'; import { useNostr } from '@utils/hooks/useNostr'; export function ChatScreen() { - const listRef = useRef(null); - const { db } = useStorage(); const { ndk } = useNDK(); const { pubkey } = useParams(); @@ -30,10 +28,39 @@ export function ChatScreen() { refetchOnWindowFocus: false, }); + const queryClient = useQueryClient(); + const listRef = useRef(null); + + const newMessage = useMutation({ + mutationFn: async (event: NDKEvent) => { + // Cancel any outgoing refetches + await queryClient.cancelQueries({ queryKey: ['nip04-dm', pubkey] }); + + // Snapshot the previous value + const prevMessages = queryClient.getQueryData(['nip04-dm', pubkey]); + + // Optimistically update to the new value + queryClient.setQueryData(['nip04-dm', pubkey], (prev: NDKEvent[]) => [ + ...prev, + event, + ]); + + // Return a context object with the snapshotted value + return { prevMessages }; + }, + onSettled: () => { + queryClient.invalidateQueries({ queryKey: ['nip04-dm', pubkey] }); + }, + }); + const renderItem = useCallback( (message: NDKEvent) => { return ( - + ); }, [data] @@ -57,7 +84,7 @@ export function ChatScreen() { ); sub.addListener('event', (event) => { - console.log(event); + newMessage.mutate(event); }); return () => { @@ -96,11 +123,7 @@ export function ChatScreen() { )}
- +
diff --git a/src/app/chats/components/chatForm.tsx b/src/app/chats/components/chatForm.tsx index ace68a08..3cf6c4d0 100644 --- a/src/app/chats/components/chatForm.tsx +++ b/src/app/chats/components/chatForm.tsx @@ -1,6 +1,6 @@ -import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk'; -import { nip04 } from 'nostr-tools'; -import { useCallback, useState } from 'react'; +import { NDKEvent, NDKKind, NDKUser } from '@nostr-dev-kit/ndk'; +import { useState } from 'react'; +import { toast } from 'sonner'; import { MediaUploader } from '@app/chats/components/mediaUploader'; @@ -8,34 +8,26 @@ import { useNDK } from '@libs/ndk/provider'; import { EnterIcon } from '@shared/icons'; -export function ChatForm({ - receiverPubkey, - userPrivkey, -}: { - receiverPubkey: string; - userPubkey: string; - userPrivkey: string; -}) { +export function ChatForm({ receiverPubkey }: { receiverPubkey: string }) { const { ndk } = useNDK(); const [value, setValue] = useState(''); - const encryptMessage = useCallback(async () => { - return await nip04.encrypt(userPrivkey, receiverPubkey, value); - }, [receiverPubkey, value]); - const submit = async () => { - const message = await encryptMessage(); - const tags = [['p', receiverPubkey]]; + try { + const recipient = new NDKUser({ pubkey: receiverPubkey }); + const message = await ndk.signer.encrypt(recipient, value); - const event = new NDKEvent(ndk); - event.content = message; - event.kind = NDKKind.EncryptedDirectMessage; - event.tags = tags; + const event = new NDKEvent(ndk); + event.content = message; + event.kind = NDKKind.EncryptedDirectMessage; + event.tag(recipient); - await event.publish(); + const publish = await event.publish(); - // reset state - setValue(''); + if (publish) setValue(''); + } catch (e) { + toast.error(e); + } }; const handleEnterPress = (e: { @@ -61,7 +53,7 @@ export function ChatForm({ autoComplete="off" autoCorrect="off" autoCapitalize="off" - placeholder="Message" + placeholder="Message..." className="h-10 flex-1 resize-none bg-transparent px-3 text-neutral-900 placeholder:text-neutral-600 focus:outline-none dark:text-neutral-100 dark:placeholder:text-neutral-300" />