Files
SimpleMercies/app/src/main/java/space/bloggin/mercies/Daily.kt
T

110 lines
5.0 KiB
Kotlin

package space.bloggin.mercies
import android.Manifest
import android.app.AlarmManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.BroadcastReceiver
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import java.time.LocalDate
import java.util.Calendar
object Daily {
private const val CH = "mercies"
fun open(ctx: Context, tab: String, code: Int): PendingIntent {
val i = Intent(ctx, MainActivity::class.java).apply {
action = "space.bloggin.mercies.OPEN_$tab"; putExtra("tab", tab)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
}
return PendingIntent.getActivity(ctx, code, i, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
private fun alarm(ctx: Context, which: String, on: Boolean, h: Int, m: Int, code: Int) {
val am = ctx.getSystemService(AlarmManager::class.java)
val pi = PendingIntent.getBroadcast(ctx, code, Intent(ctx, DailyReceiver::class.java).putExtra("which", which),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
am.cancel(pi)
if (!on) return
val cal = Calendar.getInstance().apply {
set(Calendar.HOUR_OF_DAY, h); set(Calendar.MINUTE, m); set(Calendar.SECOND, 0)
if (timeInMillis <= System.currentTimeMillis()) add(Calendar.DAY_OF_YEAR, 1)
}
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.timeInMillis, AlarmManager.INTERVAL_DAY, pi)
}
fun schedule(ctx: Context) {
val p = Prefs.get(ctx)
alarm(ctx, "eve", p.eve, p.eveH, p.eveM, 11)
alarm(ctx, "morn", true, if (p.morn) p.mornH else 0, if (p.morn) p.mornM else 3, 12) // also refreshes the widget each day
}
fun notify(ctx: Context, which: String) {
if (Build.VERSION.SDK_INT >= 33 && ContextCompat.checkSelfPermission(ctx, Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) return
val nm = ctx.getSystemService(NotificationManager::class.java)
nm.createNotificationChannel(NotificationChannel(CH, "Gentle reminders", NotificationManager.IMPORTANCE_DEFAULT))
val n = if (which == "eve") {
val alreadyToday = Store.get(ctx).notesOn(LocalDate.now()).isNotEmpty()
if (alreadyToday) return
NotificationCompat.Builder(ctx, CH).setSmallIcon(R.drawable.ic_notify)
.setContentTitle("The jar is open")
.setContentText(Prompts.forDate(LocalDate.now()))
.setContentIntent(open(ctx, "jar", 21)).setAutoCancel(true).build()
} else {
val k = Store.get(ctx).kindToday()
NotificationCompat.Builder(ctx, CH).setSmallIcon(R.drawable.ic_notify)
.setContentTitle("Today's kindness")
.setContentText(Kindness.all[k.idx])
.setStyle(NotificationCompat.BigTextStyle().bigText(Kindness.all[k.idx]))
.setContentIntent(open(ctx, "kind", 22)).setAutoCancel(true).build()
}
nm.notify(if (which == "eve") 1 else 2, n)
}
}
class DailyReceiver : BroadcastReceiver() {
override fun onReceive(ctx: Context, intent: Intent) {
val which = intent.getStringExtra("which") ?: return
MercyWidget.refresh(ctx)
val p = Prefs.get(ctx)
if ((which == "eve" && p.eve) || (which == "morn" && p.morn)) Daily.notify(ctx, which)
}
}
class BootReceiver : BroadcastReceiver() {
override fun onReceive(ctx: Context, intent: Intent) { Daily.schedule(ctx); MercyWidget.refresh(ctx) }
}
class MercyWidget : AppWidgetProvider() {
override fun onUpdate(ctx: Context, mgr: AppWidgetManager, ids: IntArray) = update(ctx, mgr, ids)
companion object {
fun update(ctx: Context, mgr: AppWidgetManager, ids: IntArray) {
val store = Store.get(ctx)
val k = store.kindToday()
val count = store.noteCount()
for (id in ids) {
val rv = RemoteViews(ctx.packageName, R.layout.widget_mercy)
rv.setTextViewText(R.id.w_text, Kindness.all[k.idx])
rv.setTextViewText(R.id.w_foot, (if (k.status == 1) "Done ❀ " else "") + if (count == 1) "1 mercy in the jar" else "$count mercies in the jar")
rv.setOnClickPendingIntent(R.id.w_root, Daily.open(ctx, "kind", 23))
mgr.updateAppWidget(id, rv)
}
}
fun refresh(ctx: Context) = try {
val mgr = AppWidgetManager.getInstance(ctx)
update(ctx, mgr, mgr.getAppWidgetIds(ComponentName(ctx, MercyWidget::class.java)))
} catch (_: Exception) {}
}
}