@ -18,17 +18,18 @@
* /
* /
package org.isoron.uhabits.core.ui
package org.isoron.uhabits.core.ui
import kotlinx.serialization.Serializable
import org.isoron.uhabits.core.AppScope
import org.isoron.uhabits.core.AppScope
import org.isoron.uhabits.core.commands.Command
import org.isoron.uhabits.core.commands.Command
import org.isoron.uhabits.core.commands.CommandRunner
import org.isoron.uhabits.core.commands.CommandRunner
import org.isoron.uhabits.core.commands.CreateRepetitionCommand
import org.isoron.uhabits.core.commands.CreateRepetitionCommand
import org.isoron.uhabits.core.commands.DeleteHabitsCommand
import org.isoron.uhabits.core.commands.DeleteHabitsCommand
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.HabitList
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.models.Timestamp
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.preferences.Preferences
import org.isoron.uhabits.core.tasks.Task
import org.isoron.uhabits.core.tasks.Task
import org.isoron.uhabits.core.tasks.TaskRunner
import org.isoron.uhabits.core.tasks.TaskRunner
import java.util.HashMap
import java.util.Locale
import java.util.Locale
import java.util.Objects
import java.util.Objects
import javax.inject.Inject
import javax.inject.Inject
@ -38,9 +39,31 @@ class NotificationTray @Inject constructor(
private val taskRunner : TaskRunner ,
private val taskRunner : TaskRunner ,
private val commandRunner : CommandRunner ,
private val commandRunner : CommandRunner ,
private val preferences : Preferences ,
private val preferences : Preferences ,
private val systemTray : SystemTray
private val systemTray : SystemTray ,
private val habitList : HabitList
) : CommandRunner . Listener , Preferences . Listener {
) : CommandRunner . Listener , Preferences . Listener {
private val active : HashMap < Habit , NotificationData > = HashMap ( )
/ * *
* A mapping from habits to active notifications , automatically persisting on removal .
* /
private val active = object {
private val m : HashMap < Habit , NotificationData > =
preferences . getActiveNotifications ( habitList )
val entries get ( ) = m . entries
operator fun set ( habit : Habit , notificationData : NotificationData ) {
m [ habit ] = notificationData
persist ( )
}
fun remove ( habit : Habit ) {
m . remove ( habit ) ?. let { persist ( ) } // persist if changed
}
fun persist ( ) = preferences . setActiveNotifications ( m )
}
fun cancel ( habit : Habit ) {
fun cancel ( habit : Habit ) {
val notificationId = getNotificationId ( habit )
val notificationId = getNotificationId ( habit )
systemTray . removeNotification ( notificationId )
systemTray . removeNotification ( notificationId )
@ -64,7 +87,6 @@ class NotificationTray @Inject constructor(
fun show ( habit : Habit , timestamp : Timestamp , reminderTime : Long ) {
fun show ( habit : Habit , timestamp : Timestamp , reminderTime : Long ) {
val data = NotificationData ( timestamp , reminderTime )
val data = NotificationData ( timestamp , reminderTime )
active [ habit ] = data
taskRunner . execute ( ShowNotificationTask ( habit , data ) )
taskRunner . execute ( ShowNotificationTask ( habit , data ) )
}
}
@ -83,7 +105,7 @@ class NotificationTray @Inject constructor(
return ( id % Int . MAX _VALUE ) . toInt ( )
return ( id % Int . MAX _VALUE ) . toInt ( )
}
}
private fun reshowAll ( ) {
fun reshowAll ( ) {
for ( ( habit , data ) in active . entries ) {
for ( ( habit , data ) in active . entries ) {
taskRunner . execute ( ShowNotificationTask ( habit , data ) )
taskRunner . execute ( ShowNotificationTask ( habit , data ) )
}
}
@ -101,6 +123,7 @@ class NotificationTray @Inject constructor(
fun log ( msg : String )
fun log ( msg : String )
}
}
@Serializable
internal class NotificationData ( val timestamp : Timestamp , val reminderTime : Long )
internal class NotificationData ( val timestamp : Timestamp , val reminderTime : Long )
private inner class ShowNotificationTask ( private val habit : Habit , data : NotificationData ) :
private inner class ShowNotificationTask ( private val habit : Habit , data : NotificationData ) :
Task {
Task {
@ -164,6 +187,17 @@ class NotificationTray @Inject constructor(
timestamp ,
timestamp ,
reminderTime
reminderTime
)
)
if ( data . shown ) {
systemTray . log (
String . format (
Locale . US ,
" Showing notification for habit %d silently because it has been shown before. " ,
habit . id
)
)
}
data . shown = true
active [ habit ] = data
}
}
private fun shouldShowReminderToday ( ) : Boolean {
private fun shouldShowReminderToday ( ) : Boolean {