/// Configuration for function buttons (F1-F7) per wall. /// Loaded from the "functionButtons" section of the config file. class FunctionButtonConfig { final Map>> walls; const FunctionButtonConfig({this.walls = const {}}); /// Get actions for a specific wall and button. List 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 json) { final wallsJson = json['walls'] as Map? ?? {}; final walls = >>{}; for (final wallEntry in wallsJson.entries) { final buttonsJson = wallEntry.value as Map? ?? {}; final buttons = >{}; for (final buttonEntry in buttonsJson.entries) { final actionsJson = buttonEntry.value as List? ?? []; buttons[buttonEntry.key] = actionsJson .map((a) => FunctionButtonAction.fromJson(a as Map)) .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 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; } } }