Skip to content

Commit

Permalink
feat: Added support for startWeekOnMonday to MacosDatePicker
Browse files Browse the repository at this point in the history
  • Loading branch information
rklos committed Jul 3, 2023
1 parent 46eb9ca commit 50a3d28
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
## [2.0.0-beta.3]
✨ New ✨
* Added support for `startWeekOnMonday` to `MacosDatePicker`.

🛠️ Fixed 🛠️
* Better UX of the click on the calendar elements in `MacosDatePicker`

Expand Down
33 changes: 30 additions & 3 deletions lib/src/selectors/date_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class MacosDatePicker extends StatefulWidget {
this.style = DatePickerStyle.combined,
required this.onDateChanged,
this.initialDate,
this.startWeekOnMonday,
});

/// The [DatePickerStyle] to use.
Expand All @@ -59,6 +60,12 @@ class MacosDatePicker extends StatefulWidget {
/// Defaults to `DateTime.now()`.
final DateTime? initialDate;

/// Allows to change the order of day headers in the graphical Date Picker
/// to Mo, Tu, We, Th, Fr, Sa, Su
///
/// Defaults to `false`
final bool? startWeekOnMonday;

@override
State<MacosDatePicker> createState() => _MacosDatePickerState();
}
Expand Down Expand Up @@ -153,12 +160,23 @@ class _MacosDatePickerState extends State<MacosDatePicker> {
}

// Creates the day headers - Su, Mo, Tu, We, Th, Fr, Sa
// or Mo, Tu, We, Th, Fr, Sa, Su depending on the value of [startWeekOnMonday]
List<Widget> _dayHeaders(
TextStyle? headerStyle,
MaterialLocalizations localizations,
) {
final result = <Widget>[];
for (int i = localizations.firstDayOfWeekIndex; true; i = (i + 1) % 7) {

// Hack due to invalid "firstDayOfWeekIndex" implementation in MaterialLocalizations
// issue: https://github.com/flutter/flutter/issues/122274
// TODO: remove this workaround once the issue is fixed.
// Then, "firstDayOfWeekIndex" can be controlled by passing "localizationsDelegates" and "supportedLocales" to MacosApp
int firstDayOfWeekIndex = localizations.firstDayOfWeekIndex;
if (widget.startWeekOnMonday == true) {
firstDayOfWeekIndex = 1;
}

for (int i = firstDayOfWeekIndex; result.length < 7; i = (i + 1) % 7) {
final weekday = _narrowWeekdays[i];
result.add(
ExcludeSemantics(
Expand All @@ -170,7 +188,6 @@ class _MacosDatePickerState extends State<MacosDatePicker> {
),
),
);
if (i == (localizations.firstDayOfWeekIndex - 1) % 7) break;
}
return result;
}
Expand Down Expand Up @@ -474,9 +491,19 @@ class _MacosDatePickerState extends State<MacosDatePicker> {
),
localizations,
);

// Hack due to invalid "firstDayOfWeekIndex" implementation in MaterialLocalizations
// issue: https://github.com/flutter/flutter/issues/122274
// TODO: remove this workaround once the issue is fixed.
// Then, DateUtils.getDaysInMonth will work as expected when proper "localizationsDelegates" and "supportedLocales" are provided to MacosApp
int fixedDayOffset = dayOffset;
if (widget.startWeekOnMonday == true) {
fixedDayOffset = dayOffset - 1;
}

// 1-based day of month, e.g. 1-31 for January, and 1-29 for February on
// a leap year.
int day = -dayOffset;
int day = -fixedDayOffset;

final dayItems = <Widget>[];

Expand Down
92 changes: 92 additions & 0 deletions test/selectors/date_picker_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -308,4 +308,96 @@ void main() {
},
);
});

testWidgets(
'Graphical MacosDatePicker with "startWeekOnMonday" set to true shows Monday as the first day of the week',
(tester) async {
await tester.pumpWidget(
MacosApp(
home: MacosWindow(
child: MacosScaffold(
children: [
ContentArea(
builder: (context, _) {
return Center(
child: MacosDatePicker(
startWeekOnMonday: true,
initialDate: DateTime.parse('2023-04-01'),
onDateChanged: (date) {},
),
);
},
),
],
),
),
),
);

final dayHeadersRow = find.byType(GridView).first;
final dayHeaders = find.descendant(
of: dayHeadersRow,
matching: find.byType(Text),
);
final firstWeekday = dayHeaders.first;
final firstWeekdayText = (firstWeekday.evaluate().first.widget as Text).data;
await tester.pumpAndSettle();

expect(firstWeekdayText, 'Mo');

final calendarGrid = find.byType(GridView).last;
final dayOffsetWidgets = find.descendant(
of: calendarGrid,
matching: find.byType(SizedBox),
);
final dayOffset = dayOffsetWidgets.evaluate().length;

expect(dayOffset, 5);
},
);

// Regression test due to invalid "firstDayOfWeekIndex" implementation in MaterialLocalizations
// issue: https://github.com/flutter/flutter/issues/122274
// TODO: remove this once the issue is fixed and test starts failing
testWidgets(
'Graphical MacosDatePicker still needs "startWeekOnMonday" to show Monday as the first day of the week, even when the locale is set to something other than "en_US"',
(tester) async {
await tester.pumpWidget(
MacosApp(
supportedLocales: const [
Locale('en', 'PL'),
],
home: MacosWindow(
child: MacosScaffold(
children: [
ContentArea(
builder: (context, _) {
return Center(
child: MacosDatePicker(
startWeekOnMonday: true,
initialDate: DateTime.parse('2023-04-01'),
onDateChanged: (date) {},
),
);
},
),
],
),
),
),
);

final dayHeadersRow = find.byType(GridView).first;
final dayHeaders = find.descendant(
of: dayHeadersRow,
matching: find.byType(Text),
);
final firstWeekday = dayHeaders.first;
final firstWeekdayText = (firstWeekday.evaluate().first.widget as Text).data;
await tester.pumpAndSettle();

// The result will be 'Tu' if the fix is no longer needed and can be removed
expect(firstWeekdayText, 'Mo');
},
);
}

0 comments on commit 50a3d28

Please sign in to comment.