Add delete menu item

This commit is contained in:
Philipp Heckel 2022-01-11 20:47:28 -05:00
parent 5a6d45d810
commit 109a4f7e41
6 changed files with 41 additions and 6 deletions

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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<Notification, DetailAdapter.DetailViewHolder>(TopicDiffCallback) {
val selected = mutableSetOf<String>() // 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<String>, val onClick: (Notification) -> Unit, val onLongClick: (Notification) -> Unit) :
class DetailViewHolder(private val activity: Activity, private val repository: Repository, itemView: View, private val selected: Set<String>, 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

View file

@ -4,5 +4,6 @@
<item android:id="@+id/detail_item_menu_cancel" android:title="@string/detail_item_menu_cancel"/>
<item android:id="@+id/detail_item_menu_open" android:title="@string/detail_item_menu_open"/>
<item android:id="@+id/detail_item_menu_browse" android:title="@string/detail_item_menu_browse"/>
<item android:id="@+id/detail_item_menu_delete" android:title="@string/detail_item_menu_delete"/>
<item android:id="@+id/detail_item_menu_copy_url" android:title="@string/detail_item_menu_copy_url"/>
</menu>

View file

@ -111,6 +111,7 @@
<string name="detail_item_tags">Tags: %1$s</string>
<string name="detail_item_menu_open">Open file</string>
<string name="detail_item_menu_browse">Browse file</string>
<string name="detail_item_menu_delete">Delete file</string>
<string name="detail_item_menu_download">Download file</string>
<string name="detail_item_menu_cancel">Cancel download</string>
<string name="detail_item_menu_copy_url">Copy URL</string>
@ -118,6 +119,7 @@
<string name="detail_item_cannot_download">Cannot open or download attachment. Link expired and no local file found.</string>
<string name="detail_item_cannot_open">Cannot open attachment: %1$s</string>
<string name="detail_item_cannot_open_not_found">Cannot open attachment: File may have been deleted, or there is no app to open the file.</string>
<string name="detail_item_delete_failed">Cannot delete attachment: %1$s</string>
<string name="detail_item_download_failed">Attachment download failed: %1$s</string>
<string name="detail_item_download_info_not_downloaded">not downloaded</string>
<string name="detail_item_download_info_not_downloaded_expired">not downloaded, link expired</string>