mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-25 02:21:49 +01:00
Optimizations to sorting + category refactoring
Category: • new bool called isDynamic used for all category • new bool called isAlone, for when using no categories or when hiding all categories Sort Optimizing: •Using SQLite query for library mangas to also set the total chapters, instead of checking the total count later •No longer using regex for removing articles from text, because it's pretty heavy •All category now uses the same catergory sorting logic as regular categories
This commit is contained in:
parent
7083d41ffe
commit
d9ad689506
@ -19,14 +19,15 @@ interface Category : Serializable {
|
|||||||
|
|
||||||
var mangaSort: Char?
|
var mangaSort: Char?
|
||||||
|
|
||||||
var isFirst: Boolean?
|
var isAlone: Boolean
|
||||||
var isLast: Boolean?
|
|
||||||
|
|
||||||
val nameLower: String
|
val nameLower: String
|
||||||
get() = name.toLowerCase()
|
get() = name.toLowerCase()
|
||||||
|
|
||||||
var isHidden: Boolean
|
var isHidden: Boolean
|
||||||
|
|
||||||
|
var isDynamic: Boolean
|
||||||
|
|
||||||
fun isAscending(): Boolean {
|
fun isAscending(): Boolean {
|
||||||
return ((mangaSort?.minus('a') ?: 0) % 2) != 1
|
return ((mangaSort?.minus('a') ?: 0) % 2) != 1
|
||||||
}
|
}
|
||||||
@ -49,7 +50,7 @@ interface Category : Serializable {
|
|||||||
LAST_READ_ASC, LAST_READ_DSC -> R.string.last_read
|
LAST_READ_ASC, LAST_READ_DSC -> R.string.last_read
|
||||||
TOTAL_ASC, TOTAL_DSC -> R.string.total_chapters
|
TOTAL_ASC, TOTAL_DSC -> R.string.total_chapters
|
||||||
DATE_ADDED_ASC, DATE_ADDED_DSC -> R.string.date_added
|
DATE_ADDED_ASC, DATE_ADDED_DSC -> R.string.date_added
|
||||||
else -> if (id == -1) R.string.category else R.string.drag_and_drop
|
else -> if (isDynamic) R.string.category else R.string.drag_and_drop
|
||||||
}
|
}
|
||||||
|
|
||||||
fun catSortingMode(): Int? = when (mangaSort) {
|
fun catSortingMode(): Int? = when (mangaSort) {
|
||||||
@ -96,12 +97,10 @@ interface Category : Serializable {
|
|||||||
fun createDefault(context: Context): Category =
|
fun createDefault(context: Context): Category =
|
||||||
create(context.getString(R.string.default_value)).apply {
|
create(context.getString(R.string.default_value)).apply {
|
||||||
id = 0
|
id = 0
|
||||||
isFirst = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createAll(context: Context, libSort: Int, ascending: Boolean): Category =
|
fun createCustom(name: String, libSort: Int, ascending: Boolean): Category =
|
||||||
create(context.getString(R.string.all)).apply {
|
create(name).apply {
|
||||||
id = -1
|
|
||||||
mangaSort = when (libSort) {
|
mangaSort = when (libSort) {
|
||||||
LibrarySort.ALPHA -> ALPHA_ASC
|
LibrarySort.ALPHA -> ALPHA_ASC
|
||||||
LibrarySort.LATEST_CHAPTER -> UPDATED_ASC
|
LibrarySort.LATEST_CHAPTER -> UPDATED_ASC
|
||||||
@ -113,11 +112,15 @@ interface Category : Serializable {
|
|||||||
else -> DRAG_AND_DROP
|
else -> DRAG_AND_DROP
|
||||||
}
|
}
|
||||||
if (mangaSort != DRAG_AND_DROP && !ascending) {
|
if (mangaSort != DRAG_AND_DROP && !ascending) {
|
||||||
mangaSort?.plus(1)
|
mangaSort = mangaSort?.plus(1)
|
||||||
}
|
}
|
||||||
|
isDynamic = true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createAll(context: Context, libSort: Int, ascending: Boolean): Category =
|
||||||
|
createCustom(context.getString(R.string.all), libSort, ascending).apply {
|
||||||
|
id = -1
|
||||||
order = -1
|
order = -1
|
||||||
isFirst = true
|
|
||||||
isLast = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,12 @@ class CategoryImpl : Category {
|
|||||||
|
|
||||||
override var mangaSort: Char? = null
|
override var mangaSort: Char? = null
|
||||||
|
|
||||||
override var isFirst: Boolean? = null
|
override var isAlone: Boolean = false
|
||||||
|
|
||||||
override var isLast: Boolean? = null
|
|
||||||
|
|
||||||
override var isHidden: Boolean = false
|
override var isHidden: Boolean = false
|
||||||
|
|
||||||
|
override var isDynamic: Boolean = false
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other == null || javaClass != other.javaClass) return false
|
if (other == null || javaClass != other.javaClass) return false
|
||||||
|
@ -3,10 +3,15 @@ package eu.kanade.tachiyomi.data.database.models
|
|||||||
class LibraryManga : MangaImpl() {
|
class LibraryManga : MangaImpl() {
|
||||||
|
|
||||||
var unread: Int = 0
|
var unread: Int = 0
|
||||||
|
var read: Int = 0
|
||||||
|
|
||||||
var category: Int = 0
|
var category: Int = 0
|
||||||
|
|
||||||
var hasRead: Boolean = false
|
val totalChapters
|
||||||
|
get() = read + unread
|
||||||
|
|
||||||
|
val hasRead
|
||||||
|
get() = read > 0
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun createBlank(categoryId: Int): LibraryManga = LibraryManga().apply {
|
fun createBlank(categoryId: Int): LibraryManga = LibraryManga().apply {
|
||||||
|
@ -18,7 +18,7 @@ class LibraryMangaGetResolver : DefaultGetResolver<LibraryManga>(), BaseMangaGet
|
|||||||
mapBaseFromCursor(manga, cursor)
|
mapBaseFromCursor(manga, cursor)
|
||||||
manga.unread = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_UNREAD))
|
manga.unread = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_UNREAD))
|
||||||
manga.category = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_CATEGORY))
|
manga.category = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_CATEGORY))
|
||||||
manga.hasRead = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_HAS_READ)) > 0
|
manga.read = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_HAS_READ))
|
||||||
|
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,7 @@ class LibraryCategoryAdapter(val controller: LibraryController) :
|
|||||||
else recyclerView.context.getString(R.string.read)
|
else recyclerView.context.getString(R.string.read)
|
||||||
}
|
}
|
||||||
LibrarySort.TOTAL -> {
|
LibrarySort.TOTAL -> {
|
||||||
val total = item.chapterCount
|
val total = item.manga.totalChapters
|
||||||
if (total > 0) recyclerView.resources.getQuantityString(
|
if (total > 0) recyclerView.resources.getQuantityString(
|
||||||
R.plurals.chapters, total, total
|
R.plurals.chapters, total, total
|
||||||
)
|
)
|
||||||
|
@ -1109,8 +1109,9 @@ class LibraryController(
|
|||||||
|
|
||||||
override fun manageCategory(position: Int) {
|
override fun manageCategory(position: Int) {
|
||||||
val category = (adapter.getItem(position) as? LibraryHeaderItem)?.category ?: return
|
val category = (adapter.getItem(position) as? LibraryHeaderItem)?.category ?: return
|
||||||
if (category.id ?: 0 > -1)
|
if (!category.isDynamic) {
|
||||||
ManageCategoryDialog(this, category).showDialog(router)
|
ManageCategoryDialog(this, category).showDialog(router)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun sortCategory(catId: Int, sortBy: Int) {
|
override fun sortCategory(catId: Int, sortBy: Int) {
|
||||||
|
@ -143,7 +143,7 @@ class LibraryHeaderItem(
|
|||||||
}
|
}
|
||||||
val category = item.category
|
val category = item.category
|
||||||
|
|
||||||
if (category.isFirst == true && category.isLast == true) sectionText.text = ""
|
if (category.isAlone) sectionText.text = ""
|
||||||
else sectionText.text = category.name
|
else sectionText.text = category.name
|
||||||
sortText.text = itemView.context.getString(
|
sortText.text = itemView.context.getString(
|
||||||
R.string.sort_by_, itemView.context.getString(category.sortRes())
|
R.string.sort_by_, itemView.context.getString(category.sortRes())
|
||||||
@ -165,14 +165,15 @@ class LibraryHeaderItem(
|
|||||||
when {
|
when {
|
||||||
adapter.mode == SelectableAdapter.Mode.MULTI -> {
|
adapter.mode == SelectableAdapter.Mode.MULTI -> {
|
||||||
checkboxImage.visibleIf(!category.isHidden)
|
checkboxImage.visibleIf(!category.isHidden)
|
||||||
expandImage.visibleIf(category.isHidden && !adapter.isSingleCategory)
|
expandImage.visibleIf(category.isHidden && !adapter.isSingleCategory && !category.isDynamic)
|
||||||
updateButton.gone()
|
updateButton.gone()
|
||||||
catProgress.gone()
|
catProgress.gone()
|
||||||
setSelection()
|
setSelection()
|
||||||
}
|
}
|
||||||
category.id == -1 -> {
|
category.isDynamic -> {
|
||||||
expandImage.gone()
|
expandImage.gone()
|
||||||
checkboxImage.gone()
|
checkboxImage.gone()
|
||||||
|
catProgress.gone()
|
||||||
updateButton.gone()
|
updateButton.gone()
|
||||||
}
|
}
|
||||||
LibraryUpdateService.categoryInQueue(category.id) -> {
|
LibraryUpdateService.categoryInQueue(category.id) -> {
|
||||||
@ -185,7 +186,7 @@ class LibraryHeaderItem(
|
|||||||
expandImage.visibleIf(!adapter.isSingleCategory)
|
expandImage.visibleIf(!adapter.isSingleCategory)
|
||||||
catProgress.gone()
|
catProgress.gone()
|
||||||
checkboxImage.gone()
|
checkboxImage.gone()
|
||||||
updateButton.visibleIf(category.id ?: 0 > -1 && !adapter.isSingleCategory)
|
updateButton.visibleIf(!adapter.isSingleCategory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,9 +26,10 @@ abstract class LibraryHolder(
|
|||||||
abstract fun onSetValues(item: LibraryItem)
|
abstract fun onSetValues(item: LibraryItem)
|
||||||
|
|
||||||
fun setUnreadBadge(badge: LibraryBadge, item: LibraryItem) {
|
fun setUnreadBadge(badge: LibraryBadge, item: LibraryItem) {
|
||||||
|
val showTotal = item.header.category.sortingMode() == LibrarySort.TOTAL
|
||||||
badge.setUnreadDownload(
|
badge.setUnreadDownload(
|
||||||
when {
|
when {
|
||||||
item.chapterCount > -1 -> item.chapterCount
|
showTotal -> item.manga.totalChapters
|
||||||
item.unreadType == 2 -> item.manga.unread
|
item.unreadType == 2 -> item.manga.unread
|
||||||
item.unreadType == 1 -> if (item.manga.unread > 0) -1 else -2
|
item.unreadType == 1 -> if (item.manga.unread > 0) -1 else -2
|
||||||
else -> -2
|
else -> -2
|
||||||
@ -38,7 +39,7 @@ abstract class LibraryHolder(
|
|||||||
item.manga.source == LocalSource.ID -> -2
|
item.manga.source == LocalSource.ID -> -2
|
||||||
else -> item.downloadCount
|
else -> item.downloadCount
|
||||||
},
|
},
|
||||||
item.chapterCount > -1)
|
showTotal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setReadingButton(item: LibraryItem) {
|
fun setReadingButton(item: LibraryItem) {
|
||||||
|
@ -35,7 +35,6 @@ class LibraryItem(
|
|||||||
|
|
||||||
var downloadCount = -1
|
var downloadCount = -1
|
||||||
var unreadType = 2
|
var unreadType = 2
|
||||||
var chapterCount = -1
|
|
||||||
|
|
||||||
private val uniformSize: Boolean
|
private val uniformSize: Boolean
|
||||||
get() = preferences.uniformGrid().getOrDefault()
|
get() = preferences.uniformGrid().getOrDefault()
|
||||||
|
@ -54,6 +54,10 @@ class LibraryPresenter(
|
|||||||
var categories: List<Category> = emptyList()
|
var categories: List<Category> = emptyList()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
var hashCategories: HashMap<Int, Category> = hashMapOf()
|
||||||
|
|
||||||
|
var removeArticles: Boolean = preferences.removeArticles().getOrDefault()
|
||||||
|
|
||||||
/** All categories of the library, in case they are hidden because of hide categories is on */
|
/** All categories of the library, in case they are hidden because of hide categories is on */
|
||||||
var allCategories: List<Category> = emptyList()
|
var allCategories: List<Category> = emptyList()
|
||||||
private set
|
private set
|
||||||
@ -67,8 +71,6 @@ class LibraryPresenter(
|
|||||||
val showAllCategories
|
val showAllCategories
|
||||||
get() = preferences.showAllCategories().get()
|
get() = preferences.showAllCategories().get()
|
||||||
|
|
||||||
private var totalChapters: Map<Long, Int>? = null
|
|
||||||
|
|
||||||
/** Save the current list to speed up loading later */
|
/** Save the current list to speed up loading later */
|
||||||
fun onDestroy() {
|
fun onDestroy() {
|
||||||
lastLibraryItems = libraryItems
|
lastLibraryItems = libraryItems
|
||||||
@ -86,7 +88,6 @@ class LibraryPresenter(
|
|||||||
/** Get favorited manga for library and sort and filter it */
|
/** Get favorited manga for library and sort and filter it */
|
||||||
fun getLibrary() {
|
fun getLibrary() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
totalChapters = null
|
|
||||||
val library = withContext(Dispatchers.IO) { getLibraryFromDB() }
|
val library = withContext(Dispatchers.IO) { getLibraryFromDB() }
|
||||||
library.apply {
|
library.apply {
|
||||||
setDownloadCount(library)
|
setDownloadCount(library)
|
||||||
@ -98,9 +99,6 @@ class LibraryPresenter(
|
|||||||
mangaMap = applySort(mangaMap)
|
mangaMap = applySort(mangaMap)
|
||||||
val freshStart = libraryItems.isEmpty()
|
val freshStart = libraryItems.isEmpty()
|
||||||
sectionLibrary(mangaMap, freshStart)
|
sectionLibrary(mangaMap, freshStart)
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
setTotalChapters()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,74 +311,81 @@ class LibraryPresenter(
|
|||||||
* @param itemList the map to sort.
|
* @param itemList the map to sort.
|
||||||
*/
|
*/
|
||||||
private fun applySort(itemList: List<LibraryItem>): List<LibraryItem> {
|
private fun applySort(itemList: List<LibraryItem>): List<LibraryItem> {
|
||||||
val sortingMode = preferences.librarySortingMode().getOrDefault()
|
|
||||||
|
|
||||||
val lastReadManga by lazy {
|
val lastReadManga by lazy {
|
||||||
var counter = 0
|
var counter = 0
|
||||||
db.getLastReadManga().executeAsBlocking().associate { it.id!! to counter++ }
|
db.getLastReadManga().executeAsBlocking().associate { it.id!! to counter++ }
|
||||||
}
|
}
|
||||||
|
|
||||||
val ascending = preferences.librarySortingAscending().getOrDefault()
|
|
||||||
val useDnD = !preferences.hideCategories().getOrDefault()
|
|
||||||
|
|
||||||
val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 ->
|
val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 ->
|
||||||
if (!(sortingMode == LibrarySort.DRAG_AND_DROP || useDnD)) {
|
if (i1.header.category.id == i2.header.category.id) {
|
||||||
i1.chapterCount = -1
|
val category = i1.header.category
|
||||||
i2.chapterCount = -1
|
if (category.mangaOrder.isNullOrEmpty() && category.mangaSort == null) {
|
||||||
}
|
category.changeSortTo(preferences.librarySortingMode().getOrDefault())
|
||||||
val compare = when {
|
if (category.id == 0) preferences.defaultMangaOrder()
|
||||||
sortingMode == LibrarySort.DRAG_AND_DROP || useDnD ->
|
.set(category.mangaSort.toString())
|
||||||
sortCategory(i1, i2, lastReadManga)
|
else if (!category.isDynamic) db.insertCategory(category).executeAsBlocking()
|
||||||
sortingMode == LibrarySort.ALPHA -> sortAlphabetical(i1, i2)
|
|
||||||
sortingMode == LibrarySort.LAST_READ -> {
|
|
||||||
// Get index of manga, set equal to list if size unknown.
|
|
||||||
val manga1LastRead = lastReadManga[i1.manga.id!!] ?: lastReadManga.size
|
|
||||||
val manga2LastRead = lastReadManga[i2.manga.id!!] ?: lastReadManga.size
|
|
||||||
manga1LastRead.compareTo(manga2LastRead)
|
|
||||||
}
|
}
|
||||||
sortingMode == LibrarySort.LATEST_CHAPTER -> i2.manga.last_update.compareTo(i1
|
val compare = when {
|
||||||
.manga.last_update)
|
category.mangaSort != null -> {
|
||||||
sortingMode == LibrarySort.UNREAD ->
|
var sort = when (category.sortingMode()) {
|
||||||
when {
|
LibrarySort.ALPHA -> sortAlphabetical(i1, i2)
|
||||||
i1.manga.unread == i2.manga.unread -> 0
|
LibrarySort.LATEST_CHAPTER -> i2.manga.last_update.compareTo(i1.manga.last_update)
|
||||||
i1.manga.unread == 0 -> if (ascending) 1 else -1
|
LibrarySort.UNREAD -> when {
|
||||||
i2.manga.unread == 0 -> if (ascending) -1 else 1
|
i1.manga.unread == i2.manga.unread -> 0
|
||||||
else -> i1.manga.unread.compareTo(i2.manga.unread)
|
i1.manga.unread == 0 -> if (category.isAscending()) 1 else -1
|
||||||
|
i2.manga.unread == 0 -> if (category.isAscending()) -1 else 1
|
||||||
|
else -> i1.manga.unread.compareTo(i2.manga.unread)
|
||||||
|
}
|
||||||
|
LibrarySort.LAST_READ -> {
|
||||||
|
val manga1LastRead = lastReadManga[i1.manga.id!!] ?: lastReadManga.size
|
||||||
|
val manga2LastRead = lastReadManga[i2.manga.id!!] ?: lastReadManga.size
|
||||||
|
manga1LastRead.compareTo(manga2LastRead)
|
||||||
|
}
|
||||||
|
LibrarySort.TOTAL -> {
|
||||||
|
i1.manga.totalChapters.compareTo(i2.manga.totalChapters)
|
||||||
|
}
|
||||||
|
LibrarySort.DATE_ADDED -> i2.manga.date_added.compareTo(i1.manga.date_added)
|
||||||
|
else -> {
|
||||||
|
if (LibrarySort.DRAG_AND_DROP == category.sortingMode() && category.isDynamic) {
|
||||||
|
val category1 =
|
||||||
|
allCategories.find { i1.manga.category == it.id }?.order
|
||||||
|
?: 0
|
||||||
|
val category2 =
|
||||||
|
allCategories.find { i2.manga.category == it.id }?.order
|
||||||
|
?: 0
|
||||||
|
category1.compareTo(category2)
|
||||||
|
} else {
|
||||||
|
sortAlphabetical(i1, i2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!category.isAscending()) sort *= -1
|
||||||
|
sort
|
||||||
}
|
}
|
||||||
sortingMode == LibrarySort.TOTAL -> {
|
category.mangaOrder.isNotEmpty() -> {
|
||||||
setTotalChapters()
|
val order = category.mangaOrder
|
||||||
val manga1TotalChapter = totalChapters!![i1.manga.id!!] ?: 0
|
val index1 = order.indexOf(i1.manga.id!!)
|
||||||
val mange2TotalChapter = totalChapters!![i2.manga.id!!] ?: 0
|
val index2 = order.indexOf(i2.manga.id!!)
|
||||||
i1.chapterCount = totalChapters!![i1.manga.id!!] ?: 0
|
when {
|
||||||
i2.chapterCount = totalChapters!![i2.manga.id!!] ?: 0
|
index1 == index2 -> 0
|
||||||
manga1TotalChapter.compareTo(mange2TotalChapter)
|
index1 == -1 -> -1
|
||||||
|
index2 == -1 -> 1
|
||||||
|
else -> index1.compareTo(index2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> 0
|
||||||
}
|
}
|
||||||
sortingMode == LibrarySort.DATE_ADDED -> {
|
if (compare == 0) {
|
||||||
i2.manga.date_added.compareTo(i1.manga.date_added)
|
sortAlphabetical(i1, i2)
|
||||||
}
|
} else compare
|
||||||
else -> 0
|
} else {
|
||||||
|
val category = i1.header.category.order
|
||||||
|
val category2 = i2.header.category.order
|
||||||
|
category.compareTo(category2)
|
||||||
}
|
}
|
||||||
if (!(sortingMode == LibrarySort.DRAG_AND_DROP || useDnD) && compare == 0) {
|
|
||||||
if (ascending) sortAlphabetical(i1, i2)
|
|
||||||
else sortAlphabetical(i2, i1)
|
|
||||||
} else compare
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val comparator = if (ascending || useDnD)
|
return itemList.sortedWith(Comparator(sortFn))
|
||||||
Comparator(sortFn)
|
|
||||||
else
|
|
||||||
Collections.reverseOrder(sortFn)
|
|
||||||
|
|
||||||
return itemList.sortedWith(comparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the total chapters for the manga in the library */
|
|
||||||
private fun setTotalChapters() {
|
|
||||||
if (totalChapters != null) return
|
|
||||||
val mangaMap = allLibraryItems
|
|
||||||
totalChapters = mangaMap.map {
|
|
||||||
it.manga.id!! to db.getChapters(it.manga).executeAsBlocking().size
|
|
||||||
}.toMap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the category by id
|
/** Gets the category by id
|
||||||
@ -388,89 +393,11 @@ class LibraryPresenter(
|
|||||||
* @param categoryId id of the categoty to get
|
* @param categoryId id of the categoty to get
|
||||||
*/
|
*/
|
||||||
private fun getCategory(categoryId: Int): Category {
|
private fun getCategory(categoryId: Int): Category {
|
||||||
val category = categories.find { it.id == categoryId } ?: createDefaultCategory()
|
val category = hashCategories[categoryId] ?: createDefaultCategory()
|
||||||
if (category.isFirst == null) {
|
category.isAlone = categories.size <= 1
|
||||||
category.isFirst = categories.minBy { it.order }?.id == category.id
|
|
||||||
}
|
|
||||||
if (category.isLast == null) category.isLast = categories.lastOrNull()?.id == category.id
|
|
||||||
return category
|
return category
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sort 2 manga by the category's sorting
|
|
||||||
*
|
|
||||||
* @param i1 the first manga
|
|
||||||
* @param i2 the second manga to compare
|
|
||||||
* @param lastReadManga map of the last read of the library
|
|
||||||
*/
|
|
||||||
private fun sortCategory(
|
|
||||||
i1: LibraryItem,
|
|
||||||
i2: LibraryItem,
|
|
||||||
lastReadManga: Map<Long, Int>
|
|
||||||
): Int {
|
|
||||||
return if (i1.header.category.id == i2.header.category.id) {
|
|
||||||
val category = i1.header.category
|
|
||||||
if (category.mangaOrder.isNullOrEmpty() && category.mangaSort == null) {
|
|
||||||
category.changeSortTo(preferences.librarySortingMode().getOrDefault())
|
|
||||||
if (category.id == 0) preferences.defaultMangaOrder()
|
|
||||||
.set(category.mangaSort.toString())
|
|
||||||
else if (category.id ?: 0 > 0) db.insertCategory(category).executeAsBlocking()
|
|
||||||
}
|
|
||||||
i1.chapterCount = -1
|
|
||||||
i2.chapterCount = -1
|
|
||||||
val compare = when {
|
|
||||||
category.mangaSort != null -> {
|
|
||||||
var sort = when (category.sortingMode()) {
|
|
||||||
LibrarySort.ALPHA -> sortAlphabetical(i1, i2)
|
|
||||||
LibrarySort.LATEST_CHAPTER -> i2.manga.last_update.compareTo(i1.manga.last_update)
|
|
||||||
LibrarySort.UNREAD -> when {
|
|
||||||
i1.manga.unread == i2.manga.unread -> 0
|
|
||||||
i1.manga.unread == 0 -> if (category.isAscending()) 1 else -1
|
|
||||||
i2.manga.unread == 0 -> if (category.isAscending()) -1 else 1
|
|
||||||
else -> i1.manga.unread.compareTo(i2.manga.unread)
|
|
||||||
}
|
|
||||||
LibrarySort.LAST_READ -> {
|
|
||||||
val manga1LastRead = lastReadManga[i1.manga.id!!] ?: lastReadManga.size
|
|
||||||
val manga2LastRead = lastReadManga[i2.manga.id!!] ?: lastReadManga.size
|
|
||||||
manga1LastRead.compareTo(manga2LastRead)
|
|
||||||
}
|
|
||||||
LibrarySort.TOTAL -> {
|
|
||||||
setTotalChapters()
|
|
||||||
val manga1TotalChapter = totalChapters!![i1.manga.id!!] ?: 0
|
|
||||||
val mange2TotalChapter = totalChapters!![i2.manga.id!!] ?: 0
|
|
||||||
i1.chapterCount = totalChapters!![i1.manga.id!!] ?: 0
|
|
||||||
i2.chapterCount = totalChapters!![i2.manga.id!!] ?: 0
|
|
||||||
manga1TotalChapter.compareTo(mange2TotalChapter)
|
|
||||||
}
|
|
||||||
LibrarySort.DATE_ADDED -> i2.manga.date_added.compareTo(i1.manga.date_added)
|
|
||||||
else -> sortAlphabetical(i1, i2)
|
|
||||||
}
|
|
||||||
if (!category.isAscending()) sort *= -1
|
|
||||||
sort
|
|
||||||
}
|
|
||||||
category.mangaOrder.isNotEmpty() -> {
|
|
||||||
val order = category.mangaOrder
|
|
||||||
val index1 = order.indexOf(i1.manga.id!!)
|
|
||||||
val index2 = order.indexOf(i2.manga.id!!)
|
|
||||||
when {
|
|
||||||
index1 == index2 -> 0
|
|
||||||
index1 == -1 -> -1
|
|
||||||
index2 == -1 -> 1
|
|
||||||
else -> index1.compareTo(index2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> 0
|
|
||||||
}
|
|
||||||
if (compare == 0) {
|
|
||||||
sortAlphabetical(i1, i2)
|
|
||||||
} else compare
|
|
||||||
} else {
|
|
||||||
val category = i1.header.category.order
|
|
||||||
val category2 = i2.header.category.order
|
|
||||||
category.compareTo(category2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sort 2 manga by the their title (and remove articles if need be)
|
* Sort 2 manga by the their title (and remove articles if need be)
|
||||||
*
|
*
|
||||||
@ -478,9 +405,11 @@ class LibraryPresenter(
|
|||||||
* @param i2 the second manga to compare
|
* @param i2 the second manga to compare
|
||||||
*/
|
*/
|
||||||
private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int {
|
private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int {
|
||||||
return if (preferences.removeArticles().getOrDefault())
|
return if (removeArticles) {
|
||||||
i1.manga.title.removeArticles().compareTo(i2.manga.title.removeArticles(), true)
|
i1.manga.title.removeArticles().compareTo(i2.manga.title.removeArticles(), true)
|
||||||
else i1.manga.title.compareTo(i2.manga.title, true)
|
} else {
|
||||||
|
i1.manga.title.compareTo(i2.manga.title, true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -489,6 +418,7 @@ class LibraryPresenter(
|
|||||||
* @return an list of all the manga in a itemized form.
|
* @return an list of all the manga in a itemized form.
|
||||||
*/
|
*/
|
||||||
private fun getLibraryFromDB(): List<LibraryItem> {
|
private fun getLibraryFromDB(): List<LibraryItem> {
|
||||||
|
removeArticles = preferences.removeArticles().getOrDefault()
|
||||||
val categories = db.getCategories().executeAsBlocking().toMutableList()
|
val categories = db.getCategories().executeAsBlocking().toMutableList()
|
||||||
val showCategories = !preferences.hideCategories().getOrDefault()
|
val showCategories = !preferences.hideCategories().getOrDefault()
|
||||||
var libraryManga = db.getLibraryMangas().executeAsBlocking()
|
var libraryManga = db.getLibraryMangas().executeAsBlocking()
|
||||||
@ -550,6 +480,10 @@ class LibraryPresenter(
|
|||||||
this.categories = if (!showCategories) arrayListOf(categoryAll)
|
this.categories = if (!showCategories) arrayListOf(categoryAll)
|
||||||
else categories
|
else categories
|
||||||
|
|
||||||
|
hashCategories = HashMap(this.categories.mapNotNull {
|
||||||
|
it.id!! to it
|
||||||
|
}.toMap())
|
||||||
|
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,7 +628,7 @@ class LibraryPresenter(
|
|||||||
fun sortCategory(catId: Int, order: Int) {
|
fun sortCategory(catId: Int, order: Int) {
|
||||||
val category = categories.find { catId == it.id } ?: return
|
val category = categories.find { catId == it.id } ?: return
|
||||||
category.mangaSort = ('a' + (order - 1))
|
category.mangaSort = ('a' + (order - 1))
|
||||||
if (catId == -1) {
|
if (catId == -1 || category.isDynamic) {
|
||||||
val sort = category.sortingMode() ?: LibrarySort.ALPHA
|
val sort = category.sortingMode() ?: LibrarySort.ALPHA
|
||||||
preferences.librarySortingMode().set(sort)
|
preferences.librarySortingMode().set(sort)
|
||||||
preferences.librarySortingAscending().set(category.isAscending())
|
preferences.librarySortingAscending().set(category.isAscending())
|
||||||
@ -709,6 +643,7 @@ class LibraryPresenter(
|
|||||||
fun rearrangeCategory(catId: Int?, mangaIds: List<Long>) {
|
fun rearrangeCategory(catId: Int?, mangaIds: List<Long>) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val category = categories.find { catId == it.id } ?: return@launch
|
val category = categories.find { catId == it.id } ?: return@launch
|
||||||
|
if (category.isDynamic) return@launch
|
||||||
category.mangaSort = null
|
category.mangaSort = null
|
||||||
category.mangaOrder = mangaIds
|
category.mangaOrder = mangaIds
|
||||||
if (category.id == 0) preferences.defaultMangaOrder().set(mangaIds.joinToString("/"))
|
if (category.id == 0) preferences.defaultMangaOrder().set(mangaIds.joinToString("/"))
|
||||||
@ -726,6 +661,7 @@ class LibraryPresenter(
|
|||||||
scope.launch {
|
scope.launch {
|
||||||
val categoryId = catId ?: return@launch
|
val categoryId = catId ?: return@launch
|
||||||
val category = categories.find { catId == it.id } ?: return@launch
|
val category = categories.find { catId == it.id } ?: return@launch
|
||||||
|
if (category.isDynamic) return@launch
|
||||||
|
|
||||||
val oldCatId = manga.category
|
val oldCatId = manga.category
|
||||||
manga.category = categoryId
|
manga.category = categoryId
|
||||||
@ -762,7 +698,7 @@ class LibraryPresenter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun toggleCategoryVisibility(categoryId: Int) {
|
fun toggleCategoryVisibility(categoryId: Int) {
|
||||||
if (categoryId <= -1) return
|
if (categoryId <= -1 || categories.find { it.id == categoryId }?.isDynamic == true) return
|
||||||
val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull {
|
val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull {
|
||||||
it.toIntOrNull()
|
it.toIntOrNull()
|
||||||
}.toMutableSet()
|
}.toMutableSet()
|
||||||
|
@ -14,7 +14,12 @@ fun String.chop(count: Int, replacement: String = "..."): String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun String.removeArticles(): String {
|
fun String.removeArticles(): String {
|
||||||
return this.replace(Regex("^(an|a|the) ", RegexOption.IGNORE_CASE), "")
|
return when {
|
||||||
|
startsWith("a ", true) -> substring(2)
|
||||||
|
startsWith("an ", true) -> substring(3)
|
||||||
|
startsWith("the ", true) -> substring(4)
|
||||||
|
else -> this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user