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:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user