package com.vgmlr.kiln
import android.Manifest
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.core.app.NotificationChannelCompat
object KilnNotifications {
const val EXTRA_ID = "notif_id"
const val EXTRA_ACCOUNT = "account_id"
const val EXTRA_STOP_RUN = "stop_run"
private const val CHANNEL_PMS = "kiln_pms"
private const val CHANNEL_PERIOD = "kiln_period"
private const val ACTION_DISMISS = "com.vgmlr.kiln.DISMISS"
private const val SLOTS = 2
fun pmsId(accountId: Long): Int = (accountId * SLOTS).toInt()
fun periodId(accountId: Long): Int = (accountId * SLOTS + 1).toInt()
fun ensureChannels(context: Context) {
val nm = NotificationManagerCompat.from(context)
nm.createNotificationChannel(
NotificationChannelCompat
.Builder(CHANNEL_PMS, NotificationManagerCompat.IMPORTANCE_DEFAULT)
.setName("PMS Alert")
.build()
)
nm.createNotificationChannel(
NotificationChannelCompat
.Builder(CHANNEL_PERIOD, NotificationManagerCompat.IMPORTANCE_DEFAULT)
.setName("Menstruation Alert")
.build()
)
}
fun allowed(context: Context): Boolean =
Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU ||
ContextCompat.checkSelfPermission(
context, Manifest.permission.POST_NOTIFICATIONS
) == PackageManager.PERMISSION_GRANTED
fun pms(context: Context, account: KilnAccount) = post(
context, pmsId(account.id), CHANNEL_PMS,
"Kiln: ${account.name}: PMS Alert", account.pmsMessage, account.id, stopsRun = false
)
fun menstruation(context: Context, account: KilnAccount) = post(
context, periodId(account.id), CHANNEL_PERIOD,
"Kiln: ${account.name}: Menstruation?", account.menstruationMessage,
account.id, stopsRun = true
)
private fun post(
context: Context,
id: Int,
channel: String,
title: String,
body: String,
accountId: Long,
stopsRun: Boolean
) {
if (!allowed(context)) return
val dismiss = dismissIntent(context, id, accountId, stopsRun)
val notif = NotificationCompat.Builder(context, channel)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle(title)
.apply { if (body.isNotBlank()) setContentText(body) }
.setContentIntent(openIntent(context, id))
.setAutoCancel(true)
.addAction(0, "Dismiss", dismiss)
.setDeleteIntent(dismiss)
.build()
try {
NotificationManagerCompat.from(context).notify(id, notif)
} catch (_: SecurityException) {
}
}
private fun openIntent(context: Context, id: Int): PendingIntent =
PendingIntent.getActivity(
context, id,
Intent(context, MainActivity::class.java)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
private fun dismissIntent(
context: Context,
id: Int,
accountId: Long,
stopsRun: Boolean
): PendingIntent = PendingIntent.getBroadcast(
context, id,
Intent(context, KilnDismissReceiver::class.java)
.setAction("$ACTION_DISMISS.$id")
.putExtra(EXTRA_ID, id)
.putExtra(EXTRA_ACCOUNT, accountId)
.putExtra(EXTRA_STOP_RUN, stopsRun),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
}