Flutter web app replacing legacy WPF CCTV surveillance keyboard controller. Includes wall overview, section view with monitor grid, camera input, PTZ control, alarm/lock/sequence BLoCs, and legacy-matching UI styling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
395 lines
12 KiB
Markdown
395 lines
12 KiB
Markdown
# Flutter COPILOT Keyboard UI Design
|
|
|
|
## Overview
|
|
|
|
This document defines the Flutter UI implementation based on the existing D6 application and the Klavesnice Business Analysis specification.
|
|
|
|
## Screen Structure
|
|
|
|
### 1. Main Screen (Basic View)
|
|
|
|
The main screen consists of three primary areas:
|
|
|
|
```
|
|
+--------------------------------------------------+
|
|
| Connection Status Bar |
|
|
+--------------------------------------------------+
|
|
| |
|
|
| Video Wall Grid |
|
|
| (Physical Monitors with Viewers) |
|
|
| |
|
|
+--------------------------------------------------+
|
|
| Bottom Toolbar |
|
|
+--------------------------------------------------+
|
|
```
|
|
|
|
### 2. Video Wall Grid
|
|
|
|
Based on D6 screenshots, the wall is divided into **5 sections**:
|
|
- Vrchní část (Top section) - monitors 210-234
|
|
- Pravá část (Right section)
|
|
- Levá část (Left section)
|
|
- Dolní část (Bottom section)
|
|
- Střední část (Middle section)
|
|
|
|
Each section contains:
|
|
- Section header with name
|
|
- Grid of physical monitors
|
|
- Each physical monitor can contain 1-4 viewers (quad view)
|
|
|
|
#### Monitor Display States
|
|
|
|
| State | Visual |
|
|
|-------|--------|
|
|
| Normal | Dark background, white text |
|
|
| Selected (touched) | Cyan/blue border (thick) |
|
|
| Active Alarm | Red background |
|
|
| Alarm + Selected | Red background + cyan border |
|
|
| Locked by current user | Lock icon visible |
|
|
| Locked by other user | Lock icon + disabled |
|
|
|
|
#### Viewer Number Display
|
|
|
|
- Each viewer shows its viewer number (e.g., 210, 211, 212, 213)
|
|
- Quad view: 4 viewers in one physical monitor with visible border around physical monitor
|
|
- Single view: One viewer fills the physical monitor
|
|
|
|
### 3. Bottom Toolbar (Button Strip)
|
|
|
|
Dynamic button strip that changes based on context:
|
|
|
|
#### Default State (No Selection)
|
|
```
|
|
[Search] [500] [501] [502] [HOME] [F1] [F2] [F3] [F4] [F5] [F6] [F7]
|
|
```
|
|
|
|
#### Monitor Selected (Camera View)
|
|
```
|
|
[←] [PREPOS] [PvZ] [ALARM] [LOCK/UNLOCK] [SEARCH]
|
|
```
|
|
|
|
Where:
|
|
- **←** Back to default
|
|
- **PREPOS** Open preposition list (only for PTZ cameras when unlocked)
|
|
- **PvZ** Enter playback mode (only if keyboard has permission)
|
|
- **ALARM** Open alarm history list
|
|
- **LOCK/UNLOCK** Toggle PTZ lock
|
|
- **SEARCH** Open camera search dialog
|
|
|
|
### 4. Camera Prefix Selection
|
|
|
|
Three prefix buttons for camera number input:
|
|
- **500** - GeViScope cameras (500001-500999)
|
|
- **501** - G-CORE cameras (501001-501999)
|
|
- **502** - GeViServer cameras (502001-502999)
|
|
|
|
Selected prefix is highlighted. User then types 3-digit camera number.
|
|
|
|
### 5. Camera Number Input
|
|
|
|
```
|
|
+----------------------------------+
|
|
| Input Field: [500] + [ ] |
|
|
| Current: 500201 |
|
|
+----------------------------------+
|
|
| [1] [2] [3] |
|
|
| [4] [5] [6] |
|
|
| [7] [8] [9] |
|
|
| [C] [0] [OK] |
|
|
+----------------------------------+
|
|
```
|
|
|
|
- Number input via touchscreen or physical USB keyboard
|
|
- C = Clear, OK = Confirm CrossSwitch
|
|
- ESC/Back = Cancel
|
|
|
|
---
|
|
|
|
## Secondary Screens
|
|
|
|
### 6. Search Screen
|
|
|
|
Opened via Search button when monitor is selected:
|
|
|
|
```
|
|
+--------------------------------------------------+
|
|
| Search Camera [X] |
|
|
+--------------------------------------------------+
|
|
| Camera Number: [________] |
|
|
| |
|
|
| [Keyboard toggle] |
|
|
+--------------------------------------------------+
|
|
| Search Results: |
|
|
| [500001 - Jindřišská, tramvaj] |
|
|
| [500002 - Václavské náměstí] |
|
|
| ... |
|
|
+--------------------------------------------------+
|
|
| [←] [OK] |
|
|
+--------------------------------------------------+
|
|
```
|
|
|
|
### 7. Preposition List Screen
|
|
|
|
```
|
|
+--------------------------------------------------+
|
|
| PREPOZICE - Kamera 500005 [X] |
|
|
+--------------------------------------------------+
|
|
| [2] Jindřišská, tramvajový ostrůvek |
|
|
| [10] Jindřišská, křižovatka [●] |
|
|
| [15] U Bulhara směr centrum |
|
|
| ... |
|
|
+--------------------------------------------------+
|
|
| [←] [+] [🗑] [✓] |
|
|
+--------------------------------------------------+
|
|
```
|
|
|
|
- Blue highlight on selected preposition
|
|
- [+] Add new preposition (disabled if AppServer unavailable)
|
|
- [🗑] Delete preposition (disabled if editable=0 or positions 1-9)
|
|
- [✓] Confirm/go to selected preposition
|
|
|
|
### 8. Add Preposition Screen
|
|
|
|
```
|
|
+--------------------------------------------------+
|
|
| Nová prepozice - Kamera 500005 [X] |
|
|
+--------------------------------------------------+
|
|
| Číslo prepozice: [__] (10-99 only) |
|
|
| |
|
|
| Název prepozice: [________________] |
|
|
| |
|
|
| [Keyboard] |
|
|
+--------------------------------------------------+
|
|
| [←] [ULOŽIT] |
|
|
+--------------------------------------------------+
|
|
```
|
|
|
|
Save button disabled until both fields filled.
|
|
|
|
### 9. Playback Mode (PvZ) Screen
|
|
|
|
Overlay controls on main view:
|
|
|
|
```
|
|
+--------------------------------------------------+
|
|
| PvZ: Kamera 500005 |
|
|
| Čas: 2026-02-03 14:35:22 |
|
|
+--------------------------------------------------+
|
|
| [|◄] [◄◄] [◄] [⏸] [►] [►►] [►|] [LIVE] |
|
|
+--------------------------------------------------+
|
|
| Speed: [-7 ... -1] [0] [+1 ... +7] |
|
|
+--------------------------------------------------+
|
|
```
|
|
|
|
Jog-shuttle speed table:
|
|
- Position -7 to -1: Reverse (slow to fast)
|
|
- Position 0: Pause
|
|
- Position +1 to +7: Forward (slow to fast)
|
|
|
|
### 10. Alarm List Screen
|
|
|
|
```
|
|
+--------------------------------------------------+
|
|
| Alarmy - Kamera 500005 [X] |
|
|
+--------------------------------------------------+
|
|
| Od: [2026-02-01] [📅] Do: [2026-02-03] [📅] |
|
|
+--------------------------------------------------+
|
|
| Začátek | Konec |
|
|
| 02-03 14:30:15 | 02-03 14:32:45 [●] |
|
|
| 02-03 12:15:30 | 02-03 12:18:22 |
|
|
| 02-02 23:45:00 | 02-02 23:47:15 |
|
|
+--------------------------------------------------+
|
|
| [←] [LIVE] [⏩] [▶⏩] [◄◄] [⏸] |
|
|
+--------------------------------------------------+
|
|
```
|
|
|
|
- [⏩] Jump to timestamp (paused)
|
|
- [▶⏩] Jump to timestamp and play
|
|
- [◄◄] Reverse playback
|
|
- [⏸] Stop playback
|
|
- [LIVE] Return to live stream
|
|
|
|
### 11. Function Button Config (F1-F7, HOME)
|
|
|
|
Each function button triggers predefined wall configuration:
|
|
- Stored on Application Server
|
|
- Can set camera or sequence per monitor
|
|
- Before CrossSwitch, check if sequence is running and stop it
|
|
|
|
### 12. Service Menu
|
|
|
|
Activated by holding Backspace for 3 seconds:
|
|
|
|
```
|
|
+----------------------------------+
|
|
| Servisní Menu [X] |
|
|
+----------------------------------+
|
|
| (1) Restartovat aplikaci |
|
|
| (2) Restartovat klávesnici |
|
|
| (3) Vypnout klávesnici |
|
|
+----------------------------------+
|
|
```
|
|
|
|
---
|
|
|
|
## Component Specifications
|
|
|
|
### Color Palette
|
|
|
|
| Element | Color | Hex |
|
|
|---------|-------|-----|
|
|
| Background | Dark blue-gray | #1a2332 |
|
|
| Monitor normal | Dark gray | #2d3748 |
|
|
| Monitor selected | Cyan border | #00d4ff |
|
|
| Monitor alarm | Red | #ff4444 |
|
|
| Button active | Blue | #3182ce |
|
|
| Button disabled | Gray | #4a5568 |
|
|
| Text primary | White | #ffffff |
|
|
| Text secondary | Gray | #a0aec0 |
|
|
| Preposition highlight | Blue | #2b6cb0 |
|
|
|
|
### Typography
|
|
|
|
- Monitor numbers: Monospace, bold, 16-20px
|
|
- Section headers: Sans-serif, semibold, 14px
|
|
- Button labels: Sans-serif, medium, 12-14px
|
|
- Input fields: Monospace, regular, 16px
|
|
|
|
### Touch Targets
|
|
|
|
- Minimum touch target: 44x44 pixels
|
|
- Monitor tiles: Variable (based on grid)
|
|
- Toolbar buttons: 48px height
|
|
- List items: 48px height minimum
|
|
|
|
---
|
|
|
|
## State Management (BLoC)
|
|
|
|
### Required BLoCs
|
|
|
|
1. **ConnectionBloc** - Server connection states
|
|
2. **WallBloc** - Video wall state, monitor selection
|
|
3. **AlarmBloc** - Active alarms, alarm history
|
|
4. **CameraBloc** - Camera input, CrossSwitch operations
|
|
5. **PTZBloc** - Lock state, telemetry controls
|
|
6. **PlaybackBloc** - PvZ mode, jog-shuttle
|
|
7. **PrepositionBloc** - Preposition list, add/delete
|
|
8. **FunctionButtonBloc** - Function button configurations
|
|
9. **SequenceBloc** - Sequence state per monitor
|
|
|
|
### Events & States Example (WallBloc)
|
|
|
|
```dart
|
|
// Events
|
|
abstract class WallEvent {}
|
|
class LoadWallConfig extends WallEvent {}
|
|
class SelectMonitor extends WallEvent { final int viewerId; }
|
|
class DeselectMonitor extends WallEvent {}
|
|
class CrossSwitchCamera extends WallEvent { final int cameraId; final int viewerId; }
|
|
|
|
// States
|
|
abstract class WallState {}
|
|
class WallLoading extends WallState {}
|
|
class WallLoaded extends WallState {
|
|
final List<WallSection> sections;
|
|
final int? selectedViewerId;
|
|
final int? selectedPhysicalMonitorId;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Implementation Priority
|
|
|
|
### Phase 1: Core UI (MVP)
|
|
1. Main screen layout with wall grid
|
|
2. Monitor selection (touch)
|
|
3. Camera number input (prefix + digits)
|
|
4. CrossSwitch command
|
|
5. Connection status bar
|
|
|
|
### Phase 2: Alarms & Status
|
|
1. Alarm state display (red monitors)
|
|
2. Alarm blocking (prevent CrossSwitch on active alarm)
|
|
3. Monitor lock indicators
|
|
|
|
### Phase 3: PTZ & Playback
|
|
1. PTZ lock/unlock
|
|
2. Telemetry controls (pan/tilt/zoom)
|
|
3. Playback mode (PvZ)
|
|
4. Jog-shuttle controls
|
|
|
|
### Phase 4: Advanced Features
|
|
1. Preposition management
|
|
2. Alarm history list
|
|
3. Function buttons (F1-F7, HOME)
|
|
4. Sequences
|
|
5. Search functionality
|
|
|
|
### Phase 5: Polish
|
|
1. Service menu
|
|
2. CAMEA integration
|
|
3. Autonomous mode fallbacks
|
|
4. Error handling dialogs
|
|
|
|
---
|
|
|
|
## Autonomous Mode Behavior
|
|
|
|
When Application Server is unavailable:
|
|
|
|
| Feature | Available | Notes |
|
|
|---------|-----------|-------|
|
|
| CrossSwitch | ✓ | Direct to bridge |
|
|
| PTZ Lock | ✓ | Local lock only |
|
|
| CAMEA Reserve | ✓ | Direct to CAMEA |
|
|
| Preposition List | ✓ | Cached config |
|
|
| Add Preposition | ✗ | Requires AppServer |
|
|
| Delete Preposition | ✗ | Requires AppServer |
|
|
| Sequences | ✗ | Run by AppServer |
|
|
| Function Buttons | ✓ | Cached config |
|
|
| Alarm Management | ✗ | Run by GeViSoft |
|
|
|
|
---
|
|
|
|
## File Structure
|
|
|
|
```
|
|
lib/
|
|
├── presentation/
|
|
│ ├── screens/
|
|
│ │ ├── main_screen.dart
|
|
│ │ ├── search_screen.dart
|
|
│ │ ├── preposition_screen.dart
|
|
│ │ ├── alarm_list_screen.dart
|
|
│ │ ├── playback_overlay.dart
|
|
│ │ └── service_menu_dialog.dart
|
|
│ ├── widgets/
|
|
│ │ ├── wall_grid/
|
|
│ │ │ ├── wall_grid.dart
|
|
│ │ │ ├── wall_section.dart
|
|
│ │ │ ├── physical_monitor.dart
|
|
│ │ │ └── viewer_tile.dart
|
|
│ │ ├── toolbar/
|
|
│ │ │ ├── bottom_toolbar.dart
|
|
│ │ │ ├── prefix_buttons.dart
|
|
│ │ │ ├── function_buttons.dart
|
|
│ │ │ └── action_buttons.dart
|
|
│ │ ├── input/
|
|
│ │ │ ├── camera_input.dart
|
|
│ │ │ ├── numeric_keypad.dart
|
|
│ │ │ └── datetime_picker.dart
|
|
│ │ └── common/
|
|
│ │ ├── connection_status_bar.dart
|
|
│ │ └── confirmation_dialog.dart
|
|
│ └── blocs/
|
|
│ ├── wall/
|
|
│ ├── alarm/
|
|
│ ├── camera/
|
|
│ ├── ptz/
|
|
│ ├── playback/
|
|
│ ├── preposition/
|
|
│ └── function_button/
|
|
```
|