import { useEffect, useState } from 'react';
import { useSession } from '../context/SessionContext.jsx';
import { useSettingsNamespace } from '../settings/index.js';
import { useRoomCameraSnapshots } from '../hooks/useRoomCameraSnapshots.js';
import RoomCameraFeed from './RoomCameraFeed.jsx';
function EmptyState() {
return (
No room cameras configured.
Add entries to server config to populate this list.
);
}
const ORIENTATIONS = ['horizontal', 'vertical'];
function normalizeOrientation(value, fallback) {
if (ORIENTATIONS.includes(value)) {
return value;
}
return fallback;
}
export default function RoomCameraPanel({
defaultOrientation = 'horizontal',
orientation: forcedOrientation,
hideLayoutToggle = false,
hideHeader = false,
panelId = null,
}) {
const { session } = useSession();
const cameras = session?.roomCameras || [];
const feedMap = useRoomCameraSnapshots(cameras.map((camera) => ({ id: camera.id })));
const { value: orientationSettings, save: saveOrientationSettings } = useSettingsNamespace('roomCameraPanels', {});
const [orientation, setOrientation] = useState(() =>
normalizeOrientation(
panelId ? orientationSettings?.[panelId] : defaultOrientation,
'horizontal',
),
);
useEffect(() => {
if (!panelId) return;
const stored = orientationSettings?.[panelId];
if (!stored) return;
setOrientation(normalizeOrientation(stored, 'horizontal'));
// only respond to changes for this panel id
}, [panelId, orientationSettings?.[panelId]]);
const effectiveOrientation = forcedOrientation
? normalizeOrientation(forcedOrientation, 'horizontal')
: orientation;
const containerClass =
effectiveOrientation === 'vertical' ? 'flex flex-col gap-0.5' : 'grid gap-0.5 md:grid-cols-2';
const showLayoutToggle = !hideLayoutToggle && !forcedOrientation && cameras.length > 0;
const applyOrientation = (next) => {
setOrientation(next);
if (panelId) {
saveOrientationSettings((current) => ({ ...(current || {}), [panelId]: next }));
}
};
if (cameras.length === 0) {
return ;
}
return (
{!hideHeader && (
Room cameras
{cameras.length}
{showLayoutToggle && (
Layout:
{ORIENTATIONS.map((option) => (
))}
)}
)}
{cameras.map((camera) => {
const feed = feedMap[camera.id] || null;
return (
{/* */}
);
})}
);
}