mirror of https://github.com/tasks/tasks
Convert ReminderService to Kotlin
parent
9cd9f1ada2
commit
20353023d8
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
|
||||
package com.todoroo.astrid.reminders;
|
||||
|
||||
import static com.google.common.collect.Lists.transform;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import com.todoroo.andlib.utility.DateUtilities;
|
||||
import com.todoroo.astrid.dao.TaskDaoBlocking;
|
||||
import com.todoroo.astrid.data.Task;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import org.tasks.jobs.NotificationQueue;
|
||||
import org.tasks.jobs.ReminderEntry;
|
||||
import org.tasks.preferences.Preferences;
|
||||
import org.tasks.reminders.Random;
|
||||
import org.tasks.time.DateTime;
|
||||
|
||||
@Singleton
|
||||
public final class ReminderService {
|
||||
|
||||
public static final int TYPE_DUE = 0;
|
||||
public static final int TYPE_OVERDUE = 1;
|
||||
public static final int TYPE_RANDOM = 2;
|
||||
public static final int TYPE_SNOOZE = 3;
|
||||
public static final int TYPE_ALARM = 4;
|
||||
public static final int TYPE_GEOFENCE_ENTER = 5;
|
||||
public static final int TYPE_GEOFENCE_EXIT = 6;
|
||||
|
||||
private static final long NO_ALARM = Long.MAX_VALUE;
|
||||
|
||||
private final NotificationQueue jobs;
|
||||
private final Random random;
|
||||
private final TaskDaoBlocking taskDao;
|
||||
private final Preferences preferences;
|
||||
|
||||
@Inject
|
||||
ReminderService(Preferences preferences, NotificationQueue notificationQueue, TaskDaoBlocking taskDao) {
|
||||
this(preferences, notificationQueue, new Random(), taskDao);
|
||||
}
|
||||
|
||||
ReminderService(Preferences preferences, NotificationQueue jobs, Random random, TaskDaoBlocking taskDao) {
|
||||
this.preferences = preferences;
|
||||
this.jobs = jobs;
|
||||
this.random = random;
|
||||
this.taskDao = taskDao;
|
||||
}
|
||||
|
||||
public void scheduleAllAlarms(List<Long> taskIds) {
|
||||
jobs.add(transform(taskDao.fetch(taskIds), this::getReminderEntry));
|
||||
}
|
||||
|
||||
public void scheduleAllAlarms() {
|
||||
jobs.add(transform(taskDao.getTasksWithReminders(), this::getReminderEntry));
|
||||
}
|
||||
|
||||
public void scheduleAlarm(Task task) {
|
||||
ReminderEntry reminder = getReminderEntry(task);
|
||||
if (reminder != null) {
|
||||
jobs.add(reminder);
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelReminder(long taskId) {
|
||||
jobs.cancelReminder(taskId);
|
||||
}
|
||||
|
||||
private @Nullable ReminderEntry getReminderEntry(Task task) {
|
||||
if (task == null || !task.isSaved()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
long taskId = task.getId();
|
||||
|
||||
// Make sure no alarms are scheduled other than the next one. When that one is shown, it
|
||||
// will schedule the next one after it, and so on and so forth.
|
||||
cancelReminder(taskId);
|
||||
|
||||
if (task.isCompleted() || task.isDeleted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// snooze reminder
|
||||
long whenSnooze = calculateNextSnoozeReminder(task);
|
||||
|
||||
// random reminders
|
||||
long whenRandom = calculateNextRandomReminder(task);
|
||||
|
||||
// notifications at due date
|
||||
long whenDueDate = calculateNextDueDateReminder(task);
|
||||
|
||||
// notifications after due date
|
||||
long whenOverdue = calculateNextOverdueReminder(task);
|
||||
|
||||
// snooze trumps all
|
||||
if (whenSnooze != NO_ALARM) {
|
||||
return new ReminderEntry(taskId, whenSnooze, TYPE_SNOOZE);
|
||||
} else if (whenRandom < whenDueDate && whenRandom < whenOverdue) {
|
||||
return new ReminderEntry(taskId, whenRandom, TYPE_RANDOM);
|
||||
} else if (whenDueDate < whenOverdue) {
|
||||
return new ReminderEntry(taskId, whenDueDate, TYPE_DUE);
|
||||
} else if (whenOverdue != NO_ALARM) {
|
||||
return new ReminderEntry(taskId, whenOverdue, TYPE_OVERDUE);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private long calculateNextSnoozeReminder(Task task) {
|
||||
if (task.getReminderSnooze() > task.getReminderLast()) {
|
||||
return task.getReminderSnooze();
|
||||
}
|
||||
return NO_ALARM;
|
||||
}
|
||||
|
||||
private long calculateNextOverdueReminder(Task task) {
|
||||
// Uses getNowValue() instead of DateUtilities.now()
|
||||
if (task.hasDueDate() && task.isNotifyAfterDeadline()) {
|
||||
DateTime overdueDate = new DateTime(task.getDueDate()).plusDays(1);
|
||||
if (!task.hasDueTime()) {
|
||||
overdueDate = overdueDate.withMillisOfDay(preferences.getDefaultDueTime());
|
||||
}
|
||||
|
||||
DateTime lastReminder = new DateTime(task.getReminderLast());
|
||||
|
||||
if (overdueDate.isAfter(lastReminder)) {
|
||||
return overdueDate.getMillis();
|
||||
}
|
||||
|
||||
overdueDate = lastReminder.withMillisOfDay(overdueDate.getMillisOfDay());
|
||||
|
||||
return overdueDate.isAfter(lastReminder)
|
||||
? overdueDate.getMillis()
|
||||
: overdueDate.plusDays(1).getMillis();
|
||||
}
|
||||
return NO_ALARM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the next alarm time for due date reminders.
|
||||
*
|
||||
* <p>This alarm always returns the due date, and is triggered if the last reminder time occurred
|
||||
* before the due date. This means it is possible to return due dates in the past.
|
||||
*
|
||||
* <p>If the date was indicated to not have a due time, we read from preferences and assign a
|
||||
* time.
|
||||
*/
|
||||
private long calculateNextDueDateReminder(Task task) {
|
||||
if (task.hasDueDate() && task.isNotifyAtDeadline()) {
|
||||
long dueDate = task.getDueDate();
|
||||
long lastReminder = task.getReminderLast();
|
||||
|
||||
long dueDateAlarm;
|
||||
|
||||
if (task.hasDueTime()) {
|
||||
dueDateAlarm = dueDate;
|
||||
} else {
|
||||
dueDateAlarm =
|
||||
new DateTime(dueDate).withMillisOfDay(preferences.getDefaultDueTime()).getMillis();
|
||||
}
|
||||
|
||||
return lastReminder < dueDateAlarm ? dueDateAlarm : NO_ALARM;
|
||||
}
|
||||
return NO_ALARM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the next alarm time for random reminders.
|
||||
*
|
||||
* <p>We take the last reminder time and add approximately the reminder period. If it's still in
|
||||
* the past, we set it to some time in the near future.
|
||||
*/
|
||||
private long calculateNextRandomReminder(Task task) {
|
||||
long reminderPeriod = task.getReminderPeriod();
|
||||
if ((reminderPeriod) > 0) {
|
||||
long when = task.getReminderLast();
|
||||
|
||||
if (when == 0) {
|
||||
when = task.getCreationDate();
|
||||
}
|
||||
|
||||
when += (long) (reminderPeriod * (0.85f + 0.3f * random.nextFloat()));
|
||||
|
||||
if (when < DateUtilities.now()) {
|
||||
when =
|
||||
DateUtilities.now() + (long) ((0.5f + 6 * random.nextFloat()) * DateUtilities.ONE_HOUR);
|
||||
}
|
||||
|
||||
return when;
|
||||
}
|
||||
return NO_ALARM;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Todoroo Inc
|
||||
*
|
||||
* See the file "LICENSE" for the full license governing this code.
|
||||
*/
|
||||
package com.todoroo.astrid.reminders
|
||||
|
||||
import com.todoroo.andlib.utility.DateUtilities
|
||||
import com.todoroo.astrid.dao.TaskDao
|
||||
import com.todoroo.astrid.data.Task
|
||||
import org.tasks.jobs.NotificationQueue
|
||||
import org.tasks.jobs.ReminderEntry
|
||||
import org.tasks.preferences.Preferences
|
||||
import org.tasks.reminders.Random
|
||||
import org.tasks.time.DateTime
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class ReminderService internal constructor(
|
||||
private val preferences: Preferences,
|
||||
private val jobs: NotificationQueue,
|
||||
private val random: Random,
|
||||
private val taskDao: TaskDao) {
|
||||
|
||||
@Inject
|
||||
internal constructor(
|
||||
preferences: Preferences,
|
||||
notificationQueue: NotificationQueue,
|
||||
taskDao: TaskDao
|
||||
) : this(preferences, notificationQueue, Random(), taskDao)
|
||||
|
||||
suspend fun scheduleAllAlarms(taskIds: List<Long>) {
|
||||
taskDao
|
||||
.fetch(taskIds)
|
||||
.map { getReminderEntry(it) }
|
||||
.let { jobs.add(it) }
|
||||
}
|
||||
|
||||
suspend fun scheduleAllAlarms() {
|
||||
taskDao
|
||||
.getTasksWithReminders()
|
||||
.map { getReminderEntry(it) }
|
||||
.let { jobs.add(it) }
|
||||
}
|
||||
|
||||
fun scheduleAlarm(task: Task?) {
|
||||
val reminder = getReminderEntry(task)
|
||||
if (reminder != null) {
|
||||
jobs.add(reminder)
|
||||
}
|
||||
}
|
||||
|
||||
fun cancelReminder(taskId: Long) {
|
||||
jobs.cancelReminder(taskId)
|
||||
}
|
||||
|
||||
private fun getReminderEntry(task: Task?): ReminderEntry? {
|
||||
if (task == null || !task.isSaved) {
|
||||
return null
|
||||
}
|
||||
val taskId = task.id
|
||||
|
||||
// Make sure no alarms are scheduled other than the next one. When that one is shown, it
|
||||
// will schedule the next one after it, and so on and so forth.
|
||||
cancelReminder(taskId)
|
||||
if (task.isCompleted || task.isDeleted) {
|
||||
return null
|
||||
}
|
||||
|
||||
// snooze reminder
|
||||
val whenSnooze = calculateNextSnoozeReminder(task)
|
||||
|
||||
// random reminders
|
||||
val whenRandom = calculateNextRandomReminder(task)
|
||||
|
||||
// notifications at due date
|
||||
val whenDueDate = calculateNextDueDateReminder(task)
|
||||
|
||||
// notifications after due date
|
||||
val whenOverdue = calculateNextOverdueReminder(task)
|
||||
|
||||
// snooze trumps all
|
||||
if (whenSnooze != NO_ALARM) {
|
||||
return ReminderEntry(taskId, whenSnooze, TYPE_SNOOZE)
|
||||
} else if (whenRandom < whenDueDate && whenRandom < whenOverdue) {
|
||||
return ReminderEntry(taskId, whenRandom, TYPE_RANDOM)
|
||||
} else if (whenDueDate < whenOverdue) {
|
||||
return ReminderEntry(taskId, whenDueDate, TYPE_DUE)
|
||||
} else if (whenOverdue != NO_ALARM) {
|
||||
return ReminderEntry(taskId, whenOverdue, TYPE_OVERDUE)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun calculateNextSnoozeReminder(task: Task): Long {
|
||||
return if (task.reminderSnooze > task.reminderLast) {
|
||||
task.reminderSnooze
|
||||
} else NO_ALARM
|
||||
}
|
||||
|
||||
private fun calculateNextOverdueReminder(task: Task): Long {
|
||||
// Uses getNowValue() instead of DateUtilities.now()
|
||||
if (task.hasDueDate() && task.isNotifyAfterDeadline) {
|
||||
var overdueDate = DateTime(task.dueDate).plusDays(1)
|
||||
if (!task.hasDueTime()) {
|
||||
overdueDate = overdueDate.withMillisOfDay(preferences.defaultDueTime)
|
||||
}
|
||||
val lastReminder = DateTime(task.reminderLast)
|
||||
if (overdueDate.isAfter(lastReminder)) {
|
||||
return overdueDate.millis
|
||||
}
|
||||
overdueDate = lastReminder.withMillisOfDay(overdueDate.millisOfDay)
|
||||
return if (overdueDate.isAfter(lastReminder)) overdueDate.millis else overdueDate.plusDays(1).millis
|
||||
}
|
||||
return NO_ALARM
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the next alarm time for due date reminders.
|
||||
*
|
||||
*
|
||||
* This alarm always returns the due date, and is triggered if the last reminder time occurred
|
||||
* before the due date. This means it is possible to return due dates in the past.
|
||||
*
|
||||
*
|
||||
* If the date was indicated to not have a due time, we read from preferences and assign a
|
||||
* time.
|
||||
*/
|
||||
private fun calculateNextDueDateReminder(task: Task): Long {
|
||||
if (task.hasDueDate() && task.isNotifyAtDeadline) {
|
||||
val dueDate = task.dueDate
|
||||
val lastReminder = task.reminderLast
|
||||
val dueDateAlarm: Long
|
||||
dueDateAlarm = if (task.hasDueTime()) {
|
||||
dueDate
|
||||
} else {
|
||||
DateTime(dueDate).withMillisOfDay(preferences.defaultDueTime).millis
|
||||
}
|
||||
return if (lastReminder < dueDateAlarm) dueDateAlarm else NO_ALARM
|
||||
}
|
||||
return NO_ALARM
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the next alarm time for random reminders.
|
||||
*
|
||||
*
|
||||
* We take the last reminder time and add approximately the reminder period. If it's still in
|
||||
* the past, we set it to some time in the near future.
|
||||
*/
|
||||
private fun calculateNextRandomReminder(task: Task): Long {
|
||||
val reminderPeriod = task.reminderPeriod
|
||||
if (reminderPeriod > 0) {
|
||||
var `when` = task.reminderLast
|
||||
if (`when` == 0L) {
|
||||
`when` = task.creationDate
|
||||
}
|
||||
`when` += (reminderPeriod * (0.85f + 0.3f * random.nextFloat())).toLong()
|
||||
if (`when` < DateUtilities.now()) {
|
||||
`when` = DateUtilities.now() + ((0.5f + 6 * random.nextFloat()) * DateUtilities.ONE_HOUR).toLong()
|
||||
}
|
||||
return `when`
|
||||
}
|
||||
return NO_ALARM
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE_DUE = 0
|
||||
const val TYPE_OVERDUE = 1
|
||||
const val TYPE_RANDOM = 2
|
||||
const val TYPE_SNOOZE = 3
|
||||
const val TYPE_ALARM = 4
|
||||
const val TYPE_GEOFENCE_ENTER = 5
|
||||
const val TYPE_GEOFENCE_EXIT = 6
|
||||
private const val NO_ALARM = Long.MAX_VALUE
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue