feat: sender filter for message search with from:@user autocomplete
Type 'from:@name' in the search box to filter by sender — a dropdown of matching users (avatar + display name + full ID) appears as you type and selecting one converts it into a removable sender chip in the filter bar. Multiple senders supported. Also works via manual entry on submit. - SearchInput: detects trailing 'from:@...' pattern on every keystroke, shows PopOut autocomplete from mx.getUsers(), onMouseDown prevents input blur when selecting, cleans up fragment after selection - SearchFilters: selectedSenders/onSelectedSendersChange props, sender chips rendered with user icon and X to remove - useLocalMessageSearch: filters cached events by sender set when senders param is provided (encrypted room search respects the filter too) - MessageSearch: handleSenderAdd deduplicates and writes to ?senders= URL param; localResult now passes senders to the local search Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,12 @@ import { useCallback } from 'react';
|
||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||
import { ResultGroup, ResultItem } from './useMessageSearch';
|
||||
|
||||
export type LocalSearchParams = {
|
||||
term: string;
|
||||
roomIds: string[];
|
||||
senders?: string[];
|
||||
};
|
||||
|
||||
export type LocalSearchResult = {
|
||||
groups: ResultGroup[];
|
||||
/** How many rooms in scope are encrypted */
|
||||
@@ -23,13 +29,14 @@ export const useLocalMessageSearch = () => {
|
||||
const mx = useMatrixClient();
|
||||
|
||||
const search = useCallback(
|
||||
(roomIds: string[], term: string): LocalSearchResult => {
|
||||
({ term, roomIds, senders }: LocalSearchParams): LocalSearchResult => {
|
||||
const trimmedTerm = term.trim();
|
||||
if (!trimmedTerm) {
|
||||
return { groups: [], encryptedRoomsCount: 0, searchedRoomsCount: 0 };
|
||||
}
|
||||
|
||||
const termLower = trimmedTerm.toLowerCase();
|
||||
const senderSet = senders && senders.length > 0 ? new Set(senders) : null;
|
||||
const groups: ResultGroup[] = [];
|
||||
let encryptedRoomsCount = 0;
|
||||
let searchedRoomsCount = 0;
|
||||
@@ -56,6 +63,7 @@ export const useLocalMessageSearch = () => {
|
||||
if (event.getType() !== EventType.RoomMessage) continue;
|
||||
if (event.isDecryptionFailure()) continue;
|
||||
if (event.isRedacted()) continue;
|
||||
if (senderSet && !senderSet.has(event.getSender() ?? '')) continue;
|
||||
|
||||
// getContent() returns decrypted plaintext regardless of encryption
|
||||
const content = event.getContent();
|
||||
|
||||
Reference in New Issue
Block a user