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,64 @@
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
import '../../../config/app_config.dart';
|
||||
import '../../../data/services/bridge_service.dart';
|
||||
import 'camera_event.dart';
|
||||
import 'camera_state.dart';
|
||||
|
||||
class CameraBloc extends Bloc<CameraEvent, CameraState> {
|
||||
final BridgeService _bridgeService;
|
||||
final AppConfig _config;
|
||||
|
||||
CameraBloc({
|
||||
required BridgeService bridgeService,
|
||||
required AppConfig config,
|
||||
}) : _bridgeService = bridgeService,
|
||||
_config = config,
|
||||
super(CameraState(availableCameras: config.allCameraIds)) {
|
||||
on<SelectCamera>(_onSelectCamera);
|
||||
on<ConnectCameraToMonitor>(_onConnectCameraToMonitor);
|
||||
on<ClearCameraSelection>(_onClearCameraSelection);
|
||||
}
|
||||
|
||||
void _onSelectCamera(
|
||||
SelectCamera event,
|
||||
Emitter<CameraState> emit,
|
||||
) {
|
||||
emit(state.copyWith(selectedCameraId: event.cameraId, error: null));
|
||||
}
|
||||
|
||||
Future<void> _onConnectCameraToMonitor(
|
||||
ConnectCameraToMonitor event,
|
||||
Emitter<CameraState> emit,
|
||||
) async {
|
||||
emit(state.copyWith(isConnecting: true, error: null));
|
||||
|
||||
try {
|
||||
final success = await _bridgeService.viewerConnectLive(
|
||||
event.monitorId,
|
||||
event.cameraId,
|
||||
);
|
||||
|
||||
if (success) {
|
||||
emit(state.copyWith(isConnecting: false));
|
||||
} else {
|
||||
emit(state.copyWith(
|
||||
isConnecting: false,
|
||||
error: 'Failed to connect camera ${event.cameraId} to monitor ${event.monitorId}',
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(state.copyWith(
|
||||
isConnecting: false,
|
||||
error: e.toString(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void _onClearCameraSelection(
|
||||
ClearCameraSelection event,
|
||||
Emitter<CameraState> emit,
|
||||
) {
|
||||
emit(state.copyWith(clearSelection: true, error: null));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
abstract class CameraEvent extends Equatable {
|
||||
const CameraEvent();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
|
||||
/// Select a camera for viewing/control
|
||||
class SelectCamera extends CameraEvent {
|
||||
final int cameraId;
|
||||
|
||||
const SelectCamera(this.cameraId);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [cameraId];
|
||||
}
|
||||
|
||||
/// Connect selected camera to a monitor
|
||||
class ConnectCameraToMonitor extends CameraEvent {
|
||||
final int cameraId;
|
||||
final int monitorId;
|
||||
|
||||
const ConnectCameraToMonitor({
|
||||
required this.cameraId,
|
||||
required this.monitorId,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [cameraId, monitorId];
|
||||
}
|
||||
|
||||
/// Clear selection
|
||||
class ClearCameraSelection extends CameraEvent {
|
||||
const ClearCameraSelection();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class CameraState extends Equatable {
|
||||
final int? selectedCameraId;
|
||||
final bool isConnecting;
|
||||
final String? error;
|
||||
final List<int> availableCameras;
|
||||
|
||||
const CameraState({
|
||||
this.selectedCameraId,
|
||||
this.isConnecting = false,
|
||||
this.error,
|
||||
this.availableCameras = const [],
|
||||
});
|
||||
|
||||
bool get hasSelection => selectedCameraId != null;
|
||||
|
||||
CameraState copyWith({
|
||||
int? selectedCameraId,
|
||||
bool? isConnecting,
|
||||
String? error,
|
||||
List<int>? availableCameras,
|
||||
bool clearSelection = false,
|
||||
}) {
|
||||
return CameraState(
|
||||
selectedCameraId:
|
||||
clearSelection ? null : (selectedCameraId ?? this.selectedCameraId),
|
||||
isConnecting: isConnecting ?? this.isConnecting,
|
||||
error: error,
|
||||
availableCameras: availableCameras ?? this.availableCameras,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props =>
|
||||
[selectedCameraId, isConnecting, error, availableCameras];
|
||||
}
|
||||
Reference in New Issue
Block a user