feat: add experimental feature + fix old camera padding

This commit is contained in:
JohnMark Sill 2022-01-13 12:50:01 -06:00
parent e7ab6d2d0d
commit 875c74686d
4 changed files with 46 additions and 41 deletions

View File

@ -43,6 +43,8 @@ class DetectorConfig(FrigateBaseModel):
device: str = Field(default="usb", title="Device Type") device: str = Field(default="usb", title="Device Type")
num_threads: int = Field(default=3, title="Number of detection threads") num_threads: int = Field(default=3, title="Number of detection threads")
class UIConfig(FrigateBaseModel):
useExperimentalUI: bool = Field(default=False, title="Experimental UI")
class MqttConfig(FrigateBaseModel): class MqttConfig(FrigateBaseModel):
host: str = Field(title="MQTT Host") host: str = Field(title="MQTT Host")
@ -682,6 +684,7 @@ class FrigateConfig(FrigateBaseModel):
environment_vars: Dict[str, str] = Field( environment_vars: Dict[str, str] = Field(
default_factory=dict, title="Frigate environment variables." default_factory=dict, title="Frigate environment variables."
) )
ui: UIConfig = Field(default_factory=UIConfig, title="UI configuration.")
model: ModelConfig = Field( model: ModelConfig = Field(
default_factory=ModelConfig, title="Detection model configuration." default_factory=ModelConfig, title="Detection model configuration."
) )

View File

@ -10,29 +10,30 @@ import { DarkModeProvider, DrawerProvider } from './context';
import { FetchStatus, useConfig } from './api'; import { FetchStatus, useConfig } from './api';
export default function App() { export default function App() {
const { status } = useConfig(); const { status, data: config } = useConfig();
const cameraComponent = config && config.ui.useExperimentalUI ? Routes.getCameraV2 : Routes.getCamera;
return ( return (
<DarkModeProvider> <DarkModeProvider>
<DrawerProvider> <DrawerProvider>
<div data-testid="app" className="w-full"> <div data-testid='app' className='w-full'>
<AppBar /> <AppBar />
{status !== FetchStatus.LOADED ? ( {status !== FetchStatus.LOADED ? (
<div className="flex flex-grow-1 min-h-screen justify-center items-center"> <div className='flex flex-grow-1 min-h-screen justify-center items-center'>
<ActivityIndicator /> <ActivityIndicator />
</div> </div>
) : ( ) : (
<div className="flex flex-row min-h-screen w-full bg-white dark:bg-gray-900 text-gray-900 dark:text-white"> <div className='flex flex-row min-h-screen w-full bg-white dark:bg-gray-900 text-gray-900 dark:text-white'>
<Sidebar /> <Sidebar />
<div className="w-full flex-auto mt-16 min-w-0"> <div className='w-full flex-auto mt-16 min-w-0'>
<Router> <Router>
<AsyncRoute path="/cameras/:camera/editor" getComponent={Routes.getCameraMap} /> <AsyncRoute path='/cameras/:camera/editor' getComponent={Routes.getCameraMap} />
<AsyncRoute path="/cameras/:camera" getComponent={Routes.getCameraV2} /> <AsyncRoute path='/cameras/:camera' getComponent={cameraComponent} />
<AsyncRoute path="/birdseye" getComponent={Routes.getBirdseye} /> <AsyncRoute path='/birdseye' getComponent={Routes.getBirdseye} />
<AsyncRoute path="/events" getComponent={Routes.getEvents} /> <AsyncRoute path='/events' getComponent={Routes.getEvents} />
<AsyncRoute path="/recording/:camera/:date?/:hour?/:seconds?" getComponent={Routes.getRecording} /> <AsyncRoute path='/recording/:camera/:date?/:hour?/:seconds?' getComponent={Routes.getRecording} />
<AsyncRoute path="/debug" getComponent={Routes.getDebug} /> <AsyncRoute path='/debug' getComponent={Routes.getDebug} />
<AsyncRoute path="/styleguide" getComponent={Routes.getStyleGuide} /> <AsyncRoute path='/styleguide' getComponent={Routes.getStyleGuide} />
<Cameras default path="/" /> <Cameras default path='/' />
</Router> </Router>
</div> </div>
</div> </div>

View File

@ -162,7 +162,9 @@ export default function Timeline({ events, offset, currentIndex, onChange }) {
<div className='relative flex-grow-1'> <div className='relative flex-grow-1'>
<div className='absolute left-0 top-0 h-full w-full' style={{ textAlign: 'center' }}> <div className='absolute left-0 top-0 h-full w-full' style={{ textAlign: 'center' }}>
<div className='h-full' style={{ margin: '0 auto', textAlign: 'center' }}> <div className='h-full' style={{ margin: '0 auto', textAlign: 'center' }}>
<span className='z-20 text-white'>{markerTime && <span>{markerTime.toLocaleTimeString()}</span>}</span> <span className='z-20 text-black dark:text-white'>
{markerTime && <span>{markerTime.toLocaleTimeString()}</span>}
</span>
<div <div
className='z-20 h-full absolute' className='z-20 h-full absolute'
style={{ style={{

View File

@ -21,7 +21,7 @@ export default function Camera({ camera }) {
const [viewMode, setViewMode] = useState('live'); const [viewMode, setViewMode] = useState('live');
const cameraConfig = config?.cameras[camera]; const cameraConfig = config?.cameras[camera];
const liveWidth = Math.round(cameraConfig.live.height * (cameraConfig.detect.width / cameraConfig.detect.height)) const liveWidth = Math.round(cameraConfig.live.height * (cameraConfig.detect.width / cameraConfig.detect.height));
const [options, setOptions] = usePersistence(`${camera}-feed`, emptyObject); const [options, setOptions] = usePersistence(`${camera}-feed`, emptyObject);
const handleSetOption = useCallback( const handleSetOption = useCallback(
@ -48,36 +48,36 @@ export default function Camera({ camera }) {
}, [showSettings, setShowSettings]); }, [showSettings, setShowSettings]);
const optionContent = showSettings ? ( const optionContent = showSettings ? (
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"> <div className='grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4'>
<Switch <Switch
checked={options['bbox']} checked={options['bbox']}
id="bbox" id='bbox'
onChange={handleSetOption} onChange={handleSetOption}
label="Bounding box" label='Bounding box'
labelPosition="after" labelPosition='after'
/> />
<Switch <Switch
checked={options['timestamp']} checked={options['timestamp']}
id="timestamp" id='timestamp'
onChange={handleSetOption} onChange={handleSetOption}
label="Timestamp" label='Timestamp'
labelPosition="after" labelPosition='after'
/> />
<Switch checked={options['zones']} id="zones" onChange={handleSetOption} label="Zones" labelPosition="after" /> <Switch checked={options['zones']} id='zones' onChange={handleSetOption} label='Zones' labelPosition='after' />
<Switch checked={options['mask']} id="mask" onChange={handleSetOption} label="Masks" labelPosition="after" /> <Switch checked={options['mask']} id='mask' onChange={handleSetOption} label='Masks' labelPosition='after' />
<Switch <Switch
checked={options['motion']} checked={options['motion']}
id="motion" id='motion'
onChange={handleSetOption} onChange={handleSetOption}
label="Motion boxes" label='Motion boxes'
labelPosition="after" labelPosition='after'
/> />
<Switch <Switch
checked={options['regions']} checked={options['regions']}
id="regions" id='regions'
onChange={handleSetOption} onChange={handleSetOption}
label="Regions" label='Regions'
labelPosition="after" labelPosition='after'
/> />
<Link href={`/cameras/${camera}/editor`}>Mask & Zone creator</Link> <Link href={`/cameras/${camera}/editor`}>Mask & Zone creator</Link>
</div> </div>
@ -92,38 +92,37 @@ export default function Camera({ camera }) {
</div> </div>
</Fragment> </Fragment>
); );
} } else if (viewMode === 'debug') {
else if (viewMode === 'debug') {
player = ( player = (
<Fragment> <Fragment>
<div> <div>
<AutoUpdatingCameraImage camera={camera} searchParams={searchParams} /> <AutoUpdatingCameraImage camera={camera} searchParams={searchParams} />
</div> </div>
<Button onClick={handleToggleSettings} type="text"> <Button onClick={handleToggleSettings} type='text'>
<span className="w-5 h-5"> <span className='w-5 h-5'>
<SettingsIcon /> <SettingsIcon />
</span>{' '} </span>{' '}
<span>{showSettings ? 'Hide' : 'Show'} Options</span> <span>{showSettings ? 'Hide' : 'Show'} Options</span>
</Button> </Button>
{showSettings ? <Card header="Options" elevated={false} content={optionContent} /> : null} {showSettings ? <Card header='Options' elevated={false} content={optionContent} /> : null}
</Fragment> </Fragment>
); );
} }
return ( return (
<div className="space-y-4"> <div className='space-y-4 p-2 px-4'>
<Heading size="2xl">{camera}</Heading> <Heading size='2xl'>{camera}</Heading>
<ButtonsTabbed viewModes={['live', 'debug']} setViewMode={setViewMode} /> <ButtonsTabbed viewModes={['live', 'debug']} setViewMode={setViewMode} />
{player} {player}
<div className="space-y-4"> <div className='space-y-4'>
<Heading size="sm">Tracked objects</Heading> <Heading size='sm'>Tracked objects</Heading>
<div className="flex flex-wrap justify-start"> <div className='flex flex-wrap justify-start'>
{cameraConfig.objects.track.map((objectType) => ( {cameraConfig.objects.track.map((objectType) => (
<Card <Card
className="mb-4 mr-4" className='mb-4 mr-4'
key={objectType} key={objectType}
header={objectType} header={objectType}
href={`/events?camera=${camera}&label=${objectType}`} href={`/events?camera=${camera}&label=${objectType}`}