mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-06 21:44:13 +03:00
use swr as single source of truth for searchDetail
rather than maintaining a separate state, derive the selected item from swr cache. fixes websocket sync when regenerating descriptions or fetching transcriptions
This commit is contained in:
parent
c9758278e2
commit
43071efa06
@ -16,7 +16,6 @@ import ImageLoadingIndicator from "@/components/indicators/ImageLoadingIndicator
|
||||
import useImageLoaded from "@/hooks/use-image-loaded";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import { useTrackedObjectUpdate } from "@/api/ws";
|
||||
import { isEqual } from "lodash";
|
||||
import TimeAgo from "@/components/dynamic/TimeAgo";
|
||||
import SearchResultActions from "@/components/menu/SearchResultActions";
|
||||
import { SearchTab } from "@/components/overlay/detail/SearchDetailDialog";
|
||||
@ -25,14 +24,12 @@ import { useTranslation } from "react-i18next";
|
||||
import { getTranslatedLabel } from "@/utils/i18n";
|
||||
|
||||
type ExploreViewProps = {
|
||||
searchDetail: SearchResult | undefined;
|
||||
setSearchDetail: (search: SearchResult | undefined) => void;
|
||||
setSimilaritySearch: (search: SearchResult) => void;
|
||||
onSelectSearch: (item: SearchResult, ctrl: boolean, page?: SearchTab) => void;
|
||||
};
|
||||
|
||||
export default function ExploreView({
|
||||
searchDetail,
|
||||
setSearchDetail,
|
||||
setSimilaritySearch,
|
||||
onSelectSearch,
|
||||
@ -83,20 +80,6 @@ export default function ExploreView({
|
||||
}
|
||||
}, [wsUpdate, mutate]);
|
||||
|
||||
// update search detail when results change
|
||||
|
||||
useEffect(() => {
|
||||
if (searchDetail && events) {
|
||||
const updatedSearchDetail = events.find(
|
||||
(result) => result.id === searchDetail.id,
|
||||
);
|
||||
|
||||
if (updatedSearchDetail && !isEqual(updatedSearchDetail, searchDetail)) {
|
||||
setSearchDetail(updatedSearchDetail);
|
||||
}
|
||||
}
|
||||
}, [events, searchDetail, setSearchDetail]);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<ActivityIndicator className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2" />
|
||||
|
||||
@ -19,7 +19,6 @@ import useKeyboardListener, {
|
||||
import scrollIntoView from "scroll-into-view-if-needed";
|
||||
import InputWithTags from "@/components/input/InputWithTags";
|
||||
import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
|
||||
import { isEqual } from "lodash";
|
||||
import { formatDateToLocaleString } from "@/utils/dateUtil";
|
||||
import SearchThumbnailFooter from "@/components/card/SearchThumbnailFooter";
|
||||
import ExploreSettings from "@/components/settings/SearchSettings";
|
||||
@ -213,7 +212,7 @@ export default function SearchView({
|
||||
|
||||
// detail
|
||||
|
||||
const [searchDetail, setSearchDetail] = useState<SearchResult>();
|
||||
const [selectedId, setSelectedId] = useState<string>();
|
||||
const [page, setPage] = useState<SearchTab>("snapshot");
|
||||
|
||||
// remove duplicate event ids
|
||||
@ -229,6 +228,16 @@ export default function SearchView({
|
||||
return results;
|
||||
}, [searchResults]);
|
||||
|
||||
const searchDetail = useMemo(() => {
|
||||
if (!selectedId) return undefined;
|
||||
// summary view
|
||||
if (defaultView === "summary" && exploreEvents) {
|
||||
return exploreEvents.find((r) => r.id === selectedId);
|
||||
}
|
||||
// grid view
|
||||
return uniqueResults.find((r) => r.id === selectedId);
|
||||
}, [selectedId, uniqueResults, exploreEvents, defaultView]);
|
||||
|
||||
// search interaction
|
||||
|
||||
const [selectedObjects, setSelectedObjects] = useState<string[]>([]);
|
||||
@ -256,7 +265,7 @@ export default function SearchView({
|
||||
}
|
||||
} else {
|
||||
setPage(page);
|
||||
setSearchDetail(item);
|
||||
setSelectedId(item.id);
|
||||
}
|
||||
},
|
||||
[selectedObjects],
|
||||
@ -295,26 +304,12 @@ export default function SearchView({
|
||||
}
|
||||
};
|
||||
|
||||
// update search detail when results change
|
||||
|
||||
// clear selected item when search results clear
|
||||
useEffect(() => {
|
||||
if (searchDetail) {
|
||||
const results =
|
||||
defaultView === "summary" ? exploreEvents : searchResults?.flat();
|
||||
if (results) {
|
||||
const updatedSearchDetail = results.find(
|
||||
(result) => result.id === searchDetail.id,
|
||||
);
|
||||
|
||||
if (
|
||||
updatedSearchDetail &&
|
||||
!isEqual(updatedSearchDetail, searchDetail)
|
||||
) {
|
||||
setSearchDetail(updatedSearchDetail);
|
||||
if (!searchResults && !exploreEvents) {
|
||||
setSelectedId(undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [searchResults, exploreEvents, searchDetail, defaultView]);
|
||||
}, [searchResults, exploreEvents]);
|
||||
|
||||
const hasExistingSearch = useMemo(
|
||||
() => searchResults != undefined || searchFilter != undefined,
|
||||
@ -340,7 +335,7 @@ export default function SearchView({
|
||||
? results.length - 1
|
||||
: (currentIndex - 1 + results.length) % results.length;
|
||||
|
||||
setSearchDetail(results[newIndex]);
|
||||
setSelectedId(results[newIndex].id);
|
||||
}
|
||||
}, [uniqueResults, exploreEvents, searchDetail, defaultView]);
|
||||
|
||||
@ -357,7 +352,7 @@ export default function SearchView({
|
||||
const newIndex =
|
||||
currentIndex === -1 ? 0 : (currentIndex + 1) % results.length;
|
||||
|
||||
setSearchDetail(results[newIndex]);
|
||||
setSelectedId(results[newIndex].id);
|
||||
}
|
||||
}, [uniqueResults, exploreEvents, searchDetail, defaultView]);
|
||||
|
||||
@ -509,7 +504,7 @@ export default function SearchView({
|
||||
<SearchDetailDialog
|
||||
search={searchDetail}
|
||||
page={page}
|
||||
setSearch={setSearchDetail}
|
||||
setSearch={(item) => setSelectedId(item?.id)}
|
||||
setSearchPage={setPage}
|
||||
setSimilarity={
|
||||
searchDetail && (() => setSimilaritySearch(searchDetail))
|
||||
@ -629,7 +624,7 @@ export default function SearchView({
|
||||
detail: boolean,
|
||||
) => {
|
||||
if (detail && selectedObjects.length == 0) {
|
||||
setSearchDetail(value);
|
||||
setSelectedId(value.id);
|
||||
} else {
|
||||
onSelectSearch(
|
||||
value,
|
||||
@ -724,8 +719,7 @@ export default function SearchView({
|
||||
defaultView == "summary" && (
|
||||
<div className="scrollbar-container flex size-full flex-col overflow-y-auto">
|
||||
<ExploreView
|
||||
searchDetail={searchDetail}
|
||||
setSearchDetail={setSearchDetail}
|
||||
setSearchDetail={(item) => setSelectedId(item?.id)}
|
||||
setSimilaritySearch={setSimilaritySearch}
|
||||
onSelectSearch={onSelectSearch}
|
||||
/>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user