From 8f5f72d9fd3cb889d768c8981861b59819b40118 Mon Sep 17 00:00:00 2001 From: Quentin Hibon Date: Thu, 21 Jan 2021 14:04:43 +0100 Subject: [PATCH] Convert ReminderScheduler --- .../isoron/uhabits/intents/IntentScheduler.kt | 2 +- .../SnoozeDelayPickerActivity.kt | 2 +- .../uhabits/receivers/ReminderController.kt | 4 +- .../core/reminders/ReminderScheduler.java | 176 ------------------ .../core/reminders/ReminderScheduler.kt | 150 +++++++++++++++ 5 files changed, 154 insertions(+), 180 deletions(-) delete mode 100644 uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java create mode 100644 uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.kt diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt b/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt index 5a4c79f1d..5d699944c 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt @@ -80,7 +80,7 @@ class IntentScheduler return schedule(updateTime, intent, RTC) } - override fun log(componentName: String, msg: String) { + override fun log(componentName: String?, msg: String?) { Log.d(componentName, msg) } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt index bc3afb97c..eeb0730b9 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/notifications/SnoozeDelayPickerActivity.kt @@ -79,7 +79,7 @@ class SnoozeDelayPickerActivity : FragmentActivity(), OnItemClickListener { override fun onItemClick(parent: AdapterView<*>?, view: View, position: Int, id: Long) { val snoozeValues = resources.getIntArray(R.array.snooze_picker_values) if (snoozeValues[position] >= 0) { - reminderController!!.onSnoozeDelayPicked(habit, snoozeValues[position]) + reminderController!!.onSnoozeDelayPicked(habit!!, snoozeValues[position]) finish() } else showTimePicker() } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.kt b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.kt index 7e1e18a46..38ba3a1b4 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderController.kt @@ -54,9 +54,9 @@ class ReminderController @Inject constructor( showSnoozeDelayPicker(habit, context) } - fun onSnoozeDelayPicked(habit: Habit?, delayInMinutes: Int) { + fun onSnoozeDelayPicked(habit: Habit, delayInMinutes: Int) { reminderScheduler.snoozeReminder(habit, delayInMinutes.toLong()) - notificationTray.cancel(habit!!) + notificationTray.cancel(habit) } fun onSnoozeTimePicked(habit: Habit?, hour: Int, minute: Int) { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java deleted file mode 100644 index 5f93c32c7..000000000 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2016-2021 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -package org.isoron.uhabits.core.reminders; - -import androidx.annotation.*; - -import org.isoron.uhabits.core.*; -import org.isoron.uhabits.core.commands.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.preferences.*; - -import java.util.*; - -import javax.inject.*; - -import static org.isoron.uhabits.core.utils.DateUtils.*; - -@AppScope -public class ReminderScheduler implements CommandRunner.Listener -{ - private final WidgetPreferences widgetPreferences; - - private CommandRunner commandRunner; - - private HabitList habitList; - - private SystemScheduler sys; - - @Inject - public ReminderScheduler(@NonNull CommandRunner commandRunner, - @NonNull HabitList habitList, - @NonNull SystemScheduler sys, - @NonNull WidgetPreferences widgetPreferences) - { - this.commandRunner = commandRunner; - this.habitList = habitList; - this.sys = sys; - this.widgetPreferences = widgetPreferences; - } - - @Override - public synchronized void onCommandFinished(@Nullable Command command) - { - if (command instanceof CreateRepetitionCommand) return; - if (command instanceof ChangeHabitColorCommand) return; - scheduleAll(); - } - - public synchronized void schedule(@NonNull Habit habit) - { - if (habit.getId() == null) - { - sys.log("ReminderScheduler", "Habit has null id. Returning."); - return; - } - - if (!habit.hasReminder()) - { - sys.log("ReminderScheduler", "habit=" + habit.getId() + " has no reminder. Skipping."); - return; - } - - long reminderTime = Objects.requireNonNull(habit.getReminder()).getTimeInMillis(); - long snoozeReminderTime = widgetPreferences.getSnoozeTime(habit.getId()); - - if (snoozeReminderTime != 0) - { - long now = applyTimezone(getLocalTime()); - sys.log("ReminderScheduler", String.format( - Locale.US, - "Habit %d has been snoozed until %d", - habit.getId(), - snoozeReminderTime)); - - if (snoozeReminderTime > now) - { - sys.log("ReminderScheduler", "Snooze time is in the future. Accepting."); - reminderTime = snoozeReminderTime; - } - else - { - sys.log("ReminderScheduler", "Snooze time is in the past. Discarding."); - widgetPreferences.removeSnoozeTime(habit.getId()); - } - } - scheduleAtTime(habit, reminderTime); - - } - - public synchronized void scheduleAtTime(@NonNull Habit habit, long reminderTime) - { - sys.log("ReminderScheduler", "Scheduling alarm for habit=" + habit.getId()); - - if (!habit.hasReminder()) - { - sys.log("ReminderScheduler", "habit=" + habit.getId() + " has no reminder. Skipping."); - return; - } - - if (habit.isArchived()) - { - sys.log("ReminderScheduler", "habit=" + habit.getId() + " is archived. Skipping."); - return; - } - - long timestamp = getStartOfDayWithOffset(removeTimezone(reminderTime)); - sys.log("ReminderScheduler", - String.format( - Locale.US, - "reminderTime=%d removeTimezone=%d timestamp=%d", - reminderTime, - removeTimezone(reminderTime), - timestamp)); - - sys.scheduleShowReminder(reminderTime, habit, timestamp); - } - - public synchronized void scheduleAll() - { - sys.log("ReminderScheduler", "Scheduling all alarms"); - HabitList reminderHabits = - habitList.getFiltered(HabitMatcher.WITH_ALARM); - for (Habit habit : reminderHabits) - schedule(habit); - } - - public synchronized void startListening() - { - commandRunner.addListener(this); - } - - public synchronized void stopListening() - { - commandRunner.removeListener(this); - } - - public synchronized void snoozeReminder(Habit habit, long minutes) - { - long now = applyTimezone(getLocalTime()); - long snoozedUntil = now + minutes * 60 * 1000; - widgetPreferences.setSnoozeTime(habit.getId(), snoozedUntil); - schedule(habit); - } - - public interface SystemScheduler - { - SchedulerResult scheduleShowReminder(long reminderTime, Habit habit, long timestamp); - - SchedulerResult scheduleWidgetUpdate(long updateTime); - - void log(String componentName, String msg); - } - - public enum SchedulerResult - { - IGNORED, - OK - } -} diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.kt new file mode 100644 index 000000000..7f602e11a --- /dev/null +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/reminders/ReminderScheduler.kt @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2016-2021 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.uhabits.core.reminders + +import org.isoron.uhabits.core.AppScope +import org.isoron.uhabits.core.commands.ChangeHabitColorCommand +import org.isoron.uhabits.core.commands.Command +import org.isoron.uhabits.core.commands.CommandRunner +import org.isoron.uhabits.core.commands.CreateRepetitionCommand +import org.isoron.uhabits.core.models.Habit +import org.isoron.uhabits.core.models.HabitList +import org.isoron.uhabits.core.models.HabitMatcher +import org.isoron.uhabits.core.preferences.WidgetPreferences +import org.isoron.uhabits.core.utils.DateUtils.Companion.applyTimezone +import org.isoron.uhabits.core.utils.DateUtils.Companion.getLocalTime +import org.isoron.uhabits.core.utils.DateUtils.Companion.getStartOfDayWithOffset +import org.isoron.uhabits.core.utils.DateUtils.Companion.removeTimezone +import java.util.Locale +import java.util.Objects +import javax.inject.Inject + +@AppScope +class ReminderScheduler @Inject constructor( + private val commandRunner: CommandRunner, + private val habitList: HabitList, + private val sys: SystemScheduler, + private val widgetPreferences: WidgetPreferences +) : CommandRunner.Listener { + @Synchronized + override fun onCommandFinished(command: Command) { + if (command is CreateRepetitionCommand) return + if (command is ChangeHabitColorCommand) return + scheduleAll() + } + + @Synchronized + fun schedule(habit: Habit) { + if (habit.id == null) { + sys.log("ReminderScheduler", "Habit has null id. Returning.") + return + } + if (!habit.hasReminder()) { + sys.log("ReminderScheduler", "habit=" + habit.id + " has no reminder. Skipping.") + return + } + var reminderTime = Objects.requireNonNull(habit.reminder)!!.timeInMillis + val snoozeReminderTime = widgetPreferences.getSnoozeTime(habit.id!!) + if (snoozeReminderTime != 0L) { + val now = applyTimezone(getLocalTime()) + sys.log( + "ReminderScheduler", + String.format( + Locale.US, + "Habit %d has been snoozed until %d", + habit.id, + snoozeReminderTime + ) + ) + if (snoozeReminderTime > now) { + sys.log("ReminderScheduler", "Snooze time is in the future. Accepting.") + reminderTime = snoozeReminderTime + } else { + sys.log("ReminderScheduler", "Snooze time is in the past. Discarding.") + widgetPreferences.removeSnoozeTime(habit.id!!) + } + } + scheduleAtTime(habit, reminderTime) + } + + @Synchronized + fun scheduleAtTime(habit: Habit, reminderTime: Long) { + sys.log("ReminderScheduler", "Scheduling alarm for habit=" + habit.id) + if (!habit.hasReminder()) { + sys.log("ReminderScheduler", "habit=" + habit.id + " has no reminder. Skipping.") + return + } + if (habit.isArchived) { + sys.log("ReminderScheduler", "habit=" + habit.id + " is archived. Skipping.") + return + } + val timestamp = getStartOfDayWithOffset(removeTimezone(reminderTime)) + sys.log( + "ReminderScheduler", + String.format( + Locale.US, + "reminderTime=%d removeTimezone=%d timestamp=%d", + reminderTime, + removeTimezone(reminderTime), + timestamp + ) + ) + sys.scheduleShowReminder(reminderTime, habit, timestamp) + } + + @Synchronized + fun scheduleAll() { + sys.log("ReminderScheduler", "Scheduling all alarms") + val reminderHabits = habitList.getFiltered(HabitMatcher.WITH_ALARM) + for (habit in reminderHabits) schedule(habit) + } + + @Synchronized + fun startListening() { + commandRunner.addListener(this) + } + + @Synchronized + fun stopListening() { + commandRunner.removeListener(this) + } + + @Synchronized + fun snoozeReminder(habit: Habit, minutes: Long) { + val now = applyTimezone(getLocalTime()) + val snoozedUntil = now + minutes * 60 * 1000 + widgetPreferences.setSnoozeTime(habit.id, snoozedUntil) + schedule(habit) + } + + interface SystemScheduler { + fun scheduleShowReminder( + reminderTime: Long, + habit: Habit, + timestamp: Long + ): SchedulerResult + + fun scheduleWidgetUpdate(updateTime: Long): SchedulerResult? + fun log(componentName: String?, msg: String?) + } + + enum class SchedulerResult { + IGNORED, OK + } +}