From 277a9ce4f007e472571c10fcbb909f837620f892 Mon Sep 17 00:00:00 2001 From: mohammad Date: Tue, 24 Jun 2025 15:38:16 +0300 Subject: [PATCH] Add countdown seconds to schedule management --- .../schedule_device/bloc/schedule_bloc.dart | 14 +++- .../schedule_device/bloc/schedule_event.dart | 4 +- .../schedule_device/bloc/schedule_state.dart | 13 +++- .../count_down_inching_view.dart | 66 +++++++++++++++++-- .../schedule_widgets/schedual_view.dart | 4 +- 5 files changed, 90 insertions(+), 11 deletions(-) diff --git a/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart b/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart index 62213205..fbf7ae64 100644 --- a/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart +++ b/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart @@ -83,6 +83,12 @@ class ScheduleBloc extends Bloc { emit(currentState.copyWith( scheduleMode: event.scheduleMode, countdownRemaining: Duration.zero, + countdownHours: 0, + countdownMinutes: 0, + inchingHours: 0, + inchingMinutes: 0, + isCountdownActive: false, + isInchingActive: false, )); } } @@ -94,6 +100,7 @@ class ScheduleBloc extends Bloc { if (state is ScheduleLoaded) { final currentState = state as ScheduleLoaded; emit(currentState.copyWith( + countdownSeconds: event.seconds, countdownHours: event.hours, countdownMinutes: event.minutes, inchingHours: 0, @@ -113,6 +120,7 @@ class ScheduleBloc extends Bloc { inchingHours: event.hours, inchingMinutes: event.minutes, countdownRemaining: Duration.zero, + inchingSeconds: 0, // Add this )); } } @@ -424,6 +432,7 @@ class ScheduleBloc extends Bloc { countdownMinutes: countdownDuration.inMinutes % 60, countdownRemaining: countdownDuration, isCountdownActive: true, + countdownSeconds: countdownDuration.inSeconds, ), ); @@ -437,6 +446,7 @@ class ScheduleBloc extends Bloc { countdownMinutes: 0, countdownRemaining: Duration.zero, isCountdownActive: false, + countdownSeconds: 0, ), ); } @@ -448,6 +458,7 @@ class ScheduleBloc extends Bloc { inchingMinutes: inchingDuration.inMinutes % 60, isInchingActive: true, countdownRemaining: inchingDuration, + countdownSeconds: inchingDuration.inSeconds, ), ); } @@ -574,8 +585,7 @@ class ScheduleBloc extends Bloc { } String extractTime(String isoDateTime) { - // Example input: "2025-06-19T15:45:00.000" - return isoDateTime.split('T')[1].split('.')[0]; // gives "15:45:00" + return isoDateTime.split('T')[1].split('.')[0]; } int? getTimeStampWithoutSeconds(DateTime? dateTime) { diff --git a/lib/pages/device_managment/schedule_device/bloc/schedule_event.dart b/lib/pages/device_managment/schedule_device/bloc/schedule_event.dart index 7ec144fe..0b9ec581 100644 --- a/lib/pages/device_managment/schedule_device/bloc/schedule_event.dart +++ b/lib/pages/device_managment/schedule_device/bloc/schedule_event.dart @@ -146,14 +146,16 @@ class UpdateScheduleModeEvent extends ScheduleEvent { class UpdateCountdownTimeEvent extends ScheduleEvent { final int hours; final int minutes; + final int seconds; const UpdateCountdownTimeEvent({ required this.hours, required this.minutes, + required this.seconds, }); @override - List get props => [hours, minutes]; + List get props => [hours, minutes, seconds]; } class UpdateInchingTimeEvent extends ScheduleEvent { diff --git a/lib/pages/device_managment/schedule_device/bloc/schedule_state.dart b/lib/pages/device_managment/schedule_device/bloc/schedule_state.dart index 10cd7611..63551c3a 100644 --- a/lib/pages/device_managment/schedule_device/bloc/schedule_state.dart +++ b/lib/pages/device_managment/schedule_device/bloc/schedule_state.dart @@ -26,11 +26,15 @@ class ScheduleLoaded extends ScheduleState { final bool isCountdownActive; final int inchingHours; final int inchingMinutes; + final int inchingSeconds; final bool isInchingActive; final ScheduleModes scheduleMode; final Duration? countdownRemaining; + final int? countdownSeconds; const ScheduleLoaded({ + this.countdownSeconds = 0, + this.inchingSeconds = 0, required this.schedules, this.selectedTime, required this.selectedDays, @@ -61,6 +65,9 @@ class ScheduleLoaded extends ScheduleState { bool? isInchingActive, ScheduleModes? scheduleMode, Duration? countdownRemaining, + String? deviceId, + int? countdownSeconds, + int? inchingSeconds, }) { return ScheduleLoaded( schedules: schedules ?? this.schedules, @@ -68,7 +75,7 @@ class ScheduleLoaded extends ScheduleState { selectedDays: selectedDays ?? this.selectedDays, functionOn: functionOn ?? this.functionOn, isEditing: isEditing ?? this.isEditing, - deviceId: deviceId, + deviceId: deviceId ?? this.deviceId, countdownHours: countdownHours ?? this.countdownHours, countdownMinutes: countdownMinutes ?? this.countdownMinutes, isCountdownActive: isCountdownActive ?? this.isCountdownActive, @@ -77,6 +84,8 @@ class ScheduleLoaded extends ScheduleState { isInchingActive: isInchingActive ?? this.isInchingActive, scheduleMode: scheduleMode ?? this.scheduleMode, countdownRemaining: countdownRemaining ?? this.countdownRemaining, + countdownSeconds: countdownSeconds ?? this.countdownSeconds, + inchingSeconds: inchingSeconds ?? this.inchingSeconds, ); } @@ -96,6 +105,8 @@ class ScheduleLoaded extends ScheduleState { isInchingActive, scheduleMode, countdownRemaining, + countdownSeconds, + inchingSeconds, ]; } diff --git a/lib/pages/device_managment/schedule_device/schedule_widgets/count_down_inching_view.dart b/lib/pages/device_managment/schedule_device/schedule_widgets/count_down_inching_view.dart index d45073ec..418bab6c 100644 --- a/lib/pages/device_managment/schedule_device/schedule_widgets/count_down_inching_view.dart +++ b/lib/pages/device_managment/schedule_device/schedule_widgets/count_down_inching_view.dart @@ -6,7 +6,8 @@ import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; class CountdownInchingView extends StatefulWidget { - const CountdownInchingView({super.key}); + final String deviceId; + const CountdownInchingView({super.key, required this.deviceId}); @override State createState() => _CountdownInchingViewState(); @@ -15,25 +16,30 @@ class CountdownInchingView extends StatefulWidget { class _CountdownInchingViewState extends State { late FixedExtentScrollController _hoursController; late FixedExtentScrollController _minutesController; + late FixedExtentScrollController _secondsController; int _lastHours = -1; int _lastMinutes = -1; + int _lastSeconds = -1; @override void initState() { super.initState(); _hoursController = FixedExtentScrollController(); _minutesController = FixedExtentScrollController(); + _secondsController = FixedExtentScrollController(); } @override void dispose() { _hoursController.dispose(); _minutesController.dispose(); + _secondsController.dispose(); super.dispose(); } - void _updateControllers(int displayHours, int displayMinutes) { + void _updateControllers( + int displayHours, int displayMinutes, int displaySeconds) { if (_lastHours != displayHours) { WidgetsBinding.instance.addPostFrameCallback((_) { if (_hoursController.hasClients) { @@ -50,6 +56,15 @@ class _CountdownInchingViewState extends State { }); _lastMinutes = displayMinutes; } + // Update seconds controller + if (_lastSeconds != displaySeconds) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_secondsController.hasClients) { + _secondsController.jumpToItem(displaySeconds); + } + }); + _lastSeconds = displaySeconds; + } } @override @@ -57,7 +72,6 @@ class _CountdownInchingViewState extends State { return BlocBuilder( builder: (context, state) { if (state is! ScheduleLoaded) return const SizedBox.shrink(); - final isCountDown = state.scheduleMode == ScheduleModes.countdown; final isActive = isCountDown ? state.isCountdownActive : state.isInchingActive; @@ -67,8 +81,21 @@ class _CountdownInchingViewState extends State { final displayMinutes = isActive && state.countdownRemaining != null ? state.countdownRemaining!.inMinutes.remainder(60) : (isCountDown ? state.countdownMinutes : state.inchingMinutes); + final displaySeconds = isActive && state.countdownRemaining != null + ? state.countdownRemaining!.inSeconds.remainder(60) + : (isCountDown ? state.countdownSeconds : state.inchingSeconds); + + _updateControllers(displayHours, displayMinutes, displaySeconds!); + + if (displayHours == 0 && displayMinutes == 0 && displaySeconds == 0) { + context.read().add( + StopScheduleEvent( + mode: ScheduleModes.countdown, + deviceId: widget.deviceId, + ), + ); + } - _updateControllers(displayHours, displayMinutes); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -100,7 +127,10 @@ class _CountdownInchingViewState extends State { (value) { if (!isActive) { context.read().add(UpdateCountdownTimeEvent( - hours: value, minutes: displayMinutes)); + hours: value, + minutes: displayMinutes, + seconds: displaySeconds, + )); } }, isActive: isActive, @@ -115,11 +145,35 @@ class _CountdownInchingViewState extends State { (value) { if (!isActive) { context.read().add(UpdateCountdownTimeEvent( - hours: displayHours, minutes: value)); + hours: displayHours, + minutes: value, + seconds: displaySeconds, + )); } }, isActive: isActive, ), + const SizedBox(width: 10), + if (isActive) + _buildPickerColumn( + context, + 's', + displaySeconds, + 60, + _secondsController, + (value) { + if (!isActive) { + context + .read() + .add(UpdateCountdownTimeEvent( + hours: displayHours, + minutes: displayMinutes, + seconds: value, + )); + } + }, + isActive: isActive, + ), ], ), ], diff --git a/lib/pages/device_managment/schedule_device/schedule_widgets/schedual_view.dart b/lib/pages/device_managment/schedule_device/schedule_widgets/schedual_view.dart index 2fa34559..47534d37 100644 --- a/lib/pages/device_managment/schedule_device/schedule_widgets/schedual_view.dart +++ b/lib/pages/device_managment/schedule_device/schedule_widgets/schedual_view.dart @@ -74,7 +74,9 @@ class BuildScheduleView extends StatelessWidget { ), if (state.scheduleMode == ScheduleModes.countdown || state.scheduleMode == ScheduleModes.inching) - const CountdownInchingView(), + CountdownInchingView( + deviceId: deviceUuid, + ), const SizedBox(height: 20), if (state.scheduleMode == ScheduleModes.countdown) CountdownModeButtons(