package com.tt.honeyDue.notifications import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context import android.os.Build import androidx.core.app.NotificationManagerCompat /** * Android NotificationChannels that map to the iOS UNNotificationCategory * identifiers defined in `iosApp/iosApp/PushNotifications/NotificationCategories.swift`. * * iOS uses categories + per-notification actions. Android uses channels for * importance grouping. Channels here mirror the four high-level iOS tones: * * task_reminder — default importance (upcoming/due-soon reminders) * task_overdue — high importance (user is late, needs attention) * residence_invite — default importance (social-style invite, not urgent) * subscription — low importance (billing/status changes, passive info) * * User-visible names and descriptions match the keys in * `composeApp/src/commonMain/composeResources/values/strings.xml` * (`notif_channel_*_name`, `notif_channel_*_description`). */ object NotificationChannels { const val TASK_REMINDER: String = "task_reminder" const val TASK_OVERDUE: String = "task_overdue" const val RESIDENCE_INVITE: String = "residence_invite" const val SUBSCRIPTION: String = "subscription" // English fallback strings. These are duplicated in composeResources // strings.xml under the matching notif_channel_* keys so localised builds // can override them. Services without access to Compose resources fall // back to these values. private const val NAME_TASK_REMINDER = "Task Reminders" private const val NAME_TASK_OVERDUE = "Overdue Tasks" private const val NAME_RESIDENCE_INVITE = "Residence Invites" private const val NAME_SUBSCRIPTION = "Subscription Updates" private const val DESC_TASK_REMINDER = "Upcoming and due-soon task reminders" private const val DESC_TASK_OVERDUE = "Alerts when a task is past its due date" private const val DESC_RESIDENCE_INVITE = "Invitations to join a shared residence" private const val DESC_SUBSCRIPTION = "Subscription status and billing updates" /** * Create all four channels if they don't already exist. Safe to call * repeatedly — `NotificationManagerCompat.createNotificationChannel` is * a no-op when a channel with the same id already exists. */ fun ensureChannels(context: Context) { // Channels only exist on O+; on older versions this is a no-op and the // NotificationCompat layer ignores channel ids. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return val compat = NotificationManagerCompat.from(context) val channels = listOf( NotificationChannel( TASK_REMINDER, NAME_TASK_REMINDER, NotificationManager.IMPORTANCE_DEFAULT ).apply { description = DESC_TASK_REMINDER }, NotificationChannel( TASK_OVERDUE, NAME_TASK_OVERDUE, NotificationManager.IMPORTANCE_HIGH ).apply { description = DESC_TASK_OVERDUE }, NotificationChannel( RESIDENCE_INVITE, NAME_RESIDENCE_INVITE, NotificationManager.IMPORTANCE_DEFAULT ).apply { description = DESC_RESIDENCE_INVITE }, NotificationChannel( SUBSCRIPTION, NAME_SUBSCRIPTION, NotificationManager.IMPORTANCE_LOW ).apply { description = DESC_SUBSCRIPTION } ) channels.forEach { compat.createNotificationChannel(it) } } /** * Map a [NotificationPayload.type] string to a channel id. Unknown types * fall back to [TASK_REMINDER] (default importance, safe default). */ fun channelIdForType(type: String): String = when (type) { TASK_OVERDUE -> TASK_OVERDUE RESIDENCE_INVITE -> RESIDENCE_INVITE SUBSCRIPTION -> SUBSCRIPTION TASK_REMINDER -> TASK_REMINDER else -> TASK_REMINDER } }