Actions
This commit is contained in:
parent
2d978fb4d6
commit
2f8be72c12
7 changed files with 78 additions and 4 deletions
|
@ -2,7 +2,7 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 9,
|
||||
"identityHash": "5bab75c3b41c53c9855fe3a7ef8f0669",
|
||||
"identityHash": "c1b4f54d1d3111dc5c8f02e8fa960ceb",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "Subscription",
|
||||
|
@ -82,7 +82,7 @@
|
|||
},
|
||||
{
|
||||
"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, `deleted` INTEGER NOT NULL, `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`))",
|
||||
"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, `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",
|
||||
|
@ -145,6 +145,12 @@
|
|||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "actions",
|
||||
"columnName": "actions",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deleted",
|
||||
"columnName": "deleted",
|
||||
|
@ -290,7 +296,7 @@
|
|||
"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, '5bab75c3b41c53c9855fe3a7ef8f0669')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c1b4f54d1d3111dc5c8f02e8fa960ceb')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -133,6 +133,7 @@ class Backuper(val context: Context) {
|
|||
priority = n.priority,
|
||||
tags = n.tags,
|
||||
click = n.click,
|
||||
actions = null, // FIXME
|
||||
attachment = attachment,
|
||||
deleted = n.deleted
|
||||
))
|
||||
|
|
|
@ -4,8 +4,10 @@ import android.content.Context
|
|||
import androidx.room.*
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import io.heckel.ntfy.util.shortUrl
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.lang.reflect.Type
|
||||
|
||||
@Entity(indices = [Index(value = ["baseUrl", "topic"], unique = true), Index(value = ["upConnectorToken"], unique = true)])
|
||||
data class Subscription(
|
||||
|
@ -55,6 +57,7 @@ data class Notification(
|
|||
@ColumnInfo(name = "priority", defaultValue = "3") val priority: Int, // 1=min, 3=default, 5=max
|
||||
@ColumnInfo(name = "tags") val tags: String,
|
||||
@ColumnInfo(name = "click") val click: String, // URL/intent to open on notification click
|
||||
@ColumnInfo(name = "actions") val actions: List<Action>?,
|
||||
@Embedded(prefix = "attachment_") val attachment: Attachment?,
|
||||
@ColumnInfo(name = "deleted") val deleted: Boolean,
|
||||
)
|
||||
|
@ -73,6 +76,28 @@ data class Attachment(
|
|||
this(name, type, size, expires, url, null, PROGRESS_NONE)
|
||||
}
|
||||
|
||||
@Entity
|
||||
data class Action(
|
||||
@ColumnInfo(name = "action") val action: String,
|
||||
@ColumnInfo(name = "label") val label: String,
|
||||
@ColumnInfo(name = "url") val url: String?,
|
||||
)
|
||||
|
||||
class Converters {
|
||||
private val gson = Gson()
|
||||
|
||||
@TypeConverter
|
||||
fun toActionList(value: String?): List<Action>? {
|
||||
val listType: Type = object : TypeToken<List<Action>?>() {}.type
|
||||
return gson.fromJson(value, listType)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromActionList(list: List<Action>?): String {
|
||||
return gson.toJson(list)
|
||||
}
|
||||
}
|
||||
|
||||
const val PROGRESS_NONE = -1
|
||||
const val PROGRESS_INDETERMINATE = -2
|
||||
const val PROGRESS_FAILED = -3
|
||||
|
@ -102,6 +127,7 @@ data class LogEntry(
|
|||
}
|
||||
|
||||
@androidx.room.Database(entities = [Subscription::class, Notification::class, User::class, LogEntry::class], version = 9)
|
||||
@TypeConverters(Converters::class)
|
||||
abstract class Database : RoomDatabase() {
|
||||
abstract fun subscriptionDao(): SubscriptionDao
|
||||
abstract fun notificationDao(): NotificationDao
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package io.heckel.ntfy.msg
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import io.heckel.ntfy.db.Action
|
||||
|
||||
/* This annotation ensures that proguard still works in production builds,
|
||||
* see https://stackoverflow.com/a/62753300/1440785 */
|
||||
|
@ -13,6 +14,7 @@ data class Message(
|
|||
val priority: Int?,
|
||||
val tags: List<String>?,
|
||||
val click: String?,
|
||||
val actions: List<MessageAction>?,
|
||||
val title: String?,
|
||||
val message: String,
|
||||
val encoding: String?,
|
||||
|
@ -28,4 +30,11 @@ data class MessageAttachment(
|
|||
val url: String,
|
||||
)
|
||||
|
||||
@Keep
|
||||
data class MessageAction(
|
||||
val action: String,
|
||||
val label: String,
|
||||
val url: String?,
|
||||
)
|
||||
|
||||
const val MESSAGE_ENCODING_BASE64 = "base64"
|
||||
|
|
|
@ -2,6 +2,7 @@ package io.heckel.ntfy.msg
|
|||
|
||||
import android.util.Base64
|
||||
import com.google.gson.Gson
|
||||
import io.heckel.ntfy.db.Action
|
||||
import io.heckel.ntfy.db.Attachment
|
||||
import io.heckel.ntfy.db.Notification
|
||||
import io.heckel.ntfy.util.joinTags
|
||||
|
@ -29,6 +30,11 @@ class NotificationParser {
|
|||
url = message.attachment.url,
|
||||
)
|
||||
} else null
|
||||
val actions = if (message.actions != null) {
|
||||
message.actions.map { action ->
|
||||
Action(action.action, action.label, action.url)
|
||||
}
|
||||
} else null
|
||||
val notification = Notification(
|
||||
id = message.id,
|
||||
subscriptionId = subscriptionId,
|
||||
|
@ -39,6 +45,7 @@ class NotificationParser {
|
|||
priority = toPriority(message.priority),
|
||||
tags = joinTags(message.tags),
|
||||
click = message.click ?: "",
|
||||
actions = actions,
|
||||
attachment = attachment,
|
||||
notificationId = notificationId,
|
||||
deleted = false
|
||||
|
|
|
@ -65,6 +65,7 @@ class NotificationService(val context: Context) {
|
|||
maybeAddBrowseAction(builder, notification)
|
||||
maybeAddDownloadAction(builder, notification)
|
||||
maybeAddCancelAction(builder, notification)
|
||||
maybeAddCustomActions(builder, notification)
|
||||
|
||||
maybeCreateNotificationChannel(notification.priority)
|
||||
notificationManager.notify(notification.notificationId, builder.build())
|
||||
|
@ -190,6 +191,29 @@ class NotificationService(val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
private fun maybeAddCustomActions(builder: NotificationCompat.Builder, notification: Notification) {
|
||||
notification.actions?.forEach { action ->
|
||||
when (action.action) {
|
||||
"view" -> maybeAddOpenUserAction(builder, notification, action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun maybeAddOpenUserAction(builder: NotificationCompat.Builder, notification: Notification, action: Action) {
|
||||
Log.d(TAG, "Adding user action $action")
|
||||
|
||||
val url = action.url ?: return
|
||||
try {
|
||||
val uri = Uri.parse(url)
|
||||
val intent = Intent(Intent.ACTION_VIEW, uri)
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
val pendingIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
|
||||
builder.addAction(NotificationCompat.Action.Builder(0, action.label, pendingIntent).build())
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Unable to add open user action", e)
|
||||
}
|
||||
}
|
||||
|
||||
class DownloadBroadcastReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val id = intent.getStringExtra("id") ?: return
|
||||
|
|
|
@ -131,6 +131,7 @@ class FirebaseService : FirebaseMessagingService() {
|
|||
priority = toPriority(priority),
|
||||
tags = tags ?: "",
|
||||
click = click ?: "",
|
||||
actions = null, // FIXME
|
||||
attachment = attachment,
|
||||
notificationId = Random.nextInt(),
|
||||
deleted = false
|
||||
|
|
Loading…
Reference in a new issue