feat: add cache, fix ui
This commit is contained in:
+61
-7
@@ -25,6 +25,7 @@ import { useIntersection } from "@/hooks/useIntersection";
|
||||
import Paragraph from "@/components/paragraph";
|
||||
import { nanoid } from "nanoid";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import SearchInput from "@/components/search-input";
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -36,10 +37,16 @@ type Props = {
|
||||
export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
const { client, isReady } = useWAClient();
|
||||
const router = useHashRouter();
|
||||
const msgContainerRef = useRef<HTMLDivElement>(null!);
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const { data: chats } = useChats();
|
||||
const { data: contacts } = useContacts();
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (chatId) msgContainerRef.current.scrollTop = 0;
|
||||
}, [chatId]);
|
||||
|
||||
const {
|
||||
data: messages,
|
||||
@@ -94,8 +101,26 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
);
|
||||
|
||||
const messageList = useMemo(() => {
|
||||
const q = search.trim().toLowerCase();
|
||||
|
||||
return messages
|
||||
?.filter((i) => !["revoked"].includes(i.type as never))
|
||||
?.filter((i) => {
|
||||
if (["revoked"].includes(i.type as never)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (q) {
|
||||
const body = i.caption || (i.type === "chat" ? i.body : "") || "";
|
||||
const name = getFormattedName(i.from) || "";
|
||||
return (
|
||||
body.toLowerCase().includes(q) ||
|
||||
name.toLowerCase().includes(q) ||
|
||||
i.filename?.toLowerCase().includes(q)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
?.map((i) => {
|
||||
const from = contacts?.find(
|
||||
(c) => getId(c.id) === getId(i.author || i.from),
|
||||
@@ -120,14 +145,26 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
quotedMsg,
|
||||
};
|
||||
});
|
||||
}, [messages, contacts]);
|
||||
}, [messages, contacts, search]);
|
||||
|
||||
function getMentionLabel(username: string) {
|
||||
const data = contacts?.find((c) => (c.id as any).user === username);
|
||||
return data?.notifyName || data?.formattedName || data?.name || username;
|
||||
}
|
||||
|
||||
function onMentionClick(username: string) {
|
||||
const data = contacts?.find((c) => (c.id as any).user === username);
|
||||
if (data) {
|
||||
router.push(`/?chatId=${getId(data.id)}`);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section
|
||||
className={`flex min-w-0 h-full flex-1 flex-col bg-muted ${chatId ? "flex" : "hidden md:flex"}`}
|
||||
>
|
||||
<header className="flex items-center justify-between border-b border-border bg-card px-4 py-3 sm:px-6">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<div className="flex min-w-0 items-center gap-3 w-full">
|
||||
<button
|
||||
aria-label="Back to conversations"
|
||||
onClick={() => router.goBack()}
|
||||
@@ -141,7 +178,7 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
className="size-10"
|
||||
/>
|
||||
|
||||
<div className="min-w-0">
|
||||
<div className="min-w-0 flex-1 truncate">
|
||||
<h2 className="truncate text-sm font-semibold">
|
||||
{chat?.formattedTitle || chat?.name}
|
||||
</h2>
|
||||
@@ -150,6 +187,14 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
{selected.online ? "Online now" : "Active recently"}
|
||||
</p> */}
|
||||
</div>
|
||||
|
||||
<SearchInput
|
||||
className="w-full max-w-40 md:max-w-sm"
|
||||
inputClassName="text-xs placeholder:text-xs"
|
||||
placeholder="Search..."
|
||||
defaultValue={search}
|
||||
onValueChange={setSearch}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className="flex items-center gap-1 text-muted-foreground">
|
||||
<button
|
||||
@@ -173,7 +218,10 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
</div> */}
|
||||
</header>
|
||||
|
||||
<div className="message-pattern flex-1 px-4 py-6 sm:px-8 flex flex-col-reverse overflow-y-auto">
|
||||
<div
|
||||
ref={msgContainerRef}
|
||||
className="message-pattern flex-1 px-4 py-6 sm:px-8 flex flex-col-reverse overflow-y-auto"
|
||||
>
|
||||
{/* <div className="mb-6 flex items-center justify-center gap-2 text-[11px] text-muted-foreground">
|
||||
<span className="h-px flex-1 bg-border" />
|
||||
<span>Today</span>
|
||||
@@ -245,6 +293,8 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
? item.quotedMsg.body
|
||||
: "Quoted")
|
||||
}
|
||||
getMentionLabel={getMentionLabel}
|
||||
onMentionClick={onMentionClick}
|
||||
/>
|
||||
</button>
|
||||
) : null}
|
||||
@@ -257,7 +307,11 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
) : null}
|
||||
|
||||
{item.type === "chat" || item.caption ? (
|
||||
<Paragraph text={item.caption || item.body} />
|
||||
<Paragraph
|
||||
text={item.caption || item.body}
|
||||
getMentionLabel={getMentionLabel}
|
||||
onMentionClick={onMentionClick}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{item.type === "call_log" && (
|
||||
@@ -310,7 +364,7 @@ export default function MessagesSection({ chatId, maxCount = 50 }: Props) {
|
||||
))
|
||||
: null}
|
||||
|
||||
<div ref={endScrollRef} className="h-1" />
|
||||
{messages != null && <div ref={endScrollRef} className="h-1" />}
|
||||
|
||||
<div className="mb-6 flex items-center justify-center gap-2 text-[11px] text-muted-foreground">
|
||||
<span className="h-px flex-1 bg-border" />
|
||||
|
||||
Reference in New Issue
Block a user