Migrate to LongSet in selection controller

This commit is contained in:
Koitharu
2024-07-15 19:36:11 +03:00
parent 6d07c335de
commit 92c8a13f96
10 changed files with 51 additions and 19 deletions

View File

@@ -95,7 +95,7 @@ dependencies {
implementation 'androidx.activity:activity-ktx:1.9.0'
implementation 'androidx.fragment:fragment-ktx:1.8.1'
implementation 'androidx.transition:transition-ktx:1.5.0'
implementation 'androidx.collection:collection-ktx:1.4.0'
implementation 'androidx.collection:collection-ktx:1.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.3'
implementation 'androidx.lifecycle:lifecycle-service:2.8.3'
implementation 'androidx.lifecycle:lifecycle-process:2.8.3'

View File

@@ -1,11 +1,11 @@
package org.koitharu.kotatsu.core.ui.list
import android.app.Notification.Action
import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import androidx.appcompat.app.AppCompatDelegate
import androidx.appcompat.view.ActionMode
import androidx.collection.LongSet
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
@@ -14,6 +14,8 @@ import androidx.savedstate.SavedStateRegistry
import androidx.savedstate.SavedStateRegistryOwner
import kotlinx.coroutines.Dispatchers
import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration
import org.koitharu.kotatsu.core.util.ext.toLongArray
import org.koitharu.kotatsu.core.util.ext.toSet
import kotlin.coroutines.EmptyCoroutineContext
private const val KEY_SELECTION = "selection"
@@ -35,11 +37,9 @@ class ListSelectionController(
registryOwner.lifecycle.addObserver(StateEventObserver())
}
fun snapshot(): Set<Long> {
return peekCheckedIds().toSet()
}
fun snapshot(): Set<Long> = peekCheckedIds().toSet()
fun peekCheckedIds(): Set<Long> {
fun peekCheckedIds(): LongSet {
return decoration.checkedItemsIds
}

View File

@@ -4,6 +4,8 @@ import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.RectF
import android.view.View
import androidx.collection.LongSet
import androidx.collection.MutableLongSet
import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.NO_ID
@@ -12,7 +14,7 @@ abstract class AbstractSelectionItemDecoration : RecyclerView.ItemDecoration() {
private val bounds = Rect()
private val boundsF = RectF()
protected val selection = HashSet<Long>() // TODO MutableLongSet
protected val selection = MutableLongSet()
protected var hasBackground: Boolean = true
protected var hasForeground: Boolean = false
@@ -21,7 +23,7 @@ abstract class AbstractSelectionItemDecoration : RecyclerView.ItemDecoration() {
val checkedItemsCount: Int
get() = selection.size
val checkedItemsIds: Set<Long>
val checkedItemsIds: LongSet
get() = selection
fun toggleItemChecked(id: Long) {
@@ -39,7 +41,9 @@ abstract class AbstractSelectionItemDecoration : RecyclerView.ItemDecoration() {
}
fun checkAll(ids: Collection<Long>) {
selection.addAll(ids)
for (id in ids) {
selection.add(id)
}
}
fun clearSelection() {

View File

@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.util.ext
import androidx.collection.ArrayMap
import androidx.collection.ArraySet
import androidx.collection.LongSet
import org.koitharu.kotatsu.BuildConfig
import java.util.Collections
import java.util.EnumSet
@@ -77,3 +78,16 @@ inline fun <T, reified R> Collection<T>.mapToArray(transform: (T) -> R): Array<R
forEachIndexed { index, t -> result[index] = transform(t) }
return result as Array<R>
}
fun LongSet.toLongArray(): LongArray {
val result = LongArray(size)
var i = 0
forEach { result[i++] = it }
return result
}
fun LongSet.toSet(): Set<Long> = toCollection(ArraySet<Long>(size))
fun <R : MutableCollection<Long>> LongSet.toCollection(out: R): R = out.also { result ->
forEach(result::add)
}

View File

@@ -32,6 +32,8 @@ import org.koitharu.kotatsu.core.util.ext.findAppCompatDelegate
import org.koitharu.kotatsu.core.util.ext.findParentCallback
import org.koitharu.kotatsu.core.util.ext.observe
import org.koitharu.kotatsu.core.util.ext.observeEvent
import org.koitharu.kotatsu.core.util.ext.toCollection
import org.koitharu.kotatsu.core.util.ext.toSet
import org.koitharu.kotatsu.databinding.FragmentChaptersBinding
import org.koitharu.kotatsu.details.ui.DetailsViewModel
import org.koitharu.kotatsu.details.ui.adapter.ChaptersAdapter
@@ -137,10 +139,10 @@ class ChaptersFragment :
val ids = selectionController?.peekCheckedIds()
val manga = viewModel.manga.value
when {
ids.isNullOrEmpty() || manga == null -> Unit
ids == null || ids.isEmpty() || manga == null -> Unit
ids.size == manga.chapters?.size -> viewModel.deleteLocal()
else -> {
LocalChaptersRemoveService.start(requireContext(), manga, ids)
LocalChaptersRemoveService.start(requireContext(), manga, ids.toSet())
Snackbar.make(
requireViewBinding().recyclerViewChapters,
R.string.chapters_will_removed_background,
@@ -154,7 +156,7 @@ class ChaptersFragment :
R.id.action_select_range -> {
val items = chaptersAdapter?.items ?: return false
val ids = HashSet(controller.peekCheckedIds())
val ids = controller.peekCheckedIds().toCollection(HashSet())
val buffer = HashSet<Long>()
var isAdding = false
for (x in items) {
@@ -188,8 +190,12 @@ class ChaptersFragment :
}
R.id.action_mark_current -> {
val id = controller.peekCheckedIds().singleOrNull() ?: return false
viewModel.markChapterAsCurrent(id)
val ids = controller.peekCheckedIds()
if (ids.size == 1) {
viewModel.markChapterAsCurrent(ids.first())
} else {
return false
}
mode.finish()
true
}

View File

@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.download.ui.list
import androidx.collection.ArrayMap
import androidx.collection.LongSet
import androidx.collection.LongSparseArray
import androidx.collection.getOrElse
import androidx.collection.set
@@ -182,7 +183,7 @@ class DownloadsViewModel @Inject constructor(
}
}
fun snapshot(ids: Set<Long>): Collection<DownloadItemModel> {
fun snapshot(ids: LongSet): Collection<DownloadItemModel> {
return works.value?.filterTo(ArrayList(ids.size)) { x -> x.id.mostSignificantBits in ids }.orEmpty()
}

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.explore.ui
import androidx.collection.LongSet
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
@@ -126,7 +127,7 @@ class ExploreViewModel @Inject constructor(
settings.closeTip(TIP_SUGGESTIONS)
}
fun sourcesSnapshot(ids: Set<Long>): List<MangaSourceInfo> {
fun sourcesSnapshot(ids: LongSet): List<MangaSourceInfo> {
return content.value.mapNotNull {
(it as? MangaSourceItem)?.takeIf { x -> x.id in ids }?.source
}

View File

@@ -1,5 +1,6 @@
package org.koitharu.kotatsu.favourites.ui.categories
import androidx.collection.LongSet
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
@@ -76,7 +77,7 @@ class FavouritesCategoriesViewModel @Inject constructor(
}
}
fun getCategories(ids: Set<Long>): ArrayList<FavouriteCategory> {
fun getCategories(ids: LongSet): ArrayList<FavouriteCategory> {
val items = content.requireValue()
return items.mapNotNullTo(ArrayList(ids.size)) { item ->
(item as? CategoryListModel)?.category?.takeIf { it.id in ids }

View File

@@ -14,7 +14,11 @@ import org.koitharu.kotatsu.scrobbling.common.domain.model.ScrobblerManga
class ScrobblerMangaSelectionDecoration(context: Context) : MangaSelectionDecoration(context) {
var checkedItemId: Long
get() = selection.singleOrNull() ?: NO_ID
get() = if (selection.size == 1) {
selection.first()
} else {
NO_ID
}
set(value) {
clearSelection()
if (value != NO_ID) {

View File

@@ -1,6 +1,7 @@
package org.koitharu.kotatsu.search.ui.multi
import androidx.annotation.CheckResult
import androidx.collection.LongSet
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -81,7 +82,7 @@ class MultiSearchViewModel @Inject constructor(
}
}.stateIn(viewModelScope + Dispatchers.Default, SharingStarted.Eagerly, listOf(LoadingState))
fun getItems(ids: Set<Long>): Set<Manga> {
fun getItems(ids: LongSet): Set<Manga> {
val snapshot = listData.value ?: return emptySet()
val result = HashSet<Manga>(ids.size)
snapshot.forEach { x ->