mirror of
https://github.com/luminous-devs/lume.git
synced 2024-10-02 18:00:47 +00:00
fix all dms bugs
This commit is contained in:
parent
077712cf43
commit
6725dca807
@ -1,5 +1,5 @@
|
|||||||
import { NDKEvent, NDKSubscription } from '@nostr-dev-kit/ndk';
|
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 { useCallback, useEffect, useRef } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { VList, VListHandle } from 'virtua';
|
import { VList, VListHandle } from 'virtua';
|
||||||
@ -16,8 +16,6 @@ import { User } from '@shared/user';
|
|||||||
import { useNostr } from '@utils/hooks/useNostr';
|
import { useNostr } from '@utils/hooks/useNostr';
|
||||||
|
|
||||||
export function ChatScreen() {
|
export function ChatScreen() {
|
||||||
const listRef = useRef<VListHandle>(null);
|
|
||||||
|
|
||||||
const { db } = useStorage();
|
const { db } = useStorage();
|
||||||
const { ndk } = useNDK();
|
const { ndk } = useNDK();
|
||||||
const { pubkey } = useParams();
|
const { pubkey } = useParams();
|
||||||
@ -30,10 +28,39 @@ export function ChatScreen() {
|
|||||||
refetchOnWindowFocus: false,
|
refetchOnWindowFocus: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const listRef = useRef<VListHandle>(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(
|
const renderItem = useCallback(
|
||||||
(message: NDKEvent) => {
|
(message: NDKEvent) => {
|
||||||
return (
|
return (
|
||||||
<ChatMessage message={message} self={message.pubkey === db.account.pubkey} />
|
<ChatMessage
|
||||||
|
key={message.id}
|
||||||
|
message={message}
|
||||||
|
isSelf={message.pubkey === db.account.pubkey}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
[data]
|
[data]
|
||||||
@ -57,7 +84,7 @@ export function ChatScreen() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
sub.addListener('event', (event) => {
|
sub.addListener('event', (event) => {
|
||||||
console.log(event);
|
newMessage.mutate(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@ -96,11 +123,7 @@ export function ChatScreen() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="shrink-0 rounded-b-lg border-t border-neutral-300 bg-neutral-200 p-3 dark:border-neutral-700 dark:bg-neutral-800">
|
<div className="shrink-0 rounded-b-lg border-t border-neutral-300 bg-neutral-200 p-3 dark:border-neutral-700 dark:bg-neutral-800">
|
||||||
<ChatForm
|
<ChatForm receiverPubkey={pubkey} />
|
||||||
receiverPubkey={pubkey}
|
|
||||||
userPubkey={db.account.pubkey}
|
|
||||||
userPrivkey={''}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
|
import { NDKEvent, NDKKind, NDKUser } from '@nostr-dev-kit/ndk';
|
||||||
import { nip04 } from 'nostr-tools';
|
import { useState } from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { toast } from 'sonner';
|
||||||
|
|
||||||
import { MediaUploader } from '@app/chats/components/mediaUploader';
|
import { MediaUploader } from '@app/chats/components/mediaUploader';
|
||||||
|
|
||||||
@ -8,34 +8,26 @@ import { useNDK } from '@libs/ndk/provider';
|
|||||||
|
|
||||||
import { EnterIcon } from '@shared/icons';
|
import { EnterIcon } from '@shared/icons';
|
||||||
|
|
||||||
export function ChatForm({
|
export function ChatForm({ receiverPubkey }: { receiverPubkey: string }) {
|
||||||
receiverPubkey,
|
|
||||||
userPrivkey,
|
|
||||||
}: {
|
|
||||||
receiverPubkey: string;
|
|
||||||
userPubkey: string;
|
|
||||||
userPrivkey: string;
|
|
||||||
}) {
|
|
||||||
const { ndk } = useNDK();
|
const { ndk } = useNDK();
|
||||||
const [value, setValue] = useState('');
|
const [value, setValue] = useState('');
|
||||||
|
|
||||||
const encryptMessage = useCallback(async () => {
|
|
||||||
return await nip04.encrypt(userPrivkey, receiverPubkey, value);
|
|
||||||
}, [receiverPubkey, value]);
|
|
||||||
|
|
||||||
const submit = async () => {
|
const submit = async () => {
|
||||||
const message = await encryptMessage();
|
try {
|
||||||
const tags = [['p', receiverPubkey]];
|
const recipient = new NDKUser({ pubkey: receiverPubkey });
|
||||||
|
const message = await ndk.signer.encrypt(recipient, value);
|
||||||
|
|
||||||
const event = new NDKEvent(ndk);
|
const event = new NDKEvent(ndk);
|
||||||
event.content = message;
|
event.content = message;
|
||||||
event.kind = NDKKind.EncryptedDirectMessage;
|
event.kind = NDKKind.EncryptedDirectMessage;
|
||||||
event.tags = tags;
|
event.tag(recipient);
|
||||||
|
|
||||||
await event.publish();
|
const publish = await event.publish();
|
||||||
|
|
||||||
// reset state
|
if (publish) setValue('');
|
||||||
setValue('');
|
} catch (e) {
|
||||||
|
toast.error(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEnterPress = (e: {
|
const handleEnterPress = (e: {
|
||||||
@ -61,7 +53,7 @@ export function ChatForm({
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
autoCapitalize="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"
|
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"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
@ -3,14 +3,14 @@ import { twMerge } from 'tailwind-merge';
|
|||||||
|
|
||||||
import { useDecryptMessage } from '@app/chats/hooks/useDecryptMessage';
|
import { useDecryptMessage } from '@app/chats/hooks/useDecryptMessage';
|
||||||
|
|
||||||
export function ChatMessage({ message, self }: { message: NDKEvent; self: boolean }) {
|
export function ChatMessage({ message, isSelf }: { message: NDKEvent; isSelf: boolean }) {
|
||||||
const decryptedContent = useDecryptMessage(message);
|
const decryptedContent = useDecryptMessage(message);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'my-2 w-max max-w-[400px] rounded-t-xl px-3 py-3',
|
'my-2 w-max max-w-[400px] rounded-t-xl px-3 py-3',
|
||||||
self
|
isSelf
|
||||||
? 'ml-auto rounded-l-xl bg-blue-500 text-white'
|
? 'ml-auto rounded-l-xl bg-blue-500 text-white'
|
||||||
: 'rounded-r-xl bg-neutral-200 text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100'
|
: 'rounded-r-xl bg-neutral-200 text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100'
|
||||||
)}
|
)}
|
||||||
@ -18,9 +18,7 @@ export function ChatMessage({ message, self }: { message: NDKEvent; self: boolea
|
|||||||
{!decryptedContent ? (
|
{!decryptedContent ? (
|
||||||
<p>Decrypting...</p>
|
<p>Decrypting...</p>
|
||||||
) : (
|
) : (
|
||||||
<div>
|
<p className="select-text whitespace-pre-line break-all">{decryptedContent}</p>
|
||||||
<p className="select-text whitespace-pre-line">{decryptedContent}</p>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
import { NDKEvent } from '@nostr-dev-kit/ndk';
|
||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { ChatListItem } from '@app/chats/components/chatListItem';
|
import { ChatListItem } from '@app/chats/components/chatListItem';
|
||||||
|
|
||||||
|
import { useNDK } from '@libs/ndk/provider';
|
||||||
|
|
||||||
import { LoaderIcon } from '@shared/icons';
|
import { LoaderIcon } from '@shared/icons';
|
||||||
|
|
||||||
import { useNostr } from '@utils/hooks/useNostr';
|
import { useNostr } from '@utils/hooks/useNostr';
|
||||||
|
|
||||||
export function ChatsScreen() {
|
export function ChatsScreen() {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const { ndk } = useNDK();
|
||||||
const { getAllNIP04Chats } = useNostr();
|
const { getAllNIP04Chats } = useNostr();
|
||||||
const { status, data } = useQuery({
|
const { status, data } = useQuery({
|
||||||
queryKey: ['nip04-chats'],
|
queryKey: ['nip04-chats'],
|
||||||
@ -29,6 +34,10 @@ export function ChatsScreen() {
|
|||||||
[data]
|
[data]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!ndk.signer) navigate('/new/privkey');
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full grid-cols-3">
|
<div className="grid h-full w-full grid-cols-3">
|
||||||
<div className="col-span-1 h-full overflow-y-auto border-r border-neutral-200 scrollbar-none dark:border-neutral-800">
|
<div className="col-span-1 h-full overflow-y-auto border-r border-neutral-200 scrollbar-none dark:border-neutral-800">
|
||||||
|
Loading…
Reference in New Issue
Block a user