push countdown logic

This commit is contained in:
ashrafzarkanisala
2024-09-20 00:41:59 +03:00
parent facdef4741
commit 26816b99cd
6 changed files with 381 additions and 211 deletions

View File

@ -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();
}
}

View File

@ -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 {}

View File

@ -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];
}

View File

@ -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,
];
}

View File

@ -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(

View File

@ -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,
),
);