import { filter, sortBy } from 'common/collections'; import { flow } from 'common/fp'; import { classes } from 'common/react'; import { createSearch } from 'common/string'; import { Fragment } from 'inferno'; import { useBackend, useLocalState } from '../backend'; import { Button, ByondUi, Input, Section, Dropdown } from '../components'; import { refocusLayout, Window } from '../layouts'; /** * Returns previous and next camera names relative to the currently * active camera. */ const prevNextCamera = (cameras, activeCamera) => { if (!activeCamera) { return []; } const index = cameras.findIndex((camera) => camera.name === activeCamera.name); return [cameras[index - 1]?.name, cameras[index + 1]?.name]; }; /** * Camera selector. * * Filters cameras, applies search terms and sorts the alphabetically. */ const selectCameras = (cameras, searchText = '', networkFilter = '') => { const testSearch = createSearch(searchText, (camera) => camera.name); let fl = flow([ // Null camera filter filter((camera) => camera?.name), // Optional search term searchText && filter(testSearch), // Optional network filter networkFilter && filter((camera) => camera.networks.includes(networkFilter)), // Slightly expensive, but way better than sorting in BYOND sortBy((camera) => camera.name), ])(cameras); return fl; }; export const CameraConsole = (props, context) => { return ( ); }; export const CameraConsoleContent = (props, context) => { const { act, data, config } = useBackend(context); const { mapRef, activeCamera } = data; const cameras = selectCameras(data.cameras); const [prevCameraName, nextCameraName] = prevNextCamera(cameras, activeCamera); return ( Camera: {(activeCamera && activeCamera.name) || '—'} act('pan', { dir: 8 })} /> act('pan', { dir: 1 })} /> act('pan', { dir: 4 })} /> act('pan', { dir: 2 })} /> ); }; export const CameraConsoleSearch = (props, context) => { const { act, data } = useBackend(context); const [searchText, setSearchText] = useLocalState(context, 'searchText', ''); const [networkFilter, setNetworkFilter] = useLocalState(context, 'networkFilter', ''); const { activeCamera, allNetworks } = data; allNetworks.sort(); const cameras = selectCameras(data.cameras, searchText, networkFilter); return ( setSearchText(value)} /> setNetworkFilter(value)} /> {cameras.map((camera) => ( // We're not using the component here because performance // would be absolutely abysmal (50+ ms for each re-render). { refocusLayout(); act('switch_camera', { name: camera.name, }); }}> {camera.name} ))} ); };