diff --git a/lib/pages/device_managment/water_heater/bloc/water_heater_bloc.dart b/lib/pages/device_managment/water_heater/bloc/water_heater_bloc.dart index 43372b2d..e095d425 100644 --- a/lib/pages/device_managment/water_heater/bloc/water_heater_bloc.dart +++ b/lib/pages/device_managment/water_heater/bloc/water_heater_bloc.dart @@ -12,7 +12,6 @@ class WaterHeaterBloc extends Bloc { WaterHeaterBloc() : super(WaterHeaterInitial()) { on(_fetchWaterHeaterStatus); on(_controlWaterHeater); - on(_showScheduleView); on(_updateScheduleEvent); on(_stopScheduleEvent); } @@ -23,37 +22,23 @@ class WaterHeaterBloc extends Bloc { FutureOr _updateScheduleEvent( UpdateScheduleEvent event, Emitter emit, - ) { + ) async { + final currentState = state as WaterHeaterScheduleViewState; + + final countdownRemaining = currentState.isActive + ? currentState.countdownRemaining + : Duration(hours: event.hours, minutes: event.minutes); + emit(WaterHeaterScheduleViewState( scheduleMode: event.scheduleMode, - hours: event.hours, - minutes: event.minutes, - isActive: true, + hours: countdownRemaining!.inHours, + minutes: countdownRemaining.inMinutes % 60, + isActive: currentState.isActive, + countdownRemaining: countdownRemaining, )); - } - FutureOr _showScheduleView( - ShowScheduleViewEvent event, Emitter emit) { - emit(const WaterHeaterScheduleViewState( - scheduleMode: ScheduleModes.countdown, - hours: 6, - minutes: 23, - isActive: false, - )); - } - - FutureOr _stopScheduleEvent( - StopScheduleEvent event, - Emitter emit, - ) { - if (state is WaterHeaterScheduleViewState) { - final currentState = state as WaterHeaterScheduleViewState; - emit(WaterHeaterScheduleViewState( - scheduleMode: currentState.scheduleMode, - hours: currentState.hours, - minutes: currentState.minutes, - isActive: false, - )); + if (currentState.isActive) { + _startCountdown(countdownRemaining, emit); } } @@ -65,22 +50,39 @@ class WaterHeaterBloc extends Bloc { emit(WaterHeaterDeviceStatusLoaded(deviceStatus)); - await _runDebounce( + final success = await _runDebounce( deviceId: event.deviceId, code: event.code, value: event.value, oldValue: oldValue, emit: emit, ); + + if (success && + (event.code == "countdown_1" || event.code == "switch_inching")) { + final countdownDuration = Duration(seconds: event.value); + + emit(WaterHeaterScheduleViewState( + scheduleMode: deviceStatus.scheduleMode, + hours: countdownDuration.inHours, + minutes: (countdownDuration.inMinutes % 60), + isActive: true, + countdownRemaining: countdownDuration, + )); + + _startCountdown(countdownDuration, emit); + } } - Future _runDebounce({ + Future _runDebounce({ required String deviceId, required String code, required dynamic value, required dynamic oldValue, required Emitter emit, }) async { + final completer = Completer(); + if (_timer != null) { _timer!.cancel(); } @@ -94,11 +96,17 @@ class WaterHeaterBloc extends Bloc { if (!status) { _revertValueAndEmit(deviceId, code, oldValue, emit); + completer.complete(false); + } else { + completer.complete(true); } } catch (e) { _revertValueAndEmit(deviceId, code, oldValue, emit); + completer.complete(false); } }); + + return completer.future; } void _revertValueAndEmit(String deviceId, String code, dynamic oldValue, @@ -140,12 +148,81 @@ class WaterHeaterBloc extends Bloc { deviceStatus = WaterHeaterStatusModel.fromJson(event.deviceId, status.status); - emit(WaterHeaterDeviceStatusLoaded(deviceStatus)); + if (deviceStatus.countdownHours > 0 || + deviceStatus.countdownMinutes > 0) { + final remainingDuration = Duration( + hours: deviceStatus.countdownHours, + minutes: deviceStatus.countdownMinutes, + ); + + emit(WaterHeaterScheduleViewState( + scheduleMode: deviceStatus.scheduleMode, + hours: deviceStatus.countdownHours, + minutes: deviceStatus.countdownMinutes, + isActive: true, + countdownRemaining: remainingDuration, + )); + + _startCountdown(remainingDuration, emit); + } else { + emit(WaterHeaterScheduleViewState( + scheduleMode: deviceStatus.scheduleMode, + hours: 0, + minutes: 0, + isActive: false, + )); + } } catch (e) { emit(WaterHeaterFailedState(error: e.toString())); } } + void _startCountdown(Duration duration, Emitter emit) { + _timer?.cancel(); + + _timer = Timer.periodic(const Duration(seconds: 1), (timer) { + final state = this.state as WaterHeaterScheduleViewState; + final remaining = state.countdownRemaining! - const Duration(seconds: 1); + + if (remaining.isNegative || remaining == Duration.zero) { + _timer?.cancel(); + emit(WaterHeaterScheduleViewState( + scheduleMode: state.scheduleMode, + hours: 0, + minutes: 0, + isActive: false, + countdownRemaining: Duration.zero, + )); + } else { + emit(WaterHeaterScheduleViewState( + scheduleMode: state.scheduleMode, + hours: remaining.inHours, + minutes: remaining.inMinutes % 60, + isActive: true, + countdownRemaining: remaining, + )); + } + }); + } + + FutureOr _stopScheduleEvent( + StopScheduleEvent event, + Emitter emit, + ) { + _timer?.cancel(); + deviceStatus = deviceStatus.copyWith( + countdownHours: 0, + countdownMinutes: 0, + scheduleMode: ScheduleModes.countdown, + ); + emit(const WaterHeaterScheduleViewState( + scheduleMode: ScheduleModes.countdown, + hours: 0, + minutes: 0, + isActive: false, + )); + } + @override Future close() { _timer?.cancel(); diff --git a/lib/pages/device_managment/water_heater/bloc/water_heater_event.dart b/lib/pages/device_managment/water_heater/bloc/water_heater_event.dart index 4c1354f9..a0164b3a 100644 --- a/lib/pages/device_managment/water_heater/bloc/water_heater_event.dart +++ b/lib/pages/device_managment/water_heater/bloc/water_heater_event.dart @@ -51,6 +51,6 @@ class WaterHeaterFetchBatchStatusEvent extends WaterHeaterEvent { List get props => [deviceId]; } -class ShowScheduleViewEvent extends WaterHeaterEvent { - const ShowScheduleViewEvent(); -} +// class ShowScheduleViewEvent extends WaterHeaterEvent { +// const ShowScheduleViewEvent(); +// } diff --git a/lib/pages/device_managment/water_heater/bloc/water_heater_state.dart b/lib/pages/device_managment/water_heater/bloc/water_heater_state.dart index a4216e44..2dc45367 100644 --- a/lib/pages/device_managment/water_heater/bloc/water_heater_state.dart +++ b/lib/pages/device_managment/water_heater/bloc/water_heater_state.dart @@ -45,14 +45,17 @@ class WaterHeaterScheduleViewState extends WaterHeaterState { final int hours; final int minutes; final bool isActive; + final Duration? countdownRemaining; const WaterHeaterScheduleViewState({ required this.scheduleMode, required this.hours, required this.minutes, required this.isActive, + this.countdownRemaining, }); @override - List get props => [scheduleMode, hours, minutes]; + List get props => + [scheduleMode, hours, minutes, isActive, countdownRemaining]; } diff --git a/lib/pages/device_managment/water_heater/models/water_heater_status_model.dart b/lib/pages/device_managment/water_heater/models/water_heater_status_model.dart index 3cf29a96..fd16df50 100644 --- a/lib/pages/device_managment/water_heater/models/water_heater_status_model.dart +++ b/lib/pages/device_managment/water_heater/models/water_heater_status_model.dart @@ -23,8 +23,7 @@ class WaterHeaterStatusModel { factory WaterHeaterStatusModel.fromJson(String id, List jsonList) { late bool heaterSwitch = false; - late int countdownHours = 0; - late int countdownMinutes = 0; + late int countdownInSeconds = 0; late String relayStatus = ''; late String cycleTiming = ''; late ScheduleModes scheduleMode = ScheduleModes.countdown; @@ -35,7 +34,7 @@ class WaterHeaterStatusModel { heaterSwitch = status.value ?? false; break; case 'countdown_1': - countdownHours = status.value ?? 0; + countdownInSeconds = status.value ?? 0; break; case 'relay_status': relayStatus = status.value ?? 'memory'; @@ -49,6 +48,10 @@ class WaterHeaterStatusModel { } } + final countdownHours = countdownInSeconds ~/ 3600; + final countdownMinutes = + (countdownInSeconds % 3600) ~/ 60; + return WaterHeaterStatusModel( uuid: id, heaterSwitch: heaterSwitch, diff --git a/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart b/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart index 5974e735..6063a544 100644 --- a/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart +++ b/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart @@ -75,7 +75,7 @@ class WaterHeaterDeviceControl extends StatelessWidget ), GestureDetector( onTap: () { - context.read().add(const ShowScheduleViewEvent()); + // context.read().add(const ShowScheduleViewEvent()); showDialog( context: context, builder: (ctx) => BlocProvider.value( diff --git a/lib/pages/device_managment/water_heater/widgets/schedual_view.dart b/lib/pages/device_managment/water_heater/widgets/schedual_view.dart index 411621eb..3d221789 100644 --- a/lib/pages/device_managment/water_heater/widgets/schedual_view.dart +++ b/lib/pages/device_managment/water_heater/widgets/schedual_view.dart @@ -208,9 +208,11 @@ class BuildScheduleView extends StatelessWidget { Center( child: SizedBox( width: 400, + height: 50, child: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.max, children: [ Expanded( child: DefaultButton( @@ -227,12 +229,61 @@ class BuildScheduleView extends StatelessWidget { ), const SizedBox(width: 20), Expanded( - child: DefaultButton( - height: 40, - onPressed: () {}, - backgroundColor: ColorsManager.primaryColor, - child: const Text('Save'), - ), + child: (state.countdownRemaining != null && + state.isActive) + ? DefaultButton( + height: 40, + onPressed: () { + late String code; + if (state.scheduleMode == + ScheduleModes.countdown) { + code = 'countdown_1'; + } else if (state.scheduleMode == + ScheduleModes.inching) { + code = 'switch_inching'; + } + context + .read() + .add(StopScheduleEvent()); + context.read().add( + ToggleWaterHeaterEvent( + deviceId: status.uuid, + code: code, + value: 0, + ), + ); + }, + backgroundColor: Colors.red, + child: const Text('Stop'), + ) + : DefaultButton( + height: 40, + onPressed: () { + late String code; + if (state.scheduleMode == + ScheduleModes.countdown) { + code = 'countdown_1'; + } else if (state.scheduleMode == + ScheduleModes.inching) { + code = 'switch_inching'; + } + context.read().add( + ToggleWaterHeaterEvent( + deviceId: status.uuid, + code: code, + // value is time in seconds + value: Duration( + hours: state.hours, + minutes: + state.minutes) + .inSeconds, + ), + ); + }, + backgroundColor: + ColorsManager.primaryColor, + child: const Text('Save'), + ), ), ], ),