mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-07-14 18:21:57 +00:00
To-Do reminder not showing fix (#2057)
* Reminder logic updates Check for upcoming reminder and/or if reminder is happening today. Also - error on the side of showing a reminder * Error on the side of showing reminder (Even if reminder time passed) * Schedule reminders logic updates * Fixes for reminders (Week & Year) * Remove unused extensions * Refactor weekly reminder scheduling logic for specific days intervals Refactor weekly reminder scheduling logic to handle specific days and intervals correctly * Remove alarms/reminders on task deletion * Handle weekly same day reminder that already passed * Handle if no days are selected for a weekly * To-Do reminder not showing fix Schedule single reminder instance occurrence for todo, and check if reminder is from todo when actually setting the reminder (To avoid scheduling returning early due to checking Daily reminder fields) --------- Co-authored-by: Phillip Thelen <phillip@habitica.com>
This commit is contained in:
parent
afd44ab814
commit
1907d675ad
2 changed files with 68 additions and 63 deletions
|
|
@ -59,9 +59,13 @@ class TaskAlarmManager(
|
|||
*/
|
||||
private fun setAlarmsForTask(task: Task) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val reminderOccurencesToSchedule = if (task.type == TaskType.TODO) { 1 } else {
|
||||
// For dailies, we schedule multiple reminders in advance
|
||||
upcomingReminderOccurrencesToSchedule
|
||||
}
|
||||
task.reminders?.let { reminders ->
|
||||
for (reminder in reminders) {
|
||||
val upcomingReminders = task.getNextReminderOccurrences(reminder, upcomingReminderOccurrencesToSchedule)
|
||||
val upcomingReminders = task.getNextReminderOccurrences(reminder, reminderOccurencesToSchedule)
|
||||
upcomingReminders?.forEachIndexed { index, reminderNextOccurrenceTime ->
|
||||
reminder?.time = reminderNextOccurrenceTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
setAlarmForRemindersItem(task, reminder, index)
|
||||
|
|
|
|||
|
|
@ -354,6 +354,14 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
if (remindersItem == null) return null
|
||||
|
||||
val reminderTime = remindersItem.time?.parseToZonedDateTime() ?: return null
|
||||
var dateTimeOccurenceToSchedule = ZonedDateTime.now().withZoneSameInstant(ZoneId.systemDefault())
|
||||
val occurrencesList = mutableListOf<ZonedDateTime>()
|
||||
|
||||
// If the reminder is a todo, only schedule sole dueDate/time occurrence. Otherwise, schedule multiple occurrences in advance
|
||||
if (this.type == TaskType.TODO) {
|
||||
occurrencesList.add(this.dueDate?.toZonedDateTime()?.withHour(reminderTime.hour)?.withMinute(reminderTime.minute) ?: return null)
|
||||
return occurrencesList
|
||||
}
|
||||
val now = ZonedDateTime.now().withZoneSameInstant(ZoneId.systemDefault())
|
||||
var startDate = this.startDate?.toInstant()?.atZone(ZoneId.systemDefault()) ?: return null
|
||||
val frequency = this.frequency ?: return null
|
||||
|
|
@ -361,81 +369,74 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
val repeatDays = this.repeat
|
||||
startDate = startDate.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
|
||||
var dateTimeOccurenceToSchedule = ZonedDateTime.now().withZoneSameInstant(ZoneId.systemDefault())
|
||||
|
||||
val occurrencesList = mutableListOf<ZonedDateTime>()
|
||||
|
||||
while (occurrencesList.size < occurrences) {
|
||||
// Increment currentDate based on the frequency
|
||||
try {
|
||||
dateTimeOccurenceToSchedule = when (frequency) {
|
||||
Frequency.DAILY -> {
|
||||
dateTimeOccurenceToSchedule = if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
startDate
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusDays(everyX.toLong()).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
dateTimeOccurenceToSchedule
|
||||
dateTimeOccurenceToSchedule = when (frequency) {
|
||||
Frequency.DAILY -> {
|
||||
dateTimeOccurenceToSchedule = if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
startDate
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusDays(everyX.toLong()).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
Frequency.WEEKLY -> {
|
||||
// Set to start date if current date is earlier
|
||||
if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
dateTimeOccurenceToSchedule = startDate
|
||||
} else if (repeatDays?.hasAnyDaySelected() == true) {
|
||||
dateTimeOccurenceToSchedule
|
||||
}
|
||||
Frequency.WEEKLY -> {
|
||||
// Set to start date if current date is earlier
|
||||
if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
dateTimeOccurenceToSchedule = startDate
|
||||
} else if (repeatDays?.hasAnyDaySelected() == true) {
|
||||
|
||||
var nextDueDate = dateTimeOccurenceToSchedule.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
// If the next due date already happened for today, increment it by one day. Otherwise, it will be scheduled for today.
|
||||
if (nextDueDate.isBefore(now) && occurrencesList.size == 0) {
|
||||
nextDueDate = nextDueDate.plusDays(1)
|
||||
}
|
||||
var nextDueDate = dateTimeOccurenceToSchedule.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
// If the next due date already happened for today, increment it by one day. Otherwise, it will be scheduled for today.
|
||||
if (nextDueDate.isBefore(now) && occurrencesList.size == 0) {
|
||||
nextDueDate = nextDueDate.plusDays(1)
|
||||
}
|
||||
|
||||
// If the reminder being scheduled is not the first iteration of the reminder, increment it by one day
|
||||
if (occurrencesList.size > 0) {
|
||||
nextDueDate = nextDueDate.plusDays(1)
|
||||
}
|
||||
// If the reminder being scheduled is not the first iteration of the reminder, increment it by one day
|
||||
if (occurrencesList.size > 0) {
|
||||
nextDueDate = nextDueDate.plusDays(1)
|
||||
}
|
||||
|
||||
while (!nextDueDate.matchesRepeatDays(repeatDays)) {
|
||||
nextDueDate = nextDueDate.plusDays(1).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
// Calculate weeks since start and adjust for the correct interval
|
||||
val weeksSinceStart = ChronoUnit.WEEKS.between(startDate.toLocalDate(), nextDueDate.toLocalDate())
|
||||
if (weeksSinceStart % everyX != 0L) {
|
||||
val weeksToNextValidInterval = everyX - (weeksSinceStart % everyX)
|
||||
nextDueDate = nextDueDate.plusWeeks(weeksToNextValidInterval)
|
||||
// Find the exact next due day within the valid interval
|
||||
while (!nextDueDate.matchesRepeatDays(repeatDays)) {
|
||||
nextDueDate = nextDueDate.plusDays(1).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
// Calculate weeks since start and adjust for the correct interval
|
||||
val weeksSinceStart = ChronoUnit.WEEKS.between(startDate.toLocalDate(), nextDueDate.toLocalDate())
|
||||
if (everyX > 0 && weeksSinceStart % everyX != 0L) {
|
||||
val weeksToNextValidInterval = everyX - (weeksSinceStart % everyX)
|
||||
nextDueDate = nextDueDate.plusWeeks(weeksToNextValidInterval)
|
||||
// Find the exact next due day within the valid interval
|
||||
while (!nextDueDate.matchesRepeatDays(repeatDays)) {
|
||||
nextDueDate = nextDueDate.plusDays(1).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dateTimeOccurenceToSchedule = nextDueDate
|
||||
}
|
||||
// Set time to the reminder time
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
dateTimeOccurenceToSchedule
|
||||
}
|
||||
|
||||
Frequency.MONTHLY -> {
|
||||
dateTimeOccurenceToSchedule = if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
startDate
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusMonths(everyX.toLong()).withDayOfMonth(startDate.dayOfMonth).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
dateTimeOccurenceToSchedule
|
||||
}
|
||||
Frequency.YEARLY -> {
|
||||
dateTimeOccurenceToSchedule = if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
startDate
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusYears(everyX.toLong()).withDayOfMonth(startDate.dayOfMonth).withMonth(startDate.monthValue).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
dateTimeOccurenceToSchedule
|
||||
dateTimeOccurenceToSchedule = nextDueDate
|
||||
}
|
||||
// Set time to the reminder time
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
dateTimeOccurenceToSchedule
|
||||
}
|
||||
|
||||
Frequency.MONTHLY -> {
|
||||
dateTimeOccurenceToSchedule = if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
startDate
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusMonths(everyX.toLong()).withDayOfMonth(startDate.dayOfMonth).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
dateTimeOccurenceToSchedule
|
||||
}
|
||||
Frequency.YEARLY -> {
|
||||
dateTimeOccurenceToSchedule = if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
startDate
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusYears(everyX.toLong()).withDayOfMonth(startDate.dayOfMonth).withMonth(startDate.monthValue).withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
dateTimeOccurenceToSchedule
|
||||
}
|
||||
occurrencesList.add(dateTimeOccurenceToSchedule)
|
||||
} catch (_: DateTimeException) {
|
||||
// Invalid date like feb 30th
|
||||
}
|
||||
|
||||
occurrencesList.add(dateTimeOccurenceToSchedule)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue