import SearchFilterGroup from "@/components/filter/SearchFilterGroup"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import Chip from "@/components/indicators/Chip"; import SearchDetailDialog from "@/components/overlay/detail/SearchDetailDialog"; import SearchThumbnailPlayer from "@/components/player/SearchThumbnailPlayer"; import { Input } from "@/components/ui/input"; import { Toaster } from "@/components/ui/sonner"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { cn } from "@/lib/utils"; import { Preview } from "@/types/preview"; import { SearchFilter, SearchResult } from "@/types/search"; import { useCallback, useMemo, useState } from "react"; import { isMobileOnly } from "react-device-detect"; import { LuExternalLink, LuImage, LuSearchCheck, LuSearchX, LuText, LuXCircle, } from "react-icons/lu"; import { Link } from "react-router-dom"; type SearchViewProps = { search: string; searchTerm: string; searchFilter?: SearchFilter; searchResults?: SearchResult[]; allPreviews?: Preview[]; isLoading: boolean; similaritySearch?: SearchResult; setSearch: (search: string) => void; setSimilaritySearch: (search: SearchResult) => void; onUpdateFilter: (filter: SearchFilter) => void; onOpenSearch: (item: SearchResult) => void; }; export default function SearchView({ search, searchTerm, searchFilter, searchResults, allPreviews, isLoading, similaritySearch, setSearch, setSimilaritySearch, onUpdateFilter, onOpenSearch, }: SearchViewProps) { // remove duplicate event ids const uniqueResults = useMemo(() => { return searchResults?.filter( (value, index, self) => index === self.findIndex((v) => v.id === value.id), ); }, [searchResults]); // detail const [searchDetail, setSearchDetail] = useState(); // search interaction const onSelectSearch = useCallback( (item: SearchResult, detail: boolean) => { if (detail) { setSearchDetail(item); } else { onOpenSearch(item); } }, [onOpenSearch], ); // confidence score - probably needs tweaking const zScoreToConfidence = (score: number, source: string) => { let midpoint, scale; if (source === "thumbnail") { midpoint = 2; scale = 0.5; } else { midpoint = 0.5; scale = 1.5; } // Sigmoid function: 1 / (1 + e^x) const confidence = 1 / (1 + Math.exp((score - midpoint) * scale)); return Math.round(confidence * 100); }; return (
setSimilaritySearch(searchDetail)) } />
setSearch(e.target.value)} /> {search && ( setSearch("")} /> )}
{searchTerm.length == 0 && (
Search
Frigate can find detected objects in your review items.
Read the Documentation{" "}
)} {searchTerm.length > 0 && searchResults?.length == 0 && (
No Detected Objects Found
)} {isLoading && ( )}
{uniqueResults && uniqueResults.map((value) => { const selected = false; return (
{value.search_source == "thumbnail" ? ( ) : ( )} {zScoreToConfidence( value.search_distance, value.search_source, )} % Matched {value.search_source} at{" "} {zScoreToConfidence( value.search_distance, value.search_source, )} %
); })}
); }