mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-19 19:46:34 +00:00
add unknown chats modal
This commit is contained in:
parent
1362dfadda
commit
a4e03a59eb
@ -1,15 +1,15 @@
|
|||||||
import { useQuery } from '@tanstack/react-query';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { ChatsListItem } from '@app/chats/components/item';
|
import { ChatsListItem } from '@app/chats/components/item';
|
||||||
import { NewMessageModal } from '@app/chats/components/modal';
|
import { NewMessageModal } from '@app/chats/components/modal';
|
||||||
import { ChatsListSelfItem } from '@app/chats/components/self';
|
import { ChatsListSelfItem } from '@app/chats/components/self';
|
||||||
|
import { UnknownsModal } from '@app/chats/components/unknowns';
|
||||||
|
|
||||||
import { getChats } from '@libs/storage';
|
import { getChats } from '@libs/storage';
|
||||||
|
|
||||||
import { StrangersIcon } from '@shared/icons';
|
|
||||||
|
|
||||||
import { useAccount } from '@utils/hooks/useAccount';
|
import { useAccount } from '@utils/hooks/useAccount';
|
||||||
import { compactNumber } from '@utils/number';
|
import { Chats } from '@utils/types';
|
||||||
|
|
||||||
export function ChatsList() {
|
export function ChatsList() {
|
||||||
const { account } = useAccount();
|
const { account } = useAccount();
|
||||||
@ -21,6 +21,15 @@ export function ChatsList() {
|
|||||||
return await getChats();
|
return await getChats();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const renderItem = useCallback(
|
||||||
|
(item: Chats) => {
|
||||||
|
if (account.pubkey !== item.sender_pubkey) {
|
||||||
|
return <ChatsListItem key={item.sender_pubkey} data={item} />;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[chats]
|
||||||
|
);
|
||||||
|
|
||||||
if (status === 'loading') {
|
if (status === 'loading') {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
@ -46,24 +55,8 @@ export function ChatsList() {
|
|||||||
<div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" />
|
<div className="h-3 w-full animate-pulse rounded-sm bg-zinc-800" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{chats.follows.map((item) => {
|
{chats.follows.map((item) => renderItem(item))}
|
||||||
if (account.pubkey !== item.sender_pubkey) {
|
{chats.unknowns.length > 0 && <UnknownsModal data={chats.unknowns} />}
|
||||||
return <ChatsListItem key={item.sender_pubkey} data={item} />;
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5"
|
|
||||||
>
|
|
||||||
<div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900">
|
|
||||||
<StrangersIcon className="h-3 w-3 text-zinc-200" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h5 className="font-medium text-zinc-400">
|
|
||||||
{compactNumber.format(chats.unknown)} strangers
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
<NewMessageModal />
|
<NewMessageModal />
|
||||||
{isFetching && (
|
{isFetching && (
|
||||||
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5">
|
<div className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5">
|
||||||
|
@ -78,9 +78,9 @@ export function NewMessageModal() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={closeModal}
|
onClick={closeModal}
|
||||||
className="inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-900"
|
className="inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-800"
|
||||||
>
|
>
|
||||||
<CancelIcon width={20} height={20} className="text-zinc-300" />
|
<CancelIcon className="h-4 w-4 text-zinc-300" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<Dialog.Description className="text-sm leading-tight text-zinc-400">
|
<Dialog.Description className="text-sm leading-tight text-zinc-400">
|
||||||
@ -104,7 +104,7 @@ export function NewMessageModal() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => openChat(follow)}
|
onClick={() => openChat(follow)}
|
||||||
className="inline-flex w-max translate-x-20 transform rounded border-t border-zinc-600/50 bg-zinc-700 px-3 py-1.5 text-sm transition-transform duration-150 ease-in-out hover:bg-fuchsia-500 group-hover:translate-x-0"
|
className="hidden w-max rounded-md bg-zinc-700 px-3 py-1 text-sm font-medium hover:bg-fuchsia-500 group-hover:inline-flex"
|
||||||
>
|
>
|
||||||
Chat
|
Chat
|
||||||
</button>
|
</button>
|
||||||
|
117
src/app/chats/components/unknowns.tsx
Normal file
117
src/app/chats/components/unknowns.tsx
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import { Dialog, Transition } from '@headlessui/react';
|
||||||
|
import { Fragment, useState } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { User } from '@app/auth/components/user';
|
||||||
|
|
||||||
|
import { CancelIcon, StrangersIcon } from '@shared/icons';
|
||||||
|
|
||||||
|
import { compactNumber } from '@utils/number';
|
||||||
|
import { Chats } from '@utils/types';
|
||||||
|
|
||||||
|
export function UnknownsModal({ data }: { data: Chats[] }) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openModal = () => {
|
||||||
|
setIsOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const openChat = (pubkey: string) => {
|
||||||
|
closeModal();
|
||||||
|
navigate(`/app/chats/${pubkey}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => openModal()}
|
||||||
|
className="inline-flex h-9 items-center gap-2.5 rounded-md px-2.5"
|
||||||
|
>
|
||||||
|
<div className="inline-flex h-6 w-6 shrink-0 items-center justify-center rounded border-t border-zinc-800/50 bg-zinc-900">
|
||||||
|
<StrangersIcon className="h-3 w-3 text-zinc-200" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h5 className="font-medium text-zinc-400">
|
||||||
|
{compactNumber.format(data.length)} unknowns
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<Transition appear show={isOpen} as={Fragment}>
|
||||||
|
<Dialog as="div" className="relative z-10" onClose={closeModal}>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="fixed inset-0 z-50 bg-black bg-opacity-30 backdrop-blur-md" />
|
||||||
|
</Transition.Child>
|
||||||
|
<div className="fixed inset-0 z-50 flex min-h-full items-center justify-center">
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0 scale-95"
|
||||||
|
enterTo="opacity-100 scale-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100 scale-100"
|
||||||
|
leaveTo="opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<Dialog.Panel className="relative flex h-min w-full max-w-lg flex-col gap-2 rounded-lg border-t border-zinc-800/50 bg-zinc-900">
|
||||||
|
<div className="h-min w-full shrink-0 border-b border-zinc-800 px-5 py-5">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Dialog.Title
|
||||||
|
as="h3"
|
||||||
|
className="text-lg font-semibold leading-none text-zinc-100"
|
||||||
|
>
|
||||||
|
{data.length} unknowns
|
||||||
|
</Dialog.Title>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={closeModal}
|
||||||
|
className="inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-800"
|
||||||
|
>
|
||||||
|
<CancelIcon className="h-4 w-4 text-zinc-300" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Dialog.Description className="text-sm leading-tight text-zinc-400">
|
||||||
|
All messages from people you not follow
|
||||||
|
</Dialog.Description>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex h-[500px] flex-col overflow-y-auto overflow-x-hidden pb-5">
|
||||||
|
{data.map((user) => (
|
||||||
|
<div
|
||||||
|
key={user.event_id}
|
||||||
|
className="group flex items-center justify-between px-4 py-3 hover:bg-zinc-800"
|
||||||
|
>
|
||||||
|
<User pubkey={user.sender_pubkey} />
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => openChat(user.sender_pubkey)}
|
||||||
|
className="hidden w-max rounded-md bg-zinc-700 px-3 py-1 text-sm font-medium hover:bg-fuchsia-500 group-hover:inline-flex"
|
||||||
|
>
|
||||||
|
Chat
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Dialog.Panel>
|
||||||
|
</Transition.Child>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</Transition>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
@ -308,9 +308,9 @@ export async function getChats() {
|
|||||||
const follows =
|
const follows =
|
||||||
typeof account.follows === 'string' ? JSON.parse(account.follows) : account.follows;
|
typeof account.follows === 'string' ? JSON.parse(account.follows) : account.follows;
|
||||||
|
|
||||||
const chats: { follows: Array<Chats> | null; unknown: number } = {
|
const chats: { follows: Array<Chats> | null; unknowns: Array<Chats> | null } = {
|
||||||
follows: [],
|
follows: [],
|
||||||
unknown: 0,
|
unknowns: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
let result: Array<Chats> = await db.select(
|
let result: Array<Chats> = await db.select(
|
||||||
@ -326,7 +326,9 @@ export async function getChats() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
chats.unknown = result.length - chats.follows.length;
|
chats.unknowns = result.filter(
|
||||||
|
(el) => !chats.follows.includes(el) && el.sender_pubkey !== account.pubkey
|
||||||
|
);
|
||||||
|
|
||||||
return chats;
|
return chats;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user