import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_event.dart'; import 'package:syncrow_web/pages/device_managment/curtain/bloc/curtain_state.dart'; import 'package:syncrow_web/services/devices_mang_api.dart'; class CurtainBloc extends Bloc { late bool deviceStatus; final String deviceId; Timer? _timer; CurtainBloc({required this.deviceId}) : super(CurtainInitial()) { on(_onFetchDeviceStatus); on(_onFetchBatchStatus); on(_onCurtainControl); on(_onCurtainBatchControl); } FutureOr _onFetchDeviceStatus( CurtainFetchDeviceStatus event, Emitter emit) async { emit(CurtainStatusLoading()); try { final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); deviceStatus = _checkStatus(status.status[0].value); emit(CurtainStatusLoaded(deviceStatus)); } catch (e) { emit(CurtainError(e.toString())); } } FutureOr _onCurtainControl( CurtainControl event, Emitter emit) async { final oldValue = deviceStatus; _updateLocalValue(event.value, emit); emit(CurtainStatusLoaded(deviceStatus)); await _runDebounce( deviceId: event.deviceId, code: event.code, value: event.value, oldValue: oldValue, emit: emit, isBatch: false, ); } Future _runDebounce({ required dynamic deviceId, required String code, required bool value, required bool oldValue, required Emitter emit, required bool isBatch, }) async { late String id; if (deviceId is List) { id = deviceId.first; } else { id = deviceId; } if (_timer != null) { _timer!.cancel(); } _timer = Timer(const Duration(seconds: 1), () async { try { final controlValue = value ? 'open' : 'close'; late bool response; if (isBatch) { response = await DevicesManagementApi() .deviceBatchControl(deviceId, code, controlValue); } else { response = await DevicesManagementApi() .deviceControl(deviceId, Status(code: code, value: controlValue)); } if (!response) { _revertValueAndEmit(id, oldValue, emit); } } catch (e) { _revertValueAndEmit(id, oldValue, emit); } }); } void _revertValueAndEmit( String deviceId, bool oldValue, Emitter emit) { _updateLocalValue(oldValue, emit); emit(CurtainStatusLoaded(deviceStatus)); emit(const CurtainControlError('Failed to control the device.')); } void _updateLocalValue(bool value, Emitter emit) { deviceStatus = value; emit(CurtainStatusLoaded(deviceStatus)); } bool _checkStatus(String command) { return command.toLowerCase() == 'open'; } FutureOr _onFetchBatchStatus( CurtainFetchBatchStatus event, Emitter emit) async { emit(CurtainStatusLoading()); try { final status = await DevicesManagementApi().getBatchStatus(event.devicesIds); deviceStatus = _checkStatus(status.status[0].value); emit(CurtainStatusLoaded(deviceStatus)); } catch (e) { emit(CurtainError(e.toString())); } } FutureOr _onCurtainBatchControl( CurtainBatchControl event, Emitter emit) async { final oldValue = deviceStatus; _updateLocalValue(event.value, emit); emit(CurtainStatusLoaded(deviceStatus)); await _runDebounce( deviceId: event.devicesIds, code: event.code, value: event.value, oldValue: oldValue, emit: emit, isBatch: true, ); } }