mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-02 09:15:22 +03:00
feat: add experimental feature + fix old camera padding
This commit is contained in:
parent
e7ab6d2d0d
commit
875c74686d
@ -43,6 +43,8 @@ class DetectorConfig(FrigateBaseModel):
|
||||
device: str = Field(default="usb", title="Device Type")
|
||||
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):
|
||||
host: str = Field(title="MQTT Host")
|
||||
@ -682,6 +684,7 @@ class FrigateConfig(FrigateBaseModel):
|
||||
environment_vars: Dict[str, str] = Field(
|
||||
default_factory=dict, title="Frigate environment variables."
|
||||
)
|
||||
ui: UIConfig = Field(default_factory=UIConfig, title="UI configuration.")
|
||||
model: ModelConfig = Field(
|
||||
default_factory=ModelConfig, title="Detection model configuration."
|
||||
)
|
||||
|
||||
@ -10,29 +10,30 @@ import { DarkModeProvider, DrawerProvider } from './context';
|
||||
import { FetchStatus, useConfig } from './api';
|
||||
|
||||
export default function App() {
|
||||
const { status } = useConfig();
|
||||
const { status, data: config } = useConfig();
|
||||
const cameraComponent = config && config.ui.useExperimentalUI ? Routes.getCameraV2 : Routes.getCamera;
|
||||
return (
|
||||
<DarkModeProvider>
|
||||
<DrawerProvider>
|
||||
<div data-testid="app" className="w-full">
|
||||
<div data-testid='app' className='w-full'>
|
||||
<AppBar />
|
||||
{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 />
|
||||
</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 />
|
||||
<div className="w-full flex-auto mt-16 min-w-0">
|
||||
<div className='w-full flex-auto mt-16 min-w-0'>
|
||||
<Router>
|
||||
<AsyncRoute path="/cameras/:camera/editor" getComponent={Routes.getCameraMap} />
|
||||
<AsyncRoute path="/cameras/:camera" getComponent={Routes.getCameraV2} />
|
||||
<AsyncRoute path="/birdseye" getComponent={Routes.getBirdseye} />
|
||||
<AsyncRoute path="/events" getComponent={Routes.getEvents} />
|
||||
<AsyncRoute path="/recording/:camera/:date?/:hour?/:seconds?" getComponent={Routes.getRecording} />
|
||||
<AsyncRoute path="/debug" getComponent={Routes.getDebug} />
|
||||
<AsyncRoute path="/styleguide" getComponent={Routes.getStyleGuide} />
|
||||
<Cameras default path="/" />
|
||||
<AsyncRoute path='/cameras/:camera/editor' getComponent={Routes.getCameraMap} />
|
||||
<AsyncRoute path='/cameras/:camera' getComponent={cameraComponent} />
|
||||
<AsyncRoute path='/birdseye' getComponent={Routes.getBirdseye} />
|
||||
<AsyncRoute path='/events' getComponent={Routes.getEvents} />
|
||||
<AsyncRoute path='/recording/:camera/:date?/:hour?/:seconds?' getComponent={Routes.getRecording} />
|
||||
<AsyncRoute path='/debug' getComponent={Routes.getDebug} />
|
||||
<AsyncRoute path='/styleguide' getComponent={Routes.getStyleGuide} />
|
||||
<Cameras default path='/' />
|
||||
</Router>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -162,7 +162,9 @@ export default function Timeline({ events, offset, currentIndex, onChange }) {
|
||||
<div className='relative flex-grow-1'>
|
||||
<div className='absolute left-0 top-0 h-full w-full' style={{ 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
|
||||
className='z-20 h-full absolute'
|
||||
style={{
|
||||
|
||||
@ -21,7 +21,7 @@ export default function Camera({ camera }) {
|
||||
const [viewMode, setViewMode] = useState('live');
|
||||
|
||||
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 handleSetOption = useCallback(
|
||||
@ -48,36 +48,36 @@ export default function Camera({ camera }) {
|
||||
}, [showSettings, setShowSettings]);
|
||||
|
||||
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
|
||||
checked={options['bbox']}
|
||||
id="bbox"
|
||||
id='bbox'
|
||||
onChange={handleSetOption}
|
||||
label="Bounding box"
|
||||
labelPosition="after"
|
||||
label='Bounding box'
|
||||
labelPosition='after'
|
||||
/>
|
||||
<Switch
|
||||
checked={options['timestamp']}
|
||||
id="timestamp"
|
||||
id='timestamp'
|
||||
onChange={handleSetOption}
|
||||
label="Timestamp"
|
||||
labelPosition="after"
|
||||
label='Timestamp'
|
||||
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['zones']} id='zones' onChange={handleSetOption} label='Zones' labelPosition='after' />
|
||||
<Switch checked={options['mask']} id='mask' onChange={handleSetOption} label='Masks' labelPosition='after' />
|
||||
<Switch
|
||||
checked={options['motion']}
|
||||
id="motion"
|
||||
id='motion'
|
||||
onChange={handleSetOption}
|
||||
label="Motion boxes"
|
||||
labelPosition="after"
|
||||
label='Motion boxes'
|
||||
labelPosition='after'
|
||||
/>
|
||||
<Switch
|
||||
checked={options['regions']}
|
||||
id="regions"
|
||||
id='regions'
|
||||
onChange={handleSetOption}
|
||||
label="Regions"
|
||||
labelPosition="after"
|
||||
label='Regions'
|
||||
labelPosition='after'
|
||||
/>
|
||||
<Link href={`/cameras/${camera}/editor`}>Mask & Zone creator</Link>
|
||||
</div>
|
||||
@ -92,38 +92,37 @@ export default function Camera({ camera }) {
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
else if (viewMode === 'debug') {
|
||||
} else if (viewMode === 'debug') {
|
||||
player = (
|
||||
<Fragment>
|
||||
<div>
|
||||
<AutoUpdatingCameraImage camera={camera} searchParams={searchParams} />
|
||||
</div>
|
||||
|
||||
<Button onClick={handleToggleSettings} type="text">
|
||||
<span className="w-5 h-5">
|
||||
<Button onClick={handleToggleSettings} type='text'>
|
||||
<span className='w-5 h-5'>
|
||||
<SettingsIcon />
|
||||
</span>{' '}
|
||||
<span>{showSettings ? 'Hide' : 'Show'} Options</span>
|
||||
</Button>
|
||||
{showSettings ? <Card header="Options" elevated={false} content={optionContent} /> : null}
|
||||
{showSettings ? <Card header='Options' elevated={false} content={optionContent} /> : null}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Heading size="2xl">{camera}</Heading>
|
||||
<div className='space-y-4 p-2 px-4'>
|
||||
<Heading size='2xl'>{camera}</Heading>
|
||||
<ButtonsTabbed viewModes={['live', 'debug']} setViewMode={setViewMode} />
|
||||
|
||||
{player}
|
||||
|
||||
<div className="space-y-4">
|
||||
<Heading size="sm">Tracked objects</Heading>
|
||||
<div className="flex flex-wrap justify-start">
|
||||
<div className='space-y-4'>
|
||||
<Heading size='sm'>Tracked objects</Heading>
|
||||
<div className='flex flex-wrap justify-start'>
|
||||
{cameraConfig.objects.track.map((objectType) => (
|
||||
<Card
|
||||
className="mb-4 mr-4"
|
||||
className='mb-4 mr-4'
|
||||
key={objectType}
|
||||
header={objectType}
|
||||
href={`/events?camera=${camera}&label=${objectType}`}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user