Schedule attachment download in dispatcher, not in NotificationService
This commit is contained in:
parent
be750b603b
commit
d440d0a633
7 changed files with 161 additions and 112 deletions
|
@ -2,7 +2,7 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 6,
|
||||
"identityHash": "6fd36c6995d3ae734f4ba7c8beaf9a95",
|
||||
"identityHash": "1ab02dd84a7f2655b4fc651574b24240",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "Subscription",
|
||||
|
@ -80,7 +80,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, `notificationId` INTEGER NOT NULL, `priority` INTEGER NOT NULL DEFAULT 3, `tags` TEXT NOT NULL, `click` TEXT NOT NULL, `attachmentName` TEXT, `attachmentType` TEXT, `attachmentSize` INTEGER, `attachmentExpires` INTEGER, `attachmentPreviewUrl` TEXT, `attachmentUrl` TEXT, `attachmentContentUri` TEXT, `deleted` INTEGER NOT NULL, 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, `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_previewUrl` TEXT, `attachment_url` TEXT, `attachment_contentUri` TEXT, `attachment_previewFile` TEXT, `attachment_progress` INTEGER, PRIMARY KEY(`id`, `subscriptionId`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
|
@ -137,53 +137,65 @@
|
|||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachmentName",
|
||||
"columnName": "attachmentName",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachmentType",
|
||||
"columnName": "attachmentType",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachmentSize",
|
||||
"columnName": "attachmentSize",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachmentExpires",
|
||||
"columnName": "attachmentExpires",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachmentPreviewUrl",
|
||||
"columnName": "attachmentPreviewUrl",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachmentUrl",
|
||||
"columnName": "attachmentUrl",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachmentContentUri",
|
||||
"columnName": "attachmentContentUri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "deleted",
|
||||
"columnName": "deleted",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"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.previewUrl",
|
||||
"columnName": "attachment_previewUrl",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachment.url",
|
||||
"columnName": "attachment_url",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachment.contentUri",
|
||||
"columnName": "attachment_contentUri",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachment.previewFile",
|
||||
"columnName": "attachment_previewFile",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "attachment.progress",
|
||||
"columnName": "attachment_progress",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
|
@ -200,7 +212,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, '6fd36c6995d3ae734f4ba7c8beaf9a95')"
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1ab02dd84a7f2655b4fc651574b24240')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ data class Subscription(
|
|||
@ColumnInfo(name = "mutedUntil") val mutedUntil: Long, // TODO notificationSound, notificationSchedule
|
||||
@ColumnInfo(name = "upAppId") val upAppId: String?, // UnifiedPush application package name
|
||||
@ColumnInfo(name = "upConnectorToken") val upConnectorToken: String?, // UnifiedPush connector token
|
||||
// TODO autoDownloadAttachments, minPriority
|
||||
@Ignore val totalCount: Int = 0, // Total notifications
|
||||
@Ignore val newCount: Int = 0, // New notifications
|
||||
@Ignore val lastActive: Long = 0, // Unix timestamp
|
||||
|
@ -52,16 +53,26 @@ 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 = "attachmentName") val attachmentName: String?, // Filename
|
||||
@ColumnInfo(name = "attachmentType") val attachmentType: String?, // MIME type
|
||||
@ColumnInfo(name = "attachmentSize") val attachmentSize: Long?, // Size in bytes
|
||||
@ColumnInfo(name = "attachmentExpires") val attachmentExpires: Long?, // Unix timestamp
|
||||
@ColumnInfo(name = "attachmentPreviewUrl") val attachmentPreviewUrl: String?,
|
||||
@ColumnInfo(name = "attachmentUrl") val attachmentUrl: String?,
|
||||
@ColumnInfo(name = "attachmentContentUri") val attachmentContentUri: String?,
|
||||
@Embedded(prefix = "attachment_") val attachment: Attachment?,
|
||||
@ColumnInfo(name = "deleted") val deleted: Boolean,
|
||||
)
|
||||
|
||||
@Entity
|
||||
data class Attachment(
|
||||
@ColumnInfo(name = "name") val name: String?, // Filename
|
||||
@ColumnInfo(name = "type") val type: String?, // MIME type
|
||||
@ColumnInfo(name = "size") val size: Long?, // Size in bytes
|
||||
@ColumnInfo(name = "expires") val expires: Long?, // Unix timestamp
|
||||
@ColumnInfo(name = "previewUrl") val previewUrl: String?,
|
||||
@ColumnInfo(name = "url") val url: String,
|
||||
@ColumnInfo(name = "contentUri") val contentUri: String?,
|
||||
@ColumnInfo(name = "previewFile") val previewFile: String?,
|
||||
@ColumnInfo(name = "progress") val progress: Int,
|
||||
) {
|
||||
constructor(name: String?, type: String?, size: Long?, expires: Long?, previewUrl: String?, url: String) :
|
||||
this(name, type, size, expires, previewUrl, url, null, null, 0)
|
||||
}
|
||||
|
||||
@androidx.room.Database(entities = [Subscription::class, Notification::class], version = 6)
|
||||
abstract class Database : RoomDatabase() {
|
||||
abstract fun subscriptionDao(): SubscriptionDao
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.util.Log
|
|||
import androidx.annotation.Keep
|
||||
import com.google.gson.Gson
|
||||
import io.heckel.ntfy.BuildConfig
|
||||
import io.heckel.ntfy.data.Attachment
|
||||
import io.heckel.ntfy.data.Notification
|
||||
import io.heckel.ntfy.util.topicUrl
|
||||
import io.heckel.ntfy.util.topicUrlJson
|
||||
|
@ -112,6 +113,16 @@ class ApiService {
|
|||
val message = gson.fromJson(line, Message::class.java)
|
||||
if (message.event == EVENT_MESSAGE) {
|
||||
val topic = message.topic
|
||||
val attachment = if (message.attachment?.url != null) {
|
||||
Attachment(
|
||||
name = message.attachment.name,
|
||||
type = message.attachment.type,
|
||||
size = message.attachment.size,
|
||||
expires = message.attachment.expires,
|
||||
previewUrl = message.attachment.preview_url,
|
||||
url = message.attachment.url,
|
||||
)
|
||||
} else null
|
||||
val notification = Notification(
|
||||
id = message.id,
|
||||
subscriptionId = 0, // TO BE SET downstream
|
||||
|
@ -121,13 +132,7 @@ class ApiService {
|
|||
priority = toPriority(message.priority),
|
||||
tags = joinTags(message.tags),
|
||||
click = message.click ?: "",
|
||||
attachmentName = message.attachment?.name,
|
||||
attachmentType = message.attachment?.type,
|
||||
attachmentSize = message.attachment?.size,
|
||||
attachmentExpires = message.attachment?.expires,
|
||||
attachmentPreviewUrl = message.attachment?.preview_url,
|
||||
attachmentUrl = message.attachment?.url,
|
||||
attachmentContentUri = null,
|
||||
attachment = attachment,
|
||||
notificationId = Random.nextInt(),
|
||||
deleted = false
|
||||
)
|
||||
|
@ -149,6 +154,16 @@ class ApiService {
|
|||
|
||||
private fun fromString(subscriptionId: Long, s: String): Notification {
|
||||
val message = gson.fromJson(s, Message::class.java)
|
||||
val attachment = if (message.attachment?.url != null) {
|
||||
Attachment(
|
||||
name = message.attachment.name,
|
||||
type = message.attachment.type,
|
||||
size = message.attachment.size,
|
||||
expires = message.attachment.expires,
|
||||
previewUrl = message.attachment.preview_url,
|
||||
url = message.attachment.url,
|
||||
)
|
||||
} else null
|
||||
return Notification(
|
||||
id = message.id,
|
||||
subscriptionId = subscriptionId,
|
||||
|
@ -158,14 +173,8 @@ class ApiService {
|
|||
priority = toPriority(message.priority),
|
||||
tags = joinTags(message.tags),
|
||||
click = message.click ?: "",
|
||||
attachmentName = message.attachment?.name,
|
||||
attachmentType = message.attachment?.type,
|
||||
attachmentSize = message.attachment?.size,
|
||||
attachmentExpires = message.attachment?.expires,
|
||||
attachmentPreviewUrl = message.attachment?.preview_url,
|
||||
attachmentUrl = message.attachment?.url,
|
||||
attachmentContentUri = null,
|
||||
notificationId = 0,
|
||||
attachment = attachment,
|
||||
notificationId = 0, // zero!
|
||||
deleted = false
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.util.Log
|
|||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import io.heckel.ntfy.app.Application
|
||||
import io.heckel.ntfy.data.Attachment
|
||||
import io.heckel.ntfy.data.Notification
|
||||
import io.heckel.ntfy.data.Repository
|
||||
import io.heckel.ntfy.data.Subscription
|
||||
|
@ -34,15 +35,16 @@ class AttachmentDownloadWorker(private val context: Context, params: WorkerParam
|
|||
val repository = app.repository
|
||||
val notification = repository.getNotification(notificationId) ?: return Result.failure()
|
||||
val subscription = repository.getSubscription(notification.subscriptionId) ?: return Result.failure()
|
||||
if (notification.attachmentPreviewUrl != null) {
|
||||
downloadPreview(repository, subscription, notification)
|
||||
val attachment = notification.attachment ?: return Result.failure()
|
||||
if (attachment.previewUrl != null) {
|
||||
downloadPreview(subscription, notification, attachment)
|
||||
}
|
||||
downloadAttachment(repository, subscription, notification)
|
||||
downloadAttachment(repository, subscription, notification, attachment)
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
private fun downloadPreview(repository: Repository, subscription: Subscription, notification: Notification) {
|
||||
val url = notification.attachmentPreviewUrl ?: return
|
||||
private fun downloadPreview(subscription: Subscription, notification: Notification, attachment: Attachment) {
|
||||
val url = attachment.previewUrl ?: return
|
||||
Log.d(TAG, "Downloading preview from $url")
|
||||
|
||||
val request = Request.Builder()
|
||||
|
@ -63,21 +65,20 @@ class AttachmentDownloadWorker(private val context: Context, params: WorkerParam
|
|||
}
|
||||
}
|
||||
|
||||
private fun downloadAttachment(repository: Repository, subscription: Subscription, notification: Notification) {
|
||||
val url = notification.attachmentUrl ?: return
|
||||
Log.d(TAG, "Downloading attachment from $url")
|
||||
private fun downloadAttachment(repository: Repository, subscription: Subscription, notification: Notification, attachment: Attachment) {
|
||||
Log.d(TAG, "Downloading attachment from ${attachment.url}")
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(url)
|
||||
.url(attachment.url)
|
||||
.addHeader("User-Agent", ApiService.USER_AGENT)
|
||||
.build()
|
||||
client.newCall(request).execute().use { response ->
|
||||
if (!response.isSuccessful || response.body == null) {
|
||||
throw Exception("Attachment download failed: ${response.code}")
|
||||
}
|
||||
val name = notification.attachmentName ?: "attachment.bin"
|
||||
val mimeType = notification.attachmentType ?: "application/octet-stream"
|
||||
val size = notification.attachmentSize ?: 0
|
||||
val name = attachment.name ?: "attachment.bin"
|
||||
val mimeType = attachment.type ?: "application/octet-stream"
|
||||
val size = attachment.size ?: 0
|
||||
val resolver = applicationContext.contentResolver
|
||||
val details = ContentValues().apply {
|
||||
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
|
||||
|
@ -107,7 +108,8 @@ class AttachmentDownloadWorker(private val context: Context, params: WorkerParam
|
|||
}
|
||||
}
|
||||
Log.d(TAG, "Attachment download: successful response, proceeding with download")
|
||||
val newNotification = notification.copy(attachmentContentUri = uri.toString())
|
||||
val newAttachment = attachment.copy(contentUri = uri.toString())
|
||||
val newNotification = notification.copy(attachment = newAttachment)
|
||||
repository.updateNotification(newNotification)
|
||||
notifier.update(subscription, newNotification)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package io.heckel.ntfy.msg
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.workDataOf
|
||||
import io.heckel.ntfy.data.Notification
|
||||
import io.heckel.ntfy.data.Repository
|
||||
import io.heckel.ntfy.data.Subscription
|
||||
|
@ -25,6 +29,7 @@ class NotificationDispatcher(val context: Context, val repository: Repository) {
|
|||
val notify = shouldNotify(subscription, notification, muted)
|
||||
val broadcast = shouldBroadcast(subscription)
|
||||
val distribute = shouldDistribute(subscription)
|
||||
val download = shouldDownload(subscription, notification)
|
||||
if (notify) {
|
||||
notifier.display(subscription, notification)
|
||||
}
|
||||
|
@ -36,6 +41,16 @@ class NotificationDispatcher(val context: Context, val repository: Repository) {
|
|||
distributor.sendMessage(appId, connectorToken, notification.message)
|
||||
}
|
||||
}
|
||||
if (download) {
|
||||
// Download attachment (+ preview if available) in the background via WorkManager
|
||||
// The indirection via WorkManager is required since this code may be executed
|
||||
// in a doze state and Internet may not be available. It's also best practice apparently.
|
||||
scheduleAttachmentDownload(notification)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldDownload(subscription: Subscription, notification: Notification): Boolean {
|
||||
return notification.attachment != null
|
||||
}
|
||||
|
||||
private fun shouldNotify(subscription: Subscription, notification: Notification, muted: Boolean): Boolean {
|
||||
|
@ -67,4 +82,19 @@ class NotificationDispatcher(val context: Context, val repository: Repository) {
|
|||
}
|
||||
return subscription.mutedUntil == 1L || (subscription.mutedUntil > 1L && subscription.mutedUntil > System.currentTimeMillis()/1000)
|
||||
}
|
||||
|
||||
private fun scheduleAttachmentDownload(notification: Notification) {
|
||||
Log.d(TAG, "Enqueuing work to download attachment (+ preview if available)")
|
||||
val workManager = WorkManager.getInstance(context)
|
||||
val workRequest = OneTimeWorkRequest.Builder(AttachmentDownloadWorker::class.java)
|
||||
.setInputData(workDataOf(
|
||||
"id" to notification.id,
|
||||
))
|
||||
.build()
|
||||
workManager.enqueue(workRequest)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "NtfyNotifDispatch"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,16 +32,7 @@ class NotificationService(val context: Context) {
|
|||
|
||||
fun display(subscription: Subscription, notification: Notification) {
|
||||
Log.d(TAG, "Displaying notification $notification")
|
||||
|
||||
// Display notification immediately
|
||||
displayInternal(subscription, notification)
|
||||
|
||||
// Download attachment (+ preview if available) in the background via WorkManager
|
||||
// The indirection via WorkManager is required since this code may be executed
|
||||
// in a doze state and Internet may not be available. It's also best practice apparently.
|
||||
if (notification.attachmentUrl != null) {
|
||||
scheduleAttachmentDownload(subscription, notification)
|
||||
}
|
||||
}
|
||||
|
||||
fun update(subscription: Subscription, notification: Notification, progress: Int = PROGRESS_NONE) {
|
||||
|
@ -133,32 +124,21 @@ class NotificationService(val context: Context) {
|
|||
}
|
||||
|
||||
private fun maybeAddOpenAction(notificationBuilder: NotificationCompat.Builder, notification: Notification) {
|
||||
if (notification.attachmentContentUri != null) {
|
||||
val contentUri = Uri.parse(notification.attachmentContentUri)
|
||||
if (notification.attachment?.contentUri != null) {
|
||||
val contentUri = Uri.parse(notification.attachment.contentUri)
|
||||
val openIntent = PendingIntent.getActivity(context, 0, Intent(Intent.ACTION_VIEW, contentUri), 0)
|
||||
notificationBuilder.addAction(NotificationCompat.Action.Builder(0, "Open", openIntent).build())
|
||||
}
|
||||
}
|
||||
|
||||
private fun maybeAddCopyUrlAction(builder: NotificationCompat.Builder, notification: Notification) {
|
||||
if (notification.attachmentUrl != null) {
|
||||
if (notification.attachment?.url != null) {
|
||||
// XXXXXXXXx
|
||||
val copyUrlIntent = PendingIntent.getActivity(context, 0, Intent(Intent.ACTION_VIEW, Uri.parse(notification.attachmentUrl)), 0)
|
||||
val copyUrlIntent = PendingIntent.getActivity(context, 0, Intent(Intent.ACTION_VIEW, Uri.parse(notification.attachment.url)), 0)
|
||||
builder.addAction(NotificationCompat.Action.Builder(0, "Copy URL", copyUrlIntent).build())
|
||||
}
|
||||
}
|
||||
|
||||
private fun scheduleAttachmentDownload(subscription: Subscription, notification: Notification) {
|
||||
Log.d(TAG, "Enqueuing work to download attachment (+ preview if available)")
|
||||
val workManager = WorkManager.getInstance(context)
|
||||
val workRequest = OneTimeWorkRequest.Builder(AttachmentDownloadWorker::class.java)
|
||||
.setInputData(workDataOf(
|
||||
"id" to notification.id,
|
||||
))
|
||||
.build()
|
||||
workManager.enqueue(workRequest)
|
||||
}
|
||||
|
||||
private fun detailActivityIntent(subscription: Subscription): PendingIntent? {
|
||||
val intent = Intent(context, DetailActivity::class.java)
|
||||
intent.putExtra(MainActivity.EXTRA_SUBSCRIPTION_ID, subscription.id)
|
||||
|
@ -223,7 +203,7 @@ class NotificationService(val context: Context) {
|
|||
const val PROGRESS_NONE = -1
|
||||
const val PROGRESS_INDETERMINATE = -2
|
||||
|
||||
private const val TAG = "NtfyNotificationService"
|
||||
private const val TAG = "NtfyNotifService"
|
||||
private const val CHANNEL_ID_MIN = "ntfy-min"
|
||||
private const val CHANNEL_ID_LOW = "ntfy-low"
|
||||
private const val CHANNEL_ID_DEFAULT = "ntfy"
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.google.firebase.messaging.FirebaseMessagingService
|
|||
import com.google.firebase.messaging.RemoteMessage
|
||||
import io.heckel.ntfy.R
|
||||
import io.heckel.ntfy.app.Application
|
||||
import io.heckel.ntfy.data.Attachment
|
||||
import io.heckel.ntfy.data.Notification
|
||||
import io.heckel.ntfy.msg.*
|
||||
import io.heckel.ntfy.service.SubscriberService
|
||||
|
@ -81,6 +82,16 @@ class FirebaseService : FirebaseMessagingService() {
|
|||
}
|
||||
|
||||
// Add notification
|
||||
val attachment = if (attachmentUrl != null) {
|
||||
Attachment(
|
||||
name = attachmentName,
|
||||
type = attachmentType,
|
||||
size = attachmentSize,
|
||||
expires = attachmentExpires,
|
||||
previewUrl = attachmentPreviewUrl,
|
||||
url = attachmentUrl,
|
||||
)
|
||||
} else null
|
||||
val notification = Notification(
|
||||
id = id,
|
||||
subscriptionId = subscription.id,
|
||||
|
@ -90,13 +101,7 @@ class FirebaseService : FirebaseMessagingService() {
|
|||
priority = toPriority(priority),
|
||||
tags = tags ?: "",
|
||||
click = click ?: "",
|
||||
attachmentName = attachmentName,
|
||||
attachmentType = attachmentType,
|
||||
attachmentSize = attachmentSize,
|
||||
attachmentExpires = attachmentExpires,
|
||||
attachmentPreviewUrl = attachmentPreviewUrl,
|
||||
attachmentUrl = attachmentUrl,
|
||||
attachmentContentUri = null,
|
||||
attachment = attachment,
|
||||
notificationId = Random.nextInt(),
|
||||
deleted = false
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue