123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- import 'dart:async';
- import 'package:flutter/material.dart';
- import 'date_period.dart';
- import 'day_type.dart';
- import 'unselectable_period_error.dart';
- import 'utils.dart';
- /// Interface for selection logic of the different date pickers.
- ///
- /// T - is selection type.
- abstract class ISelectablePicker<T> {
- /// The earliest date the user is permitted to pick.
- ///
- /// Time is the midnight. Otherwise [isDisabled] may return undesired result.
- final DateTime? firstDate;
- /// The latest date the user is permitted to pick.
- ///
- /// Time is the millisecond before next day midnight.
- /// Otherwise [isDisabled] may return undesired result.
- final DateTime? lastDate;
- /// Function returns if day can be selected or not.
- final SelectableDayPredicate? _selectableDayPredicate;
- /// StreamController for new selection (T).
- @protected
- StreamController<T>? onUpdateController = StreamController<T>.broadcast();
- /// Stream with new selected (T) event.
- ///
- /// Throws [UnselectablePeriodException]
- /// if there is any custom disabled date in selected.
- Stream<T>? get onUpdate => onUpdateController!.stream;
- /// Constructor with required fields that used in non-abstract methods
- /// ([isDisabled]).
- ISelectablePicker(
- DateTime firstDate,
- DateTime lastDate, {
- SelectableDayPredicate? selectableDayPredicate,
- }) : firstDate = DatePickerUtils.startOfTheDay(firstDate),
- lastDate = DatePickerUtils.endOfTheDay(lastDate),
- _selectableDayPredicate = selectableDayPredicate;
- /// If current selection exists and includes day/days that can't be selected
- /// according to the [_selectableDayPredicate]'
- bool? get curSelectionIsCorrupted;
- /// Returns [DayType] for given [day].
- DayType? getDayType(DateTime day);
- /// Call when user tap on the day cell.
- void onDayTapped(DateTime selectedDate);
- /// Returns true if given day is disabled.
- ///
- /// Returns whether the given day is before the beginning of the [firstDate]
- /// or after the end of the [lastDate].
- ///
- /// If [_selectableDayPredicate] is set checks it as well.
- @protected
- bool isDisabled(DateTime day) =>
- day.isAfter(lastDate!) ||
- day.isBefore(firstDate!) ||
- !_selectableDayPredicate!(day);
- /// Closes [onUpdateController].
- /// After it [onUpdateController] can't get new events.
- void dispose() {
- onUpdateController!.close();
- }
- static bool _defaultSelectableDayPredicate(_) => true;
- }
- /// Selection logic for WeekPicker.
- class WeekSelectable extends ISelectablePicker<DatePeriod> {
- /// Initialized in ctor body.
- DateTime? _firstDayOfSelectedWeek;
- /// Initialized in ctor body.
- DateTime? _lastDayOfSelectedWeek;
- // It is int from 0 to 6 where 0 points to Sunday and 6 points to Saturday.
- // According to MaterialLocalization.firstDayOfWeekIndex.
- final int? _firstDayOfWeekIndex;
- @override
- bool? get curSelectionIsCorrupted => _checkCurSelection();
- /// Creates selection logic for WeekPicker.
- ///
- /// Entire week will be selected if
- /// * it is between [firstDate] and [lastDate]
- /// * it doesn't include unselectable days according to the
- /// [selectableDayPredicate]
- ///
- /// If one or more days of the week are before [firstDate]
- /// first selection date will be the same as [firstDate].
- ///
- /// If one or more days of the week are after [lastDate]
- /// last selection date will be the same as [lastDate].
- ///
- /// If one or more days of week are not selectable according to the
- /// [selectableDayPredicate] nothing will be returned as selection
- /// but [UnselectablePeriodException] will be thrown.
- WeekSelectable(DateTime selectedDate, this._firstDayOfWeekIndex,
- DateTime firstDate, DateTime lastDate,
- {SelectableDayPredicate? selectableDayPredicate})
- : super(firstDate, lastDate,
- selectableDayPredicate: selectableDayPredicate!) {
- DatePeriod selectedWeek = _getNewSelectedPeriod(selectedDate);
- _firstDayOfSelectedWeek = selectedWeek.start;
- _lastDayOfSelectedWeek = selectedWeek.end;
- _checkCurSelection();
- }
- @override
- DayType getDayType(DateTime date) {
- DayType result;
- DatePeriod selectedPeriod =
- DatePeriod(_firstDayOfSelectedWeek!, _lastDayOfSelectedWeek!);
- bool selectedPeriodIsBroken =
- _disabledDatesInPeriod(selectedPeriod).isNotEmpty;
- if (isDisabled(date)) {
- result = DayType.disabled;
- } else if (_isDaySelected(date) && !selectedPeriodIsBroken) {
- DateTime? firstNotDisabledDayOfSelectedWeek =
- (_firstDayOfSelectedWeek!.isBefore(firstDate!)
- ? firstDate
- : _firstDayOfSelectedWeek)!;
- DateTime lastNotDisabledDayOfSelectedWeek =
- (_lastDayOfSelectedWeek!.isAfter(lastDate!)
- ? lastDate
- : _lastDayOfSelectedWeek)!;
- if (DatePickerUtils.sameDate(date, firstNotDisabledDayOfSelectedWeek) &&
- DatePickerUtils.sameDate(date, lastNotDisabledDayOfSelectedWeek)) {
- result = DayType.single;
- } else if (DatePickerUtils.sameDate(date, _firstDayOfSelectedWeek!) ||
- DatePickerUtils.sameDate(date, firstDate!)) {
- result = DayType.start;
- } else if (DatePickerUtils.sameDate(date, _lastDayOfSelectedWeek!) ||
- DatePickerUtils.sameDate(date, lastDate!)) {
- result = DayType.end;
- } else {
- result = DayType.middle;
- }
- } else {
- result = DayType.notSelected;
- }
- return result;
- }
- @override
- void onDayTapped(DateTime selectedDate) {
- DatePeriod newPeriod = _getNewSelectedPeriod(selectedDate);
- List<DateTime> customDisabledDays = _disabledDatesInPeriod(newPeriod);
- customDisabledDays.isEmpty
- ? onUpdateController!.add(newPeriod)
- : onUpdateController!.addError(
- UnselectablePeriodException(customDisabledDays, newPeriod));
- }
- // Returns new selected period according to tapped date.
- // Doesn't check custom disabled days.
- // You have to check it separately if it needs.
- DatePeriod _getNewSelectedPeriod(DateTime tappedDay) {
- DatePeriod newPeriod;
- DateTime firstDayOfTappedWeek =
- DatePickerUtils.getFirstDayOfWeek(tappedDay, _firstDayOfWeekIndex!);
- DateTime lastDayOfTappedWeek =
- DatePickerUtils.getLastDayOfWeek(tappedDay, _firstDayOfWeekIndex!);
- DateTime firstNotDisabledDayOfSelectedWeek =
- (firstDayOfTappedWeek.isBefore(firstDate!)
- ? firstDate
- : firstDayOfTappedWeek)!;
- DateTime lastNotDisabledDayOfSelectedWeek =
- (lastDayOfTappedWeek.isAfter(lastDate!)
- ? lastDate
- : lastDayOfTappedWeek)!;
- newPeriod = DatePeriod(
- firstNotDisabledDayOfSelectedWeek, lastNotDisabledDayOfSelectedWeek);
- return newPeriod;
- }
- bool _isDaySelected(DateTime date) {
- DateTime startOfTheStartDay =
- DatePickerUtils.startOfTheDay(_firstDayOfSelectedWeek!);
- DateTime endOfTheLastDay =
- DatePickerUtils.endOfTheDay(_lastDayOfSelectedWeek!);
- return !(date.isBefore(startOfTheStartDay) ||
- date.isAfter(endOfTheLastDay));
- }
- List<DateTime> _disabledDatesInPeriod(DatePeriod period) {
- List<DateTime> result = <DateTime>[];
- var date = period.start;
- while (!date.isAfter(period.end)) {
- if (isDisabled(date)) result.add(date);
- date = date.add(Duration(days: 1));
- }
- return result;
- }
- // Returns if current selection contains disabled dates.
- // Returns false if there is no any selection.
- bool _checkCurSelection() {
- DatePeriod selectedPeriod =
- DatePeriod(_firstDayOfSelectedWeek!, _lastDayOfSelectedWeek!);
- List<DateTime> disabledDates = _disabledDatesInPeriod(selectedPeriod);
- bool selectedPeriodIsBroken = disabledDates.isNotEmpty;
- return selectedPeriodIsBroken;
- }
- }
- /// Selection logic for [day_picker.DayPicker].
- class DaySelectable extends ISelectablePicker<DateTime> {
- /// Currently selected date.
- DateTime selectedDate;
- @override
- bool get curSelectionIsCorrupted => _checkCurSelection();
- /// Creates selection logic for [day_picker.DayPicker].
- ///
- /// Every day can be selected if it is between [firstDate] and [lastDate]
- /// and not unselectable according to the [selectableDayPredicate].
- ///
- /// If day is not selectable according to the [selectableDayPredicate]
- /// nothing will be returned as selection
- /// but [UnselectablePeriodException] will be thrown.
- DaySelectable(this.selectedDate, DateTime firstDate, DateTime lastDate,
- {SelectableDayPredicate? selectableDayPredicate})
- : super(firstDate, lastDate,
- selectableDayPredicate: selectableDayPredicate!);
- @override
- DayType getDayType(DateTime date) {
- DayType result;
- if (isDisabled(date)) {
- result = DayType.disabled;
- } else if (_isDaySelected(date)) {
- result = DayType.single;
- } else {
- result = DayType.notSelected;
- }
- return result;
- }
- @override
- void onDayTapped(DateTime selectedDate) {
- DateTime newSelected = DatePickerUtils.sameDate(firstDate!, selectedDate)
- ? selectedDate
- : DateTime(selectedDate.year, selectedDate.month, selectedDate.day);
- onUpdateController!.add(newSelected);
- }
- bool _isDaySelected(DateTime date) =>
- DatePickerUtils.sameDate(date, selectedDate);
- // Returns if current selection is disabled
- // according to the [_selectableDayPredicate].
- //
- // Returns false if there is no any selection.
- bool _checkCurSelection() {
- bool selectedIsBroken = _selectableDayPredicate!(selectedDate);
- return selectedIsBroken;
- }
- }
- /// Selection logic for [day_picker.DayPicker] where many single days can be
- /// selected.
- class DayMultiSelectable extends ISelectablePicker<List<DateTime>> {
- /// Currently selected dates.
- List<DateTime> selectedDates;
- /// Creates selection logic for [day_picker.DayPicker].
- ///
- /// Every day can be selected if it is between [firstDate] and [lastDate]
- /// and not unselectable according to the [selectableDayPredicate].
- ///
- /// If day is not selectable according to the [selectableDayPredicate]
- /// nothing will be returned as selection
- /// but [UnselectablePeriodException] will be thrown.
- DayMultiSelectable(this.selectedDates, DateTime firstDate, DateTime lastDate,
- {SelectableDayPredicate? selectableDayPredicate})
- : super(firstDate, lastDate,
- selectableDayPredicate: selectableDayPredicate!);
- @override
- bool get curSelectionIsCorrupted => _checkCurSelection();
- @override
- DayType getDayType(DateTime date) {
- DayType result;
- if (isDisabled(date)) {
- result = DayType.disabled;
- } else if (_isDaySelected(date)) {
- result = DayType.single;
- } else {
- result = DayType.notSelected;
- }
- return result;
- }
- @override
- void onDayTapped(DateTime selectedDate) {
- bool alreadyExist =
- selectedDates.any((d) => DatePickerUtils.sameDate(d, selectedDate));
- if (alreadyExist) {
- List<DateTime> newSelectedDates = List.from(selectedDates)
- ..removeWhere((d) => DatePickerUtils.sameDate(d, selectedDate));
- onUpdateController!.add(newSelectedDates);
- } else {
- DateTime newSelected = DatePickerUtils.sameDate(firstDate!, selectedDate)
- ? selectedDate
- : DateTime(selectedDate.year, selectedDate.month, selectedDate.day);
- List<DateTime> newSelectedDates = List.from(selectedDates)
- ..add(newSelected);
- onUpdateController!.add(newSelectedDates);
- }
- }
- bool _isDaySelected(DateTime date) =>
- selectedDates.any((d) => DatePickerUtils.sameDate(date, d));
- // Returns if current selection is disabled
- // according to the [_selectableDayPredicate].
- //
- // Returns false if there is no any selection.
- bool _checkCurSelection() {
- if (selectedDates.isEmpty) return false;
- bool selectedIsBroken = selectedDates.every(_selectableDayPredicate!);
- return selectedIsBroken;
- }
- }
- /// Selection logic for [RangePicker].
- class RangeSelectable extends ISelectablePicker<DatePeriod> {
- /// Initially selected period.
- ///
- /// [selectedPeriod.start] time is midnight.
- /// [selectedPeriod.end] time is millisecond before next day midnight.
- DatePeriod? selectedPeriod;
- /// If [selectedPeriod] has dates unavailable to select.
- bool? _selectedPeriodIsBroken;
- @override
- bool? get curSelectionIsCorrupted => _checkCurSelection();
- /// Creates selection logic for [RangePicker].
- ///
- /// Period can be selected if
- /// * it is between [firstDate] and [lastDate]
- /// * it doesn't include unselectable days according to the
- /// [selectableDayPredicate]
- ///
- ///
- /// If one or more days of the period are not selectable according to the
- /// [selectableDayPredicate] nothing will be returned as selection
- /// but [UnselectablePeriodException] will be thrown.
- RangeSelectable(
- DatePeriod selectedPeriod, DateTime firstDate, DateTime lastDate,
- {SelectableDayPredicate? selectableDayPredicate})
- : selectedPeriod = DatePeriod(
- DatePickerUtils.startOfTheDay(selectedPeriod.start),
- DatePickerUtils.endOfTheDay(selectedPeriod.end),
- ),
- super(firstDate, lastDate,
- selectableDayPredicate: selectableDayPredicate!) {
- _selectedPeriodIsBroken = _disabledDatesInPeriod(selectedPeriod).isNotEmpty;
- }
- @override
- DayType getDayType(DateTime date) {
- DayType result;
- if (isDisabled(date)) {
- result = DayType.disabled;
- } else if (_isDaySelected(date) && !_selectedPeriodIsBroken!) {
- if (DatePickerUtils.sameDate(date, selectedPeriod!.start) &&
- DatePickerUtils.sameDate(date, selectedPeriod!.end)) {
- result = DayType.single;
- } else if (DatePickerUtils.sameDate(date, selectedPeriod!.start) ||
- DatePickerUtils.sameDate(date, firstDate!)) {
- result = DayType.start;
- } else if (DatePickerUtils.sameDate(date, selectedPeriod!.end) ||
- DatePickerUtils.sameDate(date, lastDate!)) {
- result = DayType.end;
- } else {
- result = DayType.middle;
- }
- } else {
- result = DayType.notSelected;
- }
- return result;
- }
- @override
- void onDayTapped(DateTime selectedDate) {
- DatePeriod newPeriod = _getNewSelectedPeriod(selectedDate);
- List<DateTime> customDisabledDays = _disabledDatesInPeriod(newPeriod);
- if (customDisabledDays.isEmpty) {
- selectedPeriod = newPeriod;
- _selectedPeriodIsBroken = false;
- onUpdateController!.add(newPeriod);
- } else {
- onUpdateController!
- .addError(UnselectablePeriodException(customDisabledDays, newPeriod));
- }
- }
- // Returns new selected period according to tapped date.
- DatePeriod _getNewSelectedPeriod(DateTime tappedDate) {
- // check if was selected only one date and we should generate period
- bool sameDate =
- DatePickerUtils.sameDate(selectedPeriod!.start, selectedPeriod!.end);
- DatePeriod newPeriod;
- // Was selected one-day-period.
- // With new user tap will be generated 2 dates as a period.
- if (sameDate) {
- // if user tap on the already selected single day
- bool selectedAlreadySelectedDay =
- DatePickerUtils.sameDate(tappedDate, selectedPeriod!.end);
- bool isSelectedFirstDay =
- DatePickerUtils.sameDate(tappedDate, firstDate!);
- bool isSelectedLastDay = DatePickerUtils.sameDate(tappedDate, lastDate!);
- if (selectedAlreadySelectedDay) {
- if (isSelectedFirstDay && isSelectedLastDay) {
- newPeriod = DatePeriod(firstDate!, lastDate!);
- } else if (isSelectedFirstDay) {
- newPeriod =
- DatePeriod(firstDate!, DatePickerUtils.endOfTheDay(firstDate!));
- } else if (isSelectedLastDay) {
- newPeriod =
- DatePeriod(DatePickerUtils.startOfTheDay(lastDate!), lastDate!);
- } else {
- newPeriod = DatePeriod(DatePickerUtils.startOfTheDay(tappedDate),
- DatePickerUtils.endOfTheDay(tappedDate));
- }
- } else {
- DateTime startOfTheSelectedDay =
- DatePickerUtils.startOfTheDay(selectedPeriod!.start);
- if (!tappedDate.isAfter(startOfTheSelectedDay)) {
- newPeriod = DatePickerUtils.sameDate(tappedDate, firstDate!)
- ? DatePeriod(firstDate!, selectedPeriod!.end)
- : DatePeriod(DatePickerUtils.startOfTheDay(tappedDate),
- selectedPeriod!.end);
- } else {
- newPeriod = DatePickerUtils.sameDate(tappedDate, lastDate!)
- ? DatePeriod(selectedPeriod!.start, lastDate!)
- : DatePeriod(selectedPeriod!.start,
- DatePickerUtils.endOfTheDay(tappedDate));
- }
- }
- // Was selected 2 dates as a period.
- // With new user tap new one-day-period will be generated.
- } else {
- bool sameAsFirst = DatePickerUtils.sameDate(tappedDate, firstDate!);
- bool sameAsLast = DatePickerUtils.sameDate(tappedDate, lastDate!);
- if (sameAsFirst && sameAsLast) {
- newPeriod = DatePeriod(firstDate!, lastDate!);
- } else if (sameAsFirst) {
- newPeriod =
- DatePeriod(firstDate!, DatePickerUtils.endOfTheDay(firstDate!));
- } else if (sameAsLast) {
- newPeriod =
- DatePeriod(DatePickerUtils.startOfTheDay(tappedDate), lastDate!);
- } else {
- newPeriod = DatePeriod(DatePickerUtils.startOfTheDay(tappedDate),
- DatePickerUtils.endOfTheDay(tappedDate));
- }
- }
- return newPeriod;
- }
- // Returns if current selection contains disabled dates.
- // Returns false if there is no any selection.
- bool _checkCurSelection() {
- List<DateTime> disabledDates = _disabledDatesInPeriod(selectedPeriod!);
- bool selectedPeriodIsBroken = disabledDates.isNotEmpty;
- return selectedPeriodIsBroken;
- }
- List<DateTime> _disabledDatesInPeriod(DatePeriod period) {
- List<DateTime> result = <DateTime>[];
- var date = period.start;
- while (!date.isAfter(period.end)) {
- if (isDisabled(date)) result.add(date);
- date = date.add(Duration(days: 1));
- }
- return result;
- }
- bool _isDaySelected(DateTime date) {
- DateTime startOfTheStartDay = selectedPeriod!.start;
- DateTime endOfTheLastDay = selectedPeriod!.end;
- return !(date.isBefore(startOfTheStartDay) ||
- date.isAfter(endOfTheLastDay));
- }
- }
- /// Selection logic for [day_picker.MonthPicker.single].
- class MonthSelectable extends ISelectablePicker<DateTime> {
- /// Currently selected date.
- DateTime selectedDate;
- @override
- bool get curSelectionIsCorrupted => _checkCurSelection();
- /// Creates selection logic for [day_picker.MonthPicker]
- /// with single selection.
- ///
- /// Every date can be selected if it is between [firstDate] and [lastDate]
- /// and not unselectable according to the [selectableDayPredicate].
- ///
- /// If date is not selectable according to the [selectableDayPredicate]
- /// nothing will be returned as selection
- /// but [UnselectablePeriodException] will be thrown.
- MonthSelectable(this.selectedDate, DateTime firstDate, DateTime lastDate,
- {SelectableDayPredicate? selectableDayPredicate})
- : super(firstDate, lastDate,
- selectableDayPredicate: selectableDayPredicate);
- @override
- DayType getDayType(DateTime date) {
- DayType result;
- if (isDisabled(date)) {
- result = DayType.disabled;
- } else if (_isDaySelected(date)) {
- result = DayType.single;
- } else {
- result = DayType.notSelected;
- }
- return result;
- }
- @override
- void onDayTapped(DateTime selectedDate) {
- DateTime newSelected = DatePickerUtils.sameMonth(firstDate!, selectedDate)
- ? selectedDate
- : DateTime(selectedDate.year, selectedDate.month, selectedDate.day);
- onUpdateController!.add(newSelected);
- }
- bool _isDaySelected(DateTime date) =>
- DatePickerUtils.sameMonth(date, selectedDate);
- // Returns if current selection is disabled
- // according to the [_selectableDayPredicate].
- //
- // Returns false if there is no any selection.
- bool _checkCurSelection() {
- bool selectedIsBroken = _selectableDayPredicate!(selectedDate);
- return selectedIsBroken;
- }
- // We only need to know if month of passed day
- // before the month of the firstDate or after the month of the lastDate.
- //
- // Don't need to compare day and time.
- @protected
- @override
- bool isDisabled(DateTime month) {
- DateTime beginningOfTheFirstDateMonth =
- DateTime(firstDate!.year, firstDate!.month);
- DateTime endOfTheLastDateMonth = DateTime(
- lastDate!.year,
- lastDate!.month,
- DatePickerUtils.getDaysInMonth(lastDate!.year, lastDate!.month),
- 23,
- 59,
- 59,
- 999,
- );
- return month.isAfter(endOfTheLastDateMonth) ||
- month.isBefore(beginningOfTheFirstDateMonth);
- }
- }
- /// Selection logic for [day_picker.MonthPicker.multi]
- /// where many single months can be selected.
- class MonthMultiSelectable extends ISelectablePicker<List<DateTime>> {
- /// Currently selected dates.
- List<DateTime> selectedDates;
- /// Creates selection logic for [day_picker.MonthPicker] with multi selection.
- ///
- /// Every day can be selected if it is between [firstDate] and [lastDate]
- /// and not unselectable according to the [selectableDayPredicate].
- ///
- /// If day is not selectable according to the [selectableDayPredicate]
- /// nothing will be returned as selection
- /// but [UnselectablePeriodException] will be thrown.
- MonthMultiSelectable(
- this.selectedDates,
- DateTime firstDate,
- DateTime lastDate, {
- SelectableDayPredicate? selectableDayPredicate,
- }) : super(firstDate, lastDate,
- selectableDayPredicate: selectableDayPredicate!);
- @override
- bool get curSelectionIsCorrupted => _checkCurSelection();
- @override
- DayType getDayType(DateTime date) {
- DayType result;
- if (isDisabled(date)) {
- result = DayType.disabled;
- } else if (_isDaySelected(date)) {
- result = DayType.single;
- } else {
- result = DayType.notSelected;
- }
- return result;
- }
- @override
- void onDayTapped(DateTime selectedDate) {
- bool alreadyExist =
- selectedDates.any((d) => DatePickerUtils.sameMonth(d, selectedDate));
- if (alreadyExist) {
- List<DateTime> newSelectedDates = List.from(selectedDates)
- ..removeWhere((d) => DatePickerUtils.sameMonth(d, selectedDate));
- onUpdateController!.add(newSelectedDates);
- } else {
- DateTime newSelected =
- (DatePickerUtils.sameMonth(firstDate!, selectedDate)
- ? firstDate
- : DateTime(selectedDate.year, selectedDate.month))!;
- List<DateTime> newSelectedDates = List.from(selectedDates)
- ..add(newSelected);
- onUpdateController!.add(newSelectedDates);
- }
- }
- bool _isDaySelected(DateTime date) =>
- selectedDates.any((d) => DatePickerUtils.sameMonth(date, d));
- // Returns if current selection is disabled
- // according to the [_selectableDayPredicate].
- //
- // Returns false if there is no any selection.
- bool _checkCurSelection() {
- if (selectedDates.isEmpty) return false;
- bool selectedIsBroken = selectedDates.every(_selectableDayPredicate!);
- return selectedIsBroken;
- }
- }
|