diff --git a/app/schemas/io.heckel.ntfy.db.Database/14.json b/app/schemas/io.heckel.ntfy.db.Database/14.json
new file mode 100644
index 000000000..b5bcdf401
--- /dev/null
+++ b/app/schemas/io.heckel.ntfy.db.Database/14.json
@@ -0,0 +1,362 @@
+{
+ "formatVersion": 1,
+ "database": {
+ "version": 14,
+ "identityHash": "6da97d05d0954a633ef08aed42e5ad95",
+ "entities": [
+ {
+ "tableName": "Subscription",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `baseUrl` TEXT NOT NULL, `topic` TEXT NOT NULL, `instant` INTEGER NOT NULL, `mutedUntil` INTEGER NOT NULL, `minPriority` INTEGER NOT NULL, `autoDelete` INTEGER NOT NULL, `insistent` INTEGER NOT NULL, `lastNotificationId` TEXT, `icon` TEXT, `upAppId` TEXT, `upConnectorToken` TEXT, `displayName` TEXT, `dedicatedChannels` INTEGER NOT NULL, `clientMessage` TEXT, PRIMARY KEY(`id`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "baseUrl",
+ "columnName": "baseUrl",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "topic",
+ "columnName": "topic",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "instant",
+ "columnName": "instant",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "mutedUntil",
+ "columnName": "mutedUntil",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "minPriority",
+ "columnName": "minPriority",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "autoDelete",
+ "columnName": "autoDelete",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "insistent",
+ "columnName": "insistent",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "lastNotificationId",
+ "columnName": "lastNotificationId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "icon",
+ "columnName": "icon",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "upAppId",
+ "columnName": "upAppId",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "upConnectorToken",
+ "columnName": "upConnectorToken",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "displayName",
+ "columnName": "displayName",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "dedicatedChannels",
+ "columnName": "dedicatedChannels",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "clientMessage",
+ "columnName": "clientMessage",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [
+ {
+ "name": "index_Subscription_baseUrl_topic",
+ "unique": true,
+ "columnNames": [
+ "baseUrl",
+ "topic"
+ ],
+ "orders": [],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Subscription_baseUrl_topic` ON `${TABLE_NAME}` (`baseUrl`, `topic`)"
+ },
+ {
+ "name": "index_Subscription_upConnectorToken",
+ "unique": true,
+ "columnNames": [
+ "upConnectorToken"
+ ],
+ "orders": [],
+ "createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_Subscription_upConnectorToken` ON `${TABLE_NAME}` (`upConnectorToken`)"
+ }
+ ],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Notification",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `subscriptionId` INTEGER NOT NULL, `timestamp` INTEGER NOT NULL, `title` TEXT NOT NULL, `message` TEXT NOT NULL, `encoding` TEXT NOT NULL, `notificationId` INTEGER NOT NULL, `priority` INTEGER NOT NULL DEFAULT 3, `tags` TEXT NOT NULL, `click` TEXT NOT NULL, `actions` TEXT, `deleted` INTEGER NOT NULL, `icon_url` TEXT, `icon_contentUri` TEXT, `attachment_name` TEXT, `attachment_type` TEXT, `attachment_size` INTEGER, `attachment_expires` INTEGER, `attachment_url` TEXT, `attachment_contentUri` TEXT, `attachment_progress` INTEGER, PRIMARY KEY(`id`, `subscriptionId`))",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "subscriptionId",
+ "columnName": "subscriptionId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "title",
+ "columnName": "title",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "message",
+ "columnName": "message",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "encoding",
+ "columnName": "encoding",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "notificationId",
+ "columnName": "notificationId",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "priority",
+ "columnName": "priority",
+ "affinity": "INTEGER",
+ "notNull": true,
+ "defaultValue": "3"
+ },
+ {
+ "fieldPath": "tags",
+ "columnName": "tags",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "click",
+ "columnName": "click",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "actions",
+ "columnName": "actions",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "deleted",
+ "columnName": "deleted",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "icon.url",
+ "columnName": "icon_url",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "icon.contentUri",
+ "columnName": "icon_contentUri",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "attachment.name",
+ "columnName": "attachment_name",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "attachment.type",
+ "columnName": "attachment_type",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "attachment.size",
+ "columnName": "attachment_size",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "attachment.expires",
+ "columnName": "attachment_expires",
+ "affinity": "INTEGER",
+ "notNull": false
+ },
+ {
+ "fieldPath": "attachment.url",
+ "columnName": "attachment_url",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "attachment.contentUri",
+ "columnName": "attachment_contentUri",
+ "affinity": "TEXT",
+ "notNull": false
+ },
+ {
+ "fieldPath": "attachment.progress",
+ "columnName": "attachment_progress",
+ "affinity": "INTEGER",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "id",
+ "subscriptionId"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "User",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`baseUrl` TEXT NOT NULL, `username` TEXT NOT NULL, `password` TEXT NOT NULL, PRIMARY KEY(`baseUrl`))",
+ "fields": [
+ {
+ "fieldPath": "baseUrl",
+ "columnName": "baseUrl",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "username",
+ "columnName": "username",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "password",
+ "columnName": "password",
+ "affinity": "TEXT",
+ "notNull": true
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": false,
+ "columnNames": [
+ "baseUrl"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ },
+ {
+ "tableName": "Log",
+ "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `timestamp` INTEGER NOT NULL, `tag` TEXT NOT NULL, `level` INTEGER NOT NULL, `message` TEXT NOT NULL, `exception` TEXT)",
+ "fields": [
+ {
+ "fieldPath": "id",
+ "columnName": "id",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "timestamp",
+ "columnName": "timestamp",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "tag",
+ "columnName": "tag",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "level",
+ "columnName": "level",
+ "affinity": "INTEGER",
+ "notNull": true
+ },
+ {
+ "fieldPath": "message",
+ "columnName": "message",
+ "affinity": "TEXT",
+ "notNull": true
+ },
+ {
+ "fieldPath": "exception",
+ "columnName": "exception",
+ "affinity": "TEXT",
+ "notNull": false
+ }
+ ],
+ "primaryKey": {
+ "autoGenerate": true,
+ "columnNames": [
+ "id"
+ ]
+ },
+ "indices": [],
+ "foreignKeys": []
+ }
+ ],
+ "views": [],
+ "setupQueries": [
+ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
+ "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6da97d05d0954a633ef08aed42e5ad95')"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0950b404e..17ba499f2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -176,4 +176,17 @@
android:resource="@xml/file_paths"/>
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/io/heckel/ntfy/backup/Backuper.kt b/app/src/main/java/io/heckel/ntfy/backup/Backuper.kt
index 89460c4bb..feb71d109 100644
--- a/app/src/main/java/io/heckel/ntfy/backup/Backuper.kt
+++ b/app/src/main/java/io/heckel/ntfy/backup/Backuper.kt
@@ -111,6 +111,7 @@ class Backuper(val context: Context) {
upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
+ clientMessage = s.clientMessage
)
repository.addSubscription(subscription)
@@ -258,7 +259,8 @@ class Backuper(val context: Context) {
icon = s.icon,
upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken,
- displayName = s.displayName
+ displayName = s.displayName,
+ clientMessage = s.clientMessage
)
}
}
@@ -377,7 +379,8 @@ data class Subscription(
val icon: String?,
val upAppId: String?,
val upConnectorToken: String?,
- val displayName: String?
+ val displayName: String?,
+ val clientMessage: String?,
)
data class Notification(
diff --git a/app/src/main/java/io/heckel/ntfy/db/Database.kt b/app/src/main/java/io/heckel/ntfy/db/Database.kt
index 5f397969e..f03c17bd7 100644
--- a/app/src/main/java/io/heckel/ntfy/db/Database.kt
+++ b/app/src/main/java/io/heckel/ntfy/db/Database.kt
@@ -9,6 +9,9 @@ import com.google.gson.reflect.TypeToken
import kotlinx.coroutines.flow.Flow
import java.lang.reflect.Type
+/**
+ * @param clientMessage Nullable message that may have been included by the client at registration.
+ */
@Entity(indices = [Index(value = ["baseUrl", "topic"], unique = true), Index(value = ["upConnectorToken"], unique = true)])
data class Subscription(
@PrimaryKey val id: Long, // Internal ID, only used in Repository and activities
@@ -25,6 +28,7 @@ data class Subscription(
@ColumnInfo(name = "upConnectorToken") val upConnectorToken: String?, // UnifiedPush connector token
@ColumnInfo(name = "displayName") val displayName: String?,
@ColumnInfo(name = "dedicatedChannels") val dedicatedChannels: Boolean,
+ @ColumnInfo(name = "clientMessage") val clientMessage: String?,
@Ignore val totalCount: Int = 0, // Total notifications
@Ignore val newCount: Int = 0, // New notifications
@Ignore val lastActive: Long = 0, // Unix timestamp
@@ -44,7 +48,8 @@ data class Subscription(
upAppId: String,
upConnectorToken: String,
displayName: String?,
- dedicatedChannels: Boolean
+ dedicatedChannels: Boolean,
+ clientMessage: String?,
) :
this(
id,
@@ -61,6 +66,7 @@ data class Subscription(
upConnectorToken,
displayName,
dedicatedChannels,
+ clientMessage,
totalCount = 0,
newCount = 0,
lastActive = 0,
@@ -89,7 +95,8 @@ data class SubscriptionWithMetadata(
val dedicatedChannels: Boolean,
val totalCount: Int,
val newCount: Int,
- val lastActive: Long
+ val lastActive: Long,
+ val clientMessage: String?,
)
@Entity(primaryKeys = ["id", "subscriptionId"])
@@ -196,7 +203,13 @@ data class LogEntry(
this(0, timestamp, tag, level, message, exception)
}
-@androidx.room.Database(entities = [Subscription::class, Notification::class, User::class, LogEntry::class], version = 13)
+@androidx.room.Database(
+ entities = [Subscription::class, Notification::class, User::class, LogEntry::class],
+ version = 14,
+ autoMigrations = [
+ AutoMigration(from = 13, to = 14)
+ ]
+)
@TypeConverters(Converters::class)
abstract class Database : RoomDatabase() {
abstract fun subscriptionDao(): SubscriptionDao
@@ -336,7 +349,7 @@ abstract class Database : RoomDatabase() {
interface SubscriptionDao {
@Query("""
SELECT
- s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels,
+ s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels, s.clientMessage,
COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive
@@ -349,7 +362,7 @@ interface SubscriptionDao {
@Query("""
SELECT
- s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels,
+ s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels, s.clientMessage,
COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive
@@ -362,7 +375,7 @@ interface SubscriptionDao {
@Query("""
SELECT
- s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels,
+ s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels, s.clientMessage,
COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive
@@ -375,7 +388,7 @@ interface SubscriptionDao {
@Query("""
SELECT
- s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels,
+ s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels, s.clientMessage,
COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive
@@ -388,7 +401,7 @@ interface SubscriptionDao {
@Query("""
SELECT
- s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels,
+ s.id, s.baseUrl, s.topic, s.instant, s.mutedUntil, s.minPriority, s.autoDelete, s.insistent, s.lastNotificationId, s.icon, s.upAppId, s.upConnectorToken, s.displayName, s.dedicatedChannels, s.clientMessage,
COUNT(n.id) totalCount,
COUNT(CASE n.notificationId WHEN 0 THEN NULL ELSE n.id END) newCount,
IFNULL(MAX(n.timestamp),0) AS lastActive
diff --git a/app/src/main/java/io/heckel/ntfy/db/Repository.kt b/app/src/main/java/io/heckel/ntfy/db/Repository.kt
index 71b030920..7717c5e89 100644
--- a/app/src/main/java/io/heckel/ntfy/db/Repository.kt
+++ b/app/src/main/java/io/heckel/ntfy/db/Repository.kt
@@ -419,6 +419,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
+ clientMessage = s.clientMessage,
totalCount = s.totalCount,
newCount = s.newCount,
lastActive = s.lastActive,
@@ -446,6 +447,7 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
upAppId = s.upAppId,
upConnectorToken = s.upConnectorToken,
displayName = s.displayName,
+ clientMessage = s.clientMessage,
totalCount = s.totalCount,
newCount = s.newCount,
lastActive = s.lastActive,
diff --git a/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt b/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt
index 851f43ac2..e4646c78f 100644
--- a/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt
+++ b/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt
@@ -121,6 +121,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
upAppId = null,
upConnectorToken = null,
displayName = null,
+ clientMessage = null,
totalCount = 0,
newCount = 0,
lastActive = Date().time/1000
diff --git a/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt b/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt
index e131f32c7..7af62ed73 100644
--- a/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt
+++ b/app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt
@@ -460,6 +460,7 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
upAppId = null,
upConnectorToken = null,
displayName = null,
+ clientMessage = null,
totalCount = 0,
newCount = 0,
lastActive = Date().time/1000
diff --git a/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt b/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt
index ed0d2bd0f..71a03a5b4 100644
--- a/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt
+++ b/app/src/main/java/io/heckel/ntfy/ui/MainAdapter.kt
@@ -1,12 +1,16 @@
package io.heckel.ntfy.ui
import android.content.Context
+import android.content.pm.PackageManager
import android.graphics.Color
+import android.graphics.drawable.Drawable
+import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
+import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
@@ -17,6 +21,7 @@ import io.heckel.ntfy.db.Repository
import io.heckel.ntfy.db.Subscription
import io.heckel.ntfy.util.displayName
import io.heckel.ntfy.util.readBitmapFromUriOrNull
+import io.heckel.ntfy.util.subscriptionTopicShortUrl
import java.text.DateFormat
import java.util.*
@@ -69,7 +74,7 @@ class MainAdapter(private val repository: Repository, private val onClick: (Subs
this.subscription = subscription
val isUnifiedPush = subscription.upAppId != null
var statusMessage = if (isUnifiedPush) {
- context.getString(R.string.main_item_status_unified_push, subscription.upAppId)
+ context.getString(R.string.main_item_status_unified_push, subscriptionTopicShortUrl(subscription))
} else if (subscription.totalCount == 1) {
context.getString(R.string.main_item_status_text_one, subscription.totalCount)
} else {
@@ -97,7 +102,10 @@ class MainAdapter(private val repository: Repository, private val onClick: (Subs
if (subscription.icon != null) {
imageView.setImageBitmap(subscription.icon.readBitmapFromUriOrNull(context))
} else {
- imageView.setImageResource(R.drawable.ic_sms_gray_24dp)
+ val icon = subscription.upAppId?.let {
+ getApplicationIcon(context, it)
+ } ?: ContextCompat.getDrawable(context, R.drawable.ic_sms_gray_24dp)!!
+ imageView.setImageDrawable(icon)
}
nameView.text = displayName(subscription)
statusView.text = statusMessage
@@ -120,6 +128,26 @@ class MainAdapter(private val repository: Repository, private val onClick: (Subs
itemView.setBackgroundColor(Color.TRANSPARENT)
}
}
+
+ /**
+ * @return The application icon of [packageName], or null if the package name
+ * is not among installed packages.
+ */
+ private fun getApplicationIcon(context: Context, packageName: String): Drawable? {
+ return try {
+ val info = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ context.packageManager.getApplicationInfo(
+ packageName,
+ PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong()),
+ )
+ } else {
+ context.packageManager.getApplicationInfo(packageName, 0)
+ }
+ context.packageManager.getApplicationIcon(info)
+ } catch (e: PackageManager.NameNotFoundException) {
+ null
+ }
+ }
}
object TopicDiffCallback : DiffUtil.ItemCallback() {
diff --git a/app/src/main/java/io/heckel/ntfy/up/BroadcastReceiver.kt b/app/src/main/java/io/heckel/ntfy/up/BroadcastReceiver.kt
index 46a0bcb10..a243d604d 100644
--- a/app/src/main/java/io/heckel/ntfy/up/BroadcastReceiver.kt
+++ b/app/src/main/java/io/heckel/ntfy/up/BroadcastReceiver.kt
@@ -34,6 +34,7 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
private fun register(context: Context, intent: Intent) {
val appId = intent.getStringExtra(EXTRA_APPLICATION) ?: return
val connectorToken = intent.getStringExtra(EXTRA_TOKEN) ?: return
+ val clientMessage = intent.getStringExtra(EXTRA_MESSAGE)
val app = context.applicationContext as Application
val repository = app.repository
val distributor = Distributor(app)
@@ -85,6 +86,7 @@ class BroadcastReceiver : android.content.BroadcastReceiver() {
upAppId = appId,
upConnectorToken = connectorToken,
displayName = null,
+ clientMessage = clientMessage,
totalCount = 0,
newCount = 0,
lastActive = Date().time/1000
diff --git a/app/src/main/java/io/heckel/ntfy/util/Util.kt b/app/src/main/java/io/heckel/ntfy/util/Util.kt
index 2ffbb7666..855cffd27 100644
--- a/app/src/main/java/io/heckel/ntfy/util/Util.kt
+++ b/app/src/main/java/io/heckel/ntfy/util/Util.kt
@@ -65,7 +65,11 @@ fun subscriptionTopicShortUrl(subscription: Subscription) : String {
}
fun displayName(subscription: Subscription) : String {
- return subscription.displayName ?: subscriptionTopicShortUrl(subscription)
+ if (!subscription.displayName.isNullOrBlank()) return subscription.displayName
+
+ if (!subscription.clientMessage.isNullOrBlank()) return subscription.clientMessage
+
+ return subscriptionTopicShortUrl(subscription)
}
fun shortUrl(url: String) = url
@@ -508,4 +512,3 @@ fun Button.dangerButton(context: Context) {
fun Long.nullIfZero(): Long? {
return if (this == 0L) return null else this
}
-