fix masks and zones layout issues at high browser zoom levels (#22181)
Some checks failed
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled

This commit is contained in:
Josh Hawkins 2026-03-01 14:41:33 -06:00 committed by GitHub
parent 4232cc483d
commit 1f1d546326
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 48 additions and 13 deletions

View File

@ -258,7 +258,7 @@ export function PolygonCanvas({
const updatedPolygons = [...polygons]; const updatedPolygons = [...polygons];
const activePolygon = updatedPolygons[activePolygonIndex]; const activePolygon = updatedPolygons[activePolygonIndex];
if (containerRef.current && !activePolygon.isFinished) { if (containerRef.current && activePolygon && !activePolygon.isFinished) {
containerRef.current.style.cursor = "crosshair"; containerRef.current.style.cursor = "crosshair";
} }
}; };

View File

@ -329,7 +329,7 @@ export default function PolygonItem({
<div <div
key={index} key={index}
className="transition-background my-1.5 flex flex-row items-center justify-between rounded-lg p-1 duration-100" className="transition-background relative my-1.5 flex flex-row items-center justify-between rounded-lg p-1 duration-100"
data-index={index} data-index={index}
onMouseEnter={() => setHoveredPolygonIndex(index)} onMouseEnter={() => setHoveredPolygonIndex(index)}
onMouseLeave={() => setHoveredPolygonIndex(null)} onMouseLeave={() => setHoveredPolygonIndex(null)}
@ -341,7 +341,7 @@ export default function PolygonItem({
}} }}
> >
<div <div
className={`flex items-center ${ className={`flex min-w-0 items-center ${
hoveredPolygonIndex === index hoveredPolygonIndex === index
? "text-primary" ? "text-primary"
: "text-primary-variant" : "text-primary-variant"
@ -359,7 +359,7 @@ export default function PolygonItem({
type="button" type="button"
onClick={handleToggleEnabled} onClick={handleToggleEnabled}
disabled={isLoading || polygon.enabled_in_config === false} disabled={isLoading || polygon.enabled_in_config === false}
className="mr-2 cursor-pointer border-none bg-transparent p-0 transition-opacity hover:opacity-70 disabled:cursor-not-allowed disabled:opacity-50" className="mr-2 shrink-0 cursor-pointer border-none bg-transparent p-0 transition-opacity hover:opacity-70 disabled:cursor-not-allowed disabled:opacity-50"
> >
<PolygonItemIcon <PolygonItemIcon
className="size-5" className="size-5"
@ -469,7 +469,15 @@ export default function PolygonItem({
</> </>
)} )}
{!isMobile && hoveredPolygonIndex === index && ( {!isMobile && hoveredPolygonIndex === index && (
<div className="flex flex-row items-center gap-2"> <div
className="absolute inset-y-0 right-0 flex flex-row items-center gap-2 rounded-r-lg pl-8 pr-1"
style={{
background:
polygon.color.length === 3
? `linear-gradient(to right, transparent 0%, rgba(${polygon.color[2]},${polygon.color[1]},${polygon.color[0]},0.85) 40%)`
: "linear-gradient(to right, transparent 0%, rgba(220,0,0,0.85) 40%)",
}}
>
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<IconWrapper <IconWrapper

View File

@ -64,6 +64,9 @@ export default function MasksAndZonesView({
); );
const containerRef = useRef<HTMLDivElement | null>(null); const containerRef = useRef<HTMLDivElement | null>(null);
const [editPane, setEditPane] = useState<PolygonType | undefined>(undefined); const [editPane, setEditPane] = useState<PolygonType | undefined>(undefined);
const editPaneRef = useRef(editPane);
editPaneRef.current = editPane;
const prevScaledRef = useRef<{ w: number; h: number } | null>(null);
const [activeLine, setActiveLine] = useState<number | undefined>(); const [activeLine, setActiveLine] = useState<number | undefined>();
const [snapPoints, setSnapPoints] = useState(false); const [snapPoints, setSnapPoints] = useState(false);
@ -350,12 +353,36 @@ export default function MasksAndZonesView({
...globalObjectMasks, ...globalObjectMasks,
...objectMasks, ...objectMasks,
]); ]);
setEditingPolygons([ // Don't overwrite editingPolygons during editing layout shifts
...zones, // from switching to the edit pane can trigger a resize which
...motionMasks, // recalculates scaledWidth/scaledHeight and would discard the
...globalObjectMasks, // newly-added polygon. Instead, rescale existing points
...objectMasks, // proportionally.
]); if (editPaneRef.current === undefined) {
setEditingPolygons([
...zones,
...motionMasks,
...globalObjectMasks,
...objectMasks,
]);
} else if (
prevScaledRef.current &&
(prevScaledRef.current.w !== scaledWidth ||
prevScaledRef.current.h !== scaledHeight)
) {
const prevW = prevScaledRef.current.w;
const prevH = prevScaledRef.current.h;
setEditingPolygons((prev) =>
prev.map((poly) => ({
...poly,
points: poly.points.map(([x, y]) => [
(x / prevW) * scaledWidth,
(y / prevH) * scaledHeight,
]),
})),
);
}
prevScaledRef.current = { w: scaledWidth, h: scaledHeight };
} }
// we know that these deps are correct // we know that these deps are correct
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
@ -431,7 +458,7 @@ export default function MasksAndZonesView({
{cameraConfig && editingPolygons && ( {cameraConfig && editingPolygons && (
<div className="flex size-full flex-col md:flex-row"> <div className="flex size-full flex-col md:flex-row">
<Toaster position="top-center" closeButton={true} /> <Toaster position="top-center" closeButton={true} />
<div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mr-3 md:mt-0 md:w-3/12"> <div className="scrollbar-container order-last mb-2 mt-2 flex h-full w-full flex-col overflow-y-auto rounded-lg border-[1px] border-secondary-foreground bg-background_alt p-2 md:order-none md:mr-3 md:mt-0 md:w-3/12 md:min-w-0 md:shrink-0">
{editPane == "zone" && ( {editPane == "zone" && (
<ZoneEditPane <ZoneEditPane
polygons={editingPolygons} polygons={editingPolygons}
@ -707,7 +734,7 @@ export default function MasksAndZonesView({
<div <div
ref={containerRef} ref={containerRef}
className={cn( className={cn(
"flex max-h-[50%] md:h-dvh md:max-h-full md:w-7/12 md:grow", "flex max-h-[50%] min-w-0 md:h-dvh md:max-h-full md:w-7/12 md:grow",
isDesktop && "md:mr-3", isDesktop && "md:mr-3",
)} )}
> >