From 109a4f7e41e99f3c16eb7010f77de0ee9d1f2f6d Mon Sep 17 00:00:00 2001 From: Philipp Heckel Date: Tue, 11 Jan 2022 20:47:28 -0500 Subject: [PATCH] Add delete menu item --- .../main/java/io/heckel/ntfy/data/Database.kt | 1 + .../io/heckel/ntfy/msg/NotificationService.kt | 5 +++ .../java/io/heckel/ntfy/ui/DetailActivity.kt | 2 +- .../java/io/heckel/ntfy/ui/DetailAdapter.kt | 36 ++++++++++++++++--- .../main/res/menu/menu_detail_attachment.xml | 1 + app/src/main/res/values/strings.xml | 2 ++ 6 files changed, 41 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/io/heckel/ntfy/data/Database.kt b/app/src/main/java/io/heckel/ntfy/data/Database.kt index 90e0d9a..4023f4c 100644 --- a/app/src/main/java/io/heckel/ntfy/data/Database.kt +++ b/app/src/main/java/io/heckel/ntfy/data/Database.kt @@ -74,6 +74,7 @@ data class Attachment( const val PROGRESS_NONE = -1 const val PROGRESS_INDETERMINATE = -2 const val PROGRESS_FAILED = -3 +const val PROGRESS_DELETED = -4 const val PROGRESS_DONE = 100 @androidx.room.Database(entities = [Subscription::class, Notification::class], version = 6) diff --git a/app/src/main/java/io/heckel/ntfy/msg/NotificationService.kt b/app/src/main/java/io/heckel/ntfy/msg/NotificationService.kt index 9a1e92a..9e78ce2 100644 --- a/app/src/main/java/io/heckel/ntfy/msg/NotificationService.kt +++ b/app/src/main/java/io/heckel/ntfy/msg/NotificationService.kt @@ -7,14 +7,19 @@ import android.media.RingtoneManager import android.net.Uri import android.os.Build import android.util.Log +import android.widget.Toast import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import io.heckel.ntfy.R import io.heckel.ntfy.data.* import io.heckel.ntfy.data.Notification import io.heckel.ntfy.ui.DetailActivity +import io.heckel.ntfy.ui.DetailAdapter import io.heckel.ntfy.ui.MainActivity import io.heckel.ntfy.util.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch class NotificationService(val context: Context) { private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager 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 a9616f7..fe77540 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt @@ -111,7 +111,7 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra val onNotificationClick = { n: Notification -> onNotificationClick(n) } val onNotificationLongClick = { n: Notification -> onNotificationLongClick(n) } - adapter = DetailAdapter(this, onNotificationClick, onNotificationLongClick) + adapter = DetailAdapter(this, repository, onNotificationClick, onNotificationLongClick) mainList = findViewById(R.id.detail_notification_list) mainList.adapter = adapter diff --git a/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt b/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt index b1b283e..6008746 100644 --- a/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt +++ b/app/src/main/java/io/heckel/ntfy/ui/DetailAdapter.kt @@ -27,9 +27,12 @@ import io.heckel.ntfy.data.* import io.heckel.ntfy.msg.DownloadManager import io.heckel.ntfy.msg.DownloadWorker import io.heckel.ntfy.util.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import java.util.* -class DetailAdapter(private val activity: Activity, private val onClick: (Notification) -> Unit, private val onLongClick: (Notification) -> Unit) : +class DetailAdapter(private val activity: Activity, private val repository: Repository, private val onClick: (Notification) -> Unit, private val onLongClick: (Notification) -> Unit) : ListAdapter(TopicDiffCallback) { val selected = mutableSetOf() // Notification IDs @@ -37,7 +40,7 @@ class DetailAdapter(private val activity: Activity, private val onClick: (Notifi override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DetailViewHolder { val view = LayoutInflater.from(parent.context) .inflate(R.layout.fragment_detail_item, parent, false) - return DetailViewHolder(activity, view, selected, onClick, onLongClick) + return DetailViewHolder(activity, repository, view, selected, onClick, onLongClick) } /* Gets current topic and uses it to bind view. */ @@ -54,7 +57,7 @@ class DetailAdapter(private val activity: Activity, private val onClick: (Notifi } /* ViewHolder for Topic, takes in the inflated view and the onClick behavior. */ - class DetailViewHolder(private val activity: Activity, itemView: View, private val selected: Set, val onClick: (Notification) -> Unit, val onLongClick: (Notification) -> Unit) : + class DetailViewHolder(private val activity: Activity, private val repository: Repository, itemView: View, private val selected: Set, val onClick: (Notification) -> Unit, val onLongClick: (Notification) -> Unit) : RecyclerView.ViewHolder(itemView) { private var notification: Notification? = null private val priorityImageView: ImageView = itemView.findViewById(R.id.detail_item_priority_image) @@ -185,6 +188,7 @@ class DetailAdapter(private val activity: Activity, private val onClick: (Notifi val cancelItem = popup.menu.findItem(R.id.detail_item_menu_cancel) val openItem = popup.menu.findItem(R.id.detail_item_menu_open) val browseItem = popup.menu.findItem(R.id.detail_item_menu_browse) + val deleteItem = popup.menu.findItem(R.id.detail_item_menu_delete) val copyUrlItem = popup.menu.findItem(R.id.detail_item_menu_copy_url) val expired = attachment.expires != null && attachment.expires < System.currentTimeMillis()/1000 val inProgress = attachment.progress in 0..99 @@ -214,6 +218,27 @@ class DetailAdapter(private val activity: Activity, private val onClick: (Notifi context.startActivity(intent) true } + if (attachment.contentUri != null) { + deleteItem.setOnMenuItemClickListener { + try { + val contentUri = Uri.parse(attachment.contentUri) + val resolver = context.applicationContext.contentResolver + val deleted = resolver.delete(contentUri, null, null) > 0 + if (!deleted) throw Exception("no rows deleted") + val newAttachment = attachment.copy(progress = PROGRESS_DELETED) + val newNotification = notification.copy(attachment = newAttachment) + GlobalScope.launch(Dispatchers.IO) { + repository.updateNotification(newNotification) + } + } catch (e: Exception) { + Log.w(TAG, "Failed to update notification: ${e.message}", e) + Toast + .makeText(context, context.getString(R.string.detail_item_delete_failed, e.message), Toast.LENGTH_LONG) + .show() + } + true + } + } copyUrlItem.setOnMenuItemClickListener { val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clip = ClipData.newPlainText("attachment url", attachment.url) @@ -239,9 +264,10 @@ class DetailAdapter(private val activity: Activity, private val onClick: (Notifi openItem.isVisible = exists browseItem.isVisible = exists downloadItem.isVisible = !exists && !expired && !inProgress + deleteItem.isVisible = exists copyUrlItem.isVisible = !expired cancelItem.isVisible = inProgress - val noOptions = !openItem.isVisible && !browseItem.isVisible && !downloadItem.isVisible && !copyUrlItem.isVisible && !cancelItem.isVisible + val noOptions = !openItem.isVisible && !browseItem.isVisible && !downloadItem.isVisible && !copyUrlItem.isVisible && !cancelItem.isVisible && !deleteItem.isVisible if (noOptions) { return null } @@ -252,7 +278,7 @@ class DetailAdapter(private val activity: Activity, private val onClick: (Notifi val name = queryFilename(context, attachment.contentUri, attachment.name) val notYetDownloaded = !exists && attachment.progress == PROGRESS_NONE val downloading = !exists && attachment.progress in 0..99 - val deleted = !exists && attachment.progress == PROGRESS_DONE + val deleted = !exists && (attachment.progress == PROGRESS_DONE || attachment.progress == PROGRESS_DELETED) val failed = !exists && attachment.progress == PROGRESS_FAILED val expired = attachment.expires != null && attachment.expires < System.currentTimeMillis()/1000 val expires = attachment.expires != null && attachment.expires > System.currentTimeMillis()/1000 diff --git a/app/src/main/res/menu/menu_detail_attachment.xml b/app/src/main/res/menu/menu_detail_attachment.xml index e0c6fe0..8d623bb 100644 --- a/app/src/main/res/menu/menu_detail_attachment.xml +++ b/app/src/main/res/menu/menu_detail_attachment.xml @@ -4,5 +4,6 @@ + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1d84500..e6ed19d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -111,6 +111,7 @@ Tags: %1$s Open file Browse file + Delete file Download file Cancel download Copy URL @@ -118,6 +119,7 @@ Cannot open or download attachment. Link expired and no local file found. Cannot open attachment: %1$s Cannot open attachment: File may have been deleted, or there is no app to open the file. + Cannot delete attachment: %1$s Attachment download failed: %1$s not downloaded not downloaded, link expired