mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
push countdown logic
This commit is contained in:
@ -1,3 +1,5 @@
|
||||
// water_heater_bloc.dart
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
@ -14,143 +16,147 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
on<ToggleWaterHeaterEvent>(_controlWaterHeater);
|
||||
on<UpdateScheduleEvent>(_updateScheduleEvent);
|
||||
on<StopScheduleEvent>(_stopScheduleEvent);
|
||||
on<DecrementCountdownEvent>(_onDecrementCountdown);
|
||||
}
|
||||
|
||||
late WaterHeaterStatusModel deviceStatus;
|
||||
Timer? _timer;
|
||||
Timer? _countdownTimer;
|
||||
|
||||
FutureOr<void> _updateScheduleEvent(
|
||||
UpdateScheduleEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) async {
|
||||
final currentState = state as WaterHeaterScheduleViewState;
|
||||
final currentState = state;
|
||||
if (currentState is WaterHeaterDeviceStatusLoaded) {
|
||||
final countdownRemaining =
|
||||
// currentState.isActive == true
|
||||
// ? currentState.countdownRemaining
|
||||
// :
|
||||
Duration(hours: event.hours, minutes: event.minutes);
|
||||
|
||||
final countdownRemaining = currentState.isActive
|
||||
? currentState.countdownRemaining
|
||||
: Duration(hours: event.hours, minutes: event.minutes);
|
||||
emit(currentState.copyWith(
|
||||
scheduleMode: event.scheduleMode,
|
||||
hours: countdownRemaining.inHours,
|
||||
minutes: countdownRemaining.inMinutes % 60,
|
||||
isActive: currentState.isActive,
|
||||
countdownRemaining: countdownRemaining,
|
||||
));
|
||||
|
||||
emit(WaterHeaterScheduleViewState(
|
||||
scheduleMode: event.scheduleMode,
|
||||
hours: countdownRemaining!.inHours,
|
||||
minutes: countdownRemaining.inMinutes % 60,
|
||||
isActive: currentState.isActive,
|
||||
countdownRemaining: countdownRemaining,
|
||||
));
|
||||
|
||||
if (currentState.isActive) {
|
||||
_startCountdown(countdownRemaining, emit);
|
||||
if (!currentState.isActive! && countdownRemaining > Duration.zero) {
|
||||
_startCountdown(emit, countdownRemaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _controlWaterHeater(
|
||||
ToggleWaterHeaterEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
final oldValue = _getValueByCode(event.code);
|
||||
ToggleWaterHeaterEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) async {
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
|
||||
_updateLocalValue(event.code, event.value, emit);
|
||||
final oldValue = _getValueByCode(event.code);
|
||||
|
||||
emit(WaterHeaterDeviceStatusLoaded(deviceStatus));
|
||||
_updateLocalValue(event.code, event.value);
|
||||
|
||||
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,
|
||||
emit(currentState.copyWith(
|
||||
status: deviceStatus,
|
||||
));
|
||||
|
||||
_startCountdown(countdownDuration, emit);
|
||||
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(currentState.copyWith(
|
||||
status: deviceStatus,
|
||||
scheduleMode: deviceStatus.scheduleMode,
|
||||
hours: countdownDuration.inHours,
|
||||
minutes: (countdownDuration.inMinutes % 60),
|
||||
isActive: true,
|
||||
countdownRemaining: countdownDuration,
|
||||
));
|
||||
if (countdownDuration.inSeconds > 0) {
|
||||
_startCountdown(emit, countdownDuration);
|
||||
} else {
|
||||
_countdownTimer?.cancel();
|
||||
emit(currentState.copyWith(
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
isActive: false,
|
||||
countdownRemaining: Duration.zero,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _runDebounce({
|
||||
required String deviceId,
|
||||
required String code,
|
||||
required dynamic value,
|
||||
required dynamic oldValue,
|
||||
required Emitter<WaterHeaterState> emit,
|
||||
}) async {
|
||||
final completer = Completer<bool>();
|
||||
FutureOr<void> _stopScheduleEvent(
|
||||
StopScheduleEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) async {
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
|
||||
if (_timer != null) {
|
||||
_timer!.cancel();
|
||||
}
|
||||
_countdownTimer?.cancel();
|
||||
|
||||
deviceStatus = deviceStatus.copyWith(
|
||||
countdownHours: 0,
|
||||
countdownMinutes: 0,
|
||||
scheduleMode: ScheduleModes.countdown,
|
||||
);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
status: deviceStatus,
|
||||
scheduleMode: ScheduleModes.countdown,
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
isActive: false,
|
||||
countdownRemaining: Duration.zero,
|
||||
));
|
||||
|
||||
_timer = Timer(const Duration(milliseconds: 500), () async {
|
||||
try {
|
||||
final status = await DevicesManagementApi().deviceControl(
|
||||
deviceId,
|
||||
Status(code: code, value: value),
|
||||
event.deviceId,
|
||||
Status(code: 'countdown_1', value: 0),
|
||||
);
|
||||
|
||||
if (!status) {
|
||||
_revertValueAndEmit(deviceId, code, oldValue, emit);
|
||||
completer.complete(false);
|
||||
} else {
|
||||
completer.complete(true);
|
||||
emit(const WaterHeaterFailedState(error: 'Failed to stop schedule.'));
|
||||
}
|
||||
} catch (e) {
|
||||
_revertValueAndEmit(deviceId, code, oldValue, emit);
|
||||
completer.complete(false);
|
||||
emit(WaterHeaterFailedState(error: e.toString()));
|
||||
}
|
||||
});
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
void _revertValueAndEmit(
|
||||
String deviceId, String code, dynamic oldValue, Emitter<WaterHeaterState> emit) {
|
||||
_updateLocalValue(code, oldValue, emit);
|
||||
emit(WaterHeaterDeviceStatusLoaded(deviceStatus));
|
||||
}
|
||||
|
||||
void _updateLocalValue(String code, dynamic value, Emitter<WaterHeaterState> emit) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(heaterSwitch: value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _getValueByCode(String code) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
return deviceStatus.heaterSwitch;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _fetchWaterHeaterStatus(
|
||||
WaterHeaterFetchStatusEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
WaterHeaterFetchStatusEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) async {
|
||||
emit(WaterHeaterLoadingState());
|
||||
|
||||
try {
|
||||
final status = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
deviceStatus = WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
||||
final status =
|
||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
deviceStatus =
|
||||
WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
||||
|
||||
if (deviceStatus.countdownHours > 0 || deviceStatus.countdownMinutes > 0) {
|
||||
if (deviceStatus.countdownHours > 0 ||
|
||||
deviceStatus.countdownMinutes > 0) {
|
||||
final remainingDuration = Duration(
|
||||
hours: deviceStatus.countdownHours,
|
||||
minutes: deviceStatus.countdownMinutes,
|
||||
);
|
||||
|
||||
emit(WaterHeaterScheduleViewState(
|
||||
emit(WaterHeaterDeviceStatusLoaded(
|
||||
deviceStatus,
|
||||
scheduleMode: deviceStatus.scheduleMode,
|
||||
hours: deviceStatus.countdownHours,
|
||||
minutes: deviceStatus.countdownMinutes,
|
||||
@ -158,9 +164,10 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
countdownRemaining: remainingDuration,
|
||||
));
|
||||
|
||||
// _startCountdown(remainingDuration, emit);
|
||||
_startCountdown(emit, remainingDuration);
|
||||
} else {
|
||||
emit(WaterHeaterScheduleViewState(
|
||||
emit(WaterHeaterDeviceStatusLoaded(
|
||||
deviceStatus,
|
||||
scheduleMode: deviceStatus.scheduleMode,
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
@ -172,55 +179,124 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _startCountdown(Duration duration, Emitter<WaterHeaterState> emit) {
|
||||
_timer?.cancel();
|
||||
_onDecrementCountdown(
|
||||
DecrementCountdownEvent event,
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) {
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
final state = this.state as WaterHeaterScheduleViewState;
|
||||
final remaining = state.countdownRemaining! - const Duration(seconds: 1);
|
||||
if (currentState.countdownRemaining != null &&
|
||||
currentState.countdownRemaining! > Duration.zero) {
|
||||
final newRemaining =
|
||||
currentState.countdownRemaining! - const Duration(minutes: 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,
|
||||
if (newRemaining <= Duration.zero) {
|
||||
_countdownTimer?.cancel();
|
||||
emit(currentState.copyWith(
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
isActive: false,
|
||||
countdownRemaining: Duration.zero,
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
int totalSeconds = newRemaining.inSeconds;
|
||||
|
||||
int newHours = totalSeconds ~/ 3600;
|
||||
int newMinutes = (totalSeconds % 3600) ~/ 60;
|
||||
|
||||
emit(currentState.copyWith(
|
||||
hours: newHours,
|
||||
minutes: newMinutes,
|
||||
countdownRemaining: newRemaining,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _startCountdown(
|
||||
Emitter<WaterHeaterState> emit, Duration countdownRemaining) {
|
||||
_countdownTimer?.cancel();
|
||||
|
||||
_countdownTimer = Timer.periodic(const Duration(minutes: 1), (timer) {
|
||||
add(DecrementCountdownEvent());
|
||||
});
|
||||
}
|
||||
|
||||
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,
|
||||
));
|
||||
Future<bool> _runDebounce({
|
||||
required String deviceId,
|
||||
required String code,
|
||||
required dynamic value,
|
||||
required dynamic oldValue,
|
||||
required Emitter<WaterHeaterState> emit,
|
||||
}) async {
|
||||
try {
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
|
||||
final status = await DevicesManagementApi().deviceControl(
|
||||
deviceId,
|
||||
Status(code: code, value: value),
|
||||
);
|
||||
|
||||
if (!status) {
|
||||
_revertValue(code, oldValue, emit.call);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
_revertValue(code, oldValue, emit.call);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void _revertValue(String code, dynamic oldValue,
|
||||
void Function(WaterHeaterState state) emit) {
|
||||
_updateLocalValue(code, oldValue);
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
emit(currentState.copyWith(
|
||||
status: deviceStatus,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void _updateLocalValue(String code, dynamic value) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(heaterSwitch: value);
|
||||
}
|
||||
break;
|
||||
case 'countdown_1':
|
||||
if (value is int) {
|
||||
deviceStatus = deviceStatus.copyWith(
|
||||
countdownHours: value ~/ 60,
|
||||
countdownMinutes: value % 60,
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dynamic _getValueByCode(String code) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
return deviceStatus.heaterSwitch;
|
||||
case 'countdown_1':
|
||||
return deviceStatus.countdownHours * 60 + deviceStatus.countdownMinutes;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() {
|
||||
_timer?.cancel();
|
||||
_countdownTimer?.cancel();
|
||||
return super.close();
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
part of 'water_heater_bloc.dart';
|
||||
|
||||
sealed class WaterHeaterEvent extends Equatable {
|
||||
@ -12,11 +13,14 @@ final class ToggleWaterHeaterEvent extends WaterHeaterEvent {
|
||||
final String deviceId;
|
||||
final String code;
|
||||
|
||||
const ToggleWaterHeaterEvent(
|
||||
{required this.value, required this.deviceId, required this.code});
|
||||
const ToggleWaterHeaterEvent({
|
||||
required this.value,
|
||||
required this.deviceId,
|
||||
required this.code,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [value];
|
||||
List<Object?> get props => [value, deviceId, code];
|
||||
}
|
||||
|
||||
final class UpdateScheduleEvent extends WaterHeaterEvent {
|
||||
@ -24,16 +28,23 @@ final class UpdateScheduleEvent extends WaterHeaterEvent {
|
||||
final int hours;
|
||||
final int minutes;
|
||||
|
||||
const UpdateScheduleEvent(
|
||||
{required this.scheduleMode, required this.hours, required this.minutes});
|
||||
const UpdateScheduleEvent({
|
||||
required this.scheduleMode,
|
||||
required this.hours,
|
||||
required this.minutes,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [scheduleMode, hours, minutes];
|
||||
}
|
||||
|
||||
final class StopScheduleEvent extends WaterHeaterEvent {}
|
||||
final class StopScheduleEvent extends WaterHeaterEvent {
|
||||
final String deviceId;
|
||||
|
||||
class WaterHeaterFetchStatusEvent extends WaterHeaterEvent {
|
||||
const StopScheduleEvent(this.deviceId);
|
||||
}
|
||||
|
||||
final class WaterHeaterFetchStatusEvent extends WaterHeaterEvent {
|
||||
final String deviceId;
|
||||
|
||||
const WaterHeaterFetchStatusEvent(this.deviceId);
|
||||
@ -42,7 +53,7 @@ class WaterHeaterFetchStatusEvent extends WaterHeaterEvent {
|
||||
List<Object?> get props => [deviceId];
|
||||
}
|
||||
|
||||
class WaterHeaterFetchBatchStatusEvent extends WaterHeaterEvent {
|
||||
final class WaterHeaterFetchBatchStatusEvent extends WaterHeaterEvent {
|
||||
final String deviceId;
|
||||
|
||||
const WaterHeaterFetchBatchStatusEvent(this.deviceId);
|
||||
@ -51,6 +62,4 @@ class WaterHeaterFetchBatchStatusEvent extends WaterHeaterEvent {
|
||||
List<Object?> get props => [deviceId];
|
||||
}
|
||||
|
||||
// class ShowScheduleViewEvent extends WaterHeaterEvent {
|
||||
// const ShowScheduleViewEvent();
|
||||
// }
|
||||
final class DecrementCountdownEvent extends WaterHeaterEvent {}
|
||||
|
@ -1,6 +1,6 @@
|
||||
part of 'water_heater_bloc.dart';
|
||||
// water_heater_state.dart
|
||||
|
||||
enum ScheduleType { countdown, schedule, circulate, inching }
|
||||
part of 'water_heater_bloc.dart';
|
||||
|
||||
sealed class WaterHeaterState extends Equatable {
|
||||
const WaterHeaterState();
|
||||
@ -15,11 +15,43 @@ final class WaterHeaterLoadingState extends WaterHeaterState {}
|
||||
|
||||
final class WaterHeaterDeviceStatusLoaded extends WaterHeaterState {
|
||||
final WaterHeaterStatusModel status;
|
||||
final ScheduleModes? scheduleMode;
|
||||
final int? hours;
|
||||
final int? minutes;
|
||||
final bool? isActive;
|
||||
final Duration? countdownRemaining;
|
||||
|
||||
const WaterHeaterDeviceStatusLoaded(this.status);
|
||||
const WaterHeaterDeviceStatusLoaded(
|
||||
this.status, {
|
||||
this.scheduleMode,
|
||||
this.hours,
|
||||
this.minutes,
|
||||
this.isActive,
|
||||
this.countdownRemaining,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [status];
|
||||
List<Object?> get props =>
|
||||
[status, scheduleMode, hours, minutes, isActive, countdownRemaining];
|
||||
|
||||
/// Creates a new instance with updated fields.
|
||||
WaterHeaterDeviceStatusLoaded copyWith({
|
||||
WaterHeaterStatusModel? status,
|
||||
ScheduleModes? scheduleMode,
|
||||
int? hours,
|
||||
int? minutes,
|
||||
bool? isActive,
|
||||
Duration? countdownRemaining,
|
||||
}) {
|
||||
return WaterHeaterDeviceStatusLoaded(
|
||||
status ?? this.status,
|
||||
scheduleMode: scheduleMode ?? this.scheduleMode,
|
||||
hours: hours ?? this.hours,
|
||||
minutes: minutes ?? this.minutes,
|
||||
isActive: isActive ?? this.isActive,
|
||||
countdownRemaining: countdownRemaining ?? this.countdownRemaining,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final class WaterHeaterFailedState extends WaterHeaterState {
|
||||
@ -39,23 +71,3 @@ final class WaterHeaterBatchFailedState extends WaterHeaterState {
|
||||
@override
|
||||
List<Object?> get props => [error];
|
||||
}
|
||||
|
||||
class WaterHeaterScheduleViewState extends WaterHeaterState {
|
||||
final ScheduleModes scheduleMode;
|
||||
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<Object?> get props =>
|
||||
[scheduleMode, hours, minutes, isActive, countdownRemaining];
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
|
||||
enum ScheduleModes { countdown, schedule, circulate, inching }
|
||||
|
||||
class WaterHeaterStatusModel {
|
||||
class WaterHeaterStatusModel extends Equatable {
|
||||
final String uuid;
|
||||
final bool heaterSwitch;
|
||||
final int countdownHours;
|
||||
@ -34,7 +35,7 @@ class WaterHeaterStatusModel {
|
||||
heaterSwitch = status.value ?? false;
|
||||
break;
|
||||
case 'countdown_1':
|
||||
countdownInSeconds = status.value ?? 0;
|
||||
countdownInSeconds = status.value ?? 0;
|
||||
break;
|
||||
case 'relay_status':
|
||||
relayStatus = status.value ?? 'memory';
|
||||
@ -48,9 +49,8 @@ class WaterHeaterStatusModel {
|
||||
}
|
||||
}
|
||||
|
||||
final countdownHours = countdownInSeconds ~/ 3600;
|
||||
final countdownMinutes =
|
||||
(countdownInSeconds % 3600) ~/ 60;
|
||||
final countdownHours = countdownInSeconds ~/ 3600;
|
||||
final countdownMinutes = (countdownInSeconds % 3600) ~/ 60;
|
||||
|
||||
return WaterHeaterStatusModel(
|
||||
uuid: id,
|
||||
@ -97,4 +97,15 @@ class WaterHeaterStatusModel {
|
||||
return ScheduleModes.countdown;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
uuid,
|
||||
heaterSwitch,
|
||||
countdownHours,
|
||||
countdownMinutes,
|
||||
scheduleMode,
|
||||
relayStatus,
|
||||
cycleTiming,
|
||||
];
|
||||
}
|
||||
|
@ -29,10 +29,12 @@ class WaterHeaterDeviceControl extends StatelessWidget
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
} else if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
return _buildStatusControls(context, state.status);
|
||||
} else if (state is WaterHeaterScheduleViewState) {
|
||||
final status = context.read<WaterHeaterBloc>().deviceStatus;
|
||||
return _buildStatusControls(context, status);
|
||||
} else if (state is WaterHeaterFailedState ||
|
||||
}
|
||||
// else if (state is WaterHeaterScheduleViewState) {
|
||||
// final status = context.read<WaterHeaterBloc>().deviceStatus;
|
||||
// return _buildStatusControls(context, status);
|
||||
// }
|
||||
else if (state is WaterHeaterFailedState ||
|
||||
state is WaterHeaterBatchFailedState) {
|
||||
return const Center(child: Text('Error fetching status'));
|
||||
} else {
|
||||
@ -75,7 +77,6 @@ class WaterHeaterDeviceControl extends StatelessWidget
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// context.read<WaterHeaterBloc>().add(const ShowScheduleViewEvent());
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => BlocProvider.value(
|
||||
|
@ -7,11 +7,63 @@ import 'package:syncrow_web/pages/device_managment/water_heater/models/water_hea
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class BuildScheduleView extends StatelessWidget {
|
||||
class BuildScheduleView extends StatefulWidget {
|
||||
const BuildScheduleView({super.key, required this.status});
|
||||
|
||||
final WaterHeaterStatusModel status;
|
||||
|
||||
@override
|
||||
_BuildScheduleViewState createState() => _BuildScheduleViewState();
|
||||
}
|
||||
|
||||
class _BuildScheduleViewState extends State<BuildScheduleView> {
|
||||
// late FixedExtentScrollController hoursController;
|
||||
// late FixedExtentScrollController minutesController;
|
||||
|
||||
// @override
|
||||
// void initState() {
|
||||
// super.initState();
|
||||
// _initializeControllers();
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void didUpdateWidget(covariant BuildScheduleView oldWidget) {
|
||||
// super.didUpdateWidget(oldWidget);
|
||||
// final state = context.read<WaterHeaterBloc>().state;
|
||||
// if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
// _initializeControllers();
|
||||
// }
|
||||
// }
|
||||
|
||||
// void _initializeControllers() {
|
||||
// final state = context.read<WaterHeaterBloc>().state;
|
||||
// if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
// hoursController =
|
||||
// FixedExtentScrollController(initialItem: state.hours ?? 0);
|
||||
// minutesController =
|
||||
// FixedExtentScrollController(initialItem: state.minutes ?? 0);
|
||||
// } else {
|
||||
// hoursController = FixedExtentScrollController(initialItem: 0);
|
||||
// minutesController = FixedExtentScrollController(initialItem: 0);
|
||||
// }
|
||||
// }
|
||||
|
||||
// void _updateControllers(int hours, int minutes) {
|
||||
// if (hoursController.hasClients) {
|
||||
// hoursController.jumpToItem(hours);
|
||||
// }
|
||||
// if (minutesController.hasClients) {
|
||||
// minutesController.jumpToItem(minutes);
|
||||
// }
|
||||
// }
|
||||
|
||||
// @override
|
||||
// void dispose() {
|
||||
// hoursController.dispose();
|
||||
// minutesController.dispose();
|
||||
// super.dispose();
|
||||
// }
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
@ -27,7 +79,8 @@ class BuildScheduleView extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20),
|
||||
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
|
||||
builder: (context, state) {
|
||||
if (state is WaterHeaterScheduleViewState) {
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
//_updateControllers(state.hours ?? 0, state.minutes ?? 0);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -75,9 +128,7 @@ class BuildScheduleView extends StatelessWidget {
|
||||
color: ColorsManager.grayColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 4,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
SizedBox(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
@ -101,8 +152,8 @@ class BuildScheduleView extends StatelessWidget {
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(UpdateScheduleEvent(
|
||||
scheduleMode: value,
|
||||
hours: state.hours,
|
||||
minutes: state.minutes,
|
||||
hours: state.hours ?? 0,
|
||||
minutes: state.minutes ?? 0,
|
||||
));
|
||||
}
|
||||
},
|
||||
@ -128,8 +179,8 @@ class BuildScheduleView extends StatelessWidget {
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(UpdateScheduleEvent(
|
||||
scheduleMode: value,
|
||||
hours: state.hours,
|
||||
minutes: state.minutes,
|
||||
hours: state.hours ?? 0,
|
||||
minutes: state.minutes ?? 0,
|
||||
));
|
||||
}
|
||||
},
|
||||
@ -154,8 +205,8 @@ class BuildScheduleView extends StatelessWidget {
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(UpdateScheduleEvent(
|
||||
scheduleMode: value,
|
||||
hours: state.hours,
|
||||
minutes: state.minutes,
|
||||
hours: state.hours ?? 0,
|
||||
minutes: state.minutes ?? 0,
|
||||
));
|
||||
}
|
||||
},
|
||||
@ -180,8 +231,8 @@ class BuildScheduleView extends StatelessWidget {
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(UpdateScheduleEvent(
|
||||
scheduleMode: value,
|
||||
hours: state.hours,
|
||||
minutes: state.minutes,
|
||||
hours: state.hours ?? 0,
|
||||
minutes: state.minutes ?? 0,
|
||||
));
|
||||
}
|
||||
},
|
||||
@ -230,7 +281,7 @@ class BuildScheduleView extends StatelessWidget {
|
||||
const SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: (state.countdownRemaining != null &&
|
||||
state.isActive)
|
||||
state.isActive == true)
|
||||
? DefaultButton(
|
||||
height: 40,
|
||||
onPressed: () {
|
||||
@ -242,12 +293,13 @@ class BuildScheduleView extends StatelessWidget {
|
||||
ScheduleModes.inching) {
|
||||
code = 'switch_inching';
|
||||
}
|
||||
context
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(StopScheduleEvent());
|
||||
context.read<WaterHeaterBloc>().add(
|
||||
StopScheduleEvent(
|
||||
widget.status.uuid));
|
||||
context.read<WaterHeaterBloc>().add(
|
||||
ToggleWaterHeaterEvent(
|
||||
deviceId: status.uuid,
|
||||
deviceId:
|
||||
widget.status.uuid,
|
||||
code: code,
|
||||
value: 0,
|
||||
),
|
||||
@ -269,13 +321,16 @@ class BuildScheduleView extends StatelessWidget {
|
||||
}
|
||||
context.read<WaterHeaterBloc>().add(
|
||||
ToggleWaterHeaterEvent(
|
||||
deviceId: status.uuid,
|
||||
deviceId:
|
||||
widget.status.uuid,
|
||||
code: code,
|
||||
// value is time in seconds
|
||||
value: Duration(
|
||||
hours: state.hours,
|
||||
hours:
|
||||
state.hours ??
|
||||
0,
|
||||
minutes:
|
||||
state.minutes)
|
||||
state.minutes ??
|
||||
0)
|
||||
.inSeconds,
|
||||
),
|
||||
);
|
||||
@ -303,7 +358,7 @@ class BuildScheduleView extends StatelessWidget {
|
||||
}
|
||||
|
||||
Row _hourMinutesWheel(
|
||||
WaterHeaterScheduleViewState state, BuildContext context) {
|
||||
WaterHeaterDeviceStatusLoaded state, BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
@ -320,16 +375,19 @@ class BuildScheduleView extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: ListWheelScrollView.useDelegate(
|
||||
controller:
|
||||
FixedExtentScrollController(initialItem: state.hours),
|
||||
key: ValueKey('hours_${state.hours}'),
|
||||
controller: FixedExtentScrollController(
|
||||
initialItem: state.hours ?? 0,
|
||||
),
|
||||
itemExtent: 40.0,
|
||||
physics: FixedExtentScrollPhysics(),
|
||||
physics: const FixedExtentScrollPhysics(),
|
||||
onSelectedItemChanged: (int value) {
|
||||
context.read<WaterHeaterBloc>().add(
|
||||
UpdateScheduleEvent(
|
||||
scheduleMode: state.scheduleMode,
|
||||
scheduleMode:
|
||||
state.scheduleMode ?? ScheduleModes.countdown,
|
||||
hours: value,
|
||||
minutes: state.minutes,
|
||||
minutes: state.minutes ?? 0,
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -370,15 +428,18 @@ class BuildScheduleView extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: ListWheelScrollView.useDelegate(
|
||||
controller:
|
||||
FixedExtentScrollController(initialItem: state.minutes),
|
||||
key: ValueKey('minutes_${state.minutes}'),
|
||||
controller: FixedExtentScrollController(
|
||||
initialItem: state.minutes ?? 0,
|
||||
),
|
||||
itemExtent: 40.0,
|
||||
physics: FixedExtentScrollPhysics(),
|
||||
physics: const FixedExtentScrollPhysics(),
|
||||
onSelectedItemChanged: (int value) {
|
||||
context.read<WaterHeaterBloc>().add(
|
||||
UpdateScheduleEvent(
|
||||
scheduleMode: state.scheduleMode,
|
||||
hours: state.hours,
|
||||
scheduleMode:
|
||||
state.scheduleMode ?? ScheduleModes.countdown,
|
||||
hours: state.hours ?? 0,
|
||||
minutes: value,
|
||||
),
|
||||
);
|
||||
|
Reference in New Issue
Block a user