mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
rover over
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/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>
|
<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>
|
<title>Roomba Rover</title>
|
||||||
<script type="module" crossorigin src="/assets/index-YgdVe0Du.js"></script>
|
<script type="module" crossorigin src="/assets/index-CSIsAzyE.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-17XZRVBQ.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-17XZRVBQ.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -632,6 +632,24 @@ function buildDockRequiredPayload(socket, leave) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function releaseRoverOwnershipForPtz(socket) {
|
||||||
|
/*
|
||||||
|
PTZ operation must remove the browser from every rover-control state, not
|
||||||
|
only the roverManager driver set. The normal assignment UI is backed by
|
||||||
|
assignmentService, while low-level control membership is tracked inside
|
||||||
|
roverManager. In healthy flows those two agree, but reconnects, admin paths,
|
||||||
|
or earlier cleanup can leave only one side populated. Releasing the union
|
||||||
|
keeps PTZ from looking like a second simultaneous rover assignment.
|
||||||
|
*/
|
||||||
|
if (!socket?.id) return;
|
||||||
|
const roverIds = new Set(roverManager.getRoversForSocket(socket.id));
|
||||||
|
const assignedRoverId = assignmentService.getAssignedRover?.(socket.id);
|
||||||
|
if (assignedRoverId) roverIds.add(assignedRoverId);
|
||||||
|
roverIds.forEach((roverId) => {
|
||||||
|
assignmentService.forceRelease(roverId, socket.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function revokeOperator(reason = 'release') {
|
function revokeOperator(reason = 'release') {
|
||||||
if (!state.operatorSocketId) return;
|
if (!state.operatorSocketId) return;
|
||||||
const previous = state.operatorSocketId;
|
const previous = state.operatorSocketId;
|
||||||
@@ -646,14 +664,7 @@ function revokeOperator(reason = 'release') {
|
|||||||
function activateOperator(socket) {
|
function activateOperator(socket) {
|
||||||
revokeOperator('handoff');
|
revokeOperator('handoff');
|
||||||
removeFromQueue(socket.id);
|
removeFromQueue(socket.id);
|
||||||
/*
|
releaseRoverOwnershipForPtz(socket);
|
||||||
PTZ operation is mutually exclusive with rover ownership. Releasing through
|
|
||||||
assignmentService preserves the existing queue/control cleanup rules instead
|
|
||||||
of directly mutating rover manager state.
|
|
||||||
*/
|
|
||||||
roverManager.getRoversForSocket(socket.id).forEach((roverId) => {
|
|
||||||
assignmentService.forceRelease(roverId, socket.id);
|
|
||||||
});
|
|
||||||
state.operatorSocketId = socket.id;
|
state.operatorSocketId = socket.id;
|
||||||
state.deadline = Date.now() + getTurnDurationMs();
|
state.deadline = Date.now() + getTurnDurationMs();
|
||||||
turnTimer = setTimeout(handleTurnDeadline, getTurnDurationMs());
|
turnTimer = setTimeout(handleTurnDeadline, getTurnDurationMs());
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ function QueueReplayLinksRow() {
|
|||||||
<ReplaySourcesPanel panelId="replay-sources-desktop" fillHeight />
|
<ReplaySourcesPanel panelId="replay-sources-desktop" fillHeight />
|
||||||
</div>
|
</div>
|
||||||
<div className={`min-w-0 basis-0 grow-[0.75] ${themeStackClass}`}>
|
<div className={`min-w-0 basis-0 grow-[0.75] ${themeStackClass}`}>
|
||||||
<LinkButtonsPanel />
|
<LinkButtonsPanel fillHeight={false} />
|
||||||
<PtzQueueCard layout="desktop" />
|
<PtzQueueCard layout="desktop" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function NicknameEntryPanel({ compact = false }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function LinkButtonsPanel({ className = '' }) {
|
export function LinkButtonsPanel({ className = '', fillHeight = true }) {
|
||||||
const enabled = useSessionSelector((state) => isFeatureEnabled(state, 'socials'));
|
const enabled = useSessionSelector((state) => isFeatureEnabled(state, 'socials'));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -32,7 +32,7 @@ export function LinkButtonsPanel({ className = '' }) {
|
|||||||
return (
|
return (
|
||||||
<CardFrame
|
<CardFrame
|
||||||
title="Links!"
|
title="Links!"
|
||||||
fillHeight
|
fillHeight={fillHeight}
|
||||||
className={className}
|
className={className}
|
||||||
bodyClassName="flex flex-1 min-h-0 flex-col gap-0.5 text-base"
|
bodyClassName="flex flex-1 min-h-0 flex-col gap-0.5 text-base"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user