diff --git a/web/src/pages/ChatsPage.tsx b/web/src/pages/ChatsPage.tsx index feefa52..a350c80 100644 --- a/web/src/pages/ChatsPage.tsx +++ b/web/src/pages/ChatsPage.tsx @@ -3,6 +3,8 @@ import { ChatList } from "../components/ChatList"; import { ChatInfoPanel } from "../components/ChatInfoPanel"; import { MessageComposer } from "../components/MessageComposer"; import { MessageList } from "../components/MessageList"; +import { searchMessages } from "../api/chats"; +import type { Message } from "../chat/types"; import { useRealtime } from "../hooks/useRealtime"; import { useAuthStore } from "../store/authStore"; import { useChatStore } from "../store/chatStore"; @@ -19,6 +21,10 @@ export function ChatsPage() { const activeChat = chats.find((chat) => chat.id === activeChatId); const isReadOnlyChannel = Boolean(activeChat && activeChat.type === "channel" && activeChat.my_role === "member"); const [infoOpen, setInfoOpen] = useState(false); + const [searchOpen, setSearchOpen] = useState(false); + const [searchQuery, setSearchQuery] = useState(""); + const [searchLoading, setSearchLoading] = useState(false); + const [searchResults, setSearchResults] = useState([]); useRealtime(); @@ -32,6 +38,39 @@ export function ChatsPage() { } }, [activeChatId, loadMessages]); + useEffect(() => { + if (!searchOpen) { + return; + } + const term = searchQuery.trim(); + if (term.length < 2) { + setSearchResults([]); + setSearchLoading(false); + return; + } + let cancelled = false; + setSearchLoading(true); + void (async () => { + try { + const found = await searchMessages(term, activeChatId ?? undefined); + if (!cancelled) { + setSearchResults(found); + } + } catch { + if (!cancelled) { + setSearchResults([]); + } + } finally { + if (!cancelled) { + setSearchLoading(false); + } + } + })(); + return () => { + cancelled = true; + }; + }, [searchOpen, searchQuery, activeChatId]); + return (
@@ -55,9 +94,14 @@ export function ChatsPage() {

{activeChat ? headerMetaLabel(activeChat) : "Select a chat"}

- +
+ + +
@@ -76,6 +120,41 @@ export function ChatsPage() {
setInfoOpen(false)} /> + {searchOpen ? ( +
setSearchOpen(false)}> +
e.stopPropagation()}> +
+

Search messages

+ +
+ setSearchQuery(e.target.value)} + /> + {searchLoading ?

Searching...

: null} + {!searchLoading && searchQuery.trim().length >= 2 && searchResults.length === 0 ? ( +

Nothing found

+ ) : null} +
+ {searchResults.map((message) => ( + + ))} +
+
+
+ ) : null}
); }