Newer
Older
navi-1 / android-client / app / src / main / java / com / navi / client / NaviNotifications.kt
package com.navi.client

import android.Manifest
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.PowerManager
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat

/** Static helpers for channel setup + turn-complete notifications raised from the JS bridge. */
object NaviNotifications {

    fun hasPermission(context: Context): Boolean {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return true
        return ContextCompat.checkSelfPermission(
            context, Manifest.permission.POST_NOTIFICATIONS
        ) == PackageManager.PERMISSION_GRANTED
    }

    fun notifyTurn(context: Context, title: String, body: String, openUrl: String?) {
        if (!hasPermission(context)) return
        val nm = context.getSystemService(NotificationManager::class.java)
        // Create on demand too: the background-service channel helper is only
        // invoked once the foreground mode is ever enabled.
        if (nm.getNotificationChannel(BackgroundService.CHANNEL_MSG) == null) {
            // Mirror of BackgroundService setup kept minimal — no service needed.
            createMessageChannel(nm)
        }
        val launch = Intent(context, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP
            putExtra("open_url", openUrl ?: "")
        }
        val pending = PendingIntent.getActivity(
            context, 0, launch,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )
        val notif = NotificationCompat.Builder(context, BackgroundService.CHANNEL_MSG)
            .setSmallIcon(R.drawable.ic_notification)
            .setContentTitle(title)
            .setContentText(body)
            .setStyle(NotificationCompat.BigTextStyle().bigText(body))
            .setAutoCancel(true)
            .setContentIntent(pending)
            .build()
        // Stable-ish id per session URL: a new answer of the same session replaces.
        val id = (openUrl ?: "navi").hashCode()
        nm.notify(id, notif)
    }

    private fun createMessageChannel(nm: NotificationManager) {
        nm.createNotificationChannel(
            android.app.NotificationChannel(
                BackgroundService.CHANNEL_MSG,
                "Navi · сообщения",
                NotificationManager.IMPORTANCE_HIGH
            )
        )
    }

    /** Is the app exempt from Doze (battery optimization)? */
    fun isIgnoringBatteryOptimizations(context: Context): Boolean {
        val pm = context.getSystemService(PowerManager::class.java)
        return pm.isIgnoringBatteryOptimizations(context.packageName)
    }
}