From 6a011df4274b43a21512b8ab8d123e7e33e69f86 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 5 Nov 2025 22:33:37 -0600 Subject: [PATCH] fix popover --- .../overlay/detail/SearchDetailDialog.tsx | 120 +++++++++++------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/web/src/components/overlay/detail/SearchDetailDialog.tsx b/web/src/components/overlay/detail/SearchDetailDialog.tsx index d3d0b8e5c..67f2259c6 100644 --- a/web/src/components/overlay/detail/SearchDetailDialog.tsx +++ b/web/src/components/overlay/detail/SearchDetailDialog.tsx @@ -88,8 +88,8 @@ type TabsWithActionsProps = { config?: FrigateConfig; setSearch: (s: SearchResult | undefined) => void; setSimilarity?: () => void; - showControls?: boolean; - setShowControls?: (v: boolean) => void; + isPopoverOpen: boolean; + setIsPopoverOpen: (open: boolean) => void; }; function TabsWithActions({ @@ -100,8 +100,8 @@ function TabsWithActions({ config, setSearch, setSimilarity, - showControls, - setShowControls, + isPopoverOpen, + setIsPopoverOpen, }: TabsWithActionsProps) { const { t } = useTranslation(["views/explore", "views/faceLibrary"]); @@ -152,8 +152,8 @@ function TabsWithActions({ {pageToggle === "tracking_details" && ( )} @@ -162,40 +162,69 @@ function TabsWithActions({ type AnnotationSettingsPopoverProps = { search: SearchResult; - showControls?: boolean; - setShowControls?: (v: boolean) => void; + open: boolean; + setIsOpen: (open: boolean) => void; }; function AnnotationSettingsPopover({ search, - showControls, - setShowControls, + open, + setIsOpen, }: AnnotationSettingsPopoverProps) { const { t } = useTranslation(["views/explore"]); const { annotationOffset, setAnnotationOffset } = useDetailStream(); const [showZones, setShowZones] = useState(true); + const ignoreNextOpenRef = useRef(false); + + useEffect(() => { + setIsOpen(false); + ignoreNextOpenRef.current = false; + }, [search, setIsOpen]); + + const handleOpenChange = useCallback( + (nextOpen: boolean) => { + if (nextOpen) { + if (ignoreNextOpenRef.current) { + ignoreNextOpenRef.current = false; + return; + } + setIsOpen(true); + } else { + setIsOpen(false); + } + }, + [setIsOpen], + ); + + const registerTriggerCloseIntent = useCallback(() => { + if (open) { + ignoreNextOpenRef.current = true; + } + }, [open]); + return (
- - - - - - - - - - {t("trackingDetails.adjustAnnotationSettings")} - - - + + { + if (open && (event.key === "Enter" || event.key === " ")) { + registerTriggerCloseIntent(); + } + }} + > + + void; setInputFocused: React.Dispatch>; setSimilarity?: () => void; - showControls?: boolean; - setShowControls?: (v: boolean) => void; + isPopoverOpen: boolean; + setIsPopoverOpen: (open: boolean) => void; }; function DialogContentComponent({ @@ -245,8 +274,8 @@ function DialogContentComponent({ setSearch, setInputFocused, setSimilarity, - showControls, - setShowControls, + isPopoverOpen, + setIsPopoverOpen, }: DialogContentComponentProps) { if (page === "tracking_details") { return ( @@ -263,8 +292,8 @@ function DialogContentComponent({ config={config} setSearch={setSearch} setSimilarity={setSimilarity} - showControls={showControls} - setShowControls={setShowControls} + isPopoverOpen={isPopoverOpen} + setIsPopoverOpen={setIsPopoverOpen} /> ) : undefined } @@ -321,8 +350,8 @@ function DialogContentComponent({ config={config} setSearch={setSearch} setSimilarity={setSimilarity} - showControls={showControls} - setShowControls={setShowControls} + isPopoverOpen={isPopoverOpen} + setIsPopoverOpen={setIsPopoverOpen} />
{ + setIsPopoverOpen(open); setIsOpen(open); if (!open) { // short timeout to allow the mobile page animation @@ -410,9 +441,7 @@ export default function SearchDetailDialog({ } }, [search]); - // show/hide annotation settings - - const [showControls, setShowControls] = useState(false); + // show/hide annotation settings is handled inside TabsWithActions const searchTabs = useMemo(() => { if (!config || !search) { @@ -521,6 +550,9 @@ export default function SearchDetailDialog({ isMobile && "px-4", )} onInteractOutside={(e) => { + if (isPopoverOpen) { + e.preventDefault(); + } const target = e.target as HTMLElement; if (target.closest(".nav-button")) { e.preventDefault(); @@ -545,8 +577,8 @@ export default function SearchDetailDialog({ config={config} setSearch={setSearch} setSimilarity={setSimilarity} - showControls={showControls} - setShowControls={setShowControls} + isPopoverOpen={isPopoverOpen} + setIsPopoverOpen={setIsPopoverOpen} />
)} @@ -563,8 +595,8 @@ export default function SearchDetailDialog({ setSearch={setSearch} setInputFocused={setInputFocused} setSimilarity={setSimilarity} - showControls={showControls} - setShowControls={setShowControls} + isPopoverOpen={isPopoverOpen} + setIsPopoverOpen={setIsPopoverOpen} />