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,67 @@
import 'package:logger/logger.dart';
import '../../domain/entities/function_button_config.dart';
import 'bridge_service.dart';
import 'coordination_service.dart';
/// Executes function button actions (F1-F7).
/// Ported from legacy FunctionButtonsService.cs.
class FunctionButtonService {
final BridgeService _bridgeService;
final CoordinationService _coordinationService;
final Logger _logger = Logger();
FunctionButtonConfig _config = const FunctionButtonConfig();
FunctionButtonService({
required BridgeService bridgeService,
required CoordinationService coordinationService,
}) : _bridgeService = bridgeService,
_coordinationService = coordinationService;
/// Load function button configuration.
void loadConfig(FunctionButtonConfig config) {
_config = config;
_logger.i('Loaded function button config: ${config.walls.length} walls');
}
/// Execute all actions for a button on a specific wall.
/// Actions are executed sequentially (like legacy).
Future<bool> execute(String wallId, String buttonKey) async {
final actions = _config.getActions(wallId, buttonKey);
if (actions.isEmpty) {
_logger.d('No actions for $buttonKey on wall $wallId');
return false;
}
_logger.i('Executing $buttonKey on wall $wallId (${actions.length} actions)');
for (final action in actions) {
try {
switch (action.type) {
case FunctionButtonActionType.crossSwitch:
await _bridgeService.viewerConnectLive(
action.viewerId, action.sourceId);
_logger.d(
'CrossSwitch: viewer ${action.viewerId} -> camera ${action.sourceId}');
case FunctionButtonActionType.sequenceStart:
await _coordinationService.startSequence(
action.viewerId, action.sourceId);
_logger.d(
'SequenceStart: viewer ${action.viewerId} -> sequence ${action.sourceId}');
}
} catch (e) {
_logger.e(
'Function button action failed: ${action.type.name} - $e');
}
}
return true;
}
/// Check if a button has actions for a given wall.
bool hasActions(String wallId, String buttonKey) {
return _config.hasActions(wallId, buttonKey);
}
}