Use SQLDelight on Category screen (#7310)
* Use SQLDelight on Category screen * Include category name in DuplicateNameException
This commit is contained in:
parent
602168bc48
commit
017f6b22f0
17 changed files with 286 additions and 56 deletions
12
app/src/main/java/eu/kanade/data/category/CategoryMapper.kt
Normal file
12
app/src/main/java/eu/kanade/data/category/CategoryMapper.kt
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package eu.kanade.data.category
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
|
||||||
|
val categoryMapper: (Long, String, Long, Long) -> Category = { id, name, order, flags ->
|
||||||
|
Category(
|
||||||
|
id = id,
|
||||||
|
name = name,
|
||||||
|
order = order,
|
||||||
|
flags = flags,
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package eu.kanade.data.category
|
||||||
|
|
||||||
|
import eu.kanade.data.DatabaseHandler
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.domain.category.model.CategoryUpdate
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
import eu.kanade.domain.category.repository.DuplicateNameException
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class CategoryRepositoryImpl(
|
||||||
|
private val handler: DatabaseHandler,
|
||||||
|
) : CategoryRepository {
|
||||||
|
|
||||||
|
override fun getAll(): Flow<List<Category>> {
|
||||||
|
return handler.subscribeToList { categoriesQueries.getCategories(categoryMapper) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(DuplicateNameException::class)
|
||||||
|
override suspend fun insert(name: String, order: Long) {
|
||||||
|
if (checkDuplicateName(name)) throw DuplicateNameException(name)
|
||||||
|
handler.await {
|
||||||
|
categoriesQueries.insert(
|
||||||
|
name = name,
|
||||||
|
order = order,
|
||||||
|
flags = 0L,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(DuplicateNameException::class)
|
||||||
|
override suspend fun update(payload: CategoryUpdate) {
|
||||||
|
if (payload.name != null && checkDuplicateName(payload.name)) throw DuplicateNameException(payload.name)
|
||||||
|
handler.await {
|
||||||
|
categoriesQueries.update(
|
||||||
|
name = payload.name,
|
||||||
|
order = payload.order,
|
||||||
|
flags = payload.flags,
|
||||||
|
categoryId = payload.id,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun delete(categoryId: Long) {
|
||||||
|
handler.await {
|
||||||
|
categoriesQueries.delete(
|
||||||
|
categoryId = categoryId,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun checkDuplicateName(name: String): Boolean {
|
||||||
|
return handler
|
||||||
|
.awaitList { categoriesQueries.getCategories() }
|
||||||
|
.any { it.name == name }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,9 +1,15 @@
|
||||||
package eu.kanade.domain
|
package eu.kanade.domain
|
||||||
|
|
||||||
|
import eu.kanade.data.category.CategoryRepositoryImpl
|
||||||
import eu.kanade.data.chapter.ChapterRepositoryImpl
|
import eu.kanade.data.chapter.ChapterRepositoryImpl
|
||||||
import eu.kanade.data.history.HistoryRepositoryImpl
|
import eu.kanade.data.history.HistoryRepositoryImpl
|
||||||
import eu.kanade.data.manga.MangaRepositoryImpl
|
import eu.kanade.data.manga.MangaRepositoryImpl
|
||||||
import eu.kanade.data.source.SourceRepositoryImpl
|
import eu.kanade.data.source.SourceRepositoryImpl
|
||||||
|
import eu.kanade.domain.category.interactor.DeleteCategory
|
||||||
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
|
import eu.kanade.domain.category.interactor.InsertCategory
|
||||||
|
import eu.kanade.domain.category.interactor.UpdateCategory
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
||||||
import eu.kanade.domain.chapter.interactor.ShouldUpdateDbChapter
|
import eu.kanade.domain.chapter.interactor.ShouldUpdateDbChapter
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
|
@ -45,6 +51,12 @@ import uy.kohesive.injekt.api.get
|
||||||
class DomainModule : InjektModule {
|
class DomainModule : InjektModule {
|
||||||
|
|
||||||
override fun InjektRegistrar.registerInjectables() {
|
override fun InjektRegistrar.registerInjectables() {
|
||||||
|
addSingletonFactory<CategoryRepository> { CategoryRepositoryImpl(get()) }
|
||||||
|
addFactory { GetCategories(get()) }
|
||||||
|
addFactory { InsertCategory(get()) }
|
||||||
|
addFactory { UpdateCategory(get()) }
|
||||||
|
addFactory { DeleteCategory(get()) }
|
||||||
|
|
||||||
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
|
addSingletonFactory<MangaRepository> { MangaRepositoryImpl(get()) }
|
||||||
addFactory { GetFavoritesBySourceId(get()) }
|
addFactory { GetFavoritesBySourceId(get()) }
|
||||||
addFactory { GetMangaById(get()) }
|
addFactory { GetMangaById(get()) }
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
|
||||||
|
class DeleteCategory(
|
||||||
|
private val categoryRepository: CategoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(categoryId: Long) {
|
||||||
|
categoryRepository.delete(categoryId)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
class GetCategories(
|
||||||
|
private val categoryRepository: CategoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun subscribe(): Flow<List<Category>> {
|
||||||
|
return categoryRepository.getAll()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
|
||||||
|
class InsertCategory(
|
||||||
|
private val categoryRepository: CategoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(name: String, order: Long): Result {
|
||||||
|
return try {
|
||||||
|
categoryRepository.insert(name, order)
|
||||||
|
Result.Success
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Result.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Result {
|
||||||
|
object Success : Result()
|
||||||
|
data class Error(val error: Exception) : Result()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package eu.kanade.domain.category.interactor
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.model.CategoryUpdate
|
||||||
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
|
|
||||||
|
class UpdateCategory(
|
||||||
|
private val categoryRepository: CategoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun await(payload: CategoryUpdate): Result {
|
||||||
|
return try {
|
||||||
|
categoryRepository.update(payload)
|
||||||
|
Result.Success
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Result.Error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class Result {
|
||||||
|
object Success : Result()
|
||||||
|
data class Error(val error: Exception) : Result()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package eu.kanade.domain.category.model
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class Category(
|
||||||
|
val id: Long,
|
||||||
|
val name: String,
|
||||||
|
val order: Long,
|
||||||
|
val flags: Long,
|
||||||
|
) : Serializable
|
|
@ -0,0 +1,8 @@
|
||||||
|
package eu.kanade.domain.category.model
|
||||||
|
|
||||||
|
data class CategoryUpdate(
|
||||||
|
val id: Long,
|
||||||
|
val name: String? = null,
|
||||||
|
val order: Long? = null,
|
||||||
|
val flags: Long? = null,
|
||||||
|
)
|
|
@ -0,0 +1,22 @@
|
||||||
|
package eu.kanade.domain.category.repository
|
||||||
|
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.domain.category.model.CategoryUpdate
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
interface CategoryRepository {
|
||||||
|
|
||||||
|
fun getAll(): Flow<List<Category>>
|
||||||
|
|
||||||
|
@Throws(DuplicateNameException::class)
|
||||||
|
suspend fun insert(name: String, order: Long)
|
||||||
|
|
||||||
|
@Throws(DuplicateNameException::class)
|
||||||
|
suspend fun update(payload: CategoryUpdate)
|
||||||
|
|
||||||
|
suspend fun delete(categoryId: Long)
|
||||||
|
|
||||||
|
suspend fun checkDuplicateName(name: String): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class DuplicateNameException(name: String) : Exception("There's a category which is named \"$name\" already")
|
|
@ -30,8 +30,4 @@ interface CategoryQueries : DbProvider {
|
||||||
.prepare()
|
.prepare()
|
||||||
|
|
||||||
fun insertCategory(category: Category) = db.put().`object`(category).prepare()
|
fun insertCategory(category: Category) = db.put().`object`(category).prepare()
|
||||||
|
|
||||||
fun insertCategories(categories: List<Category>) = db.put().objects(categories).prepare()
|
|
||||||
|
|
||||||
fun deleteCategories(categories: List<Category>) = db.delete().objects(categories).prepare()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,14 +14,15 @@ import dev.chrisbanes.insetter.applyInsetter
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||||
import eu.davidea.flexibleadapter.helpers.UndoHelper
|
import eu.davidea.flexibleadapter.helpers.UndoHelper
|
||||||
|
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.databinding.CategoriesControllerBinding
|
import eu.kanade.tachiyomi.databinding.CategoriesControllerBinding
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
|
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller to manage the categories for the users' library.
|
* Controller to manage the categories for the users' library.
|
||||||
|
@ -91,6 +92,12 @@ class CategoryController :
|
||||||
adapter?.isPermanentDelete = false
|
adapter?.isPermanentDelete = false
|
||||||
|
|
||||||
actionFabScrollListener = actionFab?.shrinkOnScroll(binding.recycler)
|
actionFabScrollListener = actionFab?.shrinkOnScroll(binding.recycler)
|
||||||
|
|
||||||
|
viewScope.launch {
|
||||||
|
presenter.categories.collect {
|
||||||
|
setCategories(it.map(::CategoryItem))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun configureFab(fab: ExtendedFloatingActionButton) {
|
override fun configureFab(fab: ExtendedFloatingActionButton) {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.category
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import eu.davidea.viewholders.FlexibleViewHolder
|
import eu.davidea.viewholders.FlexibleViewHolder
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.tachiyomi.databinding.CategoriesItemBinding
|
import eu.kanade.tachiyomi.databinding.CategoriesItemBinding
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,8 +5,8 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
|
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
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Category item for a recycler view.
|
* Category item for a recycler view.
|
||||||
|
@ -68,6 +68,6 @@ class CategoryItem(val category: Category) : AbstractFlexibleItem<CategoryHolder
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
override fun hashCode(): Int {
|
||||||
return category.id!!
|
return category.id.hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
package eu.kanade.tachiyomi.ui.category
|
package eu.kanade.tachiyomi.ui.category
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.domain.category.interactor.DeleteCategory
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
|
import eu.kanade.domain.category.interactor.InsertCategory
|
||||||
|
import eu.kanade.domain.category.interactor.UpdateCategory
|
||||||
|
import eu.kanade.domain.category.model.Category
|
||||||
|
import eu.kanade.domain.category.model.CategoryUpdate
|
||||||
|
import eu.kanade.domain.category.repository.DuplicateNameException
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import rx.Observable
|
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||||
import rx.android.schedulers.AndroidSchedulers
|
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||||
|
import eu.kanade.tachiyomi.util.system.logcat
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import logcat.LogPriority
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
@ -13,13 +23,14 @@ import uy.kohesive.injekt.api.get
|
||||||
* Presenter of [CategoryController]. Used to manage the categories of the library.
|
* Presenter of [CategoryController]. Used to manage the categories of the library.
|
||||||
*/
|
*/
|
||||||
class CategoryPresenter(
|
class CategoryPresenter(
|
||||||
private val db: DatabaseHelper = Injekt.get(),
|
private val getCategories: GetCategories = Injekt.get(),
|
||||||
|
private val insertCategory: InsertCategory = Injekt.get(),
|
||||||
|
private val updateCategory: UpdateCategory = Injekt.get(),
|
||||||
|
private val deleteCategory: DeleteCategory = Injekt.get(),
|
||||||
) : BasePresenter<CategoryController>() {
|
) : BasePresenter<CategoryController>() {
|
||||||
|
|
||||||
/**
|
private val _categories: MutableStateFlow<List<Category>> = MutableStateFlow(listOf())
|
||||||
* List containing categories.
|
val categories = _categories.asStateFlow()
|
||||||
*/
|
|
||||||
private var categories: List<Category> = emptyList()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the presenter is created.
|
* Called when the presenter is created.
|
||||||
|
@ -29,11 +40,12 @@ class CategoryPresenter(
|
||||||
override fun onCreate(savedState: Bundle?) {
|
override fun onCreate(savedState: Bundle?) {
|
||||||
super.onCreate(savedState)
|
super.onCreate(savedState)
|
||||||
|
|
||||||
db.getCategories().asRxObservable()
|
presenterScope.launchIO {
|
||||||
.doOnNext { categories = it }
|
getCategories.subscribe()
|
||||||
.map { it.map(::CategoryItem) }
|
.collectLatest { list ->
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
_categories.value = list
|
||||||
.subscribeLatestCache(CategoryController::setCategories)
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,20 +54,21 @@ class CategoryPresenter(
|
||||||
* @param name The name of the category to create.
|
* @param name The name of the category to create.
|
||||||
*/
|
*/
|
||||||
fun createCategory(name: String) {
|
fun createCategory(name: String) {
|
||||||
// Do not allow duplicate categories.
|
presenterScope.launchIO {
|
||||||
if (categoryExists(name)) {
|
val result = insertCategory.await(
|
||||||
Observable.just(Unit).subscribeFirst({ view, _ -> view.onCategoryExistsError() })
|
name = name,
|
||||||
return
|
order = categories.value.map { it.order + 1L }.maxOrNull() ?: 0L,
|
||||||
|
)
|
||||||
|
when (result) {
|
||||||
|
is InsertCategory.Result.Success -> {}
|
||||||
|
is InsertCategory.Result.Error -> {
|
||||||
|
logcat(LogPriority.ERROR, result.error)
|
||||||
|
if (result.error is DuplicateNameException) {
|
||||||
|
launchUI { view?.onCategoryExistsError() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create category.
|
|
||||||
val cat = Category.create(name)
|
|
||||||
|
|
||||||
// Set the new item in the last position.
|
|
||||||
cat.order = categories.map { it.order + 1 }.maxOrNull() ?: 0
|
|
||||||
|
|
||||||
// Insert into database.
|
|
||||||
db.insertCategory(cat).asRxObservable().subscribe()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,7 +77,11 @@ class CategoryPresenter(
|
||||||
* @param categories The list of categories to delete.
|
* @param categories The list of categories to delete.
|
||||||
*/
|
*/
|
||||||
fun deleteCategories(categories: List<Category>) {
|
fun deleteCategories(categories: List<Category>) {
|
||||||
db.deleteCategories(categories).asRxObservable().subscribe()
|
presenterScope.launchIO {
|
||||||
|
categories.forEach { category ->
|
||||||
|
deleteCategory.await(category.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,11 +90,16 @@ class CategoryPresenter(
|
||||||
* @param categories The list of categories to reorder.
|
* @param categories The list of categories to reorder.
|
||||||
*/
|
*/
|
||||||
fun reorderCategories(categories: List<Category>) {
|
fun reorderCategories(categories: List<Category>) {
|
||||||
categories.forEachIndexed { i, category ->
|
presenterScope.launchIO {
|
||||||
category.order = i
|
categories.forEachIndexed { order, category ->
|
||||||
|
updateCategory.await(
|
||||||
|
payload = CategoryUpdate(
|
||||||
|
id = category.id,
|
||||||
|
order = order.toLong(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.insertCategories(categories).asRxObservable().subscribe()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,20 +109,22 @@ class CategoryPresenter(
|
||||||
* @param name The new name of the category.
|
* @param name The new name of the category.
|
||||||
*/
|
*/
|
||||||
fun renameCategory(category: Category, name: String) {
|
fun renameCategory(category: Category, name: String) {
|
||||||
// Do not allow duplicate categories.
|
presenterScope.launchIO {
|
||||||
if (categoryExists(name)) {
|
val result = updateCategory.await(
|
||||||
Observable.just(Unit).subscribeFirst({ view, _ -> view.onCategoryExistsError() })
|
payload = CategoryUpdate(
|
||||||
return
|
id = category.id,
|
||||||
|
name = name,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
when (result) {
|
||||||
|
is UpdateCategory.Result.Success -> {}
|
||||||
|
is UpdateCategory.Result.Error -> {
|
||||||
|
logcat(LogPriority.ERROR, result.error)
|
||||||
|
if (result.error is DuplicateNameException) {
|
||||||
|
launchUI { view?.onCategoryExistsError() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
category.name = name
|
|
||||||
db.insertCategory(category).asRxObservable().subscribe()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if a category with the given name already exists.
|
|
||||||
*/
|
|
||||||
private fun categoryExists(name: String): Boolean {
|
|
||||||
return categories.any { it.name == name }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ import android.app.Dialog
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
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.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.widget.materialdialogs.setTextInput
|
import eu.kanade.tachiyomi.widget.materialdialogs.setTextInput
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@ _id AS id,
|
||||||
name,
|
name,
|
||||||
sort AS `order`,
|
sort AS `order`,
|
||||||
flags
|
flags
|
||||||
FROM categories;
|
FROM categories
|
||||||
|
ORDER BY sort;
|
||||||
|
|
||||||
getCategoriesByMangaId:
|
getCategoriesByMangaId:
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -28,5 +29,16 @@ insert:
|
||||||
INSERT INTO categories(name, sort, flags)
|
INSERT INTO categories(name, sort, flags)
|
||||||
VALUES (:name, :order, :flags);
|
VALUES (:name, :order, :flags);
|
||||||
|
|
||||||
|
delete:
|
||||||
|
DELETE FROM categories
|
||||||
|
WHERE _id = :categoryId;
|
||||||
|
|
||||||
|
update:
|
||||||
|
UPDATE categories
|
||||||
|
SET name = coalesce(:name, name),
|
||||||
|
sort = coalesce(:order, sort),
|
||||||
|
flags = coalesce(:flags, flags)
|
||||||
|
WHERE _id = :categoryId;
|
||||||
|
|
||||||
selectLastInsertedRowId:
|
selectLastInsertedRowId:
|
||||||
SELECT last_insert_rowid();
|
SELECT last_insert_rowid();
|
Reference in a new issue