Option to undo removing from favourites

This commit is contained in:
Koitharu
2022-05-11 16:23:37 +03:00
parent 3e785a2555
commit 36634ecca1
7 changed files with 68 additions and 3 deletions

View File

@@ -102,7 +102,7 @@ dependencies {
implementation 'com.hannesdorfmann:adapterdelegates4-kotlin-dsl-viewbinding:4.3.2'
implementation 'io.insert-koin:koin-android:3.2.0'
implementation 'io.coil-kt:coil-base:2.0.0-rc03'
implementation 'io.coil-kt:coil-base:2.0.0'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
implementation 'com.github.solkin:disk-lru-cache:1.4'

View File

@@ -0,0 +1,19 @@
package org.koitharu.kotatsu.base.domain
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.koitharu.kotatsu.utils.ext.processLifecycleScope
fun interface ReversibleHandle {
suspend fun reverse()
}
fun ReversibleHandle.reverseAsync() = processLifecycleScope.launch(Dispatchers.Default) {
reverse()
}
operator fun ReversibleHandle.plus(other: ReversibleHandle) = ReversibleHandle {
this.reverse()
other.reverse()
}

View File

@@ -15,6 +15,10 @@ abstract class HistoryDao {
@Query("SELECT * FROM history ORDER BY updated_at DESC LIMIT :limit OFFSET :offset")
abstract suspend fun findAll(offset: Int, limit: Int): List<HistoryWithManga>
@Transaction
@Query("SELECT * FROM history WHERE manga_id IN (:ids)")
abstract suspend fun findAll(ids: Collection<Long>): List<HistoryEntity?>
@Transaction
@Query("SELECT * FROM history ORDER BY updated_at DESC")
abstract fun observeAll(): Flow<List<HistoryWithManga>>
@@ -69,4 +73,13 @@ abstract class HistoryDao {
true
} else false
}
@Transaction
open suspend fun upsert(entities: Iterable<HistoryEntity>) {
for (e in entities) {
if (update(e) == 0) {
insert(e)
}
}
}
}

View File

@@ -4,6 +4,7 @@ import androidx.room.withTransaction
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import org.koitharu.kotatsu.base.domain.ReversibleHandle
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.entity.*
import org.koitharu.kotatsu.core.model.MangaHistory
@@ -100,6 +101,19 @@ class HistoryRepository(
}
}
suspend fun deleteReversible(ids: Collection<Long>): ReversibleHandle {
val entities = db.withTransaction {
val entities = db.historyDao.findAll(ids.toList()).filterNotNull()
for (id in ids) {
db.historyDao.delete(id)
}
entities
}
return ReversibleHandle {
db.historyDao.upsert(entities)
}
}
/**
* Try to replace one manga with another one
* Useful for replacing saved manga on deleting it with remove source

View File

@@ -7,8 +7,11 @@ import android.view.MenuItem
import android.view.View
import androidx.appcompat.view.ActionMode
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.snackbar.Snackbar
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.ReversibleHandle
import org.koitharu.kotatsu.base.domain.reverseAsync
import org.koitharu.kotatsu.list.ui.MangaListFragment
import org.koitharu.kotatsu.parsers.model.MangaSource
@@ -22,6 +25,7 @@ class HistoryListFragment : MangaListFragment() {
viewModel.isGroupingEnabled.observe(viewLifecycleOwner) {
activity?.invalidateOptionsMenu()
}
viewModel.onItemsRemoved.observe(viewLifecycleOwner, ::onItemsRemoved)
}
override fun onScrolledToEnd() = Unit
@@ -80,6 +84,12 @@ class HistoryListFragment : MangaListFragment() {
}
}
private fun onItemsRemoved(reversibleHandle: ReversibleHandle) {
Snackbar.make(binding.recyclerView, R.string.removed_from_history, Snackbar.LENGTH_LONG)
.setAction(R.string.undo) { reversibleHandle.reverseAsync() }
.show()
}
companion object {
fun newInstance() = HistoryListFragment()

View File

@@ -7,6 +7,8 @@ import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.onEach
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.ReversibleHandle
import org.koitharu.kotatsu.base.domain.plus
import org.koitharu.kotatsu.core.os.ShortcutsRepository
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ListMode
@@ -17,6 +19,7 @@ import org.koitharu.kotatsu.history.domain.MangaWithHistory
import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.*
import org.koitharu.kotatsu.tracker.domain.TrackingRepository
import org.koitharu.kotatsu.utils.SingleLiveEvent
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.ext.daysDiff
import org.koitharu.kotatsu.utils.ext.onFirst
@@ -31,6 +34,7 @@ class HistoryListViewModel(
) : MangaListViewModel(settings) {
val isGroupingEnabled = MutableLiveData<Boolean>()
val onItemsRemoved = SingleLiveEvent<ReversibleHandle>()
private val historyGrouping = settings.observeAsFlow(AppSettings.KEY_HISTORY_GROUPING) { historyGrouping }
.onEach { isGroupingEnabled.postValue(it) }
@@ -72,9 +76,12 @@ class HistoryListViewModel(
if (ids.isEmpty()) {
return
}
launchJob {
repository.delete(ids)
launchJob(Dispatchers.Default) {
val handle = repository.deleteReversible(ids) + ReversibleHandle {
shortcutsRepository.updateShortcuts()
}
shortcutsRepository.updateShortcuts()
onItemsRemoved.postCall(handle)
}
}

View File

@@ -293,4 +293,6 @@
<string name="bookmarks">Bookmarks</string>
<string name="bookmark_removed">Bookmark removed</string>
<string name="bookmark_added">Bookmark added</string>
<string name="undo">Undo</string>
<string name="removed_from_history">Removed from history</string>
</resources>