Files
COPILOT/copilot_keyboard/lib/presentation/blocs/connection/connection_bloc.dart
klas 40143734fc 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>
2026-02-12 14:57:38 +01:00

121 lines
3.2 KiB
Dart

import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../config/app_config.dart';
import '../../../data/services/bridge_service.dart';
import 'connection_event.dart';
import 'connection_state.dart';
class ConnectionBloc extends Bloc<ConnectionEvent, ConnectionState> {
final BridgeService _bridgeService;
final AppConfig _config;
StreamSubscription? _statusSubscription;
ConnectionBloc({
required BridgeService bridgeService,
required AppConfig config,
}) : _bridgeService = bridgeService,
_config = config,
super(const ConnectionState()) {
on<ConnectAll>(_onConnectAll);
on<ConnectServer>(_onConnectServer);
on<DisconnectServer>(_onDisconnectServer);
on<DisconnectAll>(_onDisconnectAll);
on<RetryConnections>(_onRetryConnections);
on<ConnectionStatusUpdated>(_onConnectionStatusUpdated);
// Subscribe to connection status changes
_statusSubscription = _bridgeService.connectionStatus.listen((status) {
add(ConnectionStatusUpdated(status));
});
}
Future<void> _onConnectAll(
ConnectAll event,
Emitter<ConnectionState> emit,
) async {
emit(state.copyWith(overallStatus: ConnectionOverallStatus.connecting));
try {
await _bridgeService.connectAll();
} catch (e) {
emit(state.copyWith(
overallStatus: ConnectionOverallStatus.disconnected,
error: e.toString(),
));
}
}
Future<void> _onConnectServer(
ConnectServer event,
Emitter<ConnectionState> emit,
) async {
try {
await _bridgeService.connect(event.serverId);
} catch (e) {
emit(state.copyWith(error: 'Failed to connect to ${event.serverId}: $e'));
}
}
Future<void> _onDisconnectServer(
DisconnectServer event,
Emitter<ConnectionState> emit,
) async {
await _bridgeService.disconnect(event.serverId);
}
Future<void> _onDisconnectAll(
DisconnectAll event,
Emitter<ConnectionState> emit,
) async {
await _bridgeService.disconnectAll();
emit(state.copyWith(overallStatus: ConnectionOverallStatus.disconnected));
}
Future<void> _onRetryConnections(
RetryConnections event,
Emitter<ConnectionState> emit,
) async {
// Retry only disconnected servers
final disconnected = state.serverStatus.entries
.where((e) => !e.value)
.map((e) => e.key)
.toList();
for (final serverId in disconnected) {
await _bridgeService.connect(serverId);
}
}
void _onConnectionStatusUpdated(
ConnectionStatusUpdated event,
Emitter<ConnectionState> emit,
) {
final status = event.status;
ConnectionOverallStatus overall;
if (status.isEmpty) {
overall = ConnectionOverallStatus.disconnected;
} else if (status.values.every((v) => v)) {
overall = ConnectionOverallStatus.connected;
} else if (status.values.any((v) => v)) {
overall = ConnectionOverallStatus.partial;
} else {
overall = ConnectionOverallStatus.disconnected;
}
emit(state.copyWith(
overallStatus: overall,
serverStatus: status,
error: null,
));
}
@override
Future<void> close() {
_statusSubscription?.cancel();
return super.close();
}
}