feat: Random sort

This commit is contained in:
Ahmad Ansori Palembani 2025-01-05 19:18:08 +07:00
parent eebc3dc822
commit 7fc95e3029
Signed by: null2264
GPG key ID: BA64F8B60AF3EFB6
8 changed files with 68 additions and 33 deletions

View file

@ -10,6 +10,9 @@ The format is simplified version of [Keep a Changelog](https://keepachangelog.co
## [Unreleased] ## [Unreleased]
### Additions
- Add random library sort
### Fixes ### Fixes
- Allow users to bypass onboarding's permission step if Shizuku is installed - Allow users to bypass onboarding's permission step if Shizuku is installed
- Fix Recents page shows "No recent chapters" instead of a loading screen - Fix Recents page shows "No recent chapters" instead of a loading screen

View file

@ -32,14 +32,17 @@ import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.compatToolTipText import eu.kanade.tachiyomi.util.view.compatToolTipText
import eu.kanade.tachiyomi.util.view.setText import eu.kanade.tachiyomi.util.view.setText
import eu.kanade.tachiyomi.util.view.text import eu.kanade.tachiyomi.util.view.text
import kotlin.random.Random
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import yokai.domain.library.LibraryPreferences
import yokai.i18n.MR import yokai.i18n.MR
import yokai.util.lang.getString import yokai.util.lang.getString
class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) : class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) :
BaseFlexibleViewHolder(view, adapter, true) { BaseFlexibleViewHolder(view, adapter, true) {
private val libraryPreferences: LibraryPreferences = Injekt.get()
private val binding = LibraryCategoryHeaderItemBinding.bind(view) private val binding = LibraryCategoryHeaderItemBinding.bind(view)
val progressDrawableStart = CircularProgressDrawable(itemView.context) val progressDrawableStart = CircularProgressDrawable(itemView.context)
val progressDrawableEnd = CircularProgressDrawable(itemView.context) val progressDrawableEnd = CircularProgressDrawable(itemView.context)
@ -292,6 +295,7 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) :
sortMode ?: return defaultDrawableRes sortMode ?: return defaultDrawableRes
return when (sortMode) { return when (sortMode) {
LibrarySort.DragAndDrop -> defaultDrawableRes LibrarySort.DragAndDrop -> defaultDrawableRes
LibrarySort.Random -> R.drawable.ic_shuffle_24dp
else -> { else -> {
if (if (sortMode.hasInvertedSort) !isAscending else isAscending) { if (if (sortMode.hasInvertedSort) !isAscending else isAscending) {
R.drawable.ic_arrow_downward_24dp R.drawable.ic_arrow_downward_24dp
@ -306,35 +310,27 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) :
sortingMode: Int?, sortingMode: Int?,
isAscending: Boolean, isAscending: Boolean,
@DrawableRes defaultDrawableRes: Int = R.drawable.ic_check_24dp, @DrawableRes defaultDrawableRes: Int = R.drawable.ic_check_24dp,
): Int { ): Int = getSortRes(sortingMode?.let { LibrarySort.valueOf(it) }, isAscending, defaultDrawableRes)
sortingMode ?: return defaultDrawableRes
return when (val sortMode = LibrarySort.valueOf(sortingMode)) {
LibrarySort.DragAndDrop -> defaultDrawableRes
else -> {
if (if (sortMode?.hasInvertedSort == true) !isAscending else isAscending) {
R.drawable.ic_arrow_downward_24dp
} else {
R.drawable.ic_arrow_upward_24dp
}
}
}
}
private fun onCatSortClicked(category: Category, menuId: Int?) { private fun onCatSortClicked(category: Category, menuId: Int?) {
val modType = if (menuId == null) { val (mode, modType) = if (menuId == null) {
val sortingMode = category.sortingMode() ?: LibrarySort.Title val sortingMode = category.sortingMode() ?: LibrarySort.Title
if (category.isAscending()) { sortingMode to
sortingMode.categoryValueDescending if (sortingMode != LibrarySort.Random && category.isAscending()) {
} else { sortingMode.categoryValueDescending
sortingMode.categoryValue } else {
} sortingMode.categoryValue
}
} else { } else {
val sortingMode = LibrarySort.valueOf(menuId) ?: LibrarySort.Title val sortingMode = LibrarySort.valueOf(menuId) ?: LibrarySort.Title
if (sortingMode != LibrarySort.DragAndDrop && sortingMode == category.sortingMode()) { if (sortingMode != LibrarySort.DragAndDrop && sortingMode == category.sortingMode()) {
onCatSortClicked(category, null) onCatSortClicked(category, null)
return return
} }
sortingMode.categoryValue sortingMode to sortingMode.categoryValue
}
if (mode == LibrarySort.Random) {
libraryPreferences.randomSortSeed().set(Random.nextInt())
} }
adapter.libraryListener?.sortCategory(category.id!!, modType) adapter.libraryListener?.sortCategory(category.id!!, modType)
} }

View file

@ -73,6 +73,7 @@ import yokai.domain.chapter.interactor.GetChapter
import yokai.domain.chapter.interactor.UpdateChapter import yokai.domain.chapter.interactor.UpdateChapter
import yokai.domain.chapter.models.ChapterUpdate import yokai.domain.chapter.models.ChapterUpdate
import yokai.domain.history.interactor.GetHistory import yokai.domain.history.interactor.GetHistory
import yokai.domain.library.LibraryPreferences
import yokai.domain.manga.interactor.GetLibraryManga import yokai.domain.manga.interactor.GetLibraryManga
import yokai.domain.manga.interactor.GetManga import yokai.domain.manga.interactor.GetManga
import yokai.domain.manga.interactor.UpdateManga import yokai.domain.manga.interactor.UpdateManga
@ -90,6 +91,7 @@ typealias LibraryMutableMap = MutableMap<Category, List<LibraryItem>>
*/ */
class LibraryPresenter( class LibraryPresenter(
private val preferences: PreferencesHelper = Injekt.get(), private val preferences: PreferencesHelper = Injekt.get(),
private val libraryPreferences: LibraryPreferences = Injekt.get(),
private val coverCache: CoverCache = Injekt.get(), private val coverCache: CoverCache = Injekt.get(),
val sourceManager: SourceManager = Injekt.get(), val sourceManager: SourceManager = Injekt.get(),
private val downloadCache: DownloadCache = Injekt.get(), private val downloadCache: DownloadCache = Injekt.get(),
@ -697,6 +699,9 @@ class LibraryPresenter(
sortAlphabetical(i1, i2) sortAlphabetical(i1, i2)
} }
} }
LibrarySort.Random -> {
error("You're not supposed to be here...")
}
} }
if (!category.isAscending()) sort *= -1 if (!category.isAscending()) sort *= -1
sort sort
@ -738,16 +743,28 @@ class LibraryPresenter(
} }
} }
if (LibrarySort.valueOf(category.mangaSort) == LibrarySort.Random) {
return@mapValues values
.asSequence()
.shuffled(Random(libraryPreferences.randomSortSeed().get()))
.sortedWith { i1, i2 ->
when {
i1 is LibraryPlaceholderItem -> -1
i2 is LibraryPlaceholderItem -> 1
else -> 0
}
}
.toList()
}
values.sortedWith(Comparator(sortFn)) values.sortedWith(Comparator(sortFn))
}.toSortedMap { category, category2 -> }.toSortedMap { category, category2 ->
// Force default category to always be at the top. This also for some reason fixed a bug where Default when {
// category would disappear whenever a new category is added. // Force default category to always be at the top. This also for some reason fixed a bug where Default
if (category.id == 0) { // category would disappear whenever a new category is added.
-1 category.id == 0 -> -1
} else if (category2.id == 0) { category2.id == 0 -> 1
1 else -> category.order.compareTo(category2.order)
} else {
category.order.compareTo(category2.order)
} }
} }
} }

View file

@ -1,13 +1,10 @@
package eu.kanade.tachiyomi.ui.library package eu.kanade.tachiyomi.ui.library
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import dev.icerock.moko.resources.StringResource import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import yokai.i18n.MR
import yokai.util.lang.getString
import dev.icerock.moko.resources.compose.stringResource
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
import yokai.i18n.MR
enum class LibrarySort( enum class LibrarySort(
val mainValue: Int, val mainValue: Int,
@ -33,7 +30,11 @@ enum class LibrarySort(
MR.strings.category, MR.strings.category,
R.drawable.ic_label_outline_24dp, R.drawable.ic_label_outline_24dp,
), ),
Random(
8,
MR.strings.random,
R.drawable.ic_shuffle_24dp,
)
; ;
val categoryValue: Char val categoryValue: Char
@ -50,6 +51,7 @@ enum class LibrarySort(
LatestChapter -> "LATEST_CHAPTER" LatestChapter -> "LATEST_CHAPTER"
DateFetched -> "CHAPTER_FETCH_DATE" DateFetched -> "CHAPTER_FETCH_DATE"
DateAdded -> "DATE_ADDED" DateAdded -> "DATE_ADDED"
Random -> "RANDOM"
else -> "ALPHABETICAL" else -> "ALPHABETICAL"
} }
return "$type,ASCENDING" return "$type,ASCENDING"
@ -85,6 +87,7 @@ enum class LibrarySort(
"LATEST_CHAPTER" -> LatestChapter "LATEST_CHAPTER" -> LatestChapter
"CHAPTER_FETCH_DATE" -> DateFetched "CHAPTER_FETCH_DATE" -> DateFetched
"DATE_ADDED" -> DateAdded "DATE_ADDED" -> DateAdded
"RANDOM" -> Random
else -> Title else -> Title
} }
} catch (e: Exception) { } catch (e: Exception) {

View file

@ -13,6 +13,7 @@ import org.koin.dsl.module
import yokai.domain.backup.BackupPreferences import yokai.domain.backup.BackupPreferences
import yokai.domain.base.BasePreferences import yokai.domain.base.BasePreferences
import yokai.domain.download.DownloadPreferences import yokai.domain.download.DownloadPreferences
import yokai.domain.library.LibraryPreferences
import yokai.domain.recents.RecentsPreferences import yokai.domain.recents.RecentsPreferences
import yokai.domain.source.SourcePreferences import yokai.domain.source.SourcePreferences
import yokai.domain.storage.StoragePreferences import yokai.domain.storage.StoragePreferences
@ -47,6 +48,8 @@ fun preferenceModule(application: Application) = module {
single { BackupPreferences(get()) } single { BackupPreferences(get()) }
single { LibraryPreferences(get()) }
single { single {
PreferencesHelper( PreferencesHelper(
context = application, context = application,

View file

@ -0,0 +1,7 @@
package yokai.domain.library
import eu.kanade.tachiyomi.core.preference.PreferenceStore
class LibraryPreferences(private val preferenceStore: PreferenceStore) {
fun randomSortSeed() = preferenceStore.getInt("library_random_sort_seed", 0)
}

View file

@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z"/>
</vector>

View file

@ -174,6 +174,7 @@
<string name="date_fetched">Date fetched</string> <string name="date_fetched">Date fetched</string>
<string name="latest_chapter">Latest chapter</string> <string name="latest_chapter">Latest chapter</string>
<string name="drag_and_drop">Drag &amp; Drop</string> <string name="drag_and_drop">Drag &amp; Drop</string>
<string name="random">Random</string>
<!-- Library Display --> <!-- Library Display -->
<string name="display_options">Display options</string> <string name="display_options">Display options</string>