push save and stop buttons

This commit is contained in:
ashrafzarkanisala
2024-09-19 01:31:52 +03:00
parent ba95f6774b
commit b3807f2980
6 changed files with 179 additions and 45 deletions

View File

@ -12,7 +12,6 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
WaterHeaterBloc() : super(WaterHeaterInitial()) { WaterHeaterBloc() : super(WaterHeaterInitial()) {
on<WaterHeaterFetchStatusEvent>(_fetchWaterHeaterStatus); on<WaterHeaterFetchStatusEvent>(_fetchWaterHeaterStatus);
on<ToggleWaterHeaterEvent>(_controlWaterHeater); on<ToggleWaterHeaterEvent>(_controlWaterHeater);
on<ShowScheduleViewEvent>(_showScheduleView);
on<UpdateScheduleEvent>(_updateScheduleEvent); on<UpdateScheduleEvent>(_updateScheduleEvent);
on<StopScheduleEvent>(_stopScheduleEvent); on<StopScheduleEvent>(_stopScheduleEvent);
} }
@ -23,37 +22,23 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
FutureOr<void> _updateScheduleEvent( FutureOr<void> _updateScheduleEvent(
UpdateScheduleEvent event, UpdateScheduleEvent event,
Emitter<WaterHeaterState> emit, Emitter<WaterHeaterState> emit,
) { ) async {
final currentState = state as WaterHeaterScheduleViewState;
final countdownRemaining = currentState.isActive
? currentState.countdownRemaining
: Duration(hours: event.hours, minutes: event.minutes);
emit(WaterHeaterScheduleViewState( emit(WaterHeaterScheduleViewState(
scheduleMode: event.scheduleMode, scheduleMode: event.scheduleMode,
hours: event.hours, hours: countdownRemaining!.inHours,
minutes: event.minutes, minutes: countdownRemaining.inMinutes % 60,
isActive: true, isActive: currentState.isActive,
countdownRemaining: countdownRemaining,
)); ));
}
FutureOr<void> _showScheduleView( if (currentState.isActive) {
ShowScheduleViewEvent event, Emitter<WaterHeaterState> emit) { _startCountdown(countdownRemaining, emit);
emit(const WaterHeaterScheduleViewState(
scheduleMode: ScheduleModes.countdown,
hours: 6,
minutes: 23,
isActive: false,
));
}
FutureOr<void> _stopScheduleEvent(
StopScheduleEvent event,
Emitter<WaterHeaterState> emit,
) {
if (state is WaterHeaterScheduleViewState) {
final currentState = state as WaterHeaterScheduleViewState;
emit(WaterHeaterScheduleViewState(
scheduleMode: currentState.scheduleMode,
hours: currentState.hours,
minutes: currentState.minutes,
isActive: false,
));
} }
} }
@ -65,22 +50,39 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
emit(WaterHeaterDeviceStatusLoaded(deviceStatus)); emit(WaterHeaterDeviceStatusLoaded(deviceStatus));
await _runDebounce( final success = await _runDebounce(
deviceId: event.deviceId, deviceId: event.deviceId,
code: event.code, code: event.code,
value: event.value, value: event.value,
oldValue: oldValue, oldValue: oldValue,
emit: emit, 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<void> _runDebounce({ Future<bool> _runDebounce({
required String deviceId, required String deviceId,
required String code, required String code,
required dynamic value, required dynamic value,
required dynamic oldValue, required dynamic oldValue,
required Emitter<WaterHeaterState> emit, required Emitter<WaterHeaterState> emit,
}) async { }) async {
final completer = Completer<bool>();
if (_timer != null) { if (_timer != null) {
_timer!.cancel(); _timer!.cancel();
} }
@ -94,11 +96,17 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
if (!status) { if (!status) {
_revertValueAndEmit(deviceId, code, oldValue, emit); _revertValueAndEmit(deviceId, code, oldValue, emit);
completer.complete(false);
} else {
completer.complete(true);
} }
} catch (e) { } catch (e) {
_revertValueAndEmit(deviceId, code, oldValue, emit); _revertValueAndEmit(deviceId, code, oldValue, emit);
completer.complete(false);
} }
}); });
return completer.future;
} }
void _revertValueAndEmit(String deviceId, String code, dynamic oldValue, void _revertValueAndEmit(String deviceId, String code, dynamic oldValue,
@ -140,12 +148,81 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
deviceStatus = deviceStatus =
WaterHeaterStatusModel.fromJson(event.deviceId, status.status); 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) { } catch (e) {
emit(WaterHeaterFailedState(error: e.toString())); emit(WaterHeaterFailedState(error: e.toString()));
} }
} }
void _startCountdown(Duration duration, Emitter<WaterHeaterState> 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<void> _stopScheduleEvent(
StopScheduleEvent event,
Emitter<WaterHeaterState> 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 @override
Future<void> close() { Future<void> close() {
_timer?.cancel(); _timer?.cancel();

View File

@ -51,6 +51,6 @@ class WaterHeaterFetchBatchStatusEvent extends WaterHeaterEvent {
List<Object?> get props => [deviceId]; List<Object?> get props => [deviceId];
} }
class ShowScheduleViewEvent extends WaterHeaterEvent { // class ShowScheduleViewEvent extends WaterHeaterEvent {
const ShowScheduleViewEvent(); // const ShowScheduleViewEvent();
} // }

View File

@ -45,14 +45,17 @@ class WaterHeaterScheduleViewState extends WaterHeaterState {
final int hours; final int hours;
final int minutes; final int minutes;
final bool isActive; final bool isActive;
final Duration? countdownRemaining;
const WaterHeaterScheduleViewState({ const WaterHeaterScheduleViewState({
required this.scheduleMode, required this.scheduleMode,
required this.hours, required this.hours,
required this.minutes, required this.minutes,
required this.isActive, required this.isActive,
this.countdownRemaining,
}); });
@override @override
List<Object> get props => [scheduleMode, hours, minutes]; List<Object?> get props =>
[scheduleMode, hours, minutes, isActive, countdownRemaining];
} }

View File

@ -23,8 +23,7 @@ class WaterHeaterStatusModel {
factory WaterHeaterStatusModel.fromJson(String id, List<Status> jsonList) { factory WaterHeaterStatusModel.fromJson(String id, List<Status> jsonList) {
late bool heaterSwitch = false; late bool heaterSwitch = false;
late int countdownHours = 0; late int countdownInSeconds = 0;
late int countdownMinutes = 0;
late String relayStatus = ''; late String relayStatus = '';
late String cycleTiming = ''; late String cycleTiming = '';
late ScheduleModes scheduleMode = ScheduleModes.countdown; late ScheduleModes scheduleMode = ScheduleModes.countdown;
@ -35,7 +34,7 @@ class WaterHeaterStatusModel {
heaterSwitch = status.value ?? false; heaterSwitch = status.value ?? false;
break; break;
case 'countdown_1': case 'countdown_1':
countdownHours = status.value ?? 0; countdownInSeconds = status.value ?? 0;
break; break;
case 'relay_status': case 'relay_status':
relayStatus = status.value ?? 'memory'; relayStatus = status.value ?? 'memory';
@ -49,6 +48,10 @@ class WaterHeaterStatusModel {
} }
} }
final countdownHours = countdownInSeconds ~/ 3600;
final countdownMinutes =
(countdownInSeconds % 3600) ~/ 60;
return WaterHeaterStatusModel( return WaterHeaterStatusModel(
uuid: id, uuid: id,
heaterSwitch: heaterSwitch, heaterSwitch: heaterSwitch,

View File

@ -75,7 +75,7 @@ class WaterHeaterDeviceControl extends StatelessWidget
), ),
GestureDetector( GestureDetector(
onTap: () { onTap: () {
context.read<WaterHeaterBloc>().add(const ShowScheduleViewEvent()); // context.read<WaterHeaterBloc>().add(const ShowScheduleViewEvent());
showDialog( showDialog(
context: context, context: context,
builder: (ctx) => BlocProvider.value( builder: (ctx) => BlocProvider.value(

View File

@ -208,9 +208,11 @@ class BuildScheduleView extends StatelessWidget {
Center( Center(
child: SizedBox( child: SizedBox(
width: 400, width: 400,
height: 50,
child: Center( child: Center(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [ children: [
Expanded( Expanded(
child: DefaultButton( child: DefaultButton(
@ -227,12 +229,61 @@ class BuildScheduleView extends StatelessWidget {
), ),
const SizedBox(width: 20), const SizedBox(width: 20),
Expanded( Expanded(
child: DefaultButton( child: (state.countdownRemaining != null &&
height: 40, state.isActive)
onPressed: () {}, ? DefaultButton(
backgroundColor: ColorsManager.primaryColor, height: 40,
child: const Text('Save'), onPressed: () {
), late String code;
if (state.scheduleMode ==
ScheduleModes.countdown) {
code = 'countdown_1';
} else if (state.scheduleMode ==
ScheduleModes.inching) {
code = 'switch_inching';
}
context
.read<WaterHeaterBloc>()
.add(StopScheduleEvent());
context.read<WaterHeaterBloc>().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<WaterHeaterBloc>().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'),
),
), ),
], ],
), ),