mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: Client Notification Support (#2095)
This commit is contained in:
parent
2a274e259b
commit
606d1520d8
5 changed files with 101 additions and 1 deletions
|
|
@ -434,6 +434,18 @@ class UIViewModel @Inject constructor(
|
|||
)
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
radioConfigRepository.clientNotification.filterNotNull().onEach { notification ->
|
||||
showAlert(
|
||||
title = app.getString(R.string.client_notification),
|
||||
message = notification.message,
|
||||
onConfirm = {
|
||||
radioConfigRepository.clearClientNotification()
|
||||
meshServiceNotifications.clearClientNotification(notification)
|
||||
},
|
||||
dismissable = false
|
||||
)
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
radioConfigRepository.localConfigFlow.onEach { config ->
|
||||
_localConfig.value = config
|
||||
}.launchIn(viewModelScope)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import com.geeksville.mesh.ConfigProtos.Config
|
|||
import com.geeksville.mesh.IMeshService
|
||||
import com.geeksville.mesh.LocalOnlyProtos.LocalConfig
|
||||
import com.geeksville.mesh.LocalOnlyProtos.LocalModuleConfig
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.MeshProtos.DeviceMetadata
|
||||
import com.geeksville.mesh.MeshProtos.MeshPacket
|
||||
import com.geeksville.mesh.ModuleConfigProtos.ModuleConfig
|
||||
|
|
@ -85,6 +86,7 @@ class RadioConfigRepository @Inject constructor(
|
|||
suspend fun installNodeDB(mi: MyNodeEntity, nodes: List<NodeEntity>) {
|
||||
nodeDB.installNodeDB(mi, nodes)
|
||||
}
|
||||
|
||||
suspend fun insertMetadata(fromNum: Int, metadata: DeviceMetadata) {
|
||||
nodeDB.insertMetadata(MetadataEntity(fromNum, metadata))
|
||||
}
|
||||
|
|
@ -187,6 +189,16 @@ class RadioConfigRepository @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
val clientNotification = serviceRepository.clientNotification
|
||||
|
||||
fun setClientNotification(notification: MeshProtos.ClientNotification?) {
|
||||
serviceRepository.setClientNotification(notification)
|
||||
}
|
||||
|
||||
fun clearClientNotification() {
|
||||
serviceRepository.clearClientNotification()
|
||||
}
|
||||
|
||||
val errorMessage: StateFlow<String?> get() = serviceRepository.errorMessage
|
||||
|
||||
fun setErrorMessage(text: String) {
|
||||
|
|
|
|||
|
|
@ -1723,7 +1723,8 @@ class MeshService : Service(), Logging {
|
|||
|
||||
private fun handleClientNotification(notification: MeshProtos.ClientNotification) {
|
||||
debug("Received clientNotification ${notification.toOneLineString()}")
|
||||
radioConfigRepository.setErrorMessage(notification.message)
|
||||
radioConfigRepository.setClientNotification(notification)
|
||||
serviceNotifications.showClientNotification(notification)
|
||||
// if the future for the originating request is still in the queue, complete as unsuccessful for now
|
||||
queueResponse.remove(notification.replyId)?.complete(false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import androidx.core.app.Person
|
|||
import androidx.core.app.RemoteInput
|
||||
import androidx.core.net.toUri
|
||||
import com.geeksville.mesh.MainActivity
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.TelemetryProtos.LocalStats
|
||||
import com.geeksville.mesh.android.notificationManager
|
||||
|
|
@ -69,6 +70,7 @@ class MeshServiceNotifications(
|
|||
createNewNodeNotificationChannel()
|
||||
createLowBatteryNotificationChannel()
|
||||
createLowBatteryRemoteNotificationChannel()
|
||||
createClientNotificationChannel()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -233,6 +235,25 @@ class MeshServiceNotifications(
|
|||
return channelId
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
private fun createClientNotificationChannel(): String {
|
||||
val channelId = "client_notifications"
|
||||
if (notificationManager.getNotificationChannel(channelId) == null) {
|
||||
val channelName = context.getString(R.string.client_notification)
|
||||
val channel = NotificationChannel(
|
||||
channelId,
|
||||
channelName,
|
||||
NotificationManager.IMPORTANCE_HIGH
|
||||
).apply {
|
||||
lightColor = notificationLightColor
|
||||
lockscreenVisibility = Notification.VISIBILITY_PUBLIC
|
||||
setShowBadge(true)
|
||||
}
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
}
|
||||
return channelId
|
||||
}
|
||||
|
||||
private val channelId: String by lazy {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createNotificationChannel()
|
||||
|
|
@ -287,6 +308,14 @@ class MeshServiceNotifications(
|
|||
}
|
||||
}
|
||||
|
||||
private val clientNotificationChannelId: String by lazy {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
createClientNotificationChannel()
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
private fun LocalStats?.formatToString(): String = this?.allFields?.mapNotNull { (k, v) ->
|
||||
when (k.name) {
|
||||
"num_online_nodes", "num_total_nodes" -> return@mapNotNull null
|
||||
|
|
@ -351,6 +380,16 @@ class MeshServiceNotifications(
|
|||
notificationManager.cancel(node.num)
|
||||
}
|
||||
|
||||
fun showClientNotification(notification: MeshProtos.ClientNotification) {
|
||||
notificationManager.notify(
|
||||
notification.toString().hashCode(), // show unique notifications
|
||||
createClientNotification(context.getString(R.string.client_notification), notification.message)
|
||||
)
|
||||
}
|
||||
fun clearClientNotification(notification: MeshProtos.ClientNotification) {
|
||||
notificationManager.cancel(notification.toString().hashCode())
|
||||
}
|
||||
|
||||
private val openAppIntent: PendingIntent by lazy {
|
||||
PendingIntent.getActivity(
|
||||
context,
|
||||
|
|
@ -583,4 +622,26 @@ class MeshServiceNotifications(
|
|||
return lowBatteryNotificationBuilder.build()
|
||||
}
|
||||
}
|
||||
|
||||
lateinit var clientNotificationBuilder: NotificationCompat.Builder
|
||||
|
||||
private fun createClientNotification(name: String, message: String? = null): Notification {
|
||||
if (!::clientNotificationBuilder.isInitialized) {
|
||||
clientNotificationBuilder = commonBuilder(clientNotificationChannelId)
|
||||
}
|
||||
with(clientNotificationBuilder) {
|
||||
priority = NotificationCompat.PRIORITY_DEFAULT
|
||||
setCategory(Notification.CATEGORY_ERROR)
|
||||
setAutoCancel(true)
|
||||
setContentTitle(name)
|
||||
message?.let {
|
||||
setContentText(it)
|
||||
setStyle(
|
||||
NotificationCompat.BigTextStyle()
|
||||
.bigText(message),
|
||||
)
|
||||
}
|
||||
}
|
||||
return clientNotificationBuilder.build()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package com.geeksville.mesh.service
|
||||
|
||||
import com.geeksville.mesh.IMeshService
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.MeshProtos.MeshPacket
|
||||
import com.geeksville.mesh.android.Logging
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
|
@ -32,6 +33,7 @@ import javax.inject.Singleton
|
|||
/**
|
||||
* Repository class for managing the [IMeshService] instance and connection state
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
@Singleton
|
||||
class ServiceRepository @Inject constructor() : Logging {
|
||||
var meshService: IMeshService? = null
|
||||
|
|
@ -49,6 +51,18 @@ class ServiceRepository @Inject constructor() : Logging {
|
|||
_connectionState.value = connectionState
|
||||
}
|
||||
|
||||
private val _clientNotification = MutableStateFlow<MeshProtos.ClientNotification?>(null)
|
||||
val clientNotification: StateFlow<MeshProtos.ClientNotification?> get() = _clientNotification
|
||||
fun setClientNotification(notification: MeshProtos.ClientNotification?) {
|
||||
errormsg(notification?.message.orEmpty())
|
||||
|
||||
_clientNotification.value = notification
|
||||
}
|
||||
|
||||
fun clearClientNotification() {
|
||||
_clientNotification.value = null
|
||||
}
|
||||
|
||||
private val _errorMessage = MutableStateFlow<String?>(null)
|
||||
val errorMessage: StateFlow<String?> get() = _errorMessage
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue