mirror of
https://github.com/Mail-0/Zero.git
synced 2026-07-01 08:16:28 +00:00
fixes search not being added to filters (#1179)
### TL;DR Improved search functionality in the command palette by adding automatic filter creation for search queries. ### What changed? - Removed the `processSearchQuery` function that was handling natural language date parsing - Added automatic creation of search filters when users enter search queries - Added special handling for AI-generated search queries, creating distinct filters for them - Added detection for filter syntax to prevent creating redundant search filters - Updated dependency arrays in useCallback hooks to include the new addFilter function ### How to test? 1. Open the command palette and enter a search query (e.g., "emails from John") 2. Verify that a search filter is automatically created with the label "Search: 'emails from John'" 3. Try an AI-generated search query and confirm it creates a filter with "AI Search:" prefix 4. Test queries that already use filter syntax (e.g., "from:john@example.com") and verify they don't create redundant filters 5. Ensure that multiple search filters can be added and that they properly combine in the search query ### Why make this change? This change improves the user experience by automatically creating search filters from queries, making it easier for users to see and manage their active search criteria. It also differentiates between regular searches and AI-enhanced searches, giving users better visibility into how their search terms are being processed and applied. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved search functionality by automatically adding a search filter when queries do not use filter prefixes. - Enhanced AI-generated search queries now display with an "AI Search:" label. - **Refactor** - Simplified search processing by removing custom date parsing and streamlining filter handling. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -38,11 +38,7 @@ import {
|
||||
useState,
|
||||
type ComponentType,
|
||||
} from 'react';
|
||||
import {
|
||||
getMainSearchTerm,
|
||||
parseNaturalLanguageDate,
|
||||
parseNaturalLanguageSearch,
|
||||
} from '@/lib/utils';
|
||||
import { getMainSearchTerm, parseNaturalLanguageSearch } from '@/lib/utils';
|
||||
import { DialogDescription, DialogTitle } from '@/components/ui/dialog';
|
||||
import { navigationConfig, type MessageKey } from '@/config/navigation';
|
||||
import { useSearchValue } from '@/hooks/use-search-value';
|
||||
@@ -54,11 +50,11 @@ import { Calendar } from '@/components/ui/calendar';
|
||||
import { useMutation } from '@tanstack/react-query';
|
||||
import { useThreads } from '@/hooks/use-threads';
|
||||
import { useLabels } from '@/hooks/use-labels';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { format, subDays } from 'date-fns';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { useTranslations } from 'use-intl';
|
||||
import { format, subDays } from 'date-fns';
|
||||
import { VisuallyHidden } from 'radix-ui';
|
||||
import { Pencil2 } from '../icons/icons';
|
||||
import { Button } from '../ui/button';
|
||||
@@ -433,6 +429,19 @@ export function CommandPalette({ children }: { children: React.ReactNode }) {
|
||||
finalQuery = semanticQuery || query;
|
||||
}
|
||||
|
||||
const isFilterSyntax = /^(from:|to:|subject:|has:|is:|after:|before:|label:)/.test(
|
||||
query.trim(),
|
||||
);
|
||||
if (query.trim() && !isFilterSyntax) {
|
||||
const searchFilter: ActiveFilter = {
|
||||
id: `search-${Date.now()}`,
|
||||
type: 'search',
|
||||
value: query,
|
||||
display: `Search: "${query}"`,
|
||||
};
|
||||
addFilter(searchFilter);
|
||||
}
|
||||
|
||||
const filterQuery = activeFilters.map((f) => f.value).join(' ');
|
||||
if (filterQuery) {
|
||||
finalQuery = `${finalQuery} ${filterQuery}`.trim();
|
||||
@@ -449,7 +458,7 @@ export function CommandPalette({ children }: { children: React.ReactNode }) {
|
||||
description: finalQuery,
|
||||
});
|
||||
},
|
||||
[activeFilters, searchValue.folder, setSearchValue],
|
||||
[activeFilters, searchValue.folder, setSearchValue, addFilter],
|
||||
);
|
||||
|
||||
const quickFilterOptions = useMemo(
|
||||
@@ -515,59 +524,6 @@ export function CommandPalette({ children }: { children: React.ReactNode }) {
|
||||
[addFilter, executeSearch],
|
||||
);
|
||||
|
||||
const processSearchQuery = useCallback((query: string): string => {
|
||||
let searchTerms = [];
|
||||
|
||||
try {
|
||||
if (query.trim()) {
|
||||
const searchTerm = query.trim();
|
||||
|
||||
const dateRange = parseNaturalLanguageDate(searchTerm);
|
||||
if (dateRange) {
|
||||
if (dateRange.from) {
|
||||
const fromDate = format(dateRange.from, 'yyyy/MM/dd');
|
||||
searchTerms.push(`after:${fromDate}`);
|
||||
}
|
||||
if (dateRange.to) {
|
||||
const toDate = format(dateRange.to, 'yyyy/MM/dd');
|
||||
searchTerms.push(`before:${toDate}`);
|
||||
}
|
||||
|
||||
const cleanedQuery = searchTerm
|
||||
.replace(/emails?\s+from\s+/i, '')
|
||||
.replace(/\b\d{4}\b/g, '')
|
||||
.replace(
|
||||
/\b(january|february|march|april|may|june|july|august|september|october|november|december)\b/gi,
|
||||
'',
|
||||
)
|
||||
.trim();
|
||||
|
||||
if (cleanedQuery) {
|
||||
searchTerms.push(cleanedQuery);
|
||||
}
|
||||
} else {
|
||||
const parsedTerm = parseNaturalLanguageSearch(searchTerm);
|
||||
if (parsedTerm !== searchTerm) {
|
||||
searchTerms.push(parsedTerm);
|
||||
} else {
|
||||
if (searchTerm.includes('@')) {
|
||||
searchTerms.push(`from:${searchTerm}`);
|
||||
} else {
|
||||
searchTerms.push(
|
||||
`(from:${searchTerm} OR from:"${searchTerm}" OR subject:"${searchTerm}" OR "${searchTerm}")`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return searchTerms.join(' ');
|
||||
} catch (error) {
|
||||
console.error('Search processing error:', error);
|
||||
return query;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleSearch = useCallback(
|
||||
async (query: string, useNaturalLanguage = true) => {
|
||||
setIsProcessing(true);
|
||||
@@ -581,6 +537,15 @@ export function CommandPalette({ children }: { children: React.ReactNode }) {
|
||||
toast.info('Search applied', {
|
||||
description: finalQuery,
|
||||
});
|
||||
|
||||
const searchFilter: ActiveFilter = {
|
||||
id: `ai-search-${Date.now()}`,
|
||||
type: 'search',
|
||||
value: finalQuery,
|
||||
display: `AI Search: "${query}"`,
|
||||
};
|
||||
addFilter(searchFilter);
|
||||
|
||||
return setSearchValue({
|
||||
value: finalQuery,
|
||||
highlight: getMainSearchTerm(query),
|
||||
@@ -590,6 +555,19 @@ export function CommandPalette({ children }: { children: React.ReactNode }) {
|
||||
});
|
||||
}
|
||||
|
||||
const isFilterSyntax = /^(from:|to:|subject:|has:|is:|after:|before:|label:)/.test(
|
||||
query.trim(),
|
||||
);
|
||||
if (query.trim() && !isFilterSyntax) {
|
||||
const searchFilter: ActiveFilter = {
|
||||
id: `search-${Date.now()}`,
|
||||
type: 'search',
|
||||
value: query,
|
||||
display: `Search: "${query}"`,
|
||||
};
|
||||
addFilter(searchFilter);
|
||||
}
|
||||
|
||||
const filterQuery = activeFilters.map((f) => f.value).join(' ');
|
||||
if (filterQuery) {
|
||||
finalQuery = `${finalQuery} ${filterQuery}`.trim();
|
||||
@@ -620,7 +598,7 @@ export function CommandPalette({ children }: { children: React.ReactNode }) {
|
||||
setIsProcessing(false);
|
||||
}
|
||||
},
|
||||
[activeFilters, processSearchQuery, searchValue.folder, setSearchValue, setOpen],
|
||||
[activeFilters, searchValue.folder, setSearchValue, setOpen, generateSearchQuery, addFilter],
|
||||
);
|
||||
|
||||
const quickSearchResults = useMemo(() => {
|
||||
|
||||
Reference in New Issue
Block a user