Move default category into database (#7676)
(cherry picked from commit 914831d51fbb915aea5cbb409b1da552862c380c) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/data/backup/full/FullBackupManager.kt # app/src/main/java/eu/kanade/tachiyomi/data/backup/full/models/BackupCategory.kt # app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt # app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt # app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt # app/src/main/sqldelight/migrations/19.sqm
This commit is contained in:
parent
af1ee662ed
commit
394e9b3fe6
@ -67,6 +67,12 @@ class CategoryRepositoryImpl(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun updateAllFlags(flags: Long?) {
|
||||||
|
handler.await {
|
||||||
|
categoriesQueries.updateAllFlags(flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun delete(categoryId: Long) {
|
override suspend fun delete(categoryId: Long) {
|
||||||
handler.await {
|
handler.await {
|
||||||
categoriesQueries.delete(
|
categoriesQueries.delete(
|
||||||
|
@ -13,7 +13,10 @@ import eu.kanade.domain.category.interactor.DeleteCategory
|
|||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.RenameCategory
|
import eu.kanade.domain.category.interactor.RenameCategory
|
||||||
import eu.kanade.domain.category.interactor.ReorderCategory
|
import eu.kanade.domain.category.interactor.ReorderCategory
|
||||||
|
import eu.kanade.domain.category.interactor.ResetCategoryFlags
|
||||||
|
import eu.kanade.domain.category.interactor.SetDisplayModeForCategory
|
||||||
import eu.kanade.domain.category.interactor.SetMangaCategories
|
import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
|
import eu.kanade.domain.category.interactor.SetSortModeForCategory
|
||||||
import eu.kanade.domain.category.interactor.UpdateCategory
|
import eu.kanade.domain.category.interactor.UpdateCategory
|
||||||
import eu.kanade.domain.category.repository.CategoryRepository
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapter
|
import eu.kanade.domain.chapter.interactor.GetChapter
|
||||||
@ -73,6 +76,9 @@ class DomainModule : InjektModule {
|
|||||||
override fun InjektRegistrar.registerInjectables() {
|
override fun InjektRegistrar.registerInjectables() {
|
||||||
addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) }
|
addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) }
|
||||||
addFactory { GetCategories(get()) }
|
addFactory { GetCategories(get()) }
|
||||||
|
addFactory { ResetCategoryFlags(get(), get()) }
|
||||||
|
addFactory { SetDisplayModeForCategory(get(), get()) }
|
||||||
|
addFactory { SetSortModeForCategory(get(), get()) }
|
||||||
addFactory { CreateCategoryWithName(get()) }
|
addFactory { CreateCategoryWithName(get()) }
|
||||||
addFactory { RenameCategory(get()) }
|
addFactory { RenameCategory(get()) }
|
||||||
addFactory { ReorderCategory(get()) }
|
addFactory { ReorderCategory(get()) }
|
||||||
|
@ -13,7 +13,7 @@ class ReorderCategory(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun await(categoryId: Long, newPosition: Int) = withContext(NonCancellable) await@{
|
suspend fun await(categoryId: Long, newPosition: Int) = withContext(NonCancellable) await@{
|
||||||
val categories = categoryRepository.getAll()
|
val categories = categoryRepository.getAll().filterNot(Category::isSystemCategory)
|
||||||
|
|
||||||
val currentIndex = categories.indexOfFirst { it.id == categoryId }
|
val currentIndex = categories.indexOfFirst { it.id == categoryId }
|
||||||
if (currentIndex == newPosition) {
|
if (currentIndex == newPosition) {
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
|
||||||
|
import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting
|
||||||
|
import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting
|
||||||
|
|
||||||
|
class ResetCategoryFlags(
|
||||||
|
private val preferences: PreferencesHelper,
|
||||||
|
private val categoryRepository: CategoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await() {
|
||||||
|
val display = preferences.libraryDisplayMode().get()
|
||||||
|
val sort = preferences.librarySortingMode().get()
|
||||||
|
val sortDirection = preferences.librarySortingAscending().get()
|
||||||
|
|
||||||
|
var flags = 0L
|
||||||
|
flags = flags and DisplayModeSetting.MASK.inv() or (display.flag and DisplayModeSetting.MASK)
|
||||||
|
flags = flags and SortModeSetting.MASK.inv() or (sort.flag and SortModeSetting.MASK)
|
||||||
|
flags = flags and SortDirectionSetting.MASK.inv() or (sortDirection.flag and SortDirectionSetting.MASK)
|
||||||
|
categoryRepository.updateAllFlags(flags)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.domain.category.model.CategoryUpdate
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryGroup
|
||||||
|
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
|
||||||
|
|
||||||
|
class SetDisplayModeForCategory(
|
||||||
|
private val preferences: PreferencesHelper,
|
||||||
|
private val categoryRepository: CategoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(category: Category, displayModeSetting: DisplayModeSetting) {
|
||||||
|
val flags = category.flags and DisplayModeSetting.MASK.inv() or (displayModeSetting.flag and DisplayModeSetting.MASK)
|
||||||
|
// SY -->
|
||||||
|
val isDefaultGroup = preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT
|
||||||
|
// SY <--
|
||||||
|
if (preferences.categorizedDisplaySettings().get() /* SY --> */ && isDefaultGroup/* SY <-- */) {
|
||||||
|
categoryRepository.updatePartial(
|
||||||
|
CategoryUpdate(
|
||||||
|
id = category.id,
|
||||||
|
flags = flags,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
preferences.libraryDisplayMode().set(displayModeSetting)
|
||||||
|
// SY -->
|
||||||
|
if (isDefaultGroup) {
|
||||||
|
// SY <--
|
||||||
|
categoryRepository.updateAllFlags(flags)
|
||||||
|
// SY -->
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.domain.category.model.CategoryUpdate
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryGroup
|
||||||
|
import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting
|
||||||
|
import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting
|
||||||
|
|
||||||
|
class SetSortModeForCategory(
|
||||||
|
private val preferences: PreferencesHelper,
|
||||||
|
private val categoryRepository: CategoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(category: Category, sortDirectionSetting: SortDirectionSetting) {
|
||||||
|
val sort = if (preferences.categorizedDisplaySettings().get() /* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT/* SY <-- */) {
|
||||||
|
SortModeSetting.fromFlag(category.flags)
|
||||||
|
} else {
|
||||||
|
preferences.librarySortingMode().get()
|
||||||
|
}
|
||||||
|
await(category, sort, sortDirectionSetting)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun await(category: Category, sortModeSetting: SortModeSetting) {
|
||||||
|
val direction = if (preferences.categorizedDisplaySettings().get() /* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT/* SY <-- */) {
|
||||||
|
SortDirectionSetting.fromFlag(category.flags)
|
||||||
|
} else {
|
||||||
|
preferences.librarySortingAscending().get()
|
||||||
|
}
|
||||||
|
await(category, sortModeSetting, direction)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun await(category: Category, sortModeSetting: SortModeSetting, sortDirectionSetting: SortDirectionSetting) {
|
||||||
|
var flags = category.flags and SortModeSetting.MASK.inv() or (sortModeSetting.flag and SortModeSetting.MASK)
|
||||||
|
flags = flags and SortDirectionSetting.MASK.inv() or (sortDirectionSetting.flag and SortDirectionSetting.MASK)
|
||||||
|
// SY -->
|
||||||
|
val isDefaultGroup = preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT
|
||||||
|
// SY <--
|
||||||
|
if (preferences.categorizedDisplaySettings().get() /* SY --> */ && isDefaultGroup/* SY <-- */) {
|
||||||
|
categoryRepository.updatePartial(
|
||||||
|
CategoryUpdate(
|
||||||
|
id = category.id,
|
||||||
|
flags = flags,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
preferences.librarySortingMode().set(sortModeSetting)
|
||||||
|
preferences.librarySortingAscending().set(sortDirectionSetting)
|
||||||
|
// SY -->
|
||||||
|
if (isDefaultGroup) {
|
||||||
|
// SY <--
|
||||||
|
categoryRepository.updateAllFlags(flags)
|
||||||
|
// SY -->
|
||||||
|
}
|
||||||
|
// SY <--
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,9 @@
|
|||||||
package eu.kanade.domain.category.model
|
package eu.kanade.domain.category.model
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.CategoryImpl
|
|
||||||
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
|
import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting
|
||||||
import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting
|
import eu.kanade.tachiyomi.ui.library.setting.SortDirectionSetting
|
||||||
import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting
|
import eu.kanade.tachiyomi.ui.library.setting.SortModeSetting
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category as DbCategory
|
|
||||||
|
|
||||||
data class Category(
|
data class Category(
|
||||||
val id: Long,
|
val id: Long,
|
||||||
@ -16,6 +12,8 @@ data class Category(
|
|||||||
val flags: Long,
|
val flags: Long,
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
|
|
||||||
|
val isSystemCategory: Boolean = id == UNCATEGORIZED_ID
|
||||||
|
|
||||||
val displayMode: Long
|
val displayMode: Long
|
||||||
get() = flags and DisplayModeSetting.MASK
|
get() = flags and DisplayModeSetting.MASK
|
||||||
|
|
||||||
@ -26,24 +24,11 @@ data class Category(
|
|||||||
get() = flags and SortDirectionSetting.MASK
|
get() = flags and SortDirectionSetting.MASK
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val default = { context: Context ->
|
|
||||||
Category(
|
const val UNCATEGORIZED_ID = 0L
|
||||||
id = 0,
|
|
||||||
name = context.getString(R.string.label_default),
|
|
||||||
order = 0,
|
|
||||||
flags = 0,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun List<Category>.anyWithName(name: String): Boolean {
|
internal fun List<Category>.anyWithName(name: String): Boolean {
|
||||||
return any { name.equals(it.name, ignoreCase = true) }
|
return any { name.equals(it.name, ignoreCase = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Category.toDbCategory(): DbCategory = CategoryImpl().also {
|
|
||||||
it.name = name
|
|
||||||
it.id = id.toInt()
|
|
||||||
it.order = order.toInt()
|
|
||||||
it.flags = flags.toInt()
|
|
||||||
}
|
|
||||||
|
@ -22,5 +22,7 @@ interface CategoryRepository {
|
|||||||
|
|
||||||
suspend fun updatePartial(updates: List<CategoryUpdate>)
|
suspend fun updatePartial(updates: List<CategoryUpdate>)
|
||||||
|
|
||||||
|
suspend fun updateAllFlags(flags: Long?)
|
||||||
|
|
||||||
suspend fun delete(categoryId: Long)
|
suspend fun delete(categoryId: Long)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package eu.kanade.presentation.category
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
|
||||||
|
val Category.visualName: String
|
||||||
|
@Composable
|
||||||
|
get() = when (id) {
|
||||||
|
Category.UNCATEGORIZED_ID -> stringResource(id = R.string.label_default)
|
||||||
|
else -> name
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Category.visualName(context: Context): String =
|
||||||
|
when (id) {
|
||||||
|
Category.UNCATEGORIZED_ID -> context.getString(R.string.label_default)
|
||||||
|
else -> name
|
||||||
|
}
|
@ -109,6 +109,7 @@ fun LibraryScreen(
|
|||||||
isDownloadOnly = presenter.isDownloadOnly,
|
isDownloadOnly = presenter.isDownloadOnly,
|
||||||
// SY -->
|
// SY -->
|
||||||
onOpenReader = onOpenReader,
|
onOpenReader = onOpenReader,
|
||||||
|
getCategoryName = presenter::getCategoryName,
|
||||||
// SY <--
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryGroup
|
||||||
import exh.source.PERV_EDEN_EN_SOURCE_ID
|
import exh.source.PERV_EDEN_EN_SOURCE_ID
|
||||||
import exh.source.PERV_EDEN_IT_SOURCE_ID
|
import exh.source.PERV_EDEN_IT_SOURCE_ID
|
||||||
import exh.source.isEhBasedManga
|
import exh.source.isEhBasedManga
|
||||||
@ -24,6 +25,7 @@ interface LibraryState {
|
|||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val ogCategories: List<Category>
|
val ogCategories: List<Category>
|
||||||
|
val groupType: Int
|
||||||
val showSyncExh: Boolean
|
val showSyncExh: Boolean
|
||||||
val showCleanTitles: Boolean
|
val showCleanTitles: Boolean
|
||||||
val showAddToMangadex: Boolean
|
val showAddToMangadex: Boolean
|
||||||
@ -43,6 +45,8 @@ class LibraryStateImpl : LibraryState {
|
|||||||
override var hasActiveFilters: Boolean by mutableStateOf(false)
|
override var hasActiveFilters: Boolean by mutableStateOf(false)
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
|
override var groupType: Int by mutableStateOf(LibraryGroup.BY_DEFAULT)
|
||||||
|
|
||||||
override var ogCategories: List<Category> by mutableStateOf(emptyList())
|
override var ogCategories: List<Category> by mutableStateOf(emptyList())
|
||||||
|
|
||||||
override var showSyncExh: Boolean by mutableStateOf(true)
|
override var showSyncExh: Boolean by mutableStateOf(true)
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package eu.kanade.presentation.library.components
|
package eu.kanade.presentation.library.components
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalUriHandler
|
import androidx.compose.ui.platform.LocalUriHandler
|
||||||
import com.google.accompanist.pager.rememberPagerState
|
import com.google.accompanist.pager.rememberPagerState
|
||||||
import com.google.accompanist.swiperefresh.SwipeRefresh
|
import com.google.accompanist.swiperefresh.SwipeRefresh
|
||||||
@ -44,6 +47,7 @@ fun LibraryContent(
|
|||||||
getLibraryForPage: @Composable (Int) -> State<List<LibraryItem>>,
|
getLibraryForPage: @Composable (Int) -> State<List<LibraryItem>>,
|
||||||
// SY -->
|
// SY -->
|
||||||
onOpenReader: (LibraryManga) -> Unit,
|
onOpenReader: (LibraryManga) -> Unit,
|
||||||
|
getCategoryName: (Context, Category, Int, String) -> String,
|
||||||
// SY <--
|
// SY <--
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -61,6 +65,14 @@ fun LibraryContent(
|
|||||||
getNumberOfMangaForCategory = getNumberOfMangaForCategory,
|
getNumberOfMangaForCategory = getNumberOfMangaForCategory,
|
||||||
isDownloadOnly = isDownloadOnly,
|
isDownloadOnly = isDownloadOnly,
|
||||||
isIncognitoMode = isIncognitoMode,
|
isIncognitoMode = isIncognitoMode,
|
||||||
|
// SY -->
|
||||||
|
getCategoryName = { category, name ->
|
||||||
|
val context = LocalContext.current
|
||||||
|
derivedStateOf {
|
||||||
|
getCategoryName(context, category, state.groupType, name)
|
||||||
|
}.value
|
||||||
|
},
|
||||||
|
// SY <--
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import com.google.accompanist.pager.PagerState
|
import com.google.accompanist.pager.PagerState
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.presentation.category.visualName
|
||||||
import eu.kanade.presentation.components.DownloadedOnlyModeBanner
|
import eu.kanade.presentation.components.DownloadedOnlyModeBanner
|
||||||
import eu.kanade.presentation.components.IncognitoModeBanner
|
import eu.kanade.presentation.components.IncognitoModeBanner
|
||||||
import eu.kanade.presentation.components.Pill
|
import eu.kanade.presentation.components.Pill
|
||||||
@ -36,6 +37,9 @@ fun LibraryTabs(
|
|||||||
isDownloadOnly: Boolean,
|
isDownloadOnly: Boolean,
|
||||||
isIncognitoMode: Boolean,
|
isIncognitoMode: Boolean,
|
||||||
getNumberOfMangaForCategory: @Composable (Long) -> State<Int?>,
|
getNumberOfMangaForCategory: @Composable (Long) -> State<Int?>,
|
||||||
|
// SY -->
|
||||||
|
getCategoryName: @Composable (Category, String) -> String,
|
||||||
|
// SY <--
|
||||||
) {
|
) {
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
@ -43,12 +47,12 @@ fun LibraryTabs(
|
|||||||
|
|
||||||
Column {
|
Column {
|
||||||
ScrollableTabRow(
|
ScrollableTabRow(
|
||||||
selectedTabIndex = state.currentPage,
|
selectedTabIndex = state.currentPage.coerceAtMost(categories.lastIndex),
|
||||||
edgePadding = 0.dp,
|
edgePadding = 0.dp,
|
||||||
indicator = { tabPositions ->
|
indicator = { tabPositions ->
|
||||||
TabRowDefaults.Indicator(
|
TabRowDefaults.Indicator(
|
||||||
Modifier
|
Modifier
|
||||||
.tabIndicatorOffset(tabPositions[state.currentPage])
|
.tabIndicatorOffset(tabPositions[state.currentPage.coerceAtMost(categories.lastIndex)])
|
||||||
.clip(RoundedCornerShape(topStart = 3.dp, topEnd = 3.dp)),
|
.clip(RoundedCornerShape(topStart = 3.dp, topEnd = 3.dp)),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -67,7 +71,9 @@ fun LibraryTabs(
|
|||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = category.name,
|
// SY -->
|
||||||
|
text = getCategoryName(category, category.visualName),
|
||||||
|
// SY <--
|
||||||
color = if (state.currentPage == index) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onBackground,
|
color = if (state.currentPage == index) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onBackground,
|
||||||
)
|
)
|
||||||
if (count != null) {
|
if (count != null) {
|
||||||
|
@ -5,8 +5,10 @@ import android.net.Uri
|
|||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import data.Manga_sync
|
import data.Manga_sync
|
||||||
import data.Mangas
|
import data.Mangas
|
||||||
|
import eu.kanade.data.category.categoryMapper
|
||||||
import eu.kanade.data.exh.mergedMangaReferenceMapper
|
import eu.kanade.data.exh.mergedMangaReferenceMapper
|
||||||
import eu.kanade.data.manga.mangaMapper
|
import eu.kanade.data.manga.mangaMapper
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.domain.history.model.HistoryUpdate
|
import eu.kanade.domain.history.model.HistoryUpdate
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
|
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
|
||||||
@ -160,7 +162,9 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
private suspend fun backupCategories(options: Int): List<BackupCategory> {
|
private suspend fun backupCategories(options: Int): List<BackupCategory> {
|
||||||
// Check if user wants category information in backup
|
// Check if user wants category information in backup
|
||||||
return if (options and BACKUP_CATEGORY_MASK == BACKUP_CATEGORY) {
|
return if (options and BACKUP_CATEGORY_MASK == BACKUP_CATEGORY) {
|
||||||
handler.awaitList { categoriesQueries.getCategories(backupCategoryMapper) }
|
handler.awaitList { categoriesQueries.getCategories(categoryMapper) }
|
||||||
|
.filterNot(Category::isSystemCategory)
|
||||||
|
.map(backupCategoryMapper)
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
@ -270,34 +274,37 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
|
|||||||
*/
|
*/
|
||||||
internal suspend fun restoreCategories(backupCategories: List<BackupCategory>) {
|
internal suspend fun restoreCategories(backupCategories: List<BackupCategory>) {
|
||||||
// Get categories from file and from db
|
// Get categories from file and from db
|
||||||
val dbCategories = handler.awaitList { categoriesQueries.getCategories() }
|
val dbCategories = handler.awaitList { categoriesQueries.getCategories(categoryMapper) }
|
||||||
|
|
||||||
// Iterate over them
|
val categories = backupCategories.map {
|
||||||
backupCategories
|
var category = it.getCategory()
|
||||||
.map { it.getCategoryImpl() }
|
var found = false
|
||||||
.forEach { category ->
|
for (dbCategory in dbCategories) {
|
||||||
// Used to know if the category is already in the db
|
// If the category is already in the db, assign the id to the file's category
|
||||||
var found = false
|
// and do nothing
|
||||||
for (dbCategory in dbCategories) {
|
if (category.name == dbCategory.name) {
|
||||||
// If the category is already in the db, assign the id to the file's category
|
category = category.copy(id = dbCategory.id)
|
||||||
// and do nothing
|
found = true
|
||||||
if (category.name == dbCategory.name) {
|
break
|
||||||
category.id = dbCategory.id.toInt()
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If the category isn't in the db, remove the id and insert a new category
|
|
||||||
// Store the inserted id in the category
|
|
||||||
if (!found) {
|
|
||||||
// Let the db assign the id
|
|
||||||
category.id = null
|
|
||||||
category.id = handler.awaitOne {
|
|
||||||
categoriesQueries.insert(category.name, category.order.toLong(), category.flags.toLong())
|
|
||||||
categoriesQueries.selectLastInsertedRowId()
|
|
||||||
}.toInt()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!found) {
|
||||||
|
// Let the db assign the id
|
||||||
|
val id = handler.awaitOne {
|
||||||
|
categoriesQueries.insert(category.name, category.order, category.flags)
|
||||||
|
categoriesQueries.selectLastInsertedRowId()
|
||||||
|
}
|
||||||
|
category = category.copy(id = id)
|
||||||
|
}
|
||||||
|
|
||||||
|
category
|
||||||
|
}
|
||||||
|
|
||||||
|
preferences.categorizedDisplaySettings().set(
|
||||||
|
(dbCategories + categories)
|
||||||
|
.distinctBy { it.flags }
|
||||||
|
.size > 1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.data.backup.full.models
|
package eu.kanade.tachiyomi.data.backup.full.models
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.data.database.models.CategoryImpl
|
import eu.kanade.domain.category.model.Category
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.protobuf.ProtoNumber
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
@ -14,20 +14,21 @@ class BackupCategory(
|
|||||||
// SY specific values
|
// SY specific values
|
||||||
/*@ProtoNumber(600) var mangaOrder: List<Long> = emptyList(),*/
|
/*@ProtoNumber(600) var mangaOrder: List<Long> = emptyList(),*/
|
||||||
) {
|
) {
|
||||||
fun getCategoryImpl(): CategoryImpl {
|
fun getCategory(): Category {
|
||||||
return CategoryImpl().apply {
|
return Category(
|
||||||
name = this@BackupCategory.name
|
id = 0,
|
||||||
flags = this@BackupCategory.flags.toInt()
|
name = this@BackupCategory.name,
|
||||||
order = this@BackupCategory.order.toInt()
|
flags = this@BackupCategory.flags,
|
||||||
|
order = this@BackupCategory.order,
|
||||||
/*mangaOrder = this@BackupCategory.mangaOrder*/
|
/*mangaOrder = this@BackupCategory.mangaOrder*/
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val backupCategoryMapper = { _: Long, name: String, order: Long, flags: Long ->
|
val backupCategoryMapper = { category: Category ->
|
||||||
BackupCategory(
|
BackupCategory(
|
||||||
name = name,
|
name = category.name,
|
||||||
order = order,
|
order = category.order,
|
||||||
flags = flags,
|
flags = category.flags,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.models
|
|
||||||
|
|
||||||
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 {
|
|
||||||
|
|
||||||
var id: Int?
|
|
||||||
|
|
||||||
var name: String
|
|
||||||
|
|
||||||
var order: Int
|
|
||||||
|
|
||||||
var flags: Int
|
|
||||||
|
|
||||||
private fun setFlags(flag: Int, mask: Int) {
|
|
||||||
flags = flags and mask.inv() or (flag and mask)
|
|
||||||
}
|
|
||||||
|
|
||||||
var displayMode: Int
|
|
||||||
get() = flags and DisplayModeSetting.MASK.toInt()
|
|
||||||
set(mode) = setFlags(mode, DisplayModeSetting.MASK.toInt())
|
|
||||||
|
|
||||||
var sortMode: Int
|
|
||||||
get() = flags and SortModeSetting.MASK.toInt()
|
|
||||||
set(mode) = setFlags(mode, SortModeSetting.MASK.toInt())
|
|
||||||
|
|
||||||
var sortDirection: Int
|
|
||||||
get() = flags and SortDirectionSetting.MASK.toInt()
|
|
||||||
set(mode) = setFlags(mode, SortDirectionSetting.MASK.toInt())
|
|
||||||
}
|
|
||||||
|
|
||||||
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,24 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.data.database.models
|
|
||||||
|
|
||||||
class CategoryImpl : Category {
|
|
||||||
|
|
||||||
override var id: Int? = null
|
|
||||||
|
|
||||||
override lateinit var name: String
|
|
||||||
|
|
||||||
override var order: Int = 0
|
|
||||||
|
|
||||||
override var flags: Int = 0
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other == null || javaClass != other.javaClass) return false
|
|
||||||
|
|
||||||
val category = other as Category
|
|
||||||
return name == category.name
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
return name.hashCode()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.data.track.myanimelist
|
package eu.kanade.tachiyomi.data.track.myanimelist
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.parseAs
|
import eu.kanade.tachiyomi.network.parseAs
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
@ -35,7 +35,7 @@ class CategoryPresenter(
|
|||||||
getCategories.subscribe()
|
getCategories.subscribe()
|
||||||
.collectLatest {
|
.collectLatest {
|
||||||
state.isLoading = false
|
state.isLoading = false
|
||||||
state.categories = it
|
state.categories = it.filterNot(Category::isSystemCategory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import com.bluelinelabs.conductor.ControllerChangeHandler
|
|||||||
import com.bluelinelabs.conductor.ControllerChangeType
|
import com.bluelinelabs.conductor.ControllerChangeType
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.domain.category.model.toDbCategory
|
|
||||||
import eu.kanade.domain.manga.model.Manga
|
import eu.kanade.domain.manga.model.Manga
|
||||||
import eu.kanade.domain.manga.model.toDbManga
|
import eu.kanade.domain.manga.model.toDbManga
|
||||||
import eu.kanade.presentation.library.LibraryScreen
|
import eu.kanade.presentation.library.LibraryScreen
|
||||||
@ -205,7 +204,7 @@ class LibraryController(
|
|||||||
fun showSettingsSheet() {
|
fun showSettingsSheet() {
|
||||||
if (presenter.categories.isNotEmpty() /* SY --> */ && presenter.groupType == LibraryGroup.BY_DEFAULT /* SY <-- */) {
|
if (presenter.categories.isNotEmpty() /* SY --> */ && presenter.groupType == LibraryGroup.BY_DEFAULT /* SY <-- */) {
|
||||||
presenter.categories[presenter.activeCategory].let { category ->
|
presenter.categories[presenter.activeCategory].let { category ->
|
||||||
settingsSheet?.show(category.toDbCategory())
|
settingsSheet?.show(category)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
settingsSheet?.show()
|
settingsSheet?.show()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.ui.library
|
package eu.kanade.tachiyomi.ui.library
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
@ -8,6 +9,7 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.util.fastAny
|
import androidx.compose.ui.util.fastAny
|
||||||
import com.jakewharton.rxrelay.BehaviorRelay
|
import com.jakewharton.rxrelay.BehaviorRelay
|
||||||
@ -34,6 +36,7 @@ import eu.kanade.domain.manga.model.MangaUpdate
|
|||||||
import eu.kanade.domain.manga.model.isLocal
|
import eu.kanade.domain.manga.model.isLocal
|
||||||
import eu.kanade.domain.track.interactor.GetTracks
|
import eu.kanade.domain.track.interactor.GetTracks
|
||||||
import eu.kanade.domain.track.model.Track
|
import eu.kanade.domain.track.model.Track
|
||||||
|
import eu.kanade.presentation.category.visualName
|
||||||
import eu.kanade.presentation.library.LibraryState
|
import eu.kanade.presentation.library.LibraryState
|
||||||
import eu.kanade.presentation.library.LibraryStateImpl
|
import eu.kanade.presentation.library.LibraryStateImpl
|
||||||
import eu.kanade.presentation.library.components.LibraryToolbarTitle
|
import eu.kanade.presentation.library.components.LibraryToolbarTitle
|
||||||
@ -138,15 +141,9 @@ class LibraryPresenter(
|
|||||||
// SY <--
|
// SY <--
|
||||||
) : BasePresenter<LibraryController>(), LibraryState by state {
|
) : BasePresenter<LibraryController>(), LibraryState by state {
|
||||||
|
|
||||||
private val context = preferences.context
|
|
||||||
|
|
||||||
var loadedManga by mutableStateOf(emptyMap<Long, List<LibraryItem>>())
|
var loadedManga by mutableStateOf(emptyMap<Long, List<LibraryItem>>())
|
||||||
private set
|
private set
|
||||||
|
|
||||||
val isPerCategory by preferences.categorizedDisplaySettings().asState()
|
|
||||||
|
|
||||||
var currentDisplayMode by preferences.libraryDisplayMode().asState()
|
|
||||||
|
|
||||||
val tabVisibility by preferences.categoryTabs().asState()
|
val tabVisibility by preferences.categoryTabs().asState()
|
||||||
|
|
||||||
val mangaCountVisibility by preferences.categoryNumberOfItems().asState()
|
val mangaCountVisibility by preferences.categoryNumberOfItems().asState()
|
||||||
@ -175,15 +172,13 @@ class LibraryPresenter(
|
|||||||
private var librarySubscription: Job? = null
|
private var librarySubscription: Job? = null
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
val favoritesSync = FavoritesSyncHelper(context)
|
val favoritesSync = FavoritesSyncHelper(preferences.context)
|
||||||
|
|
||||||
val groupType by preferences.groupLibraryBy().asState()
|
|
||||||
|
|
||||||
private val loggedServices by lazy { trackManager.services.filter { it.isLogged } }
|
private val loggedServices by lazy { trackManager.services.filter { it.isLogged } }
|
||||||
|
|
||||||
private val services by lazy {
|
private val services by lazy {
|
||||||
trackManager.services.associate { service ->
|
trackManager.services.associate { service ->
|
||||||
service.id to context.getString(service.nameRes())
|
service.id to preferences.context.getString(service.nameRes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +244,7 @@ class LibraryPresenter(
|
|||||||
.asFlow()
|
.asFlow()
|
||||||
.collectLatest {
|
.collectLatest {
|
||||||
// SY -->
|
// SY -->
|
||||||
|
state.groupType = preferences.groupLibraryBy().get()
|
||||||
state.categories = it.categories
|
state.categories = it.categories
|
||||||
// SY <--
|
// SY <--
|
||||||
state.isLoading = false
|
state.isLoading = false
|
||||||
@ -578,8 +574,8 @@ class LibraryPresenter(
|
|||||||
*/
|
*/
|
||||||
private fun getLibraryObservable(): Observable<Library> {
|
private fun getLibraryObservable(): Observable<Library> {
|
||||||
return combine(getCategoriesFlow(), getLibraryMangasFlow()) { dbCategories, libraryManga ->
|
return combine(getCategoriesFlow(), getLibraryMangasFlow()) { dbCategories, libraryManga ->
|
||||||
val categories = if (libraryManga.containsKey(0) || libraryManga.isEmpty()) {
|
val categories = if (libraryManga.isNotEmpty() && libraryManga.containsKey(0).not()) {
|
||||||
arrayListOf(Category.default(context)) + dbCategories
|
dbCategories.filterNot { it.id == Category.UNCATEGORIZED_ID }
|
||||||
} else {
|
} else {
|
||||||
dbCategories
|
dbCategories
|
||||||
}
|
}
|
||||||
@ -612,7 +608,8 @@ class LibraryPresenter(
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val (items, customCategories) = getGroupedMangaItems(
|
val (items, customCategories) = getGroupedMangaItems(
|
||||||
map.values.flatten().distinctBy { it.manga.id },
|
groupType = groupType,
|
||||||
|
libraryManga = map.values.flatten().distinctBy { it.manga.id },
|
||||||
)
|
)
|
||||||
editedCategories = customCategories
|
editedCategories = customCategories
|
||||||
items
|
items
|
||||||
@ -909,13 +906,18 @@ class LibraryPresenter(
|
|||||||
// TODO: This is good but should we separate title from count or get categories with count from db
|
// TODO: This is good but should we separate title from count or get categories with count from db
|
||||||
@Composable
|
@Composable
|
||||||
fun getToolbarTitle(): androidx.compose.runtime.State<LibraryToolbarTitle> {
|
fun getToolbarTitle(): androidx.compose.runtime.State<LibraryToolbarTitle> {
|
||||||
|
val context = LocalContext.current
|
||||||
val category = categories.getOrNull(activeCategory)
|
val category = categories.getOrNull(activeCategory)
|
||||||
|
|
||||||
val defaultTitle = stringResource(id = R.string.label_library)
|
val defaultTitle = stringResource(id = R.string.label_library)
|
||||||
|
val categoryName = category?.visualName ?: defaultTitle
|
||||||
|
|
||||||
val default = remember { LibraryToolbarTitle(defaultTitle) }
|
val default = remember { LibraryToolbarTitle(defaultTitle) }
|
||||||
|
|
||||||
return produceState(initialValue = default, category, loadedManga, mangaCountVisibility, tabVisibility) {
|
return produceState(initialValue = default, category, loadedManga, mangaCountVisibility, tabVisibility, groupType, context) {
|
||||||
val title = if (tabVisibility.not()) category?.name ?: defaultTitle else defaultTitle
|
val title = if (tabVisibility.not()) {
|
||||||
|
getCategoryName(context, category, groupType, categoryName)
|
||||||
|
} else defaultTitle
|
||||||
|
|
||||||
value = when {
|
value = when {
|
||||||
category == null -> default
|
category == null -> default
|
||||||
@ -928,6 +930,36 @@ class LibraryPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getCategoryName(
|
||||||
|
context: Context,
|
||||||
|
category: Category?,
|
||||||
|
groupType: Int,
|
||||||
|
categoryName: String,
|
||||||
|
): String {
|
||||||
|
return when (groupType) {
|
||||||
|
LibraryGroup.BY_STATUS -> when (category?.id) {
|
||||||
|
SManga.ONGOING.toLong() -> context.getString(R.string.ongoing)
|
||||||
|
SManga.LICENSED.toLong() -> context.getString(R.string.licensed)
|
||||||
|
SManga.CANCELLED.toLong() -> context.getString(R.string.cancelled)
|
||||||
|
SManga.ON_HIATUS.toLong() -> context.getString(R.string.on_hiatus)
|
||||||
|
SManga.PUBLISHING_FINISHED.toLong() -> context.getString(R.string.publishing_finished)
|
||||||
|
SManga.COMPLETED.toLong() -> context.getString(R.string.completed)
|
||||||
|
else -> context.getString(R.string.unknown)
|
||||||
|
}
|
||||||
|
LibraryGroup.BY_SOURCE -> if (category?.id == LocalSource.ID) {
|
||||||
|
context.getString(R.string.local_source)
|
||||||
|
} else {
|
||||||
|
categoryName
|
||||||
|
}
|
||||||
|
LibraryGroup.BY_TRACK_STATUS -> TrackStatus.values()
|
||||||
|
.find { it.int.toLong() == category?.id }
|
||||||
|
.let { it ?: TrackStatus.OTHER }
|
||||||
|
.let { context.getString(it.res) }
|
||||||
|
LibraryGroup.UNGROUPED -> context.getString(R.string.ungrouped)
|
||||||
|
else -> categoryName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
@Composable
|
@Composable
|
||||||
fun getMangaForCategory(page: Int): androidx.compose.runtime.State<List<LibraryItem>> {
|
fun getMangaForCategory(page: Int): androidx.compose.runtime.State<List<LibraryItem>> {
|
||||||
@ -1063,7 +1095,7 @@ class LibraryPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun filterTracks(constraint: String, tracks: List<eu.kanade.domain.track.model.Track>): Boolean {
|
private fun filterTracks(constraint: String, tracks: List<Track>): Boolean {
|
||||||
return tracks.any {
|
return tracks.any {
|
||||||
val trackService = trackManager.getService(it.syncId)
|
val trackService = trackManager.getService(it.syncId)
|
||||||
if (trackService != null) {
|
if (trackService != null) {
|
||||||
@ -1073,6 +1105,8 @@ class LibraryPresenter(
|
|||||||
} else false
|
} else false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val currentCategory by preferences.libraryDisplayMode().asState()
|
||||||
// SY <--
|
// SY <--
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -1080,12 +1114,12 @@ class LibraryPresenter(
|
|||||||
val category = categories[index]
|
val category = categories[index]
|
||||||
return derivedStateOf {
|
return derivedStateOf {
|
||||||
// SY -->
|
// SY -->
|
||||||
if (groupType != LibraryGroup.BY_DEFAULT || isPerCategory.not() || (category.id == 0L && groupType == LibraryGroup.BY_DEFAULT)) {
|
if (groupType != LibraryGroup.BY_DEFAULT) {
|
||||||
// SY <--
|
currentCategory
|
||||||
currentDisplayMode
|
|
||||||
} else {
|
} else {
|
||||||
DisplayModeSetting.fromFlag(category.displayMode)
|
DisplayModeSetting.fromFlag(category.displayMode)
|
||||||
}
|
}
|
||||||
|
// SY <--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1135,41 +1169,8 @@ class LibraryPresenter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getGroupedMangaItems(libraryManga: List<LibraryItem>): Pair<LibraryMap, List<Category>> {
|
private fun getGroupedMangaItems(groupType: Int, libraryManga: List<LibraryItem>): Pair<LibraryMap, List<Category>> {
|
||||||
val groupType = preferences.groupLibraryBy().get()
|
val manga = mutableMapOf<Long, MutableList<LibraryItem>>()
|
||||||
val grouping: MutableMap<Long, Pair<Long, String>> = mutableMapOf()
|
|
||||||
when (groupType) {
|
|
||||||
LibraryGroup.BY_STATUS -> {
|
|
||||||
grouping.putAll(
|
|
||||||
listOf(
|
|
||||||
SManga.ONGOING.toLong() to context.getString(R.string.ongoing),
|
|
||||||
SManga.LICENSED.toLong() to context.getString(R.string.licensed),
|
|
||||||
SManga.CANCELLED.toLong() to context.getString(R.string.cancelled),
|
|
||||||
SManga.ON_HIATUS.toLong() to context.getString(R.string.on_hiatus),
|
|
||||||
SManga.PUBLISHING_FINISHED.toLong() to context.getString(R.string.publishing_finished),
|
|
||||||
SManga.COMPLETED.toLong() to context.getString(R.string.completed),
|
|
||||||
SManga.UNKNOWN.toLong() to context.getString(R.string.unknown),
|
|
||||||
).associateBy(Pair<Long, *>::first),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
LibraryGroup.BY_SOURCE ->
|
|
||||||
libraryManga
|
|
||||||
.map { it.manga.source }
|
|
||||||
.distinct()
|
|
||||||
.sorted()
|
|
||||||
.map { sourceId ->
|
|
||||||
sourceId to (sourceId to sourceManager.getOrStub(sourceId).name)
|
|
||||||
}
|
|
||||||
.let(grouping::putAll)
|
|
||||||
LibraryGroup.BY_TRACK_STATUS -> {
|
|
||||||
grouping.putAll(
|
|
||||||
TrackStatus.values()
|
|
||||||
.map { it.int.toLong() to context.getString(it.res) }
|
|
||||||
.associateBy(Pair<Long, *>::first),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val map: MutableMap<Long, MutableList<LibraryItem>> = mutableMapOf()
|
|
||||||
|
|
||||||
when (groupType) {
|
when (groupType) {
|
||||||
LibraryGroup.BY_TRACK_STATUS -> {
|
LibraryGroup.BY_TRACK_STATUS -> {
|
||||||
@ -1179,46 +1180,39 @@ class LibraryPresenter(
|
|||||||
TrackStatus.parseTrackerStatus(track.syncId, track.status)
|
TrackStatus.parseTrackerStatus(track.syncId, track.status)
|
||||||
} ?: TrackStatus.OTHER
|
} ?: TrackStatus.OTHER
|
||||||
|
|
||||||
map.getOrPut(status.int.toLong()) { mutableListOf() } += libraryItem
|
manga.getOrPut(status.int.toLong()) { mutableListOf() } += libraryItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LibraryGroup.BY_SOURCE -> {
|
LibraryGroup.BY_SOURCE -> {
|
||||||
libraryManga.forEach { libraryItem ->
|
libraryManga.forEach { libraryItem ->
|
||||||
val group = grouping[libraryItem.manga.source]
|
manga.getOrPut(libraryItem.manga.source) { mutableListOf() } += libraryItem
|
||||||
if (group != null) {
|
|
||||||
map.getOrPut(group.first) { mutableListOf() } += libraryItem
|
|
||||||
} else {
|
|
||||||
grouping.getOrPut(Long.MAX_VALUE) {
|
|
||||||
Long.MAX_VALUE to context.getString(R.string.unknown)
|
|
||||||
}
|
|
||||||
map.getOrPut(Long.MAX_VALUE) { mutableListOf() } += libraryItem
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
libraryManga.forEach { libraryItem ->
|
libraryManga.forEach { libraryItem ->
|
||||||
val group = grouping[libraryItem.manga.status.toLong()]
|
manga.getOrPut(libraryItem.manga.status.toLong()) { mutableListOf() } += libraryItem
|
||||||
if (group != null) {
|
|
||||||
map.getOrPut(group.first) { mutableListOf() } += libraryItem
|
|
||||||
} else {
|
|
||||||
grouping.getOrPut(Long.MAX_VALUE) {
|
|
||||||
Long.MAX_VALUE to context.getString(R.string.unknown)
|
|
||||||
}
|
|
||||||
map.getOrPut(Long.MAX_VALUE) { mutableListOf() } += libraryItem
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val categories = when (groupType) {
|
val categories = when (groupType) {
|
||||||
LibraryGroup.BY_SOURCE -> grouping.values.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER, Pair<*, String>::second))
|
LibraryGroup.BY_SOURCE -> manga.keys.map { Category(it, sourceManager.getOrStub(it).name, 0, 0) }
|
||||||
LibraryGroup.BY_TRACK_STATUS, LibraryGroup.BY_STATUS -> grouping.values.filter { it.first in map.keys }
|
.sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.name })
|
||||||
else -> grouping.values
|
LibraryGroup.BY_TRACK_STATUS ->
|
||||||
}.map { (id, name) ->
|
manga.keys
|
||||||
Category(id, name, 0, 0)
|
.map { id ->
|
||||||
|
TrackStatus.values().find { id == it.int.toLong() }
|
||||||
|
?: TrackStatus.OTHER
|
||||||
|
}
|
||||||
|
.sortedBy { it.int }
|
||||||
|
.map {
|
||||||
|
Category(it.int.toLong(), "", 0, 0)
|
||||||
|
}
|
||||||
|
LibraryGroup.BY_STATUS -> manga.keys.sorted().map { Category(it, "", 0, 0) }
|
||||||
|
else -> throw IllegalStateException("Invalid group type $groupType")
|
||||||
}
|
}
|
||||||
|
|
||||||
return map to categories
|
return manga to categories
|
||||||
}
|
}
|
||||||
|
|
||||||
fun runSync() {
|
fun runSync() {
|
||||||
|
@ -5,11 +5,10 @@ import android.util.AttributeSet
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import com.bluelinelabs.conductor.Router
|
import com.bluelinelabs.conductor.Router
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.UpdateCategory
|
import eu.kanade.domain.category.interactor.SetDisplayModeForCategory
|
||||||
import eu.kanade.domain.category.model.CategoryUpdate
|
import eu.kanade.domain.category.interactor.SetSortModeForCategory
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.tachiyomi.R
|
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.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.data.track.TrackService
|
import eu.kanade.tachiyomi.data.track.TrackService
|
||||||
@ -31,7 +30,8 @@ import uy.kohesive.injekt.injectLazy
|
|||||||
class LibrarySettingsSheet(
|
class LibrarySettingsSheet(
|
||||||
router: Router,
|
router: Router,
|
||||||
private val trackManager: TrackManager = Injekt.get(),
|
private val trackManager: TrackManager = Injekt.get(),
|
||||||
private val updateCategory: UpdateCategory = Injekt.get(),
|
private val setDisplayModeForCategory: SetDisplayModeForCategory = Injekt.get(),
|
||||||
|
private val setSortModeForCategory: SetSortModeForCategory = Injekt.get(),
|
||||||
onGroupClickListener: (ExtendedNavigationView.Group) -> Unit,
|
onGroupClickListener: (ExtendedNavigationView.Group) -> Unit,
|
||||||
) : TabbedBottomSheetDialog(router.activity!!) {
|
) : TabbedBottomSheetDialog(router.activity!!) {
|
||||||
|
|
||||||
@ -226,8 +226,8 @@ class LibrarySettingsSheet(
|
|||||||
override val footer = null
|
override val footer = null
|
||||||
|
|
||||||
override fun initModels() {
|
override fun initModels() {
|
||||||
val sorting = SortModeSetting.get(preferences, currentCategory?.toDomainCategory())
|
val sorting = SortModeSetting.get(preferences, currentCategory)
|
||||||
val order = if (SortDirectionSetting.get(preferences, currentCategory?.toDomainCategory()) == SortDirectionSetting.ASCENDING) {
|
val order = if (SortDirectionSetting.get(preferences, currentCategory) == SortDirectionSetting.ASCENDING) {
|
||||||
Item.MultiSort.SORT_ASC
|
Item.MultiSort.SORT_ASC
|
||||||
} else {
|
} else {
|
||||||
Item.MultiSort.SORT_DESC
|
Item.MultiSort.SORT_DESC
|
||||||
@ -292,18 +292,8 @@ class LibrarySettingsSheet(
|
|||||||
SortDirectionSetting.DESCENDING
|
SortDirectionSetting.DESCENDING
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0 /* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT /* SY <-- */) {
|
sheetScope.launchIO {
|
||||||
currentCategory?.sortDirection = flag.flag.toInt()
|
setSortModeForCategory.await(currentCategory!!, flag)
|
||||||
sheetScope.launchIO {
|
|
||||||
updateCategory.await(
|
|
||||||
CategoryUpdate(
|
|
||||||
id = currentCategory!!.id?.toLong()!!,
|
|
||||||
flags = currentCategory!!.flags.toLong(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
preferences.librarySortingAscending().set(flag)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,18 +313,8 @@ class LibrarySettingsSheet(
|
|||||||
else -> throw NotImplementedError("Unknown display mode")
|
else -> throw NotImplementedError("Unknown display mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0 /* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT /* SY <-- */) {
|
sheetScope.launchIO {
|
||||||
currentCategory?.sortMode = flag.flag.toInt()
|
setSortModeForCategory.await(currentCategory!!, flag)
|
||||||
sheetScope.launchIO {
|
|
||||||
updateCategory.await(
|
|
||||||
CategoryUpdate(
|
|
||||||
id = currentCategory!!.id?.toLong()!!,
|
|
||||||
flags = currentCategory!!.flags.toLong(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
preferences.librarySortingMode().set(flag)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,8 +354,8 @@ class LibrarySettingsSheet(
|
|||||||
|
|
||||||
// Gets user preference of currently selected display mode at current category
|
// Gets user preference of currently selected display mode at current category
|
||||||
private fun getDisplayModePreference(): DisplayModeSetting {
|
private fun getDisplayModePreference(): DisplayModeSetting {
|
||||||
return if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0 /* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT /* SY <-- */) {
|
return if (currentCategory != null && preferences.categorizedDisplaySettings().get()/* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT /* SY <-- */) {
|
||||||
DisplayModeSetting.fromFlag(currentCategory?.displayMode?.toLong())
|
DisplayModeSetting.fromFlag(currentCategory!!.displayMode)
|
||||||
} else {
|
} else {
|
||||||
preferences.libraryDisplayMode().get()
|
preferences.libraryDisplayMode().get()
|
||||||
}
|
}
|
||||||
@ -426,18 +406,8 @@ class LibrarySettingsSheet(
|
|||||||
else -> throw NotImplementedError("Unknown display mode")
|
else -> throw NotImplementedError("Unknown display mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preferences.categorizedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0 /* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT /* SY <-- */) {
|
sheetScope.launchIO {
|
||||||
currentCategory?.displayMode = flag.flag.toInt()
|
setDisplayModeForCategory.await(currentCategory!!, flag)
|
||||||
sheetScope.launchIO {
|
|
||||||
updateCategory.await(
|
|
||||||
CategoryUpdate(
|
|
||||||
id = currentCategory!!.id?.toLong()!!,
|
|
||||||
flags = currentCategory!!.flags.toLong(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
preferences.libraryDisplayMode().set(flag)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.library.setting
|
|||||||
|
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryGroup
|
||||||
|
|
||||||
enum class SortModeSetting(val flag: Long) {
|
enum class SortModeSetting(val flag: Long) {
|
||||||
ALPHABETICAL(0b00000000),
|
ALPHABETICAL(0b00000000),
|
||||||
@ -38,7 +39,7 @@ enum class SortModeSetting(val flag: Long) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun get(preferences: PreferencesHelper, category: Category?): SortModeSetting {
|
fun get(preferences: PreferencesHelper, category: Category?): SortModeSetting {
|
||||||
return if (preferences.categorizedDisplaySettings().get() && category != null && category.id != 0L) {
|
return if (category != null && preferences.categorizedDisplaySettings().get() /* SY --> */ && preferences.groupLibraryBy().get() == LibraryGroup.BY_DEFAULT/* SY <-- */) {
|
||||||
fromFlag(category.sortMode)
|
fromFlag(category.sortMode)
|
||||||
} else {
|
} else {
|
||||||
preferences.librarySortingMode().get()
|
preferences.librarySortingMode().get()
|
||||||
|
@ -12,7 +12,7 @@ import androidx.preference.PreferenceScreen
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.presentation.category.visualName
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
@ -46,8 +46,7 @@ class SettingsDownloadController : SettingsController() {
|
|||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||||
titleRes = R.string.pref_category_downloads
|
titleRes = R.string.pref_category_downloads
|
||||||
|
|
||||||
val dbCategories = runBlocking { getCategories.await() }
|
val categories = runBlocking { getCategories.await() }
|
||||||
val categories = listOf(Category.default(context)) + dbCategories
|
|
||||||
|
|
||||||
preference {
|
preference {
|
||||||
bindTo(preferences.downloadsDirectory())
|
bindTo(preferences.downloadsDirectory())
|
||||||
@ -111,7 +110,7 @@ class SettingsDownloadController : SettingsController() {
|
|||||||
multiSelectListPreference {
|
multiSelectListPreference {
|
||||||
bindTo(preferences.removeExcludeCategories())
|
bindTo(preferences.removeExcludeCategories())
|
||||||
titleRes = R.string.pref_remove_exclude_categories
|
titleRes = R.string.pref_remove_exclude_categories
|
||||||
entries = categories.map { it.name }.toTypedArray()
|
entries = categories.map { it.visualName(context) }.toTypedArray()
|
||||||
entryValues = categories.map { it.id.toString() }.toTypedArray()
|
entryValues = categories.map { it.id.toString() }.toTypedArray()
|
||||||
|
|
||||||
preferences.removeExcludeCategories().asFlow()
|
preferences.removeExcludeCategories().asFlow()
|
||||||
@ -255,10 +254,9 @@ class SettingsDownloadController : SettingsController() {
|
|||||||
private val getCategories: GetCategories = Injekt.get()
|
private val getCategories: GetCategories = Injekt.get()
|
||||||
|
|
||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
val dbCategories = runBlocking { getCategories.await() }
|
val categories = runBlocking { getCategories.await() }
|
||||||
val categories = listOf(Category.default(activity!!)) + dbCategories
|
|
||||||
|
|
||||||
val items = categories.map { it.name }
|
val items = categories.map { it.visualName(activity!!) }
|
||||||
var selected = categories
|
var selected = categories
|
||||||
.map {
|
.map {
|
||||||
when (it.id.toString()) {
|
when (it.id.toString()) {
|
||||||
|
@ -8,7 +8,9 @@ import androidx.core.text.buildSpannedString
|
|||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
|
import eu.kanade.domain.category.interactor.ResetCategoryFlags
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.presentation.category.visualName
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
import eu.kanade.tachiyomi.data.preference.DEVICE_BATTERY_NOT_LOW
|
import eu.kanade.tachiyomi.data.preference.DEVICE_BATTERY_NOT_LOW
|
||||||
@ -55,6 +57,7 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
|
|
||||||
private val getCategories: GetCategories by injectLazy()
|
private val getCategories: GetCategories by injectLazy()
|
||||||
private val trackManager: TrackManager by injectLazy()
|
private val trackManager: TrackManager by injectLazy()
|
||||||
|
private val resetCategoryFlags: ResetCategoryFlags by injectLazy()
|
||||||
|
|
||||||
// SY -->
|
// SY -->
|
||||||
/**
|
/**
|
||||||
@ -66,8 +69,8 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
|
||||||
titleRes = R.string.pref_category_library
|
titleRes = R.string.pref_category_library
|
||||||
|
|
||||||
val dbCategories = runBlocking { getCategories.await() }
|
val allCategories = runBlocking { getCategories.await() }
|
||||||
val categories = listOf(Category.default(context)) + dbCategories
|
val userCategories = allCategories.filterNot(Category::isSystemCategory)
|
||||||
|
|
||||||
preferenceCategory {
|
preferenceCategory {
|
||||||
titleRes = R.string.pref_category_display
|
titleRes = R.string.pref_category_display
|
||||||
@ -120,7 +123,7 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
key = "pref_action_edit_categories"
|
key = "pref_action_edit_categories"
|
||||||
titleRes = R.string.action_edit_categories
|
titleRes = R.string.action_edit_categories
|
||||||
|
|
||||||
val catCount = dbCategories.size
|
val catCount = userCategories.size
|
||||||
summary = context.resources.getQuantityString(R.plurals.num_categories, catCount, catCount)
|
summary = context.resources.getQuantityString(R.plurals.num_categories, catCount, catCount)
|
||||||
|
|
||||||
onClick {
|
onClick {
|
||||||
@ -133,15 +136,15 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
titleRes = R.string.default_category
|
titleRes = R.string.default_category
|
||||||
|
|
||||||
entries = arrayOf(context.getString(R.string.default_category_summary)) +
|
entries = arrayOf(context.getString(R.string.default_category_summary)) +
|
||||||
categories.map { it.name }.toTypedArray()
|
allCategories.map { it.visualName(context) }.toTypedArray()
|
||||||
entryValues = arrayOf("-1") + categories.map { it.id.toString() }.toTypedArray()
|
entryValues = arrayOf("-1") + allCategories.map { it.id.toString() }.toTypedArray()
|
||||||
defaultValue = "-1"
|
defaultValue = "-1"
|
||||||
|
|
||||||
val selectedCategory = categories.find { it.id == preferences.defaultCategory().toLong() }
|
val selectedCategory = allCategories.find { it.id == preferences.defaultCategory().toLong() }
|
||||||
summary = selectedCategory?.name
|
summary = selectedCategory?.name
|
||||||
?: context.getString(R.string.default_category_summary)
|
?: context.getString(R.string.default_category_summary)
|
||||||
onChange { newValue ->
|
onChange { newValue ->
|
||||||
summary = categories.find {
|
summary = allCategories.find {
|
||||||
it.id == (newValue as String).toLong()
|
it.id == (newValue as String).toLong()
|
||||||
}?.name ?: context.getString(R.string.default_category_summary)
|
}?.name ?: context.getString(R.string.default_category_summary)
|
||||||
true
|
true
|
||||||
@ -151,6 +154,14 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
switchPreference {
|
switchPreference {
|
||||||
bindTo(preferences.categorizedDisplaySettings())
|
bindTo(preferences.categorizedDisplaySettings())
|
||||||
titleRes = R.string.categorized_display_settings
|
titleRes = R.string.categorized_display_settings
|
||||||
|
|
||||||
|
preferences.categorizedDisplaySettings().asFlow()
|
||||||
|
.onEach {
|
||||||
|
if (it.not()) {
|
||||||
|
resetCategoryFlags.await()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(viewScope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,19 +266,19 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
|
|
||||||
fun updateSummary() {
|
fun updateSummary() {
|
||||||
val includedCategories = preferences.libraryUpdateCategories().get()
|
val includedCategories = preferences.libraryUpdateCategories().get()
|
||||||
.mapNotNull { id -> categories.find { it.id == id.toLong() } }
|
.mapNotNull { id -> allCategories.find { it.id == id.toLong() } }
|
||||||
.sortedBy { it.order }
|
.sortedBy { it.order }
|
||||||
val excludedCategories = preferences.libraryUpdateCategoriesExclude().get()
|
val excludedCategories = preferences.libraryUpdateCategoriesExclude().get()
|
||||||
.mapNotNull { id -> categories.find { it.id == id.toLong() } }
|
.mapNotNull { id -> allCategories.find { it.id == id.toLong() } }
|
||||||
.sortedBy { it.order }
|
.sortedBy { it.order }
|
||||||
|
|
||||||
val allExcluded = excludedCategories.size == categories.size
|
val allExcluded = excludedCategories.size == allCategories.size
|
||||||
|
|
||||||
val includedItemsText = when {
|
val includedItemsText = when {
|
||||||
// Some selected, but not all
|
// Some selected, but not all
|
||||||
includedCategories.isNotEmpty() && includedCategories.size != categories.size -> includedCategories.joinToString { it.name }
|
includedCategories.isNotEmpty() && includedCategories.size != allCategories.size -> includedCategories.joinToString { it.name }
|
||||||
// All explicitly selected
|
// All explicitly selected
|
||||||
includedCategories.size == categories.size -> context.getString(R.string.all)
|
includedCategories.size == allCategories.size -> context.getString(R.string.all)
|
||||||
allExcluded -> context.getString(R.string.none)
|
allExcluded -> context.getString(R.string.none)
|
||||||
else -> context.getString(R.string.all)
|
else -> context.getString(R.string.all)
|
||||||
}
|
}
|
||||||
@ -403,10 +414,9 @@ class SettingsLibraryController : SettingsController() {
|
|||||||
private val getCategories: GetCategories = Injekt.get()
|
private val getCategories: GetCategories = Injekt.get()
|
||||||
|
|
||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
val dbCategories = runBlocking { getCategories.await() }
|
val categories = runBlocking { getCategories.await() }
|
||||||
val categories = listOf(Category.default(activity!!)) + dbCategories
|
|
||||||
|
|
||||||
val items = categories.map { it.name }
|
val items = categories.map { it.visualName(activity!!) }
|
||||||
var selected = categories
|
var selected = categories
|
||||||
.map {
|
.map {
|
||||||
when (it.id.toString()) {
|
when (it.id.toString()) {
|
||||||
|
@ -8,6 +8,17 @@ CREATE TABLE categories(
|
|||||||
manga_order TEXT AS List<Long> NOT NULL
|
manga_order TEXT AS List<Long> NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- Insert system category
|
||||||
|
INSERT OR IGNORE INTO categories(_id, name, sort, flags, manga_order) VALUES (0, "", -1, 0, "");
|
||||||
|
-- Disallow deletion of default category
|
||||||
|
CREATE TRIGGER IF NOT EXISTS system_category_delete_trigger BEFORE DELETE
|
||||||
|
ON categories
|
||||||
|
BEGIN SELECT CASE
|
||||||
|
WHEN old._id <= 0 THEN
|
||||||
|
RAISE(ABORT, "System category can't be deleted")
|
||||||
|
END;
|
||||||
|
END;
|
||||||
|
|
||||||
getCategories:
|
getCategories:
|
||||||
SELECT
|
SELECT
|
||||||
_id AS id,
|
_id AS id,
|
||||||
@ -43,5 +54,9 @@ SET name = coalesce(:name, name),
|
|||||||
flags = coalesce(:flags, flags)
|
flags = coalesce(:flags, flags)
|
||||||
WHERE _id = :categoryId;
|
WHERE _id = :categoryId;
|
||||||
|
|
||||||
|
updateAllFlags:
|
||||||
|
UPDATE categories SET
|
||||||
|
flags = coalesce(?, flags);
|
||||||
|
|
||||||
selectLastInsertedRowId:
|
selectLastInsertedRowId:
|
||||||
SELECT last_insert_rowid();
|
SELECT last_insert_rowid();
|
||||||
|
10
app/src/main/sqldelight/migrations/20.sqm
Normal file
10
app/src/main/sqldelight/migrations/20.sqm
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
-- Insert Default category
|
||||||
|
INSERT OR IGNORE INTO categories(_id, name, sort, flags, manga_order) VALUES (0, "", -1, 0, "");
|
||||||
|
-- Disallow deletion of default category
|
||||||
|
CREATE TRIGGER IF NOT EXISTS system_category_delete_trigger BEFORE DELETE
|
||||||
|
ON categories
|
||||||
|
BEGIN SELECT CASE
|
||||||
|
WHEN old._id <= 0 THEN
|
||||||
|
RAISE(ABORT, "System category can't be deleted")
|
||||||
|
END;
|
||||||
|
END;
|
Loading…
x
Reference in New Issue
Block a user