Initial commit: COPILOT D6 Flutter keyboard controller

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>
This commit is contained in:
klas
2026-02-12 14:57:38 +01:00
commit 40143734fc
125 changed files with 65073 additions and 0 deletions

View File

@@ -0,0 +1,77 @@
/// Configuration for function buttons (F1-F7) per wall.
/// Loaded from the "functionButtons" section of the config file.
class FunctionButtonConfig {
final Map<String, Map<String, List<FunctionButtonAction>>> walls;
const FunctionButtonConfig({this.walls = const {}});
/// Get actions for a specific wall and button.
List<FunctionButtonAction> getActions(String wallId, String buttonKey) {
return walls[wallId]?[buttonKey] ?? [];
}
/// Check if a button has any actions configured for this wall.
bool hasActions(String wallId, String buttonKey) {
return getActions(wallId, buttonKey).isNotEmpty;
}
factory FunctionButtonConfig.fromJson(Map<String, dynamic> json) {
final wallsJson = json['walls'] as Map<String, dynamic>? ?? {};
final walls = <String, Map<String, List<FunctionButtonAction>>>{};
for (final wallEntry in wallsJson.entries) {
final buttonsJson = wallEntry.value as Map<String, dynamic>? ?? {};
final buttons = <String, List<FunctionButtonAction>>{};
for (final buttonEntry in buttonsJson.entries) {
final actionsJson = buttonEntry.value as List<dynamic>? ?? [];
buttons[buttonEntry.key] = actionsJson
.map((a) =>
FunctionButtonAction.fromJson(a as Map<String, dynamic>))
.toList();
}
walls[wallEntry.key] = buttons;
}
return FunctionButtonConfig(walls: walls);
}
}
/// A single action triggered by a function button press.
class FunctionButtonAction {
final FunctionButtonActionType type;
final int viewerId;
final int sourceId;
const FunctionButtonAction({
required this.type,
required this.viewerId,
required this.sourceId,
});
factory FunctionButtonAction.fromJson(Map<String, dynamic> json) {
return FunctionButtonAction(
type: FunctionButtonActionType.fromString(
json['actionType'] as String? ?? ''),
viewerId: json['viewerId'] as int? ?? 0,
sourceId: json['sourceId'] as int? ?? 0,
);
}
}
enum FunctionButtonActionType {
crossSwitch,
sequenceStart;
static FunctionButtonActionType fromString(String value) {
switch (value.toLowerCase()) {
case 'crossswitch':
return FunctionButtonActionType.crossSwitch;
case 'sequencestart':
return FunctionButtonActionType.sequenceStart;
default:
return FunctionButtonActionType.crossSwitch;
}
}
}