refactor(monitor): Remove shared mutable builder from MonitorNotifications

Replace shared NotificationCompat.Builder + Mutex with a stateless
design where each method builds a fresh notification. Introduces a
baseBuilder() helper to deduplicate common setup. Removes builderLock
and suspend modifiers from getNotification/getNotificationConnected.
This commit is contained in:
darken
2026-02-22 06:32:12 +01:00
committed by Matthias Urhahn
parent 5b59ddab0f
commit 9ad3f3c180
@@ -22,8 +22,6 @@ import eu.darken.capod.pods.core.HasEarDetection
import eu.darken.capod.pods.core.PodDevice import eu.darken.capod.pods.core.PodDevice
import eu.darken.capod.pods.core.SinglePodDevice import eu.darken.capod.pods.core.SinglePodDevice
import eu.darken.capod.pods.core.formatBatteryPercent import eu.darken.capod.pods.core.formatBatteryPercent
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import javax.inject.Inject import javax.inject.Inject
@@ -33,8 +31,7 @@ class MonitorNotifications @Inject constructor(
private val notificationViewFactory: MonitorNotificationViewFactory private val notificationViewFactory: MonitorNotificationViewFactory
) { ) {
private val builderLock = Mutex() private val openPi: PendingIntent
private val builder: NotificationCompat.Builder
init { init {
ensureChannel(context) ensureChannel(context)
@@ -44,35 +41,32 @@ class MonitorNotifications @Inject constructor(
NotificationManager.IMPORTANCE_LOW NotificationManager.IMPORTANCE_LOW
).run { notificationManager.createNotificationChannel(this) } ).run { notificationManager.createNotificationChannel(this) }
val openIntent = Intent(context, MainActivity::class.java) openPi = PendingIntent.getActivity(
val openPi = PendingIntent.getActivity(
context, context,
PENDING_INTENT_REQUEST_CODE, PENDING_INTENT_REQUEST_CODE,
openIntent, Intent(context, MainActivity::class.java),
PendingIntentCompat.FLAG_IMMUTABLE PendingIntentCompat.FLAG_IMMUTABLE
) )
}
builder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID).apply { private fun baseBuilder(channelId: String): NotificationCompat.Builder =
NotificationCompat.Builder(context, channelId).apply {
setContentIntent(openPi) setContentIntent(openPi)
priority = NotificationCompat.PRIORITY_LOW priority = NotificationCompat.PRIORITY_LOW
setSmallIcon(R.drawable.device_earbuds_generic_both) setSmallIcon(R.drawable.device_earbuds_generic_both)
setOngoing(true) setOngoing(true)
setContentTitle(context.getString(R.string.app_name))
} }
}
private fun getBuilder(device: PodDevice?): NotificationCompat.Builder { private fun getBuilder(device: PodDevice?, channelId: String): NotificationCompat.Builder {
if (device == null) { if (device == null) {
return builder.apply { return baseBuilder(channelId).apply {
setCustomContentView(null)
setStyle(NotificationCompat.BigTextStyle()) setStyle(NotificationCompat.BigTextStyle())
setContentTitle(context.getString(R.string.pods_none_label_short)) setContentTitle(context.getString(R.string.pods_none_label_short))
setSubText(context.getString(R.string.app_name)) setSubText(context.getString(R.string.app_name))
setSmallIcon(R.drawable.device_earbuds_generic_both)
} }
} }
return builder.apply { return baseBuilder(channelId).apply {
// Options here should be mutually exclusive, and are prioritized by their order of importance // Options here should be mutually exclusive, and are prioritized by their order of importance
// Some options are omitted here, as they will conflict with other options // Some options are omitted here, as they will conflict with other options
@@ -135,28 +129,20 @@ class MonitorNotifications @Inject constructor(
setStyle(NotificationCompat.DecoratedCustomViewStyle()) setStyle(NotificationCompat.DecoratedCustomViewStyle())
setCustomBigContentView(notificationViewFactory.createContentView(device)) setCustomBigContentView(notificationViewFactory.createContentView(device))
setSmallIcon(R.drawable.device_earbuds_generic_both)
setContentTitle("$batteryText ~ $stateText") setContentTitle("$batteryText ~ $stateText")
setSubText(null) setSubText(null)
log(TAG, VERBOSE) { "updatingNotification(): $device" } log(TAG, VERBOSE) { "updatingNotification(): $device" }
} }
} }
suspend fun getNotification(podDevice: PodDevice?): Notification = builderLock.withLock { fun getNotification(podDevice: PodDevice?): Notification =
getBuilder(podDevice).apply { getBuilder(podDevice, NOTIFICATION_CHANNEL_ID).build()
setChannelId(NOTIFICATION_CHANNEL_ID)
}.build()
}
suspend fun getNotificationConnected(podDevice: PodDevice?): Notification = builderLock.withLock { fun getNotificationConnected(podDevice: PodDevice?): Notification =
getBuilder(podDevice).apply { getBuilder(podDevice, NOTIFICATION_CHANNEL_ID_CONNECTED).build()
setChannelId(NOTIFICATION_CHANNEL_ID_CONNECTED)
}.build()
}
fun getStartupNotification(): Notification = getBuilder(null).apply { fun getStartupNotification(): Notification =
setChannelId(NOTIFICATION_CHANNEL_ID) getBuilder(null, NOTIFICATION_CHANNEL_ID).build()
}.build()
companion object { companion object {
val TAG = logTag("Monitor", "Notifications") val TAG = logTag("Monitor", "Notifications")