Skip to content

Commit

Permalink
Merge branch 'rc-1.7.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
jenspfahl committed Aug 26, 2024
2 parents 5ce3f9d + a030caf commit d6a0cec
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 106 deletions.
96 changes: 45 additions & 51 deletions lib/model/Schedule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -298,10 +298,6 @@ class Schedule {
extractValue: (dayOfWeek) {
return dayOfWeek.index + 1;
},
shiftBack: (repetitionValue, from) {
final shift = repetitionValue * DayOfWeek.values.length; // period - 1, e.g. 2 weeks = 1 week, 3 weeks = 2 weeks
return from.subtract(Duration(days: shift));
},
) ?? nextRegularDueDate;
}

Expand All @@ -312,10 +308,7 @@ class Schedule {
},
extractValue: (dayOfMonth) {
return dayOfMonth;
},
shiftBack: (repetitionValue, from) {
return Jiffy.parseFromDateTime(from).subtract(months: repetitionValue).dateTime;
},
}
) ?? nextRegularDueDate;
}

Expand All @@ -326,10 +319,7 @@ class Schedule {
},
extractValue: (dayOfMonth) {
return dayOfMonth.value;
},
shiftBack: (repetitionValue, from) {
return Jiffy.parseFromDateTime(from).subtract(years: repetitionValue).dateTime;
},
}
) ?? nextRegularDueDate;
}
// bypass
Expand Down Expand Up @@ -380,49 +370,43 @@ class Schedule {
bool moveForward, {
required T Function (DateTime from) extractType,
required int Function (T) extractValue,
required DateTime Function (int repetitionValue, DateTime from) shiftBack,
}) {

//debugPrint("from=$from nextRegularDueDate=$nextRegularDueDate");

final sorted = days.toList();
sorted.sort((e1, e2) => extractValue(e1) - extractValue(e2));

if (moveForward) {
// first check from current period
final next = _findForwardsFromCurrentDate(from, sorted, extractType, extractValue);
final sortedAscending = days.toList();
sortedAscending.sort((e1, e2) => extractValue(e1) - extractValue(e2));

// first try to find next in current period
final next = _findForwardsFromCurrentDate(from, sortedAscending, extractType, extractValue);

//debugPrint("next = $next");
if (next != null) {
return next;
}

// second check from next period
final firstNextPeriod = _findForwardsFromBeginOfPeriod(nextRegularDueDate, sorted, extractType, extractValue);
// second try to find first in next period
final firstNextPeriod = _findForwardsFromBeginOfPeriodIn(nextRegularDueDate, sortedAscending, extractType, extractValue);

//debugPrint("firstNextPeriod = $firstNextPeriod");
return firstNextPeriod;

}
else {
// first check from current period (which is after next period here)
final last = _findBackwardsFromCurrentDate(from, sorted, extractType, extractValue);
final sortedDescending = days.toList();
sortedDescending.sort((e1, e2) => extractValue(e2) - extractValue(e1));

// first try to find last in current period
final last = _findBackwardsFromCurrentDate(from, sortedDescending, extractType, extractValue);

//debugPrint("last = $last");
if (last != null) {
// if last the max element in sorted, shift x days back
if (!sorted.any((element) => extractValue(element) >= extractValue(extractType(last)))) {
final repetition = fromRepetitionStepToCustomRepetition(repetitionStep, customRepetition);
final corrected = shiftBack(repetition.repetitionValue - 1, last);
//debugPrint("corrected = $corrected");

return corrected;
}
return last;
}

// second check from previous period
final lastPreviousPeriod = _findBackwardsFromEndOfPeriod(nextRegularDueDate, sorted, extractType, extractValue);
final lastPreviousPeriod = _findBackwardsFromEndOfPeriodIn(nextRegularDueDate, sortedDescending, extractType, extractValue);

//debugPrint("lastPreviousPeriod = $lastPreviousPeriod");
return lastPreviousPeriod;
Expand All @@ -432,14 +416,15 @@ class Schedule {
}


DateTime? _findForwardsFromCurrentDate<T>(DateTime from, List<T> days, T Function (DateTime) extractType, int Function (T) extractValue) {
DateTime? _findForwardsFromCurrentDate<T>(DateTime from, List<T> daysAscending, T Function (DateTime) extractType, int Function (T) extractValue) {

final dayFrom = extractType(from);
final nextDay = days.where((day) => extractValue(day) > extractValue(dayFrom)).firstOrNull;
final dayFromValue = extractValue(dayFrom);
final nextDay = daysAscending.where((day) => extractValue(day) > dayFromValue).firstOrNull;
//debugPrint("nextDay: $nextDay");

if (nextDay is DayOfWeek) {
final next = from.add(Duration(days: extractValue(nextDay) - extractValue(dayFrom)));
final next = from.add(Duration(days: extractValue(nextDay) - dayFromValue));
//debugPrint("found next in period $next after from");
return next;
}
Expand All @@ -449,49 +434,58 @@ class Schedule {
}


DateTime? _findForwardsFromBeginOfPeriod<T>(DateTime from, List<T> days, T Function (DateTime) extractType, int Function (T) extractValue) {
final dayBeforePeriodStartOfFrom = from.subtract(Duration(days: extractValue(extractType(from))));
//debugPrint("dayBeforePeriodStartOfFrom = $dayBeforePeriodStartOfFrom");

final firstDay = days.firstOrNull;
DateTime? _findForwardsFromBeginOfPeriodIn<T>(DateTime nextDueDate, List<T> daysAscending, T Function (DateTime) extractType, int Function (T) extractValue) {
final firstDay = daysAscending.firstOrNull;
if (firstDay is DayOfWeek) {
final date = dayBeforePeriodStartOfFrom.add(Duration(days: extractValue(firstDay)));
// get the day before Monday of the target period
final dayBeforeWeekStart = nextDueDate.subtract(Duration(days: extractValue(extractType(nextDueDate))));
debugPrint("dayBeforeWeekStart = $dayBeforeWeekStart");

// add the number of the first week day (Monday = 1, etc)
final date = dayBeforeWeekStart.add(Duration(days: extractValue(firstDay)));
//debugPrint("found first schedule in period: $date");
return date;
}
else {
return _mapFixedNonWeekScheduleDay(from, firstDay);
return _mapFixedNonWeekScheduleDay(nextDueDate, firstDay);
}
}


DateTime? _findBackwardsFromCurrentDate<T>(DateTime from, List<T> days, T Function (DateTime) extractType, int Function (T) extractValue) {
DateTime? _findBackwardsFromCurrentDate<T>(DateTime from, List<T> daysDescending, T Function (DateTime) extractType, int Function (T) extractValue) {
final dayFrom = extractType(from);
final dayFromValue = extractValue(dayFrom);
//debugPrint("dayFrom: $dayFrom");

final lastDay = days.where((day) => extractValue(day) < extractValue(dayFrom)).lastOrNull;
final lastDay = daysDescending.where((day) => extractValue(day) < dayFromValue).firstOrNull;
//debugPrint("lastDay: $lastDay");

if (lastDay is DayOfWeek) {
final next = from.add(Duration(days: extractValue(lastDay) - extractValue(dayFrom)));
//debugPrint("found last in period $next after from");
return next;
final last = from.subtract(Duration(days: dayFromValue - extractValue(lastDay)));
//debugPrint("found last in period $last after from");
return last;
}
else {
return _mapFixedNonWeekScheduleDay(from, lastDay);
}
}


DateTime? _findBackwardsFromEndOfPeriod<T>(DateTime from, List<T> days, T Function (DateTime) extractType, int Function (T) extractValue) {
final lastDay = days.lastOrNull;
DateTime? _findBackwardsFromEndOfPeriodIn<T>(DateTime previousDueDate, List<T> daysDescending, T Function (DateTime) extractType, int Function (T) extractValue) {
final lastDay = daysDescending.firstOrNull;
if (lastDay is DayOfWeek) {
final date = from.add(Duration(days: extractValue(lastDay) - 1));
//debugPrint("found last schedule in period: $date");

// get the day after Sunday of the target period
final dayAfterWeekEnd = previousDueDate.add(Duration(days: 7 + 1 - extractValue(extractType(previousDueDate))));
debugPrint("dayAfterWeekEnd = $dayAfterWeekEnd");

// subtract the backwarded number of the last week day (Monday = 1 --> 7 - 1 = 6)
final date = dayAfterWeekEnd.subtract(Duration(days: 7 + 1 - extractValue(lastDay)));
//debugPrint("found first schedule in period: $date");
return date;
}
else {
return _mapFixedNonWeekScheduleDay(from, lastDay);
return _mapFixedNonWeekScheduleDay(previousDueDate, lastDay);
}
}

Expand Down
68 changes: 42 additions & 26 deletions lib/ui/forms/ScheduledTaskForm.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,59 +92,59 @@ class _ScheduledTaskFormState extends State<ScheduledTaskForm> {
super.initState();

if (_scheduledTask != null) {
titleController.text = _scheduledTask!.translatedTitle;
descriptionController.text = _scheduledTask!.translatedDescription ?? "";
titleController.text = _scheduledTask.translatedTitle;
descriptionController.text = _scheduledTask.translatedDescription ?? "";

_selectedRepetitionStep = _scheduledTask!.schedule.repetitionStep;
_customRepetition = _scheduledTask!.schedule.customRepetition;
_selectedRepetitionStep = _scheduledTask.schedule.repetitionStep;
_customRepetition = _scheduledTask.schedule.customRepetition;

_selectedStartAt = _scheduledTask!.schedule.aroundStartAt;
final startedAt = _scheduledTask!.schedule.startAtExactly;
_selectedStartAt = _scheduledTask.schedule.aroundStartAt;
final startedAt = _scheduledTask.schedule.startAtExactly;
if (startedAt != null && _selectedStartAt == AroundWhenAtDay.CUSTOM) {
_selectedStartAt = AroundWhenAtDay.CUSTOM; // Former NOW is now CUSTOM
_customStartAt = startedAt;
}

if (_scheduledTask?.lastScheduledEventOn != null) {
if (_scheduledTask.lastScheduledEventOn != null) {
// adjust forth
final nextDueDate = _scheduledTask!.schedule.getNextRepetitionFrom(_scheduledTask!.lastScheduledEventOn!);
final nextDueDate = _scheduledTask.schedule.getNextRepetitionFrom(_scheduledTask.lastScheduledEventOn!);
_selectedNextDueOn = fromDateTimeToWhenOnDateFuture(nextDueDate);
_customNextDueOn = nextDueDate;
}

_isActive = _scheduledTask!.active;
_isImportant = _scheduledTask!.important;
_repetitionMode = _scheduledTask!.schedule.repetitionMode;
_isActive = _scheduledTask.active;
_isImportant = _scheduledTask.important;
_repetitionMode = _scheduledTask.schedule.repetitionMode;

if (_scheduledTask!.reminderNotificationEnabled != null) {
_isRemindersEnabled = _scheduledTask!.reminderNotificationEnabled!;
if (_scheduledTask.reminderNotificationEnabled != null) {
_isRemindersEnabled = _scheduledTask.reminderNotificationEnabled!;
}
if (_scheduledTask!.reminderNotificationRepetition != null) {
_reminderRepetition = _scheduledTask!.reminderNotificationRepetition!;
if (_scheduledTask.reminderNotificationRepetition != null) {
_reminderRepetition = _scheduledTask.reminderNotificationRepetition!;
}

if (_scheduledTask!.preNotificationEnabled != null) {
_isPreNotificationEnabled = _scheduledTask!.preNotificationEnabled!;
if (_scheduledTask.preNotificationEnabled != null) {
_isPreNotificationEnabled = _scheduledTask.preNotificationEnabled!;
}
if (_scheduledTask!.preNotification != null) {
_preNotification = _scheduledTask!.preNotification!;
if (_scheduledTask.preNotification != null) {
_preNotification = _scheduledTask.preNotification!;
}

weekBasedSchedules = _scheduledTask!.schedule.weekBasedSchedules.toSet();
monthBasedSchedules = _scheduledTask!.schedule.monthBasedSchedules.toSet();
yearBasedSchedules = _scheduledTask!.schedule.yearBasedSchedules.toSet();
weekBasedSchedules = _scheduledTask.schedule.weekBasedSchedules.toSet();
monthBasedSchedules = _scheduledTask.schedule.monthBasedSchedules.toSet();
yearBasedSchedules = _scheduledTask.schedule.yearBasedSchedules.toSet();

var nextDueOn = When.fromWhenOnDateFutureToDate(_selectedNextDueOn!, _customNextDueOn);

if (_repetitionMode == RepetitionMode.ONE_TIME) {
_selectedRepetitionStep = null; // we have to store a step even if ONE_TIME, so we null it when loading such modes
}
if (_repetitionMode == RepetitionMode.FIXED) {
if (_scheduledTask!.schedule.isMonthBased()) {
if (_scheduledTask.schedule.isMonthBased()) {
// remove the standard repetition day
monthBasedSchedules.remove(nextDueOn.day);
}
if (_scheduledTask!.schedule.isYearBased()) {
if (_scheduledTask.schedule.isYearBased()) {
// remove the standard repetition day
yearBasedSchedules.remove(AllYearDate(nextDueOn.day, MonthOfYear.values[nextDueOn.month - 1]));
}
Expand Down Expand Up @@ -791,14 +791,14 @@ class _ScheduledTaskFormState extends State<ScheduledTaskForm> {
var oneTimeDueOn = _scheduledTask?.schedule.oneTimeDueOn;
if (_repetitionMode == RepetitionMode.ONE_TIME) {
final now = DateTime.now();
if (_scheduledTask == null || _scheduledTask!.isOneTimeCompleted) {
if (_scheduledTask == null || _scheduledTask.isOneTimeCompleted) {
// reuse this schedule once completed
scheduleFrom = now;
oneTimeDueOn = nextDueOn;
}
else {
// just update this schedule
scheduleFrom = _scheduledTask!.lastScheduledEventOn!;
scheduleFrom = _scheduledTask.lastScheduledEventOn!;
oneTimeDueOn = nextDueOn;
}
}
Expand Down Expand Up @@ -1120,6 +1120,22 @@ class _ScheduledTaskFormState extends State<ScheduledTaskForm> {
else {
weekBasedSchedules.add(day);
}

final nextDueOn = When.fromWhenOnDateFutureToDate(_selectedNextDueOn!, _customNextDueOn);
final nextDueWeekday = DayOfWeek.values[nextDueOn.weekday - 1];
if (!weekBasedSchedules.contains(nextDueWeekday)) {
//update due date to first selected day
final days = weekBasedSchedules.toList();
days.sort((d1, d2) {
return d1.index == d2.index ? 0 : d1.index < d2.index ? 1 : -1;
});
final firstSelectedDay = days.first;
final delta = firstSelectedDay.index + 1 - nextDueOn.weekday;
if (delta != 0) {
final correctedDueDate = nextDueOn.add(Duration(days: delta));
_updateNextDueOn(correctedDueDate);
}
}
});
},
child: CircleAvatar(
Expand Down
56 changes: 28 additions & 28 deletions lib/ui/pages/ScheduledTaskList.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1063,41 +1063,41 @@ class ScheduledTaskListState extends PageScaffoldState<ScheduledTaskList> with A
_scheduledTasks
.forEach((scheduledTask) {

if (!scheduledTask.active) {
_inactiveSchedules++;
}
else if (scheduledTask.isPaused) {
_pausedSchedules++;
}
else {
_totalRunningSchedules++;

if (scheduledTask.isDue()) {
_totalDueSchedules++;
if (scheduledTask.important && !scheduledTask.isOneTimeCompleted) {
_dueAndImportantSchedules++;
}
if (!scheduledTask.active) {
_inactiveSchedules++;
}
if (scheduledTask.isNextScheduleOverdue(true)) {
_totalOverdueSchedules++;
else if (scheduledTask.isPaused) {
_pausedSchedules++;
}
else if (!scheduledTask.isOneTimeCompleted) {
_totalRunningSchedules++;

final nextSchedule = scheduledTask.getNextSchedule();
if (nextSchedule != null) {
if (nextSchedule.isBefore(truncToDate(now))) {
_dueBeforeTodaySchedules++;
}
if (isToday(nextSchedule) && !scheduledTask.isOneTimeCompleted) {
_dueTodaySchedules++;
if (scheduledTask.isDue()) {
_totalDueSchedules++;
if (scheduledTask.important) {
_dueAndImportantSchedules++;
}
}
if (isTomorrow(nextSchedule)) {
_dueTomorrowSchedules++;
if (scheduledTask.isNextScheduleOverdue(true)) {
_totalOverdueSchedules++;
}
if (isAfterTomorrow(nextSchedule)) {
_dueAfterTomorrowSchedules++;

final nextSchedule = scheduledTask.getNextSchedule();
if (nextSchedule != null) {
if (nextSchedule.isBefore(truncToDate(now))) {
_dueBeforeTodaySchedules++;
}
if (isToday(nextSchedule)) {
_dueTodaySchedules++;
}
if (isTomorrow(nextSchedule)) {
_dueTomorrowSchedules++;
}
if (isAfterTomorrow(nextSchedule)) {
_dueAfterTomorrowSchedules++;
}
}
}
}
});
});
}
Expand Down
3 changes: 3 additions & 0 deletions metadata/en-US/changelogs/10703.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* Fix fixed and weekly based schedule due data calculation (#83)
* Fix wrong number of due and overdue schedules in overview
* Ensure selected due dates match selected week days (for fixed week based schedules)
Loading

0 comments on commit d6a0cec

Please sign in to comment.