diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt index 35cf30c67a..31523a7b51 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt @@ -5,4 +5,14 @@ class LibraryManga : MangaImpl() { var unread: Int = 0 var category: Int = 0 + + fun isBlank() = id == Long.MIN_VALUE + + companion object { + fun createBlank(categoryId: Int): LibraryManga = LibraryManga().apply { + title = "" + id = Long.MIN_VALUE + category = categoryId + } + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryBadge.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryBadge.kt index 497a10d573..efe8dbbd57 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryBadge.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryBadge.kt @@ -40,7 +40,7 @@ class LibraryBadge @JvmOverloads constructor(context: Context, attrs: AttributeS } // Show the bade card if unread or downloads exists - badge_view.visibility = if (download_text.visibility == View.VISIBLE || unread_text + visibility = if (download_text.visibility == View.VISIBLE || unread_text .visibility != View.GONE) View.VISIBLE else View.GONE // Show the angles divider if both unread and downloads exists @@ -63,7 +63,7 @@ class LibraryBadge @JvmOverloads constructor(context: Context, attrs: AttributeS } fun setInLibrary(inLibrary: Boolean) { - badge_view.visibility = if (inLibrary) View.VISIBLE else View.GONE + visibility = if (inLibrary) View.VISIBLE else View.GONE unread_angle.visibility = View.GONE unread_text.updatePaddingRelative(start = 5.dpToPx) unread_text.visibility = if (inLibrary) View.VISIBLE else View.GONE diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index e07a73d48a..fe9b438fdf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -37,7 +37,7 @@ class LibraryItem( var chapterCount = -1 override fun getLayoutRes(): Int { - return if (libraryLayout.getOrDefault() == 0) + return if (libraryLayout.getOrDefault() == 0 || manga.isBlank()) R.layout.catalogue_list_item else R.layout.catalogue_grid_item @@ -48,7 +48,7 @@ class LibraryItem( return if (parent is AutofitRecyclerView) { val libraryLayout = libraryLayout.getOrDefault() val isFixedSize = fixedSize.getOrDefault() - if (libraryLayout == 0) { + if (libraryLayout == 0 || manga.isBlank()) { LibraryListHolder(view, adapter as LibraryCategoryAdapter) } else { view.apply { @@ -111,7 +111,15 @@ class LibraryItem( * Returns true if this item is draggable. */ override fun isDraggable(): Boolean { - return true + return !manga.isBlank() + } + + override fun isEnabled(): Boolean { + return !manga.isBlank() + } + + override fun isSelectable(): Boolean { + return !manga.isBlank() } /** @@ -121,6 +129,8 @@ class LibraryItem( * @return true if the manga should be included, false otherwise. */ override fun filter(constraint: String): Boolean { + if (manga.isBlank()) + return constraint.isEmpty() val sourceManager by injectLazy() val sourceName = if (manga.source == 0L) "Local" else sourceManager.getOrStub(manga.source).name diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListController.kt index 7c19ecc103..2475cd5029 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListController.kt @@ -22,10 +22,12 @@ import com.afollestad.materialdialogs.checkbox.isCheckPromptChecked import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeType import com.google.android.material.bottomsheet.BottomSheetBehavior +import com.google.android.material.snackbar.Snackbar import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.SelectableAdapter import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.library.LibraryUpdateService @@ -291,7 +293,9 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), override fun getSpanSize(position: Int): Int { if (libraryLayout == 0) return 1 val item = this@LibraryListController.adapter.getItem(position) - return if (item is LibraryHeaderItem) recycler.manager.spanCount else 1 + return if (item is LibraryHeaderItem) recycler.manager.spanCount + else if (item is LibraryItem && item.manga.isBlank()) recycler.manager.spanCount + else 1 } }) recycler.setHasFixedSize(true) @@ -493,7 +497,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), private fun toggleSelection(position: Int) { val item = adapter.getItem(position) as? LibraryItem ?: return - + if (item.manga.isBlank()) return setSelection(item.manga, !adapter.isSelected(position)) invalidateActionMode() } @@ -625,14 +629,14 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), return } if (newHeader?.category?.mangaSort == null) { - presenter.moveMangaToCategory(item, newHeader?.category?.id, mangaIds, true) + moveMangaToCategory(item.manga, newHeader?.category, mangaIds, true) } else { val keepCatSort = preferences.keepCatSort().getOrDefault() if (keepCatSort == 0) { MaterialDialog(activity!!).message(R.string.switch_to_dnd) .positiveButton(R.string.action_switch) { - presenter.moveMangaToCategory( - item, newHeader.category.id, mangaIds, true + moveMangaToCategory( + item.manga, newHeader.category, mangaIds, true ) if (it.isCheckPromptChecked()) preferences.keepCatSort().set(2) }.checkBoxPrompt(R.string.remember_choice) {}.negativeButton( @@ -643,14 +647,14 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), ) ) ) { - presenter.moveMangaToCategory( - item, newHeader.category.id, mangaIds, false + moveMangaToCategory( + item.manga, newHeader.category, mangaIds, false ) if (it.isCheckPromptChecked()) preferences.keepCatSort().set(1) }.cancelOnTouchOutside(false).show() } else { - presenter.moveMangaToCategory( - item, newHeader.category.id, mangaIds, keepCatSort == 2 + moveMangaToCategory( + item.manga, newHeader.category, mangaIds, keepCatSort == 2 ) } } @@ -658,6 +662,27 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), lastItemPosition = null } + private fun moveMangaToCategory( + manga: LibraryManga, + category: Category?, + mangaIds: List, + useDND: Boolean + ) { + if (category?.id == null) return + val oldCatId = manga.category + presenter.moveMangaToCategory(manga, category.id, mangaIds, useDND) + snack?.dismiss() + snack = view?.snack( + resources!!.getString(R.string.moved_to_category, category.name) + ) { + anchorView = bottom_sheet + setAction(R.string.action_undo) { + manga.category = category.id!! + presenter.moveMangaToCategory(manga, oldCatId, mangaIds, useDND) + } + } + } + override fun updateCategory(catId: Int): Boolean { val category = (adapter.getItem(catId) as? LibraryHeaderItem)?.category ?: return false val inQueue = LibraryUpdateService.categoryInQueue(category.id) @@ -669,7 +694,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), LibraryUpdateService.isRunning() -> R.string.adding_category_to_queue else -> R.string.updating_category_x }, category.name - ) + ), Snackbar.LENGTH_LONG ) { anchorView = bottom_sheet } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt index 38f56b30c4..3633557f19 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt @@ -7,6 +7,8 @@ import com.bumptech.glide.signature.ObjectKey import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.MangaImpl import eu.kanade.tachiyomi.data.glide.GlideApp +import eu.kanade.tachiyomi.util.view.gone +import eu.kanade.tachiyomi.util.view.visible import kotlinx.android.synthetic.main.catalogue_list_item.* import kotlinx.android.synthetic.main.catalogue_list_item.view.* import kotlinx.android.synthetic.main.unread_download_badge.* @@ -33,6 +35,17 @@ class LibraryListHolder( * @param item the manga item to bind. */ override fun onSetValues(item: LibraryItem) { + + if (item.manga.isBlank()) { + title.text = itemView.context.getString(R.string.category_is_empty) + title.textAlignment = View.TEXT_ALIGNMENT_CENTER + card.gone() + badge_view.gone() + return + } + card.visible() + title.textAlignment = View.TEXT_ALIGNMENT_TEXT_START + // Update the title of the manga. title.text = item.manga.title setUnreadBadge(badge_view, item) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 7a09187d82..e22477ba3a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -445,6 +445,7 @@ class LibraryPresenter( val showCategories = !preferences.hideCategories().getOrDefault() val unreadBadgeType = preferences.unreadBadgeType().getOrDefault() var libraryManga = db.getLibraryMangas().executeAsBlocking() + val singleList = preferences.libraryAsSingleList().getOrDefault() if (!showCategories) libraryManga = libraryManga.distinctBy { it.id } /*val libraryMap = libraryManga.map { manga -> @@ -457,7 +458,7 @@ class LibraryPresenter( preferences.librarySortingAscending().getOrDefault()) val catItemAll = LibraryHeaderItem({ categoryAll }, -1) val libraryMap = - if (!preferences.libraryAsSingleList().getOrDefault()) { + if (!singleList) { libraryManga.map { manga -> LibraryItem(manga, libraryLayout, preferences.uniformGrid(), null).apply { unreadType = unreadBadgeType } @@ -482,10 +483,27 @@ class LibraryPresenter( cat to it // LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType } }.toMap() - } + }.toMutableMap() if (libraryMap.containsKey(0)) categories.add(0, createDefaultCategory()) + if (showCategories) { + categories.forEach { category -> + if (!libraryMap.containsKey(category.id)) { + val headerItem = + LibraryHeaderItem({ getCategory(category.id!!) }, category.id!!) + libraryMap[category.id!!] = listOf( + LibraryItem( + LibraryManga.createBlank(category.id!!), + libraryLayout, + preferences.uniformGrid(), + headerItem + ) + ) + } + } + } + if (categories.size == 1 && showCategories) categories.first().name = context.getString(R.string.label_library) @@ -831,13 +849,17 @@ class LibraryPresenter( } } - fun moveMangaToCategory(item: LibraryItem, catId: Int?, mangaIds: List, useDND: Boolean) { + fun moveMangaToCategory( + manga: LibraryManga, + catId: Int?, + mangaIds: List, + useDND: Boolean + ) { GlobalScope.launch(Dispatchers.IO) { val categoryId = catId ?: return@launch val category = categories.find { catId == it.id } ?: return@launch - val manga = item.manga - val mangaMap = currentMangaMap?.toMutableMap() ?: return@launch + /*val mangaMap = currentMangaMap?.toMutableMap() ?: return@launch val oldCatId = item.manga.category val oldCatMap = mangaMap[manga.category]?.toMutableList() ?: return@launch val newCatMap = mangaMap[catId]?.toMutableList() ?: return@launch @@ -845,13 +867,14 @@ class LibraryPresenter( newCatMap.add(item) mangaMap[oldCatId] = oldCatMap mangaMap[catId] = newCatMap - currentMangaMap = mangaMap + currentMangaMap = mangaMap*/ - item.manga.category = categoryId + val oldCatId = manga.category + manga.category = categoryId val mc = ArrayList() - val categories = - db.getCategoriesForManga(manga).executeAsBlocking().filter { it.id != oldCatId } + listOf(category) + val categories = db.getCategoriesForManga(manga).executeAsBlocking() + .filter { it.id != oldCatId } + listOf(category) for (cat in categories) { mc.add(MangaCategory.create(manga, cat)) @@ -864,7 +887,8 @@ class LibraryPresenter( val ids = mangaIds.toMutableList() if (!ids.contains(manga.id!!)) ids.add(manga.id!!) category.mangaOrder = ids - if (category.id == 0) preferences.defaultMangaOrder().set(mangaIds.joinToString("/")) + if (category.id == 0) preferences.defaultMangaOrder() + .set(mangaIds.joinToString("/")) else db.insertCategory(category).executeAsBlocking() } getLibrary() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt index ae06124708..b368935837 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsController.kt @@ -98,6 +98,8 @@ import eu.kanade.tachiyomi.util.view.getText import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updatePaddingRelative +import java.io.File +import java.io.IOException import jp.wasabeef.glide.transformations.CropSquareTransformation import jp.wasabeef.glide.transformations.MaskTransformation import kotlinx.android.synthetic.main.main_activity.* @@ -106,8 +108,6 @@ import kotlinx.android.synthetic.main.manga_header_item.* import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -import java.io.File -import java.io.IOException class MangaDetailsController : BaseController, FlexibleAdapter.OnItemClickListener, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index ab2f1656fa..e752c1a384 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -51,6 +51,8 @@ class SettingsLibraryController : SettingsController() { titleRes = R.string.pref_category_library_categories preference { titleRes = R.string.action_edit_categories + val catCount = db.getCategories().executeAsBlocking().size + summary = context.resources.getQuantityString(R.plurals.category, catCount, catCount) onClick { router.pushController(CategoryController().withFadeTransaction()) } } intListPreference(activity) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt index 2e60af0912..7ee77e891f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsMainController.kt @@ -72,7 +72,7 @@ class SettingsMainController : SettingsController() { onClick { navigateTo(SettingsAdvancedController()) } } preference { - iconRes = R.drawable.ic_help_black_24dp + iconRes = R.drawable.ic_info_black_24dp iconTint = tintColor titleRes = R.string.pref_category_about onClick { navigateTo(SettingsAboutController()) } diff --git a/app/src/main/res/drawable/ic_info_black_24dp.xml b/app/src/main/res/drawable/ic_info_black_24dp.xml new file mode 100644 index 0000000000..f842adddb7 --- /dev/null +++ b/app/src/main/res/drawable/ic_info_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/catalogue_list_item.xml b/app/src/main/res/layout/catalogue_list_item.xml index 57223fa211..0cbfa71008 100644 --- a/app/src/main/res/layout/catalogue_list_item.xml +++ b/app/src/main/res/layout/catalogue_list_item.xml @@ -77,7 +77,7 @@ Landscape Default Create new category + + %d category + %d categories + Updates Library update frequency @@ -442,6 +446,8 @@ Updating %1$s Adding %1$s to update queue %1$s is already in queue + Moved to %1$s + Category is empty Local Remove from library? Switch to Drag & Drop mode?