Add delete menu item
This commit is contained in:
parent
5a6d45d810
commit
109a4f7e41
6 changed files with 41 additions and 6 deletions
app/src/main
java/io/heckel/ntfy
res
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in a new issue