Swipe to delete

This commit is contained in:
Philipp Heckel 2022-02-05 21:02:05 -05:00
parent 3b1b1a82ae
commit 90848fde95
5 changed files with 39 additions and 3 deletions

View file

@ -297,6 +297,9 @@ interface NotificationDao {
@Query("UPDATE notification SET deleted = 1 WHERE subscriptionId = :subscriptionId") @Query("UPDATE notification SET deleted = 1 WHERE subscriptionId = :subscriptionId")
fun markAllAsDeleted(subscriptionId: Long) fun markAllAsDeleted(subscriptionId: Long)
@Query("UPDATE notification SET deleted = 0 WHERE id = :notificationId")
fun undelete(notificationId: String)
@Query("DELETE FROM notification WHERE subscriptionId = :subscriptionId") @Query("DELETE FROM notification WHERE subscriptionId = :subscriptionId")
fun removeAll(subscriptionId: Long) fun removeAll(subscriptionId: Long)
} }

View file

@ -116,12 +116,14 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
notificationDao.update(notification) notificationDao.update(notification)
} }
@Suppress("RedundantSuspendModifier") fun markAsDeleted(notificationId: String) {
@WorkerThread
suspend fun markAsDeleted(notificationId: String) {
notificationDao.markAsDeleted(notificationId) notificationDao.markAsDeleted(notificationId)
} }
fun undeleteNotification(notificationId: String) {
notificationDao.undelete(notificationId)
}
fun markAllAsDeleted(subscriptionId: Long) { fun markAllAsDeleted(subscriptionId: Long) {
notificationDao.markAllAsDeleted(subscriptionId) notificationDao.markAllAsDeleted(subscriptionId)
} }

View file

@ -17,8 +17,10 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.snackbar.Snackbar
import io.heckel.ntfy.BuildConfig import io.heckel.ntfy.BuildConfig
import io.heckel.ntfy.R import io.heckel.ntfy.R
import io.heckel.ntfy.app.Application import io.heckel.ntfy.app.Application
@ -34,6 +36,7 @@ import kotlinx.coroutines.*
import java.util.* import java.util.*
import kotlin.random.Random import kotlin.random.Random
class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFragment.NotificationSettingsListener { class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFragment.NotificationSettingsListener {
private val viewModel by viewModels<DetailViewModel> { private val viewModel by viewModels<DetailViewModel> {
DetailViewModelFactory((application as Application).repository) DetailViewModelFactory((application as Application).repository)
@ -131,6 +134,28 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
} }
} }
// Swipe to remove
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
return false
}
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) {
val notification = adapter.get(viewHolder.absoluteAdapterPosition)
lifecycleScope.launch(Dispatchers.IO) {
repository.markAsDeleted(notification.id)
}
val snackbar = Snackbar.make(mainList, R.string.detail_item_snack_deleted, Snackbar.LENGTH_SHORT)
snackbar.setAction(R.string.detail_item_snack_undo) {
lifecycleScope.launch(Dispatchers.IO) {
repository.undeleteNotification(notification.id)
}
}
snackbar.show()
}
}
val itemTouchHelper = ItemTouchHelper(itemTouchCallback)
itemTouchHelper.attachToRecyclerView(mainList)
// Scroll up when new notification is added // Scroll up when new notification is added
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {

View file

@ -44,6 +44,10 @@ class DetailAdapter(private val activity: Activity, private val repository: Repo
holder.bind(getItem(position)) holder.bind(getItem(position))
} }
fun get(position: Int): Notification {
return getItem(position)
}
fun toggleSelection(notificationId: String) { fun toggleSelection(notificationId: String) {
if (selected.contains(notificationId)) { if (selected.contains(notificationId)) {
selected.remove(notificationId) selected.remove(notificationId)

View file

@ -135,6 +135,8 @@
<string name="detail_instant_delivery_disabled">Instant delivery disabled</string> <string name="detail_instant_delivery_disabled">Instant delivery disabled</string>
<string name="detail_instant_info">Instant delivery is enabled</string> <string name="detail_instant_info">Instant delivery is enabled</string>
<string name="detail_item_tags">Tags: %1$s</string> <string name="detail_item_tags">Tags: %1$s</string>
<string name="detail_item_snack_deleted">Notification deleted</string>
<string name="detail_item_snack_undo">Undo</string>
<string name="detail_item_menu_open">Open file</string> <string name="detail_item_menu_open">Open file</string>
<string name="detail_item_menu_browse">Browse 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_delete">Delete file</string>