Loading app/src/main/java/io/heckel/ntfy/backup/Backuper.kt +56 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package io.heckel.ntfy.backup import android.content.Context import android.net.Uri import androidx.room.ColumnInfo import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.stream.JsonReader Loading Loading @@ -109,6 +110,25 @@ class Backuper(val context: Context) { } notifications.forEach { n -> try { val actions = if (n.actions != null) { n.actions.map { a -> io.heckel.ntfy.db.Action( id = a.id, action = a.action, label = a.label, url = a.url, method = a.method, headers = a.headers, body = a.body, intent = a.intent, extras = a.extras, progress = a.progress, error = a.error ) } } else { null } val attachment = if (n.attachment != null) { io.heckel.ntfy.db.Attachment( name = n.attachment.name, Loading @@ -133,7 +153,7 @@ class Backuper(val context: Context) { priority = n.priority, tags = n.tags, click = n.click, actions = null, // FIXME actions = actions, attachment = attachment, deleted = n.deleted )) Loading Loading @@ -202,6 +222,25 @@ class Backuper(val context: Context) { private suspend fun createNotificationList(): List<Notification> { return repository.getNotifications().map { n -> val actions = if (n.actions != null) { n.actions.map { a -> Action( id = a.id, action = a.action, label = a.label, url = a.url, method = a.method, headers = a.headers, body = a.body, intent = a.intent, extras = a.extras, progress = a.progress, error = a.error ) } } else { null } val attachment = if (n.attachment != null) { Attachment( name = n.attachment.name, Loading @@ -225,6 +264,7 @@ class Backuper(val context: Context) { priority = n.priority, tags = n.tags, click = n.click, actions = actions, attachment = attachment, deleted = n.deleted ) Loading Loading @@ -291,10 +331,25 @@ data class Notification( val priority: Int, // 1=min, 3=default, 5=max val tags: String, val click: String, // URL/intent to open on notification click val actions: List<Action>?, val attachment: Attachment?, val deleted: Boolean ) data class Action( val id: String, // Synthetic ID to identify result, and easily pass via Broadcast and WorkManager val action: String, // "view", "http" or "broadcast" val label: String, val url: String?, // used in "view" and "http" actions val method: String?, // used in "http" action val headers: Map<String,String>?, // used in "http" action val body: String?, // used in "http" action val intent: String?, // used in "broadcast" action val extras: Map<String,String>?, // used in "broadcast" action val progress: Int?, // used to indicate progress in popup val error: String? // used to indicate errors in popup ) data class Attachment( val name: String, // Filename val type: String?, // MIME type Loading @@ -305,7 +360,6 @@ data class Attachment( val progress: Int, // Progress during download, -1 if not downloaded ) data class User( val baseUrl: String, val username: String, Loading app/src/main/java/io/heckel/ntfy/db/Database.kt +1 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ data class Action( @ColumnInfo(name = "method") val method: String?, // used in "http" action @ColumnInfo(name = "headers") val headers: Map<String,String>?, // used in "http" action @ColumnInfo(name = "body") val body: String?, // used in "http" action @ColumnInfo(name = "intent") val intent: String?, // used in "broadcast" action @ColumnInfo(name = "extras") val extras: Map<String,String>?, // used in "broadcast" action @ColumnInfo(name = "progress") val progress: Int?, // used to indicate progress in popup @ColumnInfo(name = "error") val error: String?, // used to indicate errors in popup Loading app/src/main/java/io/heckel/ntfy/msg/BroadcastService.kt +3 −3 Original line number Diff line number Diff line Loading @@ -34,17 +34,17 @@ class BroadcastService(private val ctx: Context) { intent.putExtra("muted", muted) intent.putExtra("muted_str", muted.toString()) Log.d(TAG, "Sending message intent broadcast: $intent") Log.d(TAG, "Sending message intent broadcast: ${intent.action} with extras ${intent.extras}") ctx.sendBroadcast(intent) } fun sendUserAction(action: Action) { val intent = Intent() intent.action = USER_ACTION_ACTION intent.action = action.intent ?: USER_ACTION_ACTION action.extras?.forEach { (key, value) -> intent.putExtra(key, value) } Log.d(TAG, "Sending user action intent broadcast: $intent") Log.d(TAG, "Sending user action intent broadcast: ${intent.action} with extras ${intent.extras}") ctx.sendBroadcast(intent) } Loading app/src/main/java/io/heckel/ntfy/msg/Message.kt +6 −5 Original line number Diff line number Diff line Loading @@ -35,11 +35,12 @@ data class MessageAction( val id: String, val action: String, val label: String, // "view", "broadcast" or "http" val url: String?, // used in "view" and "http" val method: String?, // used in "http", default is POST (!) val headers: Map<String,String>?, // used in "http" val body: String?, // used in "http" val extras: Map<String,String>?, // used in "broadcast" val url: String?, // used in "view" and "http" actions val method: String?, // used in "http" action, default is POST (!) val headers: Map<String,String>?, // used in "http" action val body: String?, // used in "http" action val intent: String?, // used in "broadcast" action val extras: Map<String,String>?, // used in "broadcast" action ) const val MESSAGE_ENCODING_BASE64 = "base64" app/src/main/java/io/heckel/ntfy/msg/NotificationParser.kt +15 −3 Original line number Diff line number Diff line package io.heckel.ntfy.msg import android.util.Base64 import com.google.gson.Gson import com.google.gson.reflect.TypeToken import io.heckel.ntfy.db.Action import io.heckel.ntfy.db.Attachment import io.heckel.ntfy.db.Notification import io.heckel.ntfy.util.joinTags import io.heckel.ntfy.util.randomString import io.heckel.ntfy.util.toPriority import java.lang.reflect.Type class NotificationParser { private val gson = Gson() Loading @@ -33,7 +33,7 @@ class NotificationParser { } else null val actions = if (message.actions != null) { message.actions.map { a -> Action(a.id, a.action, a.label, a.url, a.method, a.headers, a.body, a.extras, null, null) Action(a.id, a.action, a.label, a.url, a.method, a.headers, a.body, a.intent, a.extras, null, null) } } else null val notification = Notification( Loading @@ -54,5 +54,17 @@ class NotificationParser { return NotificationWithTopic(message.topic, notification) } /** * Parse JSON array to Action list. The indirection via MessageAction is probably * not necessary, but for "good form". */ fun parseActions(s: String?): List<Action>? { val listType: Type = object : TypeToken<List<MessageAction>?>() {}.type val messageActions: List<MessageAction>? = gson.fromJson(s, listType) return messageActions?.map { a -> Action(a.id, a.action, a.label, a.url, a.method, a.headers, a.body, a.intent, a.extras, null, null) } } data class NotificationWithTopic(val topic: String, val notification: Notification) } Loading
app/src/main/java/io/heckel/ntfy/backup/Backuper.kt +56 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package io.heckel.ntfy.backup import android.content.Context import android.net.Uri import androidx.room.ColumnInfo import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.stream.JsonReader Loading Loading @@ -109,6 +110,25 @@ class Backuper(val context: Context) { } notifications.forEach { n -> try { val actions = if (n.actions != null) { n.actions.map { a -> io.heckel.ntfy.db.Action( id = a.id, action = a.action, label = a.label, url = a.url, method = a.method, headers = a.headers, body = a.body, intent = a.intent, extras = a.extras, progress = a.progress, error = a.error ) } } else { null } val attachment = if (n.attachment != null) { io.heckel.ntfy.db.Attachment( name = n.attachment.name, Loading @@ -133,7 +153,7 @@ class Backuper(val context: Context) { priority = n.priority, tags = n.tags, click = n.click, actions = null, // FIXME actions = actions, attachment = attachment, deleted = n.deleted )) Loading Loading @@ -202,6 +222,25 @@ class Backuper(val context: Context) { private suspend fun createNotificationList(): List<Notification> { return repository.getNotifications().map { n -> val actions = if (n.actions != null) { n.actions.map { a -> Action( id = a.id, action = a.action, label = a.label, url = a.url, method = a.method, headers = a.headers, body = a.body, intent = a.intent, extras = a.extras, progress = a.progress, error = a.error ) } } else { null } val attachment = if (n.attachment != null) { Attachment( name = n.attachment.name, Loading @@ -225,6 +264,7 @@ class Backuper(val context: Context) { priority = n.priority, tags = n.tags, click = n.click, actions = actions, attachment = attachment, deleted = n.deleted ) Loading Loading @@ -291,10 +331,25 @@ data class Notification( val priority: Int, // 1=min, 3=default, 5=max val tags: String, val click: String, // URL/intent to open on notification click val actions: List<Action>?, val attachment: Attachment?, val deleted: Boolean ) data class Action( val id: String, // Synthetic ID to identify result, and easily pass via Broadcast and WorkManager val action: String, // "view", "http" or "broadcast" val label: String, val url: String?, // used in "view" and "http" actions val method: String?, // used in "http" action val headers: Map<String,String>?, // used in "http" action val body: String?, // used in "http" action val intent: String?, // used in "broadcast" action val extras: Map<String,String>?, // used in "broadcast" action val progress: Int?, // used to indicate progress in popup val error: String? // used to indicate errors in popup ) data class Attachment( val name: String, // Filename val type: String?, // MIME type Loading @@ -305,7 +360,6 @@ data class Attachment( val progress: Int, // Progress during download, -1 if not downloaded ) data class User( val baseUrl: String, val username: String, Loading
app/src/main/java/io/heckel/ntfy/db/Database.kt +1 −0 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ data class Action( @ColumnInfo(name = "method") val method: String?, // used in "http" action @ColumnInfo(name = "headers") val headers: Map<String,String>?, // used in "http" action @ColumnInfo(name = "body") val body: String?, // used in "http" action @ColumnInfo(name = "intent") val intent: String?, // used in "broadcast" action @ColumnInfo(name = "extras") val extras: Map<String,String>?, // used in "broadcast" action @ColumnInfo(name = "progress") val progress: Int?, // used to indicate progress in popup @ColumnInfo(name = "error") val error: String?, // used to indicate errors in popup Loading
app/src/main/java/io/heckel/ntfy/msg/BroadcastService.kt +3 −3 Original line number Diff line number Diff line Loading @@ -34,17 +34,17 @@ class BroadcastService(private val ctx: Context) { intent.putExtra("muted", muted) intent.putExtra("muted_str", muted.toString()) Log.d(TAG, "Sending message intent broadcast: $intent") Log.d(TAG, "Sending message intent broadcast: ${intent.action} with extras ${intent.extras}") ctx.sendBroadcast(intent) } fun sendUserAction(action: Action) { val intent = Intent() intent.action = USER_ACTION_ACTION intent.action = action.intent ?: USER_ACTION_ACTION action.extras?.forEach { (key, value) -> intent.putExtra(key, value) } Log.d(TAG, "Sending user action intent broadcast: $intent") Log.d(TAG, "Sending user action intent broadcast: ${intent.action} with extras ${intent.extras}") ctx.sendBroadcast(intent) } Loading
app/src/main/java/io/heckel/ntfy/msg/Message.kt +6 −5 Original line number Diff line number Diff line Loading @@ -35,11 +35,12 @@ data class MessageAction( val id: String, val action: String, val label: String, // "view", "broadcast" or "http" val url: String?, // used in "view" and "http" val method: String?, // used in "http", default is POST (!) val headers: Map<String,String>?, // used in "http" val body: String?, // used in "http" val extras: Map<String,String>?, // used in "broadcast" val url: String?, // used in "view" and "http" actions val method: String?, // used in "http" action, default is POST (!) val headers: Map<String,String>?, // used in "http" action val body: String?, // used in "http" action val intent: String?, // used in "broadcast" action val extras: Map<String,String>?, // used in "broadcast" action ) const val MESSAGE_ENCODING_BASE64 = "base64"
app/src/main/java/io/heckel/ntfy/msg/NotificationParser.kt +15 −3 Original line number Diff line number Diff line package io.heckel.ntfy.msg import android.util.Base64 import com.google.gson.Gson import com.google.gson.reflect.TypeToken import io.heckel.ntfy.db.Action import io.heckel.ntfy.db.Attachment import io.heckel.ntfy.db.Notification import io.heckel.ntfy.util.joinTags import io.heckel.ntfy.util.randomString import io.heckel.ntfy.util.toPriority import java.lang.reflect.Type class NotificationParser { private val gson = Gson() Loading @@ -33,7 +33,7 @@ class NotificationParser { } else null val actions = if (message.actions != null) { message.actions.map { a -> Action(a.id, a.action, a.label, a.url, a.method, a.headers, a.body, a.extras, null, null) Action(a.id, a.action, a.label, a.url, a.method, a.headers, a.body, a.intent, a.extras, null, null) } } else null val notification = Notification( Loading @@ -54,5 +54,17 @@ class NotificationParser { return NotificationWithTopic(message.topic, notification) } /** * Parse JSON array to Action list. The indirection via MessageAction is probably * not necessary, but for "good form". */ fun parseActions(s: String?): List<Action>? { val listType: Type = object : TypeToken<List<MessageAction>?>() {}.type val messageActions: List<MessageAction>? = gson.fromJson(s, listType) return messageActions?.map { a -> Action(a.id, a.action, a.label, a.url, a.method, a.headers, a.body, a.intent, a.extras, null, null) } } data class NotificationWithTopic(val topic: String, val notification: Notification) }