mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Migrate to more use of domain models
This commit is contained in:
		@@ -2,6 +2,9 @@ package eu.kanade.domain.category.model
 | 
			
		||||
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
 | 
			
		||||
import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting
 | 
			
		||||
import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting
 | 
			
		||||
import java.io.Serializable
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category as DbCategory
 | 
			
		||||
 | 
			
		||||
@@ -12,6 +15,15 @@ data class Category(
 | 
			
		||||
    val flags: Long,
 | 
			
		||||
) : Serializable {
 | 
			
		||||
 | 
			
		||||
    val displayMode: Long
 | 
			
		||||
        get() = flags and DisplayModeSetting.MASK
 | 
			
		||||
 | 
			
		||||
    val sortMode: Long
 | 
			
		||||
        get() = flags and SortModeSetting.MASK
 | 
			
		||||
 | 
			
		||||
    val sortDirection: Long
 | 
			
		||||
        get() = flags and SortDirectionSetting.MASK
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        val default = { context: Context ->
 | 
			
		||||
            Category(
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.widget.ExtendedNavigationView
 | 
			
		||||
import tachiyomi.source.model.MangaInfo
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
import java.io.Serializable
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga as DbManga
 | 
			
		||||
 | 
			
		||||
data class Manga(
 | 
			
		||||
@@ -29,7 +30,7 @@ data class Manga(
 | 
			
		||||
    val status: Long,
 | 
			
		||||
    val thumbnailUrl: String?,
 | 
			
		||||
    val initialized: Boolean,
 | 
			
		||||
) {
 | 
			
		||||
) : Serializable {
 | 
			
		||||
 | 
			
		||||
    fun toSManga(): SManga {
 | 
			
		||||
        return SManga.create().also {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,11 +2,9 @@ package eu.kanade.tachiyomi.data.database
 | 
			
		||||
 | 
			
		||||
import androidx.sqlite.db.SupportSQLiteOpenHelper
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.impl.DefaultStorIOSQLite
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.mappers.CategoryTypeMapping
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.mappers.ChapterTypeMapping
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.mappers.MangaCategoryTypeMapping
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.mappers.MangaTypeMapping
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Chapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
 | 
			
		||||
@@ -26,7 +24,6 @@ class DatabaseHelper(
 | 
			
		||||
        .sqliteOpenHelper(openHelper)
 | 
			
		||||
        .addTypeMapping(Manga::class.java, MangaTypeMapping())
 | 
			
		||||
        .addTypeMapping(Chapter::class.java, ChapterTypeMapping())
 | 
			
		||||
        .addTypeMapping(Category::class.java, CategoryTypeMapping())
 | 
			
		||||
        .addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping())
 | 
			
		||||
        .build()
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,64 +0,0 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.database.mappers
 | 
			
		||||
 | 
			
		||||
import android.database.Cursor
 | 
			
		||||
import androidx.core.content.contentValuesOf
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.SQLiteTypeMapping
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.operations.delete.DefaultDeleteResolver
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.operations.get.DefaultGetResolver
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.operations.put.DefaultPutResolver
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.queries.DeleteQuery
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.queries.InsertQuery
 | 
			
		||||
import com.pushtorefresh.storio.sqlite.queries.UpdateQuery
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.CategoryImpl
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_FLAGS
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_ID
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_NAME
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.COL_ORDER
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable.TABLE
 | 
			
		||||
 | 
			
		||||
class CategoryTypeMapping : SQLiteTypeMapping<Category>(
 | 
			
		||||
    CategoryPutResolver(),
 | 
			
		||||
    CategoryGetResolver(),
 | 
			
		||||
    CategoryDeleteResolver(),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
class CategoryPutResolver : DefaultPutResolver<Category>() {
 | 
			
		||||
 | 
			
		||||
    override fun mapToInsertQuery(obj: Category) = InsertQuery.builder()
 | 
			
		||||
        .table(TABLE)
 | 
			
		||||
        .build()
 | 
			
		||||
 | 
			
		||||
    override fun mapToUpdateQuery(obj: Category) = UpdateQuery.builder()
 | 
			
		||||
        .table(TABLE)
 | 
			
		||||
        .where("$COL_ID = ?")
 | 
			
		||||
        .whereArgs(obj.id)
 | 
			
		||||
        .build()
 | 
			
		||||
 | 
			
		||||
    override fun mapToContentValues(obj: Category) =
 | 
			
		||||
        contentValuesOf(
 | 
			
		||||
            COL_ID to obj.id,
 | 
			
		||||
            COL_NAME to obj.name,
 | 
			
		||||
            COL_ORDER to obj.order,
 | 
			
		||||
            COL_FLAGS to obj.flags,
 | 
			
		||||
        )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class CategoryGetResolver : DefaultGetResolver<Category>() {
 | 
			
		||||
 | 
			
		||||
    override fun mapFromCursor(cursor: Cursor): Category = CategoryImpl().apply {
 | 
			
		||||
        id = cursor.getInt(cursor.getColumnIndexOrThrow(COL_ID))
 | 
			
		||||
        name = cursor.getString(cursor.getColumnIndexOrThrow(COL_NAME))
 | 
			
		||||
        order = cursor.getInt(cursor.getColumnIndexOrThrow(COL_ORDER))
 | 
			
		||||
        flags = cursor.getInt(cursor.getColumnIndexOrThrow(COL_FLAGS))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class CategoryDeleteResolver : DefaultDeleteResolver<Category>() {
 | 
			
		||||
 | 
			
		||||
    override fun mapToDeleteQuery(obj: Category) = DeleteQuery.builder()
 | 
			
		||||
        .table(TABLE)
 | 
			
		||||
        .where("$COL_ID = ?")
 | 
			
		||||
        .whereArgs(obj.id)
 | 
			
		||||
        .build()
 | 
			
		||||
}
 | 
			
		||||
@@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
 | 
			
		||||
import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting
 | 
			
		||||
import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting
 | 
			
		||||
import java.io.Serializable
 | 
			
		||||
import eu.kanade.domain.category.model.Category as DomainCategory
 | 
			
		||||
 | 
			
		||||
interface Category : Serializable {
 | 
			
		||||
 | 
			
		||||
@@ -22,16 +23,16 @@ interface Category : Serializable {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var displayMode: Int
 | 
			
		||||
        get() = flags and DisplayModeSetting.MASK
 | 
			
		||||
        set(mode) = setFlags(mode, DisplayModeSetting.MASK)
 | 
			
		||||
        get() = flags and DisplayModeSetting.MASK.toInt()
 | 
			
		||||
        set(mode) = setFlags(mode, DisplayModeSetting.MASK.toInt())
 | 
			
		||||
 | 
			
		||||
    var sortMode: Int
 | 
			
		||||
        get() = flags and SortModeSetting.MASK
 | 
			
		||||
        set(mode) = setFlags(mode, SortModeSetting.MASK)
 | 
			
		||||
        get() = flags and SortModeSetting.MASK.toInt()
 | 
			
		||||
        set(mode) = setFlags(mode, SortModeSetting.MASK.toInt())
 | 
			
		||||
 | 
			
		||||
    var sortDirection: Int
 | 
			
		||||
        get() = flags and SortDirectionSetting.MASK
 | 
			
		||||
        set(mode) = setFlags(mode, SortDirectionSetting.MASK)
 | 
			
		||||
        get() = flags and SortDirectionSetting.MASK.toInt()
 | 
			
		||||
        set(mode) = setFlags(mode, SortDirectionSetting.MASK.toInt())
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
@@ -42,3 +43,13 @@ interface Category : Serializable {
 | 
			
		||||
        fun createDefault(context: Context): Category = create(context.getString(R.string.label_default)).apply { id = 0 }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fun Category.toDomainCategory(): DomainCategory? {
 | 
			
		||||
    val categoryId = id ?: return null
 | 
			
		||||
    return DomainCategory(
 | 
			
		||||
        id = categoryId.toLong(),
 | 
			
		||||
        name = this.name,
 | 
			
		||||
        order = this.order.toLong(),
 | 
			
		||||
        flags = this.flags.toLong(),
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.database.models
 | 
			
		||||
 | 
			
		||||
import eu.kanade.domain.category.model.Category as DomainCategory
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga as DomainManga
 | 
			
		||||
 | 
			
		||||
class MangaCategory {
 | 
			
		||||
 | 
			
		||||
    var id: Long? = null
 | 
			
		||||
@@ -10,6 +13,13 @@ class MangaCategory {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
        fun create(manga: DomainManga, category: DomainCategory): MangaCategory {
 | 
			
		||||
            val mc = MangaCategory()
 | 
			
		||||
            mc.manga_id = manga.id
 | 
			
		||||
            mc.category_id = category.id.toInt()
 | 
			
		||||
            return mc
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun create(manga: Manga, category: Category): MangaCategory {
 | 
			
		||||
            val mc = MangaCategory()
 | 
			
		||||
            mc.manga_id = manga.id!!
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
package eu.kanade.tachiyomi.data.database.queries
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.CategoryTable as Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.ChapterTable as Chapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.MangaCategoryTable as MangaCategory
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.tables.MangaTable as Manga
 | 
			
		||||
@@ -36,14 +35,3 @@ val libraryQuery =
 | 
			
		||||
        SELECT * FROM ${MangaCategory.TABLE}) AS MC
 | 
			
		||||
        ON MC.${MangaCategory.COL_MANGA_ID} = M.${Manga.COL_ID}
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Query to get the categories for a manga.
 | 
			
		||||
 */
 | 
			
		||||
fun getCategoriesForMangaQuery() =
 | 
			
		||||
    """
 | 
			
		||||
    SELECT ${Category.TABLE}.* FROM ${Category.TABLE}
 | 
			
		||||
    JOIN ${MangaCategory.TABLE} ON ${Category.TABLE}.${Category.COL_ID} =
 | 
			
		||||
    ${MangaCategory.TABLE}.${MangaCategory.COL_CATEGORY_ID}
 | 
			
		||||
    WHERE ${MangaCategory.COL_MANGA_ID} = ?
 | 
			
		||||
"""
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,4 @@ package eu.kanade.tachiyomi.data.database.tables
 | 
			
		||||
object CategoryTable {
 | 
			
		||||
 | 
			
		||||
    const val TABLE = "categories"
 | 
			
		||||
 | 
			
		||||
    const val COL_ID = "_id"
 | 
			
		||||
 | 
			
		||||
    const val COL_NAME = "name"
 | 
			
		||||
 | 
			
		||||
    const val COL_ORDER = "sort"
 | 
			
		||||
 | 
			
		||||
    const val COL_FLAGS = "flags"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import android.os.PowerManager
 | 
			
		||||
import androidx.core.content.ContextCompat
 | 
			
		||||
import eu.kanade.data.chapter.NoChaptersException
 | 
			
		||||
import eu.kanade.domain.category.interactor.GetCategories
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
 | 
			
		||||
@@ -22,7 +23,6 @@ import eu.kanade.domain.track.model.toDomainTrack
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.cache.CoverCache
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Chapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
@@ -228,7 +228,7 @@ class LibraryUpdateService(
 | 
			
		||||
        ioScope?.cancel()
 | 
			
		||||
 | 
			
		||||
        // Update favorite manga
 | 
			
		||||
        val categoryId = intent.getIntExtra(KEY_CATEGORY, -1)
 | 
			
		||||
        val categoryId = intent.getLongExtra(KEY_CATEGORY, -1L)
 | 
			
		||||
        addMangaToQueue(categoryId)
 | 
			
		||||
 | 
			
		||||
        // Destroy service when completed or in case of an error.
 | 
			
		||||
@@ -254,11 +254,11 @@ class LibraryUpdateService(
 | 
			
		||||
     *
 | 
			
		||||
     * @param categoryId the ID of the category to update, or -1 if no category specified.
 | 
			
		||||
     */
 | 
			
		||||
    fun addMangaToQueue(categoryId: Int) {
 | 
			
		||||
    fun addMangaToQueue(categoryId: Long) {
 | 
			
		||||
        val libraryManga = db.getLibraryMangas().executeAsBlocking()
 | 
			
		||||
 | 
			
		||||
        val listToUpdate = if (categoryId != -1) {
 | 
			
		||||
            libraryManga.filter { it.category == categoryId }
 | 
			
		||||
        val listToUpdate = if (categoryId != -1L) {
 | 
			
		||||
            libraryManga.filter { it.category.toLong() == categoryId }
 | 
			
		||||
        } else {
 | 
			
		||||
            val categoriesToUpdate = preferences.libraryUpdateCategories().get().map(String::toInt)
 | 
			
		||||
            val listToInclude = if (categoriesToUpdate.isNotEmpty()) {
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toDomainManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.source.CatalogueSource
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
 | 
			
		||||
@@ -149,6 +150,6 @@ class SearchController(
 | 
			
		||||
    override fun onTitleClick(source: CatalogueSource) {
 | 
			
		||||
        presenter.preferences.lastUsedSource().set(source.id)
 | 
			
		||||
 | 
			
		||||
        router.pushController(SourceSearchController(manga, source, presenter.query))
 | 
			
		||||
        router.pushController(SourceSearchController(manga?.toDomainManga(), source, presenter.query))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,8 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
 | 
			
		||||
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import android.view.View
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.domain.manga.model.toDbManga
 | 
			
		||||
import eu.kanade.tachiyomi.source.CatalogueSource
 | 
			
		||||
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.browse.source.browse.SourceItem
 | 
			
		||||
@@ -28,7 +29,7 @@ class SourceSearchController(
 | 
			
		||||
        newManga = item.manga
 | 
			
		||||
        val searchController = router.backstack.findLast { it.controller.javaClass == SearchController::class.java }?.controller as SearchController?
 | 
			
		||||
        val dialog =
 | 
			
		||||
            SearchController.MigrationDialog(oldManga, newManga, this)
 | 
			
		||||
            SearchController.MigrationDialog(oldManga?.toDbManga(), newManga?.toDbManga(), this)
 | 
			
		||||
        dialog.targetController = searchController
 | 
			
		||||
        dialog.showDialog(router)
 | 
			
		||||
        return true
 | 
			
		||||
 
 | 
			
		||||
@@ -20,11 +20,11 @@ import com.google.android.material.snackbar.Snackbar
 | 
			
		||||
import dev.chrisbanes.insetter.applyInsetter
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.davidea.flexibleadapter.items.IFlexible
 | 
			
		||||
import eu.kanade.domain.category.model.toDbCategory
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.domain.manga.model.toDbManga
 | 
			
		||||
import eu.kanade.domain.source.model.Source
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.SourceControllerBinding
 | 
			
		||||
import eu.kanade.tachiyomi.source.CatalogueSource
 | 
			
		||||
@@ -541,7 +541,7 @@ open class BrowseSourceController(bundle: Bundle) :
 | 
			
		||||
 | 
			
		||||
        adapter.allBoundViewHolders.forEach { holder ->
 | 
			
		||||
            val item = adapter.getItem(holder.bindingAdapterPosition) as? SourceItem
 | 
			
		||||
            if (item != null && item.manga.id!! == manga.id!!) {
 | 
			
		||||
            if (item != null && item.manga.id == manga.id) {
 | 
			
		||||
                return holder as SourceHolder<*>
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -575,7 +575,7 @@ open class BrowseSourceController(bundle: Bundle) :
 | 
			
		||||
     */
 | 
			
		||||
    override fun onItemClick(view: View, position: Int): Boolean {
 | 
			
		||||
        val item = adapter?.getItem(position) as? SourceItem ?: return false
 | 
			
		||||
        router.pushController(MangaController(item.manga.id!!, true))
 | 
			
		||||
        router.pushController(MangaController(item.manga.id, true))
 | 
			
		||||
 | 
			
		||||
        return false
 | 
			
		||||
    }
 | 
			
		||||
@@ -602,7 +602,7 @@ open class BrowseSourceController(bundle: Bundle) :
 | 
			
		||||
                        .setItems(arrayOf(activity.getString(R.string.remove_from_library))) { _, which ->
 | 
			
		||||
                            when (which) {
 | 
			
		||||
                                0 -> {
 | 
			
		||||
                                    presenter.changeMangaFavorite(manga)
 | 
			
		||||
                                    presenter.changeMangaFavorite(manga.toDbManga())
 | 
			
		||||
                                    adapter?.notifyItemChanged(position)
 | 
			
		||||
                                    activity.toast(activity.getString(R.string.manga_removed_library))
 | 
			
		||||
                                }
 | 
			
		||||
@@ -637,18 +637,18 @@ open class BrowseSourceController(bundle: Bundle) :
 | 
			
		||||
                when {
 | 
			
		||||
                    // Default category set
 | 
			
		||||
                    defaultCategory != null -> {
 | 
			
		||||
                        presenter.moveMangaToCategory(newManga, defaultCategory.toDbCategory())
 | 
			
		||||
                        presenter.moveMangaToCategory(newManga.toDbManga(), defaultCategory)
 | 
			
		||||
 | 
			
		||||
                        presenter.changeMangaFavorite(newManga)
 | 
			
		||||
                        presenter.changeMangaFavorite(newManga.toDbManga())
 | 
			
		||||
                        adapter?.notifyItemChanged(position)
 | 
			
		||||
                        activity.toast(activity.getString(R.string.manga_added_library))
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Automatic 'Default' or no categories
 | 
			
		||||
                    defaultCategoryId == 0 || categories.isEmpty() -> {
 | 
			
		||||
                        presenter.moveMangaToCategory(newManga, null)
 | 
			
		||||
                        presenter.moveMangaToCategory(newManga.toDbManga(), null)
 | 
			
		||||
 | 
			
		||||
                        presenter.changeMangaFavorite(newManga)
 | 
			
		||||
                        presenter.changeMangaFavorite(newManga.toDbManga())
 | 
			
		||||
                        adapter?.notifyItemChanged(position)
 | 
			
		||||
                        activity.toast(activity.getString(R.string.manga_added_library))
 | 
			
		||||
                    }
 | 
			
		||||
@@ -664,7 +664,7 @@ open class BrowseSourceController(bundle: Bundle) :
 | 
			
		||||
                            }
 | 
			
		||||
                        }.toTypedArray()
 | 
			
		||||
 | 
			
		||||
                        ChangeMangaCategoriesDialog(this@BrowseSourceController, listOf(newManga), categories.map { it.toDbCategory() }, preselected)
 | 
			
		||||
                        ChangeMangaCategoriesDialog(this@BrowseSourceController, listOf(newManga), categories, preselected)
 | 
			
		||||
                            .showDialog(router)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -681,8 +681,8 @@ open class BrowseSourceController(bundle: Bundle) :
 | 
			
		||||
    override fun updateCategoriesForMangas(mangas: List<Manga>, addCategories: List<Category>, removeCategories: List<Category>) {
 | 
			
		||||
        val manga = mangas.firstOrNull() ?: return
 | 
			
		||||
 | 
			
		||||
        presenter.changeMangaFavorite(manga)
 | 
			
		||||
        presenter.updateMangaCategories(manga, addCategories)
 | 
			
		||||
        presenter.changeMangaFavorite(manga.toDbManga())
 | 
			
		||||
        presenter.updateMangaCategories(manga.toDbManga(), addCategories)
 | 
			
		||||
 | 
			
		||||
        val position = adapter?.currentItems?.indexOfFirst { it -> (it as SourceItem).manga.id == manga.id }
 | 
			
		||||
        if (position != null) {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import eu.davidea.flexibleadapter.items.IFlexible
 | 
			
		||||
import eu.kanade.domain.category.interactor.GetCategories
 | 
			
		||||
import eu.kanade.domain.category.model.toDbCategory
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
 | 
			
		||||
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
 | 
			
		||||
@@ -11,9 +12,9 @@ import eu.kanade.domain.track.interactor.InsertTrack
 | 
			
		||||
import eu.kanade.domain.track.model.toDomainTrack
 | 
			
		||||
import eu.kanade.tachiyomi.data.cache.CoverCache
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.MangaCategory
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toDomainManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
 | 
			
		||||
@@ -52,6 +53,7 @@ import kotlinx.coroutines.flow.filter
 | 
			
		||||
import kotlinx.coroutines.flow.firstOrNull
 | 
			
		||||
import kotlinx.coroutines.flow.map
 | 
			
		||||
import kotlinx.coroutines.flow.onEach
 | 
			
		||||
import kotlinx.coroutines.runBlocking
 | 
			
		||||
import logcat.LogPriority
 | 
			
		||||
import rx.Subscription
 | 
			
		||||
import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
@@ -60,6 +62,7 @@ import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
import java.util.Date
 | 
			
		||||
import eu.kanade.domain.category.model.Category as DomainCategory
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga as DomainManga
 | 
			
		||||
 | 
			
		||||
open class BrowseSourcePresenter(
 | 
			
		||||
    private val sourceId: Long,
 | 
			
		||||
@@ -157,7 +160,7 @@ open class BrowseSourcePresenter(
 | 
			
		||||
        pagerSubscription?.let { remove(it) }
 | 
			
		||||
        pagerSubscription = pager.results()
 | 
			
		||||
            .observeOn(Schedulers.io())
 | 
			
		||||
            .map { (first, second) -> first to second.map { networkToLocalManga(it, sourceId) } }
 | 
			
		||||
            .map { (first, second) -> first to second.map { networkToLocalManga(it, sourceId).toDomainManga()!! } }
 | 
			
		||||
            .doOnNext { initializeMangas(it.second) }
 | 
			
		||||
            .map { (first, second) -> first to second.map { SourceItem(it, sourceDisplayMode) } }
 | 
			
		||||
            .observeOn(AndroidSchedulers.mainThread())
 | 
			
		||||
@@ -225,15 +228,15 @@ open class BrowseSourcePresenter(
 | 
			
		||||
     *
 | 
			
		||||
     * @param mangas the list of manga to initialize.
 | 
			
		||||
     */
 | 
			
		||||
    fun initializeMangas(mangas: List<Manga>) {
 | 
			
		||||
    fun initializeMangas(mangas: List<DomainManga>) {
 | 
			
		||||
        presenterScope.launchIO {
 | 
			
		||||
            mangas.asFlow()
 | 
			
		||||
                .filter { it.thumbnail_url == null && !it.initialized }
 | 
			
		||||
                .map { getMangaDetails(it) }
 | 
			
		||||
                .filter { it.thumbnailUrl == null && !it.initialized }
 | 
			
		||||
                .map { getMangaDetails(it.toDbManga()) }
 | 
			
		||||
                .onEach {
 | 
			
		||||
                    withUIContext {
 | 
			
		||||
                        @Suppress("DEPRECATION")
 | 
			
		||||
                        view?.onMangaInitialized(it)
 | 
			
		||||
                        view?.onMangaInitialized(it.toDomainManga()!!)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                .catch { e -> logcat(LogPriority.ERROR, e) }
 | 
			
		||||
@@ -362,8 +365,8 @@ open class BrowseSourcePresenter(
 | 
			
		||||
        return getCategories.subscribe().firstOrNull() ?: emptyList()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    suspend fun getDuplicateLibraryManga(manga: Manga): Manga? {
 | 
			
		||||
        return getDuplicateLibraryManga.await(manga.title, manga.source)?.toDbManga()
 | 
			
		||||
    suspend fun getDuplicateLibraryManga(manga: DomainManga): DomainManga? {
 | 
			
		||||
        return getDuplicateLibraryManga.await(manga.title, manga.source)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -372,9 +375,10 @@ open class BrowseSourcePresenter(
 | 
			
		||||
     * @param manga the manga to get categories from.
 | 
			
		||||
     * @return Array of category ids the manga is in, if none returns default id
 | 
			
		||||
     */
 | 
			
		||||
    suspend fun getMangaCategoryIds(manga: Manga): Array<Long?> {
 | 
			
		||||
        val categories = getCategories.await(manga.id!!)
 | 
			
		||||
        return categories.map { it.id }.toTypedArray()
 | 
			
		||||
    fun getMangaCategoryIds(manga: DomainManga): Array<Long?> {
 | 
			
		||||
        return runBlocking { getCategories.await(manga.id) }
 | 
			
		||||
            .map { it.id }
 | 
			
		||||
            .toTypedArray()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -383,8 +387,8 @@ open class BrowseSourcePresenter(
 | 
			
		||||
     * @param categories the selected categories.
 | 
			
		||||
     * @param manga the manga to move.
 | 
			
		||||
     */
 | 
			
		||||
    private fun moveMangaToCategories(manga: Manga, categories: List<Category>) {
 | 
			
		||||
        val mc = categories.filter { it.id != 0 }.map { MangaCategory.create(manga, it) }
 | 
			
		||||
    private fun moveMangaToCategories(manga: Manga, categories: List<DomainCategory>) {
 | 
			
		||||
        val mc = categories.filter { it.id != 0L }.map { MangaCategory.create(manga, it.toDbCategory()) }
 | 
			
		||||
        db.setMangaCategories(mc, listOf(manga))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -394,7 +398,7 @@ open class BrowseSourcePresenter(
 | 
			
		||||
     * @param category the selected category.
 | 
			
		||||
     * @param manga the manga to move.
 | 
			
		||||
     */
 | 
			
		||||
    fun moveMangaToCategory(manga: Manga, category: Category?) {
 | 
			
		||||
    fun moveMangaToCategory(manga: Manga, category: DomainCategory?) {
 | 
			
		||||
        moveMangaToCategories(manga, listOfNotNull(category))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -404,7 +408,7 @@ open class BrowseSourcePresenter(
 | 
			
		||||
     * @param manga needed to change
 | 
			
		||||
     * @param selectedCategories selected categories
 | 
			
		||||
     */
 | 
			
		||||
    fun updateMangaCategories(manga: Manga, selectedCategories: List<Category>) {
 | 
			
		||||
    fun updateMangaCategories(manga: Manga, selectedCategories: List<DomainCategory>) {
 | 
			
		||||
        if (!manga.favorite) {
 | 
			
		||||
            changeMangaFavorite(manga)
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
import coil.dispose
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding
 | 
			
		||||
import eu.kanade.tachiyomi.util.view.loadAutoPause
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
 | 
			
		||||
import androidx.core.view.isVisible
 | 
			
		||||
import coil.dispose
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding
 | 
			
		||||
import eu.kanade.tachiyomi.util.view.loadAutoPause
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import android.view.View
 | 
			
		||||
import androidx.viewbinding.ViewBinding
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.davidea.viewholders.FlexibleViewHolder
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Generic class used to hold the displayed data of a manga in the catalogue.
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,8 @@ import com.fredporciuncula.flow.preferences.Preference
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
 | 
			
		||||
import eu.davidea.flexibleadapter.items.IFlexible
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding
 | 
			
		||||
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,9 @@ import androidx.core.view.isVisible
 | 
			
		||||
import coil.dispose
 | 
			
		||||
import coil.load
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.SourceListItemBinding
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.getResourceColor
 | 
			
		||||
 | 
			
		||||
@@ -51,7 +51,7 @@ class SourceListHolder(private val view: View, adapter: FlexibleAdapter<*>) :
 | 
			
		||||
 | 
			
		||||
    override fun setImage(manga: Manga) {
 | 
			
		||||
        binding.thumbnail.dispose()
 | 
			
		||||
        if (!manga.thumbnail_url.isNullOrEmpty()) {
 | 
			
		||||
        if (!manga.thumbnailUrl.isNullOrEmpty()) {
 | 
			
		||||
            binding.thumbnail.load(manga) {
 | 
			
		||||
                setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,9 @@ import android.app.Dialog
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import com.bluelinelabs.conductor.Controller
 | 
			
		||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.category.CategoryController
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.library
 | 
			
		||||
import android.view.LayoutInflater
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.view.ViewGroup
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.LibraryCategoryBinding
 | 
			
		||||
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
 | 
			
		||||
@@ -153,7 +153,7 @@ class LibraryAdapter(
 | 
			
		||||
 | 
			
		||||
    override fun getViewType(position: Int): Int {
 | 
			
		||||
        val category = categories.getOrNull(position)
 | 
			
		||||
        return if (isPerCategory && category?.id != 0) {
 | 
			
		||||
        return if (isPerCategory && category?.id != 0L) {
 | 
			
		||||
            if (DisplayModeSetting.fromFlag(category?.displayMode) == DisplayModeSetting.LIST) {
 | 
			
		||||
                LIST_DISPLAY_MODE
 | 
			
		||||
            } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,8 @@ import androidx.recyclerview.widget.LinearLayoutManager
 | 
			
		||||
import dev.chrisbanes.insetter.applyInsetter
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.davidea.flexibleadapter.SelectableAdapter
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.LibraryCategoryBinding
 | 
			
		||||
 
 | 
			
		||||
@@ -15,9 +15,11 @@ import com.fredporciuncula.flow.preferences.Preference
 | 
			
		||||
import com.google.android.material.tabs.TabLayout
 | 
			
		||||
import com.jakewharton.rxrelay.BehaviorRelay
 | 
			
		||||
import com.jakewharton.rxrelay.PublishRelay
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.domain.category.model.toDbCategory
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toDomainManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.databinding.LibraryControllerBinding
 | 
			
		||||
@@ -50,6 +52,7 @@ import rx.android.schedulers.AndroidSchedulers
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
import java.util.concurrent.TimeUnit
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga as DbManga
 | 
			
		||||
 | 
			
		||||
class LibraryController(
 | 
			
		||||
    bundle: Bundle? = null,
 | 
			
		||||
@@ -74,7 +77,7 @@ class LibraryController(
 | 
			
		||||
    /**
 | 
			
		||||
     * Currently selected mangas.
 | 
			
		||||
     */
 | 
			
		||||
    val selectedMangas = mutableSetOf<Manga>()
 | 
			
		||||
    val selectedMangas = mutableSetOf<DbManga>()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Relay to notify the UI of selection updates.
 | 
			
		||||
@@ -94,12 +97,12 @@ class LibraryController(
 | 
			
		||||
    /**
 | 
			
		||||
     * Relay to notify the library's viewpager to select all manga
 | 
			
		||||
     */
 | 
			
		||||
    val selectAllRelay: PublishRelay<Int> = PublishRelay.create()
 | 
			
		||||
    val selectAllRelay: PublishRelay<Long> = PublishRelay.create()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Relay to notify the library's viewpager to select the inverse
 | 
			
		||||
     */
 | 
			
		||||
    val selectInverseRelay: PublishRelay<Int> = PublishRelay.create()
 | 
			
		||||
    val selectInverseRelay: PublishRelay<Long> = PublishRelay.create()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Number of manga per row in grid mode.
 | 
			
		||||
@@ -262,14 +265,14 @@ class LibraryController(
 | 
			
		||||
    fun showSettingsSheet() {
 | 
			
		||||
        if (adapter?.categories?.isNotEmpty() == true) {
 | 
			
		||||
            adapter?.categories?.get(binding.libraryPager.currentItem)?.let { category ->
 | 
			
		||||
                settingsSheet?.show(category)
 | 
			
		||||
                settingsSheet?.show(category.toDbCategory())
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            settingsSheet?.show()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onNextLibraryUpdate(categories: List<Category>, mangaMap: Map<Int, List<LibraryItem>>) {
 | 
			
		||||
    fun onNextLibraryUpdate(categories: List<Category>, mangaMap: LibraryMap) {
 | 
			
		||||
        val view = view ?: return
 | 
			
		||||
        val adapter = adapter ?: return
 | 
			
		||||
 | 
			
		||||
@@ -344,7 +347,7 @@ class LibraryController(
 | 
			
		||||
        if (!firstLaunch) {
 | 
			
		||||
            mangaCountVisibilityRelay.call(preferences.categoryNumberOfItems().get())
 | 
			
		||||
        }
 | 
			
		||||
        tabsVisibilityRelay.call(preferences.categoryTabs().get() && adapter?.categories?.size ?: 0 > 1)
 | 
			
		||||
        tabsVisibilityRelay.call(preferences.categoryTabs().get() && (adapter?.categories?.size ?: 0) > 1)
 | 
			
		||||
        updateTitle()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -493,7 +496,7 @@ class LibraryController(
 | 
			
		||||
        actionMode = null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun openManga(manga: Manga) {
 | 
			
		||||
    fun openManga(manga: DbManga) {
 | 
			
		||||
        // Notify the presenter a manga is being opened.
 | 
			
		||||
        presenter.onOpenManga()
 | 
			
		||||
 | 
			
		||||
@@ -506,7 +509,7 @@ class LibraryController(
 | 
			
		||||
     * @param manga the manga whose selection has changed.
 | 
			
		||||
     * @param selected whether it's now selected or not.
 | 
			
		||||
     */
 | 
			
		||||
    fun setSelection(manga: Manga, selected: Boolean) {
 | 
			
		||||
    fun setSelection(manga: DbManga, selected: Boolean) {
 | 
			
		||||
        if (selected) {
 | 
			
		||||
            if (selectedMangas.add(manga)) {
 | 
			
		||||
                selectionRelay.call(LibrarySelectionEvent.Selected(manga))
 | 
			
		||||
@@ -523,7 +526,7 @@ class LibraryController(
 | 
			
		||||
     *
 | 
			
		||||
     * @param manga the manga whose selection to change.
 | 
			
		||||
     */
 | 
			
		||||
    fun toggleSelection(manga: Manga) {
 | 
			
		||||
    fun toggleSelection(manga: DbManga) {
 | 
			
		||||
        if (selectedMangas.add(manga)) {
 | 
			
		||||
            selectionRelay.call(LibrarySelectionEvent.Selected(manga))
 | 
			
		||||
        } else if (selectedMangas.remove(manga)) {
 | 
			
		||||
@@ -550,7 +553,7 @@ class LibraryController(
 | 
			
		||||
            val mangas = selectedMangas.toList()
 | 
			
		||||
 | 
			
		||||
            // Hide the default category because it has a different behavior than the ones from db.
 | 
			
		||||
            val categories = presenter.categories.filter { it.id != 0 }
 | 
			
		||||
            val categories = presenter.categories.filter { it.id != 0L }
 | 
			
		||||
 | 
			
		||||
            // Get indexes of the common categories to preselect.
 | 
			
		||||
            val common = presenter.getCommonCategories(mangas)
 | 
			
		||||
@@ -564,7 +567,7 @@ class LibraryController(
 | 
			
		||||
                }
 | 
			
		||||
            }.toTypedArray()
 | 
			
		||||
            launchUI {
 | 
			
		||||
                ChangeMangaCategoriesDialog(this@LibraryController, mangas, categories, preselected)
 | 
			
		||||
                ChangeMangaCategoriesDialog(this@LibraryController, mangas.map { it.toDomainManga()!! }, categories, preselected)
 | 
			
		||||
                    .showDialog(router)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -591,7 +594,7 @@ class LibraryController(
 | 
			
		||||
        destroyActionModeIfNeeded()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun deleteMangas(mangas: List<Manga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
 | 
			
		||||
    override fun deleteMangas(mangas: List<DbManga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
 | 
			
		||||
        presenter.removeMangas(mangas, deleteFromLibrary, deleteChapters)
 | 
			
		||||
        destroyActionModeIfNeeded()
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ class LibraryItem(
 | 
			
		||||
 | 
			
		||||
    private val sourceManager: SourceManager = Injekt.get()
 | 
			
		||||
 | 
			
		||||
    var displayMode: Int = -1
 | 
			
		||||
    var displayMode: Long = -1
 | 
			
		||||
    var downloadCount = -1
 | 
			
		||||
    var unreadCount = -1
 | 
			
		||||
    var isLocal = false
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.library
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
 | 
			
		||||
class LibraryMangaEvent(val mangas: Map<Int, List<LibraryItem>>) {
 | 
			
		||||
class LibraryMangaEvent(val mangas: LibraryMap) {
 | 
			
		||||
 | 
			
		||||
    fun getMangaForCategory(category: Category): List<LibraryItem>? {
 | 
			
		||||
        return mangas[category.id]
 | 
			
		||||
 
 | 
			
		||||
@@ -6,19 +6,18 @@ import eu.kanade.core.util.asObservable
 | 
			
		||||
import eu.kanade.data.DatabaseHandler
 | 
			
		||||
import eu.kanade.domain.category.interactor.GetCategories
 | 
			
		||||
import eu.kanade.domain.category.interactor.SetMangaCategories
 | 
			
		||||
import eu.kanade.domain.category.model.toDbCategory
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
 | 
			
		||||
import eu.kanade.domain.chapter.model.ChapterUpdate
 | 
			
		||||
import eu.kanade.domain.chapter.model.toDbChapter
 | 
			
		||||
import eu.kanade.domain.manga.interactor.UpdateManga
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.domain.manga.model.MangaUpdate
 | 
			
		||||
import eu.kanade.domain.track.interactor.GetTracks
 | 
			
		||||
import eu.kanade.tachiyomi.data.cache.CoverCache
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Chapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.download.DownloadManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
@@ -34,7 +33,6 @@ import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchIO
 | 
			
		||||
import eu.kanade.tachiyomi.util.removeCovers
 | 
			
		||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
 | 
			
		||||
import kotlinx.coroutines.flow.map
 | 
			
		||||
import kotlinx.coroutines.runBlocking
 | 
			
		||||
import rx.Observable
 | 
			
		||||
import rx.Subscription
 | 
			
		||||
@@ -45,6 +43,7 @@ import uy.kohesive.injekt.api.get
 | 
			
		||||
import java.text.Collator
 | 
			
		||||
import java.util.Collections
 | 
			
		||||
import java.util.Locale
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga as DbManga
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class containing library information.
 | 
			
		||||
@@ -54,7 +53,7 @@ private data class Library(val categories: List<Category>, val mangaMap: Library
 | 
			
		||||
/**
 | 
			
		||||
 * Typealias for the library manga, using the category as keys, and list of manga as values.
 | 
			
		||||
 */
 | 
			
		||||
private typealias LibraryMap = Map<Int, List<LibraryItem>>
 | 
			
		||||
typealias LibraryMap = Map<Long, List<LibraryItem>>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Presenter of [LibraryController].
 | 
			
		||||
@@ -299,11 +298,11 @@ class LibraryPresenter(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val sortingModes = categories.associate { category ->
 | 
			
		||||
            (category.id ?: 0) to SortModeSetting.get(preferences, category)
 | 
			
		||||
            category.id to SortModeSetting.get(preferences, category)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val sortDirections = categories.associate { category ->
 | 
			
		||||
            (category.id ?: 0) to SortDirectionSetting.get(preferences, category)
 | 
			
		||||
            category.id to SortDirectionSetting.get(preferences, category)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val locale = Locale.getDefault()
 | 
			
		||||
@@ -311,8 +310,8 @@ class LibraryPresenter(
 | 
			
		||||
            strength = Collator.PRIMARY
 | 
			
		||||
        }
 | 
			
		||||
        val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 ->
 | 
			
		||||
            val sortingMode = sortingModes[i1.manga.category]!!
 | 
			
		||||
            val sortAscending = sortDirections[i1.manga.category]!! == SortDirectionSetting.ASCENDING
 | 
			
		||||
            val sortingMode = sortingModes[i1.manga.category.toLong()]!!
 | 
			
		||||
            val sortAscending = sortDirections[i1.manga.category.toLong()]!! == SortDirectionSetting.ASCENDING
 | 
			
		||||
            when (sortingMode) {
 | 
			
		||||
                SortModeSetting.ALPHABETICAL -> {
 | 
			
		||||
                    collator.compare(i1.manga.title.lowercase(locale), i2.manga.title.lowercase(locale))
 | 
			
		||||
@@ -355,7 +354,7 @@ class LibraryPresenter(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return map.mapValues { entry ->
 | 
			
		||||
            val sortAscending = sortDirections[entry.key]!! == SortDirectionSetting.ASCENDING
 | 
			
		||||
            val sortAscending = sortDirections[entry.key.toLong()]!! == SortDirectionSetting.ASCENDING
 | 
			
		||||
 | 
			
		||||
            val comparator = if (sortAscending) {
 | 
			
		||||
                Comparator(sortFn)
 | 
			
		||||
@@ -375,13 +374,13 @@ class LibraryPresenter(
 | 
			
		||||
    private fun getLibraryObservable(): Observable<Library> {
 | 
			
		||||
        return Observable.combineLatest(getCategoriesObservable(), getLibraryMangasObservable()) { dbCategories, libraryManga ->
 | 
			
		||||
            val categories = if (libraryManga.containsKey(0)) {
 | 
			
		||||
                arrayListOf(Category.createDefault(context)) + dbCategories
 | 
			
		||||
                arrayListOf(Category.default(context)) + dbCategories
 | 
			
		||||
            } else {
 | 
			
		||||
                dbCategories
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            libraryManga.forEach { (categoryId, libraryManga) ->
 | 
			
		||||
                val category = categories.first { category -> category.id == categoryId }
 | 
			
		||||
                val category = categories.first { category -> category.id == categoryId.toLong() }
 | 
			
		||||
                libraryManga.forEach { libraryItem ->
 | 
			
		||||
                    libraryItem.displayMode = category.displayMode
 | 
			
		||||
                }
 | 
			
		||||
@@ -398,7 +397,7 @@ class LibraryPresenter(
 | 
			
		||||
     * @return an observable of the categories.
 | 
			
		||||
     */
 | 
			
		||||
    private fun getCategoriesObservable(): Observable<List<Category>> {
 | 
			
		||||
        return getCategories.subscribe().map { it.map { it.toDbCategory() } }.asObservable()
 | 
			
		||||
        return getCategories.subscribe().asObservable()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -448,7 +447,7 @@ class LibraryPresenter(
 | 
			
		||||
                        shouldSetFromCategory,
 | 
			
		||||
                        defaultLibraryDisplayMode,
 | 
			
		||||
                    )
 | 
			
		||||
                }.groupBy { it.manga.category }
 | 
			
		||||
                }.groupBy { it.manga.category.toLong() }
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -516,10 +515,10 @@ class LibraryPresenter(
 | 
			
		||||
     *
 | 
			
		||||
     * @param mangas the list of manga.
 | 
			
		||||
     */
 | 
			
		||||
    suspend fun getCommonCategories(mangas: List<Manga>): Collection<Category> {
 | 
			
		||||
    suspend fun getCommonCategories(mangas: List<DbManga>): Collection<Category> {
 | 
			
		||||
        if (mangas.isEmpty()) return emptyList()
 | 
			
		||||
        return mangas.toSet()
 | 
			
		||||
            .map { getCategories.await(it.id!!).map { it.toDbCategory() } }
 | 
			
		||||
            .map { getCategories.await(it.id!!) }
 | 
			
		||||
            .reduce { set1, set2 -> set1.intersect(set2).toMutableList() }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -528,9 +527,9 @@ class LibraryPresenter(
 | 
			
		||||
     *
 | 
			
		||||
     * @param mangas the list of manga.
 | 
			
		||||
     */
 | 
			
		||||
    suspend fun getMixCategories(mangas: List<Manga>): Collection<Category> {
 | 
			
		||||
    suspend fun getMixCategories(mangas: List<DbManga>): Collection<Category> {
 | 
			
		||||
        if (mangas.isEmpty()) return emptyList()
 | 
			
		||||
        val mangaCategories = mangas.toSet().map { getCategories.await(it.id!!).map { it.toDbCategory() } }
 | 
			
		||||
        val mangaCategories = mangas.toSet().map { getCategories.await(it.id!!) }
 | 
			
		||||
        val common = mangaCategories.reduce { set1, set2 -> set1.intersect(set2).toMutableList() }
 | 
			
		||||
        return mangaCategories.flatten().distinct().subtract(common).toMutableList()
 | 
			
		||||
    }
 | 
			
		||||
@@ -540,7 +539,7 @@ class LibraryPresenter(
 | 
			
		||||
     *
 | 
			
		||||
     * @param mangas the list of manga.
 | 
			
		||||
     */
 | 
			
		||||
    fun downloadUnreadChapters(mangas: List<Manga>) {
 | 
			
		||||
    fun downloadUnreadChapters(mangas: List<DbManga>) {
 | 
			
		||||
        mangas.forEach { manga ->
 | 
			
		||||
            launchIO {
 | 
			
		||||
                val chapters = getChapterByMangaId.await(manga.id!!)
 | 
			
		||||
@@ -557,7 +556,7 @@ class LibraryPresenter(
 | 
			
		||||
     *
 | 
			
		||||
     * @param mangas the list of manga.
 | 
			
		||||
     */
 | 
			
		||||
    fun markReadStatus(mangas: List<Manga>, read: Boolean) {
 | 
			
		||||
    fun markReadStatus(mangas: List<DbManga>, read: Boolean) {
 | 
			
		||||
        mangas.forEach { manga ->
 | 
			
		||||
            launchIO {
 | 
			
		||||
                val chapters = getChapterByMangaId.await(manga.id!!)
 | 
			
		||||
@@ -579,7 +578,7 @@ class LibraryPresenter(
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun deleteChapters(manga: Manga, chapters: List<Chapter>) {
 | 
			
		||||
    private fun deleteChapters(manga: DbManga, chapters: List<Chapter>) {
 | 
			
		||||
        sourceManager.get(manga.source)?.let { source ->
 | 
			
		||||
            downloadManager.deleteChapters(chapters, manga, source)
 | 
			
		||||
        }
 | 
			
		||||
@@ -592,7 +591,7 @@ class LibraryPresenter(
 | 
			
		||||
     * @param deleteFromLibrary whether to delete manga from library.
 | 
			
		||||
     * @param deleteChapters whether to delete downloaded chapters.
 | 
			
		||||
     */
 | 
			
		||||
    fun removeMangas(mangaList: List<Manga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
 | 
			
		||||
    fun removeMangas(mangaList: List<DbManga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
 | 
			
		||||
        launchIO {
 | 
			
		||||
            val mangaToDelete = mangaList.distinctBy { it.id }
 | 
			
		||||
 | 
			
		||||
@@ -628,12 +627,11 @@ class LibraryPresenter(
 | 
			
		||||
    fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Category>, removeCategories: List<Category>) {
 | 
			
		||||
        presenterScope.launchIO {
 | 
			
		||||
            mangaList.map { manga ->
 | 
			
		||||
                val categoryIds = getCategories.await(manga.id!!)
 | 
			
		||||
                    .map { it.toDbCategory() }
 | 
			
		||||
                val categoryIds = getCategories.await(manga.id)
 | 
			
		||||
                    .subtract(removeCategories)
 | 
			
		||||
                    .plus(addCategories)
 | 
			
		||||
                    .mapNotNull { it.id?.toLong() }
 | 
			
		||||
                setMangaCategories.await(manga.id!!, categoryIds)
 | 
			
		||||
                    .map { it.id }
 | 
			
		||||
                setMangaCategories.await(manga.id, categoryIds)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ import eu.kanade.domain.category.interactor.UpdateCategory
 | 
			
		||||
import eu.kanade.domain.category.model.CategoryUpdate
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toDomainCategory
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackService
 | 
			
		||||
@@ -201,8 +202,8 @@ class LibrarySettingsSheet(
 | 
			
		||||
            override val footer = null
 | 
			
		||||
 | 
			
		||||
            override fun initModels() {
 | 
			
		||||
                val sorting = SortModeSetting.get(preferences, currentCategory)
 | 
			
		||||
                val order = if (SortDirectionSetting.get(preferences, currentCategory) == SortDirectionSetting.ASCENDING) {
 | 
			
		||||
                val sorting = SortModeSetting.get(preferences, currentCategory?.toDomainCategory())
 | 
			
		||||
                val order = if (SortDirectionSetting.get(preferences, currentCategory?.toDomainCategory()) == SortDirectionSetting.ASCENDING) {
 | 
			
		||||
                    Item.MultiSort.SORT_ASC
 | 
			
		||||
                } else {
 | 
			
		||||
                    Item.MultiSort.SORT_DESC
 | 
			
		||||
@@ -243,12 +244,12 @@ class LibrarySettingsSheet(
 | 
			
		||||
 | 
			
		||||
                setSortModePreference(item)
 | 
			
		||||
 | 
			
		||||
                setSortDirectionPrefernece(item)
 | 
			
		||||
                setSortDirectionPreference(item)
 | 
			
		||||
 | 
			
		||||
                item.group.items.forEach { adapter.notifyItemChanged(it) }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private fun setSortDirectionPrefernece(item: Item.MultiStateGroup) {
 | 
			
		||||
            private fun setSortDirectionPreference(item: Item.MultiStateGroup) {
 | 
			
		||||
                val flag = if (item.state == Item.MultiSort.SORT_ASC) {
 | 
			
		||||
                    SortDirectionSetting.ASCENDING
 | 
			
		||||
                } else {
 | 
			
		||||
@@ -256,7 +257,7 @@ class LibrarySettingsSheet(
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0) {
 | 
			
		||||
                    currentCategory?.sortDirection = flag.flag
 | 
			
		||||
                    currentCategory?.sortDirection = flag.flag.toInt()
 | 
			
		||||
                    sheetScope.launchIO {
 | 
			
		||||
                        updateCategory.await(
 | 
			
		||||
                            CategoryUpdate(
 | 
			
		||||
@@ -284,7 +285,7 @@ class LibrarySettingsSheet(
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0) {
 | 
			
		||||
                    currentCategory?.sortMode = flag.flag
 | 
			
		||||
                    currentCategory?.sortMode = flag.flag.toInt()
 | 
			
		||||
                    sheetScope.launchIO {
 | 
			
		||||
                        updateCategory.await(
 | 
			
		||||
                            CategoryUpdate(
 | 
			
		||||
@@ -327,7 +328,7 @@ class LibrarySettingsSheet(
 | 
			
		||||
        // Gets user preference of currently selected display mode at current category
 | 
			
		||||
        private fun getDisplayModePreference(): DisplayModeSetting {
 | 
			
		||||
            return if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0) {
 | 
			
		||||
                DisplayModeSetting.fromFlag(currentCategory?.displayMode)
 | 
			
		||||
                DisplayModeSetting.fromFlag(currentCategory?.displayMode?.toLong())
 | 
			
		||||
            } else {
 | 
			
		||||
                preferences.libraryDisplayMode().get()
 | 
			
		||||
            }
 | 
			
		||||
@@ -379,7 +380,7 @@ class LibrarySettingsSheet(
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0) {
 | 
			
		||||
                    currentCategory?.displayMode = flag.flag
 | 
			
		||||
                    currentCategory?.displayMode = flag.flag.toInt()
 | 
			
		||||
                    sheetScope.launchIO {
 | 
			
		||||
                        updateCategory.await(
 | 
			
		||||
                            CategoryUpdate(
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,15 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.library.setting
 | 
			
		||||
 | 
			
		||||
enum class DisplayModeSetting(val flag: Int) {
 | 
			
		||||
enum class DisplayModeSetting(val flag: Long) {
 | 
			
		||||
    COMPACT_GRID(0b00000000),
 | 
			
		||||
    COMFORTABLE_GRID(0b00000001),
 | 
			
		||||
    LIST(0b00000010),
 | 
			
		||||
    COVER_ONLY_GRID(0b00000011);
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val MASK = 0b00000011
 | 
			
		||||
        const val MASK = 0b00000011L
 | 
			
		||||
 | 
			
		||||
        fun fromFlag(flag: Int?): DisplayModeSetting {
 | 
			
		||||
        fun fromFlag(flag: Long?): DisplayModeSetting {
 | 
			
		||||
            return values()
 | 
			
		||||
                .find { mode -> mode.flag == flag } ?: COMPACT_GRID
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,21 +1,21 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.library.setting
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
 | 
			
		||||
enum class SortDirectionSetting(val flag: Int) {
 | 
			
		||||
enum class SortDirectionSetting(val flag: Long) {
 | 
			
		||||
    ASCENDING(0b01000000),
 | 
			
		||||
    DESCENDING(0b00000000);
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        const val MASK = 0b01000000
 | 
			
		||||
        const val MASK = 0b01000000L
 | 
			
		||||
 | 
			
		||||
        fun fromFlag(flag: Int?): SortDirectionSetting {
 | 
			
		||||
        fun fromFlag(flag: Long?): SortDirectionSetting {
 | 
			
		||||
            return values().find { mode -> mode.flag == flag } ?: ASCENDING
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun get(preferences: PreferencesHelper, category: Category?): SortDirectionSetting {
 | 
			
		||||
            return if (preferences.categorizedDisplaySettings().get() && category != null && category.id != 0) {
 | 
			
		||||
            return if (preferences.categorizedDisplaySettings().get() && category != null && category.id != 0L) {
 | 
			
		||||
                fromFlag(category.sortDirection)
 | 
			
		||||
            } else {
 | 
			
		||||
                preferences.librarySortingAscending().get()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.library.setting
 | 
			
		||||
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
 | 
			
		||||
enum class SortModeSetting(val flag: Int) {
 | 
			
		||||
enum class SortModeSetting(val flag: Long) {
 | 
			
		||||
    ALPHABETICAL(0b00000000),
 | 
			
		||||
    LAST_READ(0b00000100),
 | 
			
		||||
    LAST_MANGA_UPDATE(0b00001000),
 | 
			
		||||
@@ -25,14 +25,14 @@ enum class SortModeSetting(val flag: Int) {
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        // Mask supports for more sorting flags if necessary
 | 
			
		||||
        const val MASK = 0b00111100
 | 
			
		||||
        const val MASK = 0b00111100L
 | 
			
		||||
 | 
			
		||||
        fun fromFlag(flag: Int?): SortModeSetting {
 | 
			
		||||
        fun fromFlag(flag: Long?): SortModeSetting {
 | 
			
		||||
            return values().find { mode -> mode.flag == flag } ?: ALPHABETICAL
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fun get(preferences: PreferencesHelper, category: Category?): SortModeSetting {
 | 
			
		||||
            return if (preferences.categorizedDisplaySettings().get() && category != null && category.id != 0) {
 | 
			
		||||
            return if (preferences.categorizedDisplaySettings().get() && category != null && category.id != 0L) {
 | 
			
		||||
                fromFlag(category.sortMode)
 | 
			
		||||
            } else {
 | 
			
		||||
                preferences.librarySortingMode().get()
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,8 @@ import android.app.Dialog
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
import com.bluelinelabs.conductor.Controller
 | 
			
		||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.source.SourceManager
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.pushController
 | 
			
		||||
 
 | 
			
		||||
@@ -24,14 +24,14 @@ import com.bluelinelabs.conductor.ControllerChangeHandler
 | 
			
		||||
import com.bluelinelabs.conductor.ControllerChangeType
 | 
			
		||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
 | 
			
		||||
import eu.kanade.data.chapter.NoChaptersException
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.domain.manga.model.Manga
 | 
			
		||||
import eu.kanade.domain.manga.model.toDbManga
 | 
			
		||||
import eu.kanade.presentation.manga.ChapterDownloadAction
 | 
			
		||||
import eu.kanade.presentation.manga.DownloadAction
 | 
			
		||||
import eu.kanade.presentation.manga.MangaScreen
 | 
			
		||||
import eu.kanade.presentation.util.calculateWindowWidthSizeClass
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.download.DownloadService
 | 
			
		||||
import eu.kanade.tachiyomi.data.download.model.Download
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.model.TrackSearch
 | 
			
		||||
@@ -59,7 +59,7 @@ import eu.kanade.tachiyomi.ui.recent.history.HistoryController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchIO
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.launchUI
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.withUIContext
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.logcat
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.toast
 | 
			
		||||
import eu.kanade.tachiyomi.widget.materialdialogs.QuadStateTextView
 | 
			
		||||
@@ -211,7 +211,7 @@ class MangaController :
 | 
			
		||||
                {
 | 
			
		||||
                    AddDuplicateMangaDialog(
 | 
			
		||||
                        target = this,
 | 
			
		||||
                        libraryManga = it.toDbManga(),
 | 
			
		||||
                        libraryManga = it,
 | 
			
		||||
                        onAddToLibrary = { onFavoriteClick(checkDuplicate = false) },
 | 
			
		||||
                    ).showDialog(router)
 | 
			
		||||
                }
 | 
			
		||||
@@ -225,7 +225,7 @@ class MangaController :
 | 
			
		||||
                        QuadStateTextView.State.UNCHECKED.ordinal
 | 
			
		||||
                    }
 | 
			
		||||
                }.toTypedArray()
 | 
			
		||||
                showChangeCategoryDialog(manga.toDbManga(), categories, preselected)
 | 
			
		||||
                showChangeCategoryDialog(manga, categories, preselected)
 | 
			
		||||
            },
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
@@ -246,10 +246,6 @@ class MangaController :
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onTrackingClick() {
 | 
			
		||||
        trackSheet.show()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun onCategoriesClick() {
 | 
			
		||||
        viewScope.launchIO {
 | 
			
		||||
            val manga = presenter.manga ?: return@launchIO
 | 
			
		||||
@@ -263,8 +259,9 @@ class MangaController :
 | 
			
		||||
                    QuadStateTextView.State.UNCHECKED.ordinal
 | 
			
		||||
                }
 | 
			
		||||
            }.toTypedArray()
 | 
			
		||||
            launchUI {
 | 
			
		||||
                showChangeCategoryDialog(manga.toDbManga(), categories, preselected)
 | 
			
		||||
 | 
			
		||||
            withUIContext {
 | 
			
		||||
                showChangeCategoryDialog(manga, categories, preselected)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import android.os.Bundle
 | 
			
		||||
import androidx.compose.runtime.Immutable
 | 
			
		||||
import eu.kanade.domain.category.interactor.GetCategories
 | 
			
		||||
import eu.kanade.domain.category.interactor.SetMangaCategories
 | 
			
		||||
import eu.kanade.domain.category.model.toDbCategory
 | 
			
		||||
import eu.kanade.domain.category.model.Category
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
 | 
			
		||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
 | 
			
		||||
@@ -23,9 +23,7 @@ import eu.kanade.domain.track.interactor.GetTracks
 | 
			
		||||
import eu.kanade.domain.track.interactor.InsertTrack
 | 
			
		||||
import eu.kanade.domain.track.model.toDbTrack
 | 
			
		||||
import eu.kanade.domain.track.model.toDomainTrack
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Chapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Manga
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Track
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toDomainChapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.download.DownloadManager
 | 
			
		||||
@@ -258,22 +256,22 @@ class MangaPresenter(
 | 
			
		||||
 | 
			
		||||
                // Now check if user previously set categories, when available
 | 
			
		||||
                val categories = getCategories()
 | 
			
		||||
                val defaultCategoryId = preferences.defaultCategory()
 | 
			
		||||
                val defaultCategoryId = preferences.defaultCategory().toLong()
 | 
			
		||||
                val defaultCategory = categories.find { it.id == defaultCategoryId }
 | 
			
		||||
                when {
 | 
			
		||||
                    // Default category set
 | 
			
		||||
                    defaultCategory != null -> {
 | 
			
		||||
                        val result = updateManga.awaitUpdateFavorite(manga.id, true)
 | 
			
		||||
                        if (!result) return@launchIO
 | 
			
		||||
                        moveMangaToCategory(manga.toDbManga(), defaultCategory)
 | 
			
		||||
                        moveMangaToCategory(defaultCategory)
 | 
			
		||||
                        launchUI { onAdded() }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    // Automatic 'Default' or no categories
 | 
			
		||||
                    defaultCategoryId == 0 || categories.isEmpty() -> {
 | 
			
		||||
                    defaultCategoryId == 0L || categories.isEmpty() -> {
 | 
			
		||||
                        val result = updateManga.awaitUpdateFavorite(manga.id, true)
 | 
			
		||||
                        if (!result) return@launchIO
 | 
			
		||||
                        moveMangaToCategory(manga.toDbManga(), null)
 | 
			
		||||
                        moveMangaToCategory(null)
 | 
			
		||||
                        launchUI { onAdded() }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
@@ -326,7 +324,7 @@ class MangaPresenter(
 | 
			
		||||
     * @return List of categories, not including the default category
 | 
			
		||||
     */
 | 
			
		||||
    suspend fun getCategories(): List<Category> {
 | 
			
		||||
        return getCategories.await().map { it.toDbCategory() }
 | 
			
		||||
        return getCategories.await()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -335,15 +333,15 @@ class MangaPresenter(
 | 
			
		||||
     * @param manga the manga to get categories from.
 | 
			
		||||
     * @return Array of category ids the manga is in, if none returns default id
 | 
			
		||||
     */
 | 
			
		||||
    fun getMangaCategoryIds(manga: DomainManga): Array<Int> {
 | 
			
		||||
    fun getMangaCategoryIds(manga: DomainManga): Array<Long> {
 | 
			
		||||
        val categories = runBlocking { getCategories.await(manga.id) }
 | 
			
		||||
        return categories.map { it.id.toInt() }.toTypedArray()
 | 
			
		||||
        return categories.map { it.id }.toTypedArray()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun moveMangaToCategoriesAndAddToLibrary(manga: Manga, categories: List<Category>) {
 | 
			
		||||
        moveMangaToCategories(manga, categories)
 | 
			
		||||
    fun moveMangaToCategoriesAndAddToLibrary(manga: DomainManga, categories: List<Category>) {
 | 
			
		||||
        moveMangaToCategories(categories)
 | 
			
		||||
        presenterScope.launchIO {
 | 
			
		||||
            updateManga.awaitUpdateFavorite(manga.id!!, true)
 | 
			
		||||
            updateManga.awaitUpdateFavorite(manga.id, true)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -353,9 +351,8 @@ class MangaPresenter(
 | 
			
		||||
     * @param manga the manga to move.
 | 
			
		||||
     * @param categories the selected categories.
 | 
			
		||||
     */
 | 
			
		||||
    private fun moveMangaToCategories(manga: Manga, categories: List<Category>) {
 | 
			
		||||
        val mangaId = manga.id ?: return
 | 
			
		||||
        val categoryIds = categories.mapNotNull { it.id?.toLong() }
 | 
			
		||||
    private fun moveMangaToCategories(categories: List<Category>) {
 | 
			
		||||
        val categoryIds = categories.map { it.id }
 | 
			
		||||
        presenterScope.launchIO {
 | 
			
		||||
            setMangaCategories.await(mangaId, categoryIds)
 | 
			
		||||
        }
 | 
			
		||||
@@ -367,8 +364,8 @@ class MangaPresenter(
 | 
			
		||||
     * @param manga the manga to move.
 | 
			
		||||
     * @param category the selected category, or null for default category.
 | 
			
		||||
     */
 | 
			
		||||
    private fun moveMangaToCategory(manga: Manga, category: Category?) {
 | 
			
		||||
        moveMangaToCategories(manga, listOfNotNull(category))
 | 
			
		||||
    private fun moveMangaToCategory(category: Category?) {
 | 
			
		||||
        moveMangaToCategories(listOfNotNull(category))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun observeTrackingCount() {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user