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,90 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../../data/services/coordination_service.dart';
|
||||
import '../../../domain/entities/sequence.dart';
|
||||
import 'sequence_event.dart';
|
||||
import 'sequence_state.dart';
|
||||
|
||||
class SequenceBloc extends Bloc<SequenceEvent, SequenceState> {
|
||||
final CoordinationService _coordinationService;
|
||||
|
||||
SequenceBloc({required CoordinationService coordinationService})
|
||||
: _coordinationService = coordinationService,
|
||||
super(const SequenceState()) {
|
||||
on<LoadSequences>(_onLoadSequences);
|
||||
on<StartSequence>(_onStartSequence);
|
||||
on<StopSequence>(_onStopSequence);
|
||||
on<SelectCategory>(_onSelectCategory);
|
||||
}
|
||||
|
||||
Future<void> _onLoadSequences(
|
||||
LoadSequences event, Emitter<SequenceState> emit) async {
|
||||
emit(state.copyWith(isLoading: true, clearError: true));
|
||||
|
||||
try {
|
||||
final sequencesJson = await _coordinationService.getSequences();
|
||||
final categoriesJson = await _coordinationService.getSequenceCategories();
|
||||
final runningJson = await _coordinationService.getRunningSequences();
|
||||
|
||||
final sequences = sequencesJson
|
||||
.map((j) => SequenceDefinition.fromJson(j))
|
||||
.toList();
|
||||
final categories =
|
||||
categoriesJson.map((j) => SequenceCategory.fromJson(j)).toList();
|
||||
|
||||
final running = <int, RunningSequence>{};
|
||||
for (final j in runningJson) {
|
||||
final rs = RunningSequence.fromJson(j);
|
||||
running[rs.viewerId] = rs;
|
||||
}
|
||||
|
||||
emit(state.copyWith(
|
||||
sequences: sequences,
|
||||
categories: categories,
|
||||
running: running,
|
||||
isLoading: false,
|
||||
));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(isLoading: false, error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onStartSequence(
|
||||
StartSequence event, Emitter<SequenceState> emit) async {
|
||||
try {
|
||||
final result = await _coordinationService.startSequence(
|
||||
event.viewerId, event.sequenceId);
|
||||
|
||||
if (result != null) {
|
||||
final rs = RunningSequence.fromJson(result);
|
||||
final running = Map<int, RunningSequence>.from(state.running);
|
||||
running[rs.viewerId] = rs;
|
||||
emit(state.copyWith(running: running));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(state.copyWith(error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onStopSequence(
|
||||
StopSequence event, Emitter<SequenceState> emit) async {
|
||||
try {
|
||||
await _coordinationService.stopSequence(event.viewerId);
|
||||
|
||||
final running = Map<int, RunningSequence>.from(state.running);
|
||||
running.remove(event.viewerId);
|
||||
emit(state.copyWith(running: running));
|
||||
} catch (e) {
|
||||
emit(state.copyWith(error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
void _onSelectCategory(
|
||||
SelectCategory event, Emitter<SequenceState> emit) {
|
||||
if (event.categoryId == null) {
|
||||
emit(state.copyWith(clearCategory: true));
|
||||
} else {
|
||||
emit(state.copyWith(selectedCategoryId: event.categoryId));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user