From 5777c76c4758e7aeb6861ad7f0b91e7d52bdfd0b Mon Sep 17 00:00:00 2001 From: Till-JS <101404291+Till-JS@users.noreply.github.com> Date: Thu, 29 Jan 2026 18:41:06 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(matrix-web):=20add=20message?= =?UTF-8?q?=20search=20functionality?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add searchMessages method to Matrix store using SDK search API - Create SearchDialog component with: - Search input with keyboard navigation - Toggle between "current room" and "all rooms" scope - Result list with sender, room name, and timestamp - Query highlighting in results - Add search button to RoomHeader - Integrate search dialog into chat page Co-Authored-By: Claude Opus 4.5 --- .../src/lib/components/chat/RoomHeader.svelte | 11 +- .../lib/components/chat/SearchDialog.svelte | 185 ++++++++++++++++++ .../apps/web/src/lib/matrix/store.svelte.ts | 72 +++++++ .../web/src/routes/(app)/chat/+page.svelte | 11 +- 4 files changed, 277 insertions(+), 2 deletions(-) create mode 100644 apps/matrix/apps/web/src/lib/components/chat/SearchDialog.svelte diff --git a/apps/matrix/apps/web/src/lib/components/chat/RoomHeader.svelte b/apps/matrix/apps/web/src/lib/components/chat/RoomHeader.svelte index a802e286d..0176cb838 100644 --- a/apps/matrix/apps/web/src/lib/components/chat/RoomHeader.svelte +++ b/apps/matrix/apps/web/src/lib/components/chat/RoomHeader.svelte @@ -9,14 +9,16 @@ ShieldCheck, ShieldWarning, Users, + MagnifyingGlass, } from '@manacore/shared-icons'; interface Props { onMenuClick?: () => void; onInfoClick?: () => void; + onSearchClick?: () => void; } - let { onMenuClick, onInfoClick }: Props = $props(); + let { onMenuClick, onInfoClick, onSearchClick }: Props = $props(); let room = $derived(matrixStore.currentSimpleRoom); let cryptoReady = $derived(matrixStore.cryptoReady); @@ -101,6 +103,13 @@
+ +
+ + +
+ + +
+ + +
+ {#if searching} +
+ + Suche läuft... +
+ {:else if searchResults.length > 0} +
+ {#each searchResults as result} + + {/each} +
+ {:else if hasSearched && query.trim()} +
+ +

Keine Nachrichten gefunden

+

Versuche es mit anderen Suchbegriffen

+
+ {:else} +
+ +

Gib einen Suchbegriff ein

+

Drücke Enter zum Suchen

+
+ {/if} +
+ + +{/if} diff --git a/apps/matrix/apps/web/src/lib/matrix/store.svelte.ts b/apps/matrix/apps/web/src/lib/matrix/store.svelte.ts index 7d69a4c61..4ee45cc61 100644 --- a/apps/matrix/apps/web/src/lib/matrix/store.svelte.ts +++ b/apps/matrix/apps/web/src/lib/matrix/store.svelte.ts @@ -803,6 +803,78 @@ class MatrixStore { } } + /** + * Search messages in the current room + */ + async searchMessages( + query: string, + roomId?: string + ): Promise< + { + eventId: string; + sender: string; + senderName: string; + body: string; + timestamp: number; + roomId: string; + roomName: string; + }[] + > { + if (!this._client || !query.trim()) return []; + + const targetRoomId = roomId || this._currentRoomId; + + try { + // Use Matrix search API + const searchResult = await this._client.searchRoomEvents({ + term: query, + filter: targetRoomId + ? { + rooms: [targetRoomId], + } + : undefined, + }); + + const results: { + eventId: string; + sender: string; + senderName: string; + body: string; + timestamp: number; + roomId: string; + roomName: string; + }[] = []; + + // Process search results - cast to any since SDK types are incomplete + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const searchData = searchResult as any; + const searchResults = searchData?.search_categories?.room_events?.results || []; + for (const result of searchResults) { + const event = result.result; + if (!event) continue; + + const eventRoomId = event.room_id; + const room = this._client.getRoom(eventRoomId); + const content = event.content as { body?: string }; + + results.push({ + eventId: event.event_id || '', + sender: event.sender || '', + senderName: room?.getMember(event.sender || '')?.name || event.sender || 'Unbekannt', + body: content?.body || '', + timestamp: event.origin_server_ts || 0, + roomId: eventRoomId || '', + roomName: room?.name || 'Unbekannt', + }); + } + + return results; + } catch (e) { + console.error('Search failed:', e); + return []; + } + } + /** * Get room members */ diff --git a/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte b/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte index 117635097..0a92b65d2 100644 --- a/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte +++ b/apps/matrix/apps/web/src/routes/(app)/chat/+page.svelte @@ -3,6 +3,7 @@ import { RoomList, RoomHeader, Timeline, MessageInput } from '$lib/components/chat'; import CreateRoomDialog from '$lib/components/chat/CreateRoomDialog.svelte'; import RoomSettingsPanel from '$lib/components/chat/RoomSettingsPanel.svelte'; + import SearchDialog from '$lib/components/chat/SearchDialog.svelte'; import { ChatCircle, Plus, Gear } from '@manacore/shared-icons'; import { browser } from '$app/environment'; @@ -10,6 +11,7 @@ let sidebarOpen = $state(browser ? window.innerWidth >= 1024 : true); let showCreateRoom = $state(false); let showRoomSettings = $state(false); + let showSearch = $state(false); // Reply/Edit state let replyTo = $state(null); @@ -119,7 +121,11 @@
{#if matrixStore.currentRoom} - (showRoomSettings = true)} /> + (showRoomSettings = true)} + onSearchClick={() => (showSearch = true)} + /> @@ -179,3 +185,6 @@ onClose={() => (showCreateRoom = false)} onCreated={handleRoomCreated} /> + + + (showSearch = false)} />