mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-07 22:05:44 +03:00
fix popover
This commit is contained in:
parent
78e278d5e8
commit
6a011df427
@ -88,8 +88,8 @@ type TabsWithActionsProps = {
|
|||||||
config?: FrigateConfig;
|
config?: FrigateConfig;
|
||||||
setSearch: (s: SearchResult | undefined) => void;
|
setSearch: (s: SearchResult | undefined) => void;
|
||||||
setSimilarity?: () => void;
|
setSimilarity?: () => void;
|
||||||
showControls?: boolean;
|
isPopoverOpen: boolean;
|
||||||
setShowControls?: (v: boolean) => void;
|
setIsPopoverOpen: (open: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function TabsWithActions({
|
function TabsWithActions({
|
||||||
@ -100,8 +100,8 @@ function TabsWithActions({
|
|||||||
config,
|
config,
|
||||||
setSearch,
|
setSearch,
|
||||||
setSimilarity,
|
setSimilarity,
|
||||||
showControls,
|
isPopoverOpen,
|
||||||
setShowControls,
|
setIsPopoverOpen,
|
||||||
}: TabsWithActionsProps) {
|
}: TabsWithActionsProps) {
|
||||||
const { t } = useTranslation(["views/explore", "views/faceLibrary"]);
|
const { t } = useTranslation(["views/explore", "views/faceLibrary"]);
|
||||||
|
|
||||||
@ -152,8 +152,8 @@ function TabsWithActions({
|
|||||||
{pageToggle === "tracking_details" && (
|
{pageToggle === "tracking_details" && (
|
||||||
<AnnotationSettingsPopover
|
<AnnotationSettingsPopover
|
||||||
search={search}
|
search={search}
|
||||||
showControls={showControls}
|
open={isPopoverOpen}
|
||||||
setShowControls={setShowControls}
|
setIsOpen={setIsPopoverOpen}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -162,40 +162,69 @@ function TabsWithActions({
|
|||||||
|
|
||||||
type AnnotationSettingsPopoverProps = {
|
type AnnotationSettingsPopoverProps = {
|
||||||
search: SearchResult;
|
search: SearchResult;
|
||||||
showControls?: boolean;
|
open: boolean;
|
||||||
setShowControls?: (v: boolean) => void;
|
setIsOpen: (open: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function AnnotationSettingsPopover({
|
function AnnotationSettingsPopover({
|
||||||
search,
|
search,
|
||||||
showControls,
|
open,
|
||||||
setShowControls,
|
setIsOpen,
|
||||||
}: AnnotationSettingsPopoverProps) {
|
}: AnnotationSettingsPopoverProps) {
|
||||||
const { t } = useTranslation(["views/explore"]);
|
const { t } = useTranslation(["views/explore"]);
|
||||||
const { annotationOffset, setAnnotationOffset } = useDetailStream();
|
const { annotationOffset, setAnnotationOffset } = useDetailStream();
|
||||||
const [showZones, setShowZones] = useState(true);
|
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 (
|
return (
|
||||||
<div className="ml-2">
|
<div className="ml-2">
|
||||||
<Popover modal={true} open={showControls} onOpenChange={setShowControls}>
|
<Popover modal={true} open={open} onOpenChange={handleOpenChange}>
|
||||||
<Tooltip>
|
<PopoverTrigger
|
||||||
<TooltipTrigger asChild>
|
asChild
|
||||||
<PopoverTrigger asChild>
|
onPointerDown={registerTriggerCloseIntent}
|
||||||
|
onKeyDown={(event) => {
|
||||||
|
if (open && (event.key === "Enter" || event.key === " ")) {
|
||||||
|
registerTriggerCloseIntent();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Button
|
<Button
|
||||||
variant={showControls ? "select" : "default"}
|
type="button"
|
||||||
className="size-7 p-1.5"
|
className="size-7 p-1.5"
|
||||||
|
variant={open ? "select" : "default"}
|
||||||
aria-label={t("trackingDetails.adjustAnnotationSettings")}
|
aria-label={t("trackingDetails.adjustAnnotationSettings")}
|
||||||
|
aria-expanded={open}
|
||||||
>
|
>
|
||||||
<LuSettings className="size-5" />
|
<LuSettings className="size-5" />
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipPortal>
|
|
||||||
<TooltipContent>
|
|
||||||
{t("trackingDetails.adjustAnnotationSettings")}
|
|
||||||
</TooltipContent>
|
|
||||||
</TooltipPortal>
|
|
||||||
</Tooltip>
|
|
||||||
<PopoverContent className="w-[90vw] max-w-2xl p-0" align="end">
|
<PopoverContent className="w-[90vw] max-w-2xl p-0" align="end">
|
||||||
<AnnotationSettingsPane
|
<AnnotationSettingsPane
|
||||||
event={search as unknown as Event}
|
event={search as unknown as Event}
|
||||||
@ -229,8 +258,8 @@ type DialogContentComponentProps = {
|
|||||||
setSearch: (s: SearchResult | undefined) => void;
|
setSearch: (s: SearchResult | undefined) => void;
|
||||||
setInputFocused: React.Dispatch<React.SetStateAction<boolean>>;
|
setInputFocused: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
setSimilarity?: () => void;
|
setSimilarity?: () => void;
|
||||||
showControls?: boolean;
|
isPopoverOpen: boolean;
|
||||||
setShowControls?: (v: boolean) => void;
|
setIsPopoverOpen: (open: boolean) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function DialogContentComponent({
|
function DialogContentComponent({
|
||||||
@ -245,8 +274,8 @@ function DialogContentComponent({
|
|||||||
setSearch,
|
setSearch,
|
||||||
setInputFocused,
|
setInputFocused,
|
||||||
setSimilarity,
|
setSimilarity,
|
||||||
showControls,
|
isPopoverOpen,
|
||||||
setShowControls,
|
setIsPopoverOpen,
|
||||||
}: DialogContentComponentProps) {
|
}: DialogContentComponentProps) {
|
||||||
if (page === "tracking_details") {
|
if (page === "tracking_details") {
|
||||||
return (
|
return (
|
||||||
@ -263,8 +292,8 @@ function DialogContentComponent({
|
|||||||
config={config}
|
config={config}
|
||||||
setSearch={setSearch}
|
setSearch={setSearch}
|
||||||
setSimilarity={setSimilarity}
|
setSimilarity={setSimilarity}
|
||||||
showControls={showControls}
|
isPopoverOpen={isPopoverOpen}
|
||||||
setShowControls={setShowControls}
|
setIsPopoverOpen={setIsPopoverOpen}
|
||||||
/>
|
/>
|
||||||
) : undefined
|
) : undefined
|
||||||
}
|
}
|
||||||
@ -321,8 +350,8 @@ function DialogContentComponent({
|
|||||||
config={config}
|
config={config}
|
||||||
setSearch={setSearch}
|
setSearch={setSearch}
|
||||||
setSimilarity={setSimilarity}
|
setSimilarity={setSimilarity}
|
||||||
showControls={showControls}
|
isPopoverOpen={isPopoverOpen}
|
||||||
setShowControls={setShowControls}
|
setIsPopoverOpen={setIsPopoverOpen}
|
||||||
/>
|
/>
|
||||||
<div className="scrollbar-container flex-1 overflow-y-auto">
|
<div className="scrollbar-container flex-1 overflow-y-auto">
|
||||||
<ObjectDetailsTab
|
<ObjectDetailsTab
|
||||||
@ -389,9 +418,11 @@ export default function SearchDetailDialog({
|
|||||||
// dialog and mobile page
|
// dialog and mobile page
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(search != undefined);
|
const [isOpen, setIsOpen] = useState(search != undefined);
|
||||||
|
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||||
|
|
||||||
const handleOpenChange = useCallback(
|
const handleOpenChange = useCallback(
|
||||||
(open: boolean) => {
|
(open: boolean) => {
|
||||||
|
setIsPopoverOpen(open);
|
||||||
setIsOpen(open);
|
setIsOpen(open);
|
||||||
if (!open) {
|
if (!open) {
|
||||||
// short timeout to allow the mobile page animation
|
// short timeout to allow the mobile page animation
|
||||||
@ -410,9 +441,7 @@ export default function SearchDetailDialog({
|
|||||||
}
|
}
|
||||||
}, [search]);
|
}, [search]);
|
||||||
|
|
||||||
// show/hide annotation settings
|
// show/hide annotation settings is handled inside TabsWithActions
|
||||||
|
|
||||||
const [showControls, setShowControls] = useState(false);
|
|
||||||
|
|
||||||
const searchTabs = useMemo(() => {
|
const searchTabs = useMemo(() => {
|
||||||
if (!config || !search) {
|
if (!config || !search) {
|
||||||
@ -521,6 +550,9 @@ export default function SearchDetailDialog({
|
|||||||
isMobile && "px-4",
|
isMobile && "px-4",
|
||||||
)}
|
)}
|
||||||
onInteractOutside={(e) => {
|
onInteractOutside={(e) => {
|
||||||
|
if (isPopoverOpen) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
const target = e.target as HTMLElement;
|
const target = e.target as HTMLElement;
|
||||||
if (target.closest(".nav-button")) {
|
if (target.closest(".nav-button")) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -545,8 +577,8 @@ export default function SearchDetailDialog({
|
|||||||
config={config}
|
config={config}
|
||||||
setSearch={setSearch}
|
setSearch={setSearch}
|
||||||
setSimilarity={setSimilarity}
|
setSimilarity={setSimilarity}
|
||||||
showControls={showControls}
|
isPopoverOpen={isPopoverOpen}
|
||||||
setShowControls={setShowControls}
|
setIsPopoverOpen={setIsPopoverOpen}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -563,8 +595,8 @@ export default function SearchDetailDialog({
|
|||||||
setSearch={setSearch}
|
setSearch={setSearch}
|
||||||
setInputFocused={setInputFocused}
|
setInputFocused={setInputFocused}
|
||||||
setSimilarity={setSimilarity}
|
setSimilarity={setSimilarity}
|
||||||
showControls={showControls}
|
isPopoverOpen={isPopoverOpen}
|
||||||
setShowControls={setShowControls}
|
setIsPopoverOpen={setIsPopoverOpen}
|
||||||
/>
|
/>
|
||||||
</Content>
|
</Content>
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user