diff --git a/mobile/src/foss/java/org/openhab/habdroid/core/NotificationPoller.kt b/mobile/src/foss/java/org/openhab/habdroid/core/NotificationPoller.kt
index 1a362f8514..c75dc5d556 100644
--- a/mobile/src/foss/java/org/openhab/habdroid/core/NotificationPoller.kt
+++ b/mobile/src/foss/java/org/openhab/habdroid/core/NotificationPoller.kt
@@ -19,6 +19,7 @@ import androidx.core.content.edit
import org.json.JSONArray
import org.json.JSONException
import org.openhab.habdroid.core.connection.ConnectionFactory
+import org.openhab.habdroid.model.CloudNotificationType
import org.openhab.habdroid.model.toCloudNotification
import org.openhab.habdroid.util.HttpClient
import org.openhab.habdroid.util.PrefKeys
@@ -65,8 +66,18 @@ object NotificationPoller {
val newMessages = if (lastSeenIndex >= 0) messages.subList(0, lastSeenIndex) else messages
val notifHelper = NotificationHelper(context)
- newMessages.forEach { message ->
- notifHelper.showNotification(message)
+ // Reverse list, so old notifications are processed first and can be hidden by newer notifications.
+ newMessages.reversed().forEach { message ->
+ when (message.type) {
+ CloudNotificationType.NOTIFICATION -> notifHelper.showNotification(message)
+ CloudNotificationType.HIDE_NOTIFICATION -> {
+ if (!message.tag.isNullOrEmpty()) {
+ notifHelper.cancelNotificationsByTag(message.tag)
+ } else {
+ notifHelper.cancelNotificationById(message.id)
+ }
+ }
+ }
}
}
}
diff --git a/mobile/src/full/java/org/openhab/habdroid/core/FcmMessageListenerService.kt b/mobile/src/full/java/org/openhab/habdroid/core/FcmMessageListenerService.kt
index 07a0ed34cf..b093f1d4d0 100644
--- a/mobile/src/full/java/org/openhab/habdroid/core/FcmMessageListenerService.kt
+++ b/mobile/src/full/java/org/openhab/habdroid/core/FcmMessageListenerService.kt
@@ -20,6 +20,7 @@ import kotlinx.coroutines.runBlocking
import org.openhab.habdroid.model.CloudNotification
import org.openhab.habdroid.model.CloudNotificationAction
import org.openhab.habdroid.model.CloudNotificationId
+import org.openhab.habdroid.model.CloudNotificationType
import org.openhab.habdroid.model.toCloudNotificationAction
import org.openhab.habdroid.model.toOH2IconResource
import org.openhab.habdroid.util.map
@@ -52,6 +53,7 @@ class FcmMessageListenerService : FirebaseMessagingService() {
?.map { it.toCloudNotificationAction() }
?.filterNotNull()
val cloudNotification = CloudNotification(
+ type = CloudNotificationType.NOTIFICATION,
id = CloudNotificationId(data["persistedId"].orEmpty(), data["reference-id"]),
title = data["title"].orEmpty(),
message = data["message"].orEmpty(),
diff --git a/mobile/src/main/java/org/openhab/habdroid/model/CloudNotification.kt b/mobile/src/main/java/org/openhab/habdroid/model/CloudNotification.kt
index 4956565d8a..6fb2a4f47e 100644
--- a/mobile/src/main/java/org/openhab/habdroid/model/CloudNotification.kt
+++ b/mobile/src/main/java/org/openhab/habdroid/model/CloudNotification.kt
@@ -44,8 +44,21 @@ data class CloudNotificationId internal constructor(
val notificationId get() = (referenceId ?: persistedId).hashCode()
}
+@Parcelize
+enum class CloudNotificationType : Parcelable {
+ NOTIFICATION,
+ HIDE_NOTIFICATION
+}
+
+fun String.toCloudNotificationType() = when (this) {
+ "notification" -> CloudNotificationType.NOTIFICATION
+ "hideNotification" -> CloudNotificationType.HIDE_NOTIFICATION
+ else -> null
+}
+
@Parcelize
data class CloudNotification internal constructor(
+ val type: CloudNotificationType,
val id: CloudNotificationId,
val title: String,
val message: String,
@@ -117,9 +130,11 @@ fun JSONObject.toCloudNotification(): CloudNotification {
val payload = optJSONObject("payload")
return CloudNotification(
+ // Old notifications don't contain "type", so fallback to normal notifications here.
+ type = payload?.optString("type")?.toCloudNotificationType() ?: CloudNotificationType.NOTIFICATION,
id = CloudNotificationId(getString("_id"), payload?.optStringOrNull("reference-id")),
title = payload?.optString("title").orEmpty(),
- message = payload?.getString("message") ?: getString("message"),
+ message = payload?.optString("message") ?: optString("message"),
createdTimestamp = created,
icon = payload?.optStringOrNull("icon").toOH2IconResource() ?: optStringOrNull("icon").toOH2IconResource(),
tag = payload?.optStringOrNull("tag") ?: optStringOrNull("severity"),
diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationListFragment.kt b/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationListFragment.kt
index c2bdd55667..a213ff074b 100644
--- a/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationListFragment.kt
+++ b/mobile/src/main/java/org/openhab/habdroid/ui/CloudNotificationListFragment.kt
@@ -36,6 +36,7 @@ import org.json.JSONArray
import org.json.JSONException
import org.openhab.habdroid.R
import org.openhab.habdroid.core.connection.ConnectionFactory
+import org.openhab.habdroid.model.CloudNotificationType
import org.openhab.habdroid.model.ServerConfiguration
import org.openhab.habdroid.model.toCloudNotification
import org.openhab.habdroid.util.HttpClient
@@ -152,6 +153,7 @@ class CloudNotificationListFragment : Fragment(), View.OnClickListener, SwipeRef
try {
val response = conn.httpClient.get(url).asText().response
val items = JSONArray(response).map { obj -> obj.toCloudNotification() }
+ .filter { notification -> notification.type == CloudNotificationType.NOTIFICATION }
Log.d(TAG, "Notifications request success, got ${items.size} items")
loadOffset += items.size
adapter.addLoadedItems(items, items.size == PAGE_SIZE)
diff --git a/mobile/src/main/java/org/openhab/habdroid/ui/MainActivity.kt b/mobile/src/main/java/org/openhab/habdroid/ui/MainActivity.kt
index 8e638e9c66..638647df9b 100644
--- a/mobile/src/main/java/org/openhab/habdroid/ui/MainActivity.kt
+++ b/mobile/src/main/java/org/openhab/habdroid/ui/MainActivity.kt
@@ -415,7 +415,8 @@ class MainActivity : AbstractBaseActivity(), ConnectionFactory.UpdateListener {
connection != null && SpeechRecognizer.isRecognitionAvailable(this)
val debugItems = listOf(
R.id.mainmenu_debug_crash,
- R.id.mainmenu_debug_clear_mtm
+ R.id.mainmenu_debug_clear_mtm,
+ R.id.mainmenu_poll_notifications
)
debugItems.forEach {
menu.findItem(it).isVisible = BuildConfig.DEBUG
@@ -454,6 +455,14 @@ class MainActivity : AbstractBaseActivity(), ConnectionFactory.UpdateListener {
}
true
}
+ R.id.mainmenu_poll_notifications -> {
+ if (CloudMessagingHelper.needsPollingForNotifications(this)) {
+ launch {
+ CloudMessagingHelper.pollForNotifications(this@MainActivity)
+ }
+ }
+ true
+ }
else -> super.onOptionsItemSelected(item)
}
}
diff --git a/mobile/src/main/res/menu/main_menu.xml b/mobile/src/main/res/menu/main_menu.xml
index 03ee41a6ec..0e57d8f1e4 100644
--- a/mobile/src/main/res/menu/main_menu.xml
+++ b/mobile/src/main/res/menu/main_menu.xml
@@ -10,6 +10,12 @@
android:title="@string/mainmenu_openhab_voice_recognition"
app:showAsAction="always"
app:iconTint="?android:textColorSecondary" />
+