From 1d5087eb30382a763b17ddaff68011383faaa7d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Schramm?= <89677437+Pachebel@users.noreply.github.com> Date: Tue, 22 Oct 2024 16:37:19 -0300 Subject: [PATCH] fix: CupertinoDatePicker.DateAndTime using showDayOfWeek (#155260) As mentioned in the issue https://github.com/flutter/flutter/issues/153576, even if we declare the 'showDayOfWeek' value as false, when using the mode CupertinoDatePickerMode.dateAndTime, the days of week still shows in the screen. This PR is about making an assert that prevent developers from using `DateTimePicker.DateAndTime` with `showDayOfWeek` as false (because it only works on date mode) as suggested by @Piinks. --- .../lib/src/cupertino/date_picker.dart | 73 +++++++++---------- .../test/cupertino/date_picker_test.dart | 49 +++++++++++++ 2 files changed, 84 insertions(+), 38 deletions(-) diff --git a/packages/flutter/lib/src/cupertino/date_picker.dart b/packages/flutter/lib/src/cupertino/date_picker.dart index 0e89098938..ccb2b644ff 100644 --- a/packages/flutter/lib/src/cupertino/date_picker.dart +++ b/packages/flutter/lib/src/cupertino/date_picker.dart @@ -301,43 +301,38 @@ class CupertinoDatePicker extends StatefulWidget { this.itemExtent = _kItemExtent, this.selectionOverlayBuilder, }) : initialDateTime = initialDateTime ?? DateTime.now(), - assert( - itemExtent > 0, - 'item extent should be greater than 0', - ), - assert( - minuteInterval > 0 && 60 % minuteInterval == 0, - 'minute interval is not a positive integer factor of 60', - ) { - assert( - mode != CupertinoDatePickerMode.dateAndTime || minimumDate == null || !this.initialDateTime.isBefore(minimumDate!), - 'initial date is before minimum date', - ); - assert( - mode != CupertinoDatePickerMode.dateAndTime || maximumDate == null || !this.initialDateTime.isAfter(maximumDate!), - 'initial date is after maximum date', - ); - assert( - (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || (minimumYear >= 1 && this.initialDateTime.year >= minimumYear), - 'initial year is not greater than minimum year, or minimum year is not positive', - ); - assert( - (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || maximumYear == null || this.initialDateTime.year <= maximumYear!, - 'initial year is not smaller than maximum year', - ); - assert( - (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || minimumDate == null || !minimumDate!.isAfter(this.initialDateTime), - 'initial date ${this.initialDateTime} is not greater than or equal to minimumDate $minimumDate', - ); - assert( - (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || maximumDate == null || !maximumDate!.isBefore(this.initialDateTime), - 'initial date ${this.initialDateTime} is not less than or equal to maximumDate $maximumDate', - ); - assert( - this.initialDateTime.minute % minuteInterval == 0, - 'initial minute is not divisible by minute interval', - ); - } + assert(itemExtent > 0, 'item extent should be greater than 0'), + assert(minuteInterval > 0 && 60 % minuteInterval == 0, 'minute interval is not a positive integer factor of 60'), + assert( + mode != CupertinoDatePickerMode.dateAndTime || minimumDate == null || !(initialDateTime ?? DateTime.now()).isBefore(minimumDate), + 'initial date is before minimum date', + ), + assert( + mode != CupertinoDatePickerMode.dateAndTime || maximumDate == null || !(initialDateTime ?? DateTime.now()).isAfter(maximumDate), + 'initial date is after maximum date', + ), + assert( + (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || (minimumYear >= 1 && (initialDateTime ?? DateTime.now()).year >= minimumYear), + 'initial year is not greater than minimum year, or minimum year is not positive', + ), + assert( + (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || maximumYear == null || (initialDateTime ?? DateTime.now()).year <= maximumYear, + 'initial year is not smaller than maximum year', + ), + assert( + (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || minimumDate == null || !minimumDate.isAfter(initialDateTime ?? DateTime.now()), + 'initial date ${initialDateTime ?? DateTime.now()} is not greater than or equal to minimumDate $minimumDate', + ), + assert( + (mode != CupertinoDatePickerMode.date && mode != CupertinoDatePickerMode.monthYear) || maximumDate == null || !maximumDate.isBefore(initialDateTime ?? DateTime.now()), + 'initial date ${initialDateTime ?? DateTime.now()} is not less than or equal to maximumDate $maximumDate', + ), + assert( + (mode == CupertinoDatePickerMode.date) || !showDayOfWeek, + 'showDayOfWeek is only supported in date mode', + ), + assert((initialDateTime ?? DateTime.now()).minute % minuteInterval == 0, 'initial minute is not divisible by minute interval'); + /// The mode of the date picker as one of [CupertinoDatePickerMode]. Defaults /// to [CupertinoDatePickerMode.dateAndTime]. Value cannot change after @@ -414,7 +409,9 @@ class CupertinoDatePicker extends StatefulWidget { /// Defaults to null, which disables background painting entirely. final Color? backgroundColor; - /// Whether to show day of week alongside day. Defaults to false. + /// Whether to show the day of week alongside the day in [CupertinoDatePickerMode.date] mode. + /// + /// Defaults to false. final bool showDayOfWeek; /// {@macro flutter.cupertino.picker.itemExtent} diff --git a/packages/flutter/test/cupertino/date_picker_test.dart b/packages/flutter/test/cupertino/date_picker_test.dart index 7a751bf171..a9a9ad1dcb 100644 --- a/packages/flutter/test/cupertino/date_picker_test.dart +++ b/packages/flutter/test/cupertino/date_picker_test.dart @@ -261,6 +261,55 @@ void main() { }); }); + testWidgets('showDayOfWeek is only supported in date mode', (WidgetTester tester) async { + expect( + () => CupertinoDatePicker( + mode: CupertinoDatePickerMode.date, + onDateTimeChanged: (DateTime _) {}, + showDayOfWeek: true, + ), + returnsNormally, + ); + + expect( + () => CupertinoDatePicker( + mode: CupertinoDatePickerMode.time, + onDateTimeChanged: (DateTime _) {}, + showDayOfWeek: true, + ), + throwsA(isA().having( + (AssertionError e) => e.message ?? 'Unknown error', + 'message', + contains('showDayOfWeek is only supported in date mode'), + )), + ); + + expect( + () => CupertinoDatePicker( + mode: CupertinoDatePickerMode.monthYear, + onDateTimeChanged: (DateTime _) {}, + showDayOfWeek: true, + ), + throwsA(isA().having( + (AssertionError e) => e.message ?? 'Unknown error', + 'message', + contains('showDayOfWeek is only supported in date mode'), + )), + ); + + expect( + () => CupertinoDatePicker( + onDateTimeChanged: (DateTime _) {}, + showDayOfWeek: true, + ), + throwsA(isA().having( + (AssertionError e) => e.message ?? 'Unknown error', + 'message', + contains('showDayOfWeek is only supported in date mode'), + )), + ); + }); + testWidgets('picker honors minuteInterval and secondInterval', (WidgetTester tester) async { late Duration duration; await tester.pumpWidget(