diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt index 2b71324e42..883285eff5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt @@ -19,6 +19,8 @@ interface Category : Serializable { var mangaSort:Char? + var isFirst:Boolean? + val nameLower: String get() = name.toLowerCase() @@ -85,9 +87,10 @@ interface Category : Serializable { LibrarySort.UNREAD -> UNREAD_ASC LibrarySort.LAST_READ -> LAST_READ_ASC LibrarySort.TOTAL -> TOTAL_ASC - else -> 'D' + LibrarySort.DRAG_AND_DROP -> DRAG_AND_DROP + else -> DRAG_AND_DROP } - if (mangaSort != 'D' && !ascending) { + if (mangaSort != DRAG_AND_DROP && !ascending) { mangaSort?.plus(1) } order = -1 diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt index 7374effc3d..9ca9caf8d8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt @@ -14,6 +14,8 @@ class CategoryImpl : Category { override var mangaSort: Char? = null + override var isFirst: Boolean? = null + override fun equals(other: Any?): Boolean { if (this === other) return true if (other == null || javaClass != other.javaClass) return false diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index 7362b1e743..23eca24891 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -52,7 +52,7 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) : */ fun indexOf(categoryOrder: Int): Int { return currentItems.indexOfFirst { - if (it is LibraryHeaderItem) it.gCategory().order == categoryOrder + if (it is LibraryHeaderItem) it.category.order == categoryOrder else false } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 8e471f4e55..b534705536 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -576,8 +576,9 @@ open class LibraryController( } } R.id.action_migrate -> { + val skipPre = preferences.skipPreMigration().getOrDefault() router.pushController( - if (preferences.skipPreMigration().getOrDefault()) { + if (skipPre) { MigrationListController.create( MigrationProcedureConfig( selectedMangas.mapNotNull { it.id },null) @@ -586,7 +587,7 @@ open class LibraryController( else { PreMigrationController.create( selectedMangas.mapNotNull { it.id } ) } - .withFadeTransaction()) + .withFadeTransaction().tag(if (skipPre) MigrationListController.TAG else null)) destroyActionModeIfNeeded() } /*R.id.action_to_top, R.id.action_to_bottom -> { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt index 862cc5f96b..72498c78eb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt @@ -1,12 +1,14 @@ package eu.kanade.tachiyomi.ui.library import android.graphics.drawable.Drawable +import android.os.Build import android.view.View import android.widget.ImageView import android.widget.ProgressBar import android.widget.TextView import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.PopupMenu +import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.ContextCompat import androidx.recyclerview.widget.RecyclerView import com.google.android.material.button.MaterialButton @@ -18,9 +20,11 @@ import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.library.LibraryUpdateService +import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.view.gone +import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.visible import kotlinx.android.synthetic.main.library_category_header_item.view.* @@ -47,13 +51,13 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int holder.bind(categoryF(catId)) } - var category:Category = categoryF(catId) - fun gCategory():Category = categoryF(catId) + val category:Category + get() = categoryF(catId) override fun equals(other: Any?): Boolean { if (this === other) return true if (other is LibraryHeaderItem) { - return gCategory().id == other.gCategory().id + return category.id == other.category.id } return false } @@ -67,7 +71,7 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int } override fun hashCode(): Int { - return -(gCategory().id!!) + return -(category.id!!) } class Holder(val view: View, private val adapter: LibraryCategoryAdapter) : @@ -81,16 +85,25 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int init { updateButton.setOnClickListener { addCategoryToUpdate() } - sortText.setOnClickListener { showCatSortOptions() } + sortText.setOnClickListener { it.post { showCatSortOptions() } } checkboxImage.setOnClickListener { selectAll() } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + sortText.compoundDrawablesRelative[2]?.mutate()?.setTint( + ContextCompat.getColor(contentView.context, R.color.gray_button)) + } } fun bind(category: Category) { + sectionText.updateLayoutParams { + topMargin = (if (category.isFirst == true) 2 else 32).dpToPx + } sectionText.text = category.name sortText.text = itemView.context.getString( when (category.sortingMode()) { LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated - LibrarySort.DRAG_AND_DROP -> R.string.action_sort_drag_and_drop + LibrarySort.DRAG_AND_DROP -> + if (category.id == -1) R.string.category + else R.string.action_sort_drag_and_drop LibrarySort.TOTAL -> R.string.action_sort_total LibrarySort.UNREAD -> R.string.action_filter_unread LibrarySort.LAST_READ -> R.string.action_sort_last_read @@ -134,7 +147,7 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int } private fun showCatSortOptions() { val category = - (adapter.getItem(adapterPosition) as? LibraryHeaderItem)?.gCategory() ?: return + (adapter.getItem(adapterPosition) as? LibraryHeaderItem)?.category ?: return // Create a PopupMenu, giving it the clicked view for an anchor val popup = PopupMenu(itemView.context, view.category_sort) @@ -162,6 +175,11 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int } ) + if (category.id == -1) + popup.menu.findItem(R.id.action_drag_and_drop).title = contentView.context.getString( + R.string.category + ) + if (sortingMode != null && popup.menu is MenuBuilder) { val m = popup.menu as MenuBuilder m.setOptionalIconsVisible(true) @@ -193,6 +211,10 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int } else { val order = when (menuId) { + R.id.action_drag_and_drop -> { + adapter.libraryListener.sortCategory(category.id!!, 'D' - 'a' + 1) + return + } R.id.action_total_chaps -> 4 R.id.action_last_read -> 3 R.id.action_unread -> 2 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 1b7607feca..e9135d4d7b 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 @@ -54,7 +54,7 @@ class LibraryItem(val manga: LibraryManga, val marginParams = card.layoutParams as ConstraintLayout.LayoutParams marginParams.bottomMargin = 6.dpToPx card.layoutParams = marginParams - cover_thumbnail.maxHeight = Integer.MAX_VALUE + cover_thumbnail.maxHeight = coverHeight constraint_layout.minHeight = 0 cover_thumbnail.adjustViewBounds = false cover_thumbnail.layoutParams = FrameLayout.LayoutParams( 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 d965101746..4aad609b6c 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 @@ -9,6 +9,7 @@ import android.view.MenuInflater import android.view.View import android.view.ViewGroup import android.widget.Spinner +import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode import androidx.appcompat.widget.SearchView import androidx.core.content.ContextCompat @@ -72,7 +73,11 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), override fun contentView():View = recycler_layout override fun getTitle(): String? { - return null + return when { + spinnerAdapter?.array?.size ?: 0 > 1 -> null + spinnerAdapter?.array?.size == 1 -> return spinnerAdapter?.array?.firstOrNull() + else -> return super.getTitle() + } } private var scrollListener = object : RecyclerView.OnScrollListener () { @@ -81,7 +86,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), val position = (recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition() val order = when (val item = adapter.getItem(position)) { - is LibraryHeaderItem -> item.gCategory().order + is LibraryHeaderItem -> item.category.order is LibraryItem -> presenter.categories.find { it.id == item.manga.category }?.order else -> null } @@ -92,9 +97,10 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), bottom_sheet.lastCategory = category bottom_sheet.updateTitle() - if (spinner.selectedItemPosition != order + 1) { + val categortPosition = presenter.categories.indexOf(category) + if (spinner.selectedItemPosition != categortPosition) { updateScroll = true - spinner.setSelection(order + 1, true) + spinner.setSelection(categortPosition, true) } } } @@ -148,7 +154,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), view.context, tv.resourceId ) (activity as MainActivity).supportActionBar?.customView = spinner - (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(true) + (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(false) spinnerAdapter = SpinnerAdapter( view.context, R.layout.library_spinner_textview, @@ -161,7 +167,9 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { super.onChangeStarted(handler, type) if (type.isEnter) { - (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(true) + (activity as MainActivity).supportActionBar + ?.setDisplayShowCustomEnabled(router?.backstack?.lastOrNull()?.controller() == + this && spinnerAdapter?.array?.size ?: 0 > 1) } else if (type == ControllerChangeType.PUSH_EXIT) { (activity as MainActivity).toolbar.menu.findItem(R.id @@ -187,11 +195,19 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), spinner.onItemSelectedListener = null + val categoryNames = presenter.categories.map { it.name }.toTypedArray() spinnerAdapter = SpinnerAdapter(spinner.context, R.layout.library_spinner_textview, - presenter.categories.map { it.name }.toTypedArray()) + if (categoryNames.isNotEmpty()) categoryNames + else arrayOf(spinner.context.getString(R.string.label_library)) + ) spinnerAdapter?.setDropDownViewResource(R.layout.library_spinner_entry_text) spinner.adapter = spinnerAdapter + val isCurrentController = router?.backstack?.lastOrNull()?.controller() == + this + (activity as AppCompatActivity).supportActionBar + ?.setDisplayShowCustomEnabled(isCurrentController && categoryNames.size > 1) + if (isCurrentController) setTitle() spinner.setSelection(min(presenter.categories.size - 1, activeCategory + 1)) updateScroll = false @@ -202,10 +218,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), } else if (justStarted) { - val position = if (freshStart) adapter.indexOf(activeCategory) else null - if (position != null) - (recycler.layoutManager as LinearLayoutManager) - .scrollToPositionWithOffset(position, (-30).dpToPx) + if (freshStart) scrollToHeader(activeCategory) } else { updateScroll = true @@ -213,21 +226,25 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), adapter.isLongPressDragEnabled = canDrag() tabsVisibilityRelay.call(false) - bottom_sheet.lastCategory = presenter.categories[MathUtils.clamp( + bottom_sheet.lastCategory = presenter.categories.getOrNull(MathUtils.clamp( activeCategory, 0, presenter.categories.size - 1 - )] + )) bottom_sheet.updateTitle() spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos -> if (updateScroll) { updateScroll = false return@IgnoreFirstSpinnerListener } - val headerPosition = adapter.indexOf(pos - 1) - if (headerPosition > -1) { - (recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( - headerPosition, (-30).dpToPx - ) - } + scrollToHeader(pos - 1) + } + } + + private fun scrollToHeader(pos: Int) { + val headerPosition = adapter.indexOf(pos) + if (headerPosition > -1) { + (recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( + headerPosition, if (headerPosition == 0) 0 else (-30).dpToPx + ) } } 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 2758280af0..720e58c258 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 @@ -345,8 +345,13 @@ class LibraryPresenter( } } - fun getCategory(categoryId: Int): Category { - return categories.find { it.id == categoryId } ?: createDefaultCategory() + private fun getCategory(categoryId: Int): Category { + val category = categories.find { it.id == categoryId } ?: createDefaultCategory() + if (category.isFirst == null) { + category.isFirst = (category.id ?: 0 <= 0 || + (category.order == 0 && categories.none { it.id == 0 })) + } + return category } private fun sortCategory(i1: LibraryItem, i2: LibraryItem, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index a8d97343d2..835bc4641d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -26,10 +26,12 @@ import eu.kanade.tachiyomi.ui.base.controller.RxController import eu.kanade.tachiyomi.ui.base.controller.TabbedController import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe import eu.kanade.tachiyomi.ui.catalogue.CatalogueController +import eu.kanade.tachiyomi.ui.main.BottomNavBarInterface import eu.kanade.tachiyomi.ui.main.SearchActivity import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersController import eu.kanade.tachiyomi.ui.manga.info.MangaInfoController import eu.kanade.tachiyomi.ui.manga.track.TrackController +import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate import eu.kanade.tachiyomi.util.system.toast import kotlinx.android.synthetic.main.main_activity.* @@ -40,7 +42,7 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.util.Date -class MangaController : RxController, TabbedController { +class MangaController : RxController, TabbedController, BottomNavBarInterface { constructor(manga: Manga?, fromCatalogue: Boolean = false, @@ -216,6 +218,13 @@ class MangaController : RxController, TabbedController { //tab.icon = drawable } + override fun canChangeTabs(block: () -> Unit): Boolean { + val migrationListController = router.getControllerWithTag(MigrationListController.TAG) + as? BottomNavBarInterface + if (migrationListController != null) return migrationListController.canChangeTabs(block) + return true + } + private inner class MangaDetailAdapter : RouterPagerAdapter(this@MangaController) { private val tabCount = if (Injekt.get().hasLoggedServices()) 3 else 2 diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt index dd1dc42a40..2119503112 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/SearchController.kt @@ -18,12 +18,13 @@ import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchPresenter +import eu.kanade.tachiyomi.ui.main.BottomNavBarInterface import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController import uy.kohesive.injekt.injectLazy class SearchController( private var manga: Manga? = null -) : CatalogueSearchController(manga?.originalTitle()) { +) : CatalogueSearchController(manga?.originalTitle()), BottomNavBarInterface{ private var newManga: Manga? = null private var progress = 1 @@ -191,5 +192,10 @@ class SearchController( } } - + override fun canChangeTabs(block: () -> Unit): Boolean { + val migrationListController = router.getControllerWithTag(MigrationListController.TAG) + as? BottomNavBarInterface + if (migrationListController != null) return migrationListController.canChangeTabs(block) + return true + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt index e909fe7c33..c92326dbba 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/design/PreMigrationController.kt @@ -17,13 +17,12 @@ import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController +import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig import eu.kanade.tachiyomi.util.view.doOnApplyWindowInsets import eu.kanade.tachiyomi.util.view.marginBottom import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.updatePaddingRelative -import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationProcedureConfig -import kotlinx.android.synthetic.main.pre_migration_controller.fab -import kotlinx.android.synthetic.main.pre_migration_controller.recycler +import kotlinx.android.synthetic.main.pre_migration_controller.* import uy.kohesive.injekt.injectLazy class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), FlexibleAdapter @@ -98,7 +97,7 @@ class PreMigrationController(bundle: Bundle? = null) : BaseController(bundle), F config.toList(), extraSearchParams = extraParam ) - ).withFadeTransaction()) + ).withFadeTransaction().tag(MigrationListController.TAG)) } override fun onSaveInstanceState(outState: Bundle) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt index 29098b4fb6..49e8ace767 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/migration/manga/process/MigrationListController.kt @@ -446,6 +446,7 @@ class MigrationListController(bundle: Bundle? = null) : BaseController(bundle), companion object { const val CONFIG_EXTRA = "config_extra" + const val TAG = "migration_list" fun create(config: MigrationProcedureConfig): MigrationListController { return MigrationListController(Bundle().apply { diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt index 8d001a631b..628e0f50bf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/AutofitRecyclerView.kt @@ -21,7 +21,10 @@ class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: Att } val itemWidth: Int - get() = measuredWidth / manager.spanCount + get() { + return if (spanCount == 0) measuredWidth / getTempSpan() + else measuredWidth / manager.spanCount + } init { if (attrs != null) { @@ -34,6 +37,13 @@ class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: Att layoutManager = manager } + private fun getTempSpan():Int { + if (spanCount == 0 && columnWidth > 0) { + return max(1, measuredWidth / columnWidth) + } + return 2 + } + override fun onMeasure(widthSpec: Int, heightSpec: Int) { super.onMeasure(widthSpec, heightSpec) if (spanCount == 0 && columnWidth > 0) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 080bef7e0b..6c26267fc7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -443,6 +443,8 @@ Remember this choice Manga already in category + Category + Search filters