mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
ptz queue stuff fix
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -78,7 +78,7 @@
|
||||
<script defer src="https://analytics.otter.land/script.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land"></script>
|
||||
<script defer src="https://analytics.otter.land/recorder.js" data-website-id="82dd56a5-db44-4279-bd1e-a4d9fee39af7" data-domains="rover.otter.land" data-sample-rate="0.15" data-mask-level="moderate" data-max-duration="300000"></script>
|
||||
<title>Roomba Rover</title>
|
||||
<script type="module" crossorigin src="/assets/index-9jcNKvk8.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-C0TiWXHh.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CSRq98ER.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -714,8 +714,44 @@ export function PtzControllerPage({ layout = 'desktop' }) {
|
||||
const navigate = useNavigate();
|
||||
const [releasePending, setReleasePending] = useState(false);
|
||||
const autoClaimSocketRef = useRef(null);
|
||||
const routeExitReleaseTimerRef = useRef(null);
|
||||
const participantRef = useRef(false);
|
||||
const closingThroughButtonRef = useRef(false);
|
||||
const isMobile = layout !== 'desktop';
|
||||
const canUse = Boolean(ptz?.canUse || isVerified || role === 'admin' || role === 'lockdown');
|
||||
const isParticipant = Boolean(ptz?.isOperator || ptz?.queuedPosition);
|
||||
|
||||
useEffect(() => {
|
||||
// Route-exit cleanup runs after the last render, so retain the latest
|
||||
// server-confirmed membership without making the lifecycle effect resubscribe.
|
||||
participantRef.current = isParticipant;
|
||||
}, [isParticipant]);
|
||||
|
||||
useEffect(() => {
|
||||
if (routeExitReleaseTimerRef.current) {
|
||||
clearTimeout(routeExitReleaseTimerRef.current);
|
||||
routeExitReleaseTimerRef.current = null;
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (!participantRef.current || closingThroughButtonRef.current) return;
|
||||
/*
|
||||
Browser Back and route navigation unmount the PTZ page without invoking
|
||||
its Close button. Defer release by one task so React Strict Mode's
|
||||
development-only cleanup/remount cycle can cancel it in the next setup;
|
||||
a real route exit has no replacement setup, so membership is released.
|
||||
|
||||
This is intentionally membership-gated. An admin release command can
|
||||
revoke the current operator even when the admin is not that operator,
|
||||
so an admin merely visiting/leaving a disabled or unjoined page must not
|
||||
emit a release command.
|
||||
*/
|
||||
routeExitReleaseTimerRef.current = setTimeout(() => {
|
||||
routeExitReleaseTimerRef.current = null;
|
||||
ptzRelease().catch(() => {});
|
||||
}, 0);
|
||||
};
|
||||
}, [ptzRelease]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!featureEnabled || !ptz || !socketId || !canUse) return undefined;
|
||||
@@ -766,6 +802,7 @@ export function PtzControllerPage({ layout = 'desktop' }) {
|
||||
const releaseAndClose = useCallback(async () => {
|
||||
if (releasePending) return;
|
||||
setReleasePending(true);
|
||||
closingThroughButtonRef.current = true;
|
||||
try {
|
||||
/*
|
||||
Stop first so a held key/pointer cannot leave ONVIF continuous movement
|
||||
@@ -776,6 +813,11 @@ export function PtzControllerPage({ layout = 'desktop' }) {
|
||||
await ptzRelease();
|
||||
}
|
||||
navigate('/');
|
||||
} catch (err) {
|
||||
// A rejected manual release leaves the route mounted, so route-exit
|
||||
// cleanup must remain armed for a later Back/navigation attempt.
|
||||
closingThroughButtonRef.current = false;
|
||||
throw err;
|
||||
} finally {
|
||||
setReleasePending(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user