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 eaf2c6cdd7..6e2090f55c 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 @@ -20,6 +20,7 @@ interface Category : Serializable { var mangaSort:Char? var isFirst:Boolean? + var isLast:Boolean? val nameLower: String get() = name.toLowerCase() @@ -76,6 +77,7 @@ interface Category : Serializable { fun createDefault(context: Context): Category = create(context.getString(R.string.default_columns)).apply { id = 0 + isFirst = true } fun createAll(context: Context, libSort: Int, ascending: Boolean): Category = @@ -95,6 +97,7 @@ interface Category : Serializable { } order = -1 isFirst = true + isLast = true } } 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 9ca9caf8d8..2bea32c07c 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 @@ -16,6 +16,8 @@ class CategoryImpl : Category { override var isFirst: Boolean? = null + override var isLast: 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/data/database/models/Manga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt index 42f76f1558..32b983a039 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt @@ -96,8 +96,8 @@ interface Manga : SManga { const val DISPLAY_NUMBER = 0x00100000 const val DISPLAY_MASK = 0x00100000 - const val TYPE_MANGA = 1 - const val TYPE_MANHWA = 2 + const val TYPE_MANGA = 0 + const val TYPE_MANHWA = 1 fun create(source: Long): Manga = MangaImpl().apply { this.source = source diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 6e595872b9..25fc09fec3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -243,12 +243,5 @@ class PreferencesHelper(val context: Context) { fun keepCatSort() = rxPrefs.getInteger(Keys.keepCatSort, 0) - fun upgradeFilters() { - val filterDl = rxPrefs.getBoolean(Keys.filterDownloaded, false).getOrDefault() - val filterUn = rxPrefs.getBoolean(Keys.filterUnread, false).getOrDefault() - val filterCm = rxPrefs.getBoolean(Keys.filterCompleted, false).getOrDefault() - filterDownloaded().set(if (filterDl) 1 else 0) - filterUnread().set(if (filterUn) 1 else 0) - filterCompleted().set(if (filterCm) 1 else 0) - } + fun hideFiltersAtStart() = rxPrefs.getBoolean("hide_filters_at_start", false) } 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 f3221ebbb2..38c9df652e 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 @@ -23,7 +23,7 @@ class LibraryBadge @JvmOverloads constructor(context: Context, attrs: AttributeS context.getResourceColor(android.R.attr.colorAccent) else Color.WHITE) setBackgroundColor( - if (showTotalChapters) ContextCompat.getColor(context, R.color.md_red_500) + if (showTotalChapters) ContextCompat.getColor(context, R.color.total_green) else context.getResourceColor(android.R.attr.colorAccent)) visibility = when { unread > 0 || unread == -1 || showTotalChapters -> View.VISIBLE @@ -47,7 +47,7 @@ class LibraryBadge @JvmOverloads constructor(context: Context, attrs: AttributeS unread_angle.visibility = if (download_text.visibility == View.VISIBLE && unread_text .visibility != View.GONE) View.VISIBLE else View.GONE unread_angle.setColorFilter( - if (showTotalChapters) ContextCompat.getColor(context, R.color.md_red_500) + if (showTotalChapters) ContextCompat.getColor(context, R.color.total_green) else context.getResourceColor(android.R.attr.colorAccent)) if (unread_angle.visibility == View.VISIBLE) { download_text.updatePaddingRelative(end = 8.dpToPx) 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 23eca24891..fa2ce407c4 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 @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.ui.library +import android.view.View import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.IFlexible import eu.kanade.tachiyomi.data.database.DatabaseHelper @@ -181,5 +182,6 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) : fun sortCategory(catId: Int, sortBy: Int) fun selectAll(position: Int) fun allSelected(position: Int): Boolean + fun showCategories(position: Int, view: View) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt index 9d46d40c78..b46ec61726 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt @@ -398,4 +398,5 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att override fun sortCategory(catId: Int, sortBy: Int) { } override fun selectAll(position: Int) { } override fun allSelected(position: Int): Boolean = false + override fun showCategories(position: Int, view: View) { } } 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 3e3758cefe..1c1ccb44df 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 @@ -122,6 +122,8 @@ open class LibraryController( val stopRefreshRelay: PublishRelay = PublishRelay.create() + protected var phoneLandscape = false + /** * Number of manga per row in grid mode. */ @@ -206,6 +208,11 @@ open class LibraryController( fab.isFocusable = true } + val config = resources?.configuration + phoneLandscape = (config?.orientation == Configuration.ORIENTATION_LANDSCAPE && + (config.screenLayout.and(Configuration.SCREENLAYOUT_SIZE_MASK)) < + Configuration.SCREENLAYOUT_SIZE_LARGE) + presenter.onRestore() val library = presenter.getAllManga() if (library != null) presenter.updateViewBlocking() @@ -457,13 +464,6 @@ open class LibraryController( override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.library, menu) - val config = resources?.configuration - - val phoneLandscape = (config?.orientation == Configuration.ORIENTATION_LANDSCAPE && - (config.screenLayout.and(Configuration.SCREENLAYOUT_SIZE_MASK)) < - Configuration.SCREENLAYOUT_SIZE_LARGE) - menu.findItem(R.id.action_library_filter).isVisible = phoneLandscape - val searchItem = menu.findItem(R.id.action_search) val searchView = searchItem.actionView as SearchView searchView.queryHint = resources?.getString(R.string.search_hint) @@ -492,7 +492,8 @@ open class LibraryController( override fun handleRootBack(): Boolean { val sheetBehavior = BottomSheetBehavior.from(bottom_sheet) - if (sheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED) { + if (sheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED && + sheetBehavior.state != BottomSheetBehavior.STATE_HIDDEN) { sheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED return true } @@ -514,7 +515,10 @@ open class LibraryController( when (item.itemId) { R.id.action_search -> expandActionViewFromInteraction = true R.id.action_library_filter -> { - if (bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED) + if (bottom_sheet.sheetBehavior?.isHideable == true && + bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED) + bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_HIDDEN + else if (bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED) bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED else bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED } @@ -524,6 +528,12 @@ open class LibraryController( return true } + fun showFiltersBottomSheet() { + if (bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_HIDDEN) + bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED + } + + /** * Invalidates the action mode, forcing it to refresh its content. */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt index b86f254cba..6491415840 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGridHolder.kt @@ -55,28 +55,6 @@ class LibraryGridHolder( title.text = item.manga.currentTitle() subtitle.text = item.manga.originalAuthor()?.trim() - /* if (!fixedSize) { - title.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener { - override fun onPreDraw(): Boolean { - title.viewTreeObserver.removeOnPreDrawListener(this) - // Drawing happens after layout so we can assume getLineCount() returns the correct value - val marginParams = title.layoutParams as ConstraintLayout.LayoutParams - if (title.lineCount == 2) { - // Do whatever you want in case text view has more than 2 lines - subtitle.gone() - marginParams.bottomMargin = 10.dpToPx - marginParams.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID - } else { - subtitle.visible() - marginParams.bottomMargin = 0 - marginParams.bottomToBottom = -1 - } - title.layoutParams = marginParams - return true - } - }) - }*/ - compact_title.text = title.text setUnreadBadge(badge_view, item) 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 90195692df..b576b8ed5f 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 @@ -78,15 +78,20 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int private val sortText: TextView = view.findViewById(R.id.category_sort) private val updateButton: ImageView = view.findViewById(R.id.update_button) private val checkboxImage: ImageView = view.findViewById(R.id.checkbox) + private val dropDown:Drawable? init { updateButton.setOnClickListener { addCategoryToUpdate() } sortText.setOnClickListener { it.post { showCatSortOptions() } } checkboxImage.setOnClickListener { selectAll() } + sectionText.setOnClickListener { it.post { + adapter.libraryListener.showCategories(adapterPosition, it) + } } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { sortText.compoundDrawablesRelative[2]?.mutate()?.setTint( ContextCompat.getColor(contentView.context, R.color.gray_button)) } + dropDown = sectionText.compoundDrawablesRelative[2] updateButton.drawable.mutate() } @@ -94,8 +99,14 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int sectionText.updateLayoutParams { topMargin = (if (category.isFirst == true) 2 else 32).dpToPx } + if (category.isFirst == true && category.isLast == true) + sectionText.setCompoundDrawablesRelative(null, null, null, null) + else + sectionText.setCompoundDrawablesRelative(null, null, dropDown, null) + sectionText.text = category.name - sortText.text = itemView.context.getString( + sortText.text = itemView.context.getString(R.string.sort_by_, + itemView.context.getString( when (category.sortingMode()) { LibrarySort.LAST_UPDATED -> R.string.action_sort_last_updated LibrarySort.DRAG_AND_DROP -> @@ -107,7 +118,7 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int LibrarySort.ALPHA -> R.string.title else -> R.string.action_sort_drag_and_drop } - ) + )) when { adapter.mode == SelectableAdapter.Mode.MULTI -> { 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 e9135d4d7b..b9edeee1c7 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 @@ -63,6 +63,7 @@ class LibraryItem(val manga: LibraryManga, ) } else if (libraryLayout == 2) { constraint_layout.minHeight = coverHeight + cover_thumbnail.minimumHeight = (parent.itemWidth / 3f * 3.6f).toInt() cover_thumbnail.maxHeight = (parent.itemWidth / 3f * 6f).toInt() constraint_layout.background = ContextCompat.getDrawable( context, R.drawable.library_item_selector 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 9d3605ebe4..b63283772a 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 @@ -1,19 +1,20 @@ package eu.kanade.tachiyomi.ui.library -import android.content.res.Configuration import android.os.Bundle import android.util.TypedValue +import android.view.Gravity import android.view.LayoutInflater import android.view.Menu import android.view.MenuInflater import android.view.View import android.view.ViewGroup -import android.widget.Spinner +import android.widget.LinearLayout import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode +import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.SearchView -import androidx.core.content.ContextCompat import androidx.core.math.MathUtils +import androidx.core.math.MathUtils.clamp import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -38,13 +39,13 @@ import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.updatePaddingRelative import eu.kanade.tachiyomi.widget.AutofitRecyclerView -import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener import kotlinx.android.synthetic.main.filter_bottom_sheet.* import kotlinx.android.synthetic.main.library_list_controller.* import kotlinx.android.synthetic.main.main_activity.* +import kotlinx.android.synthetic.main.spinner_title.view.* import kotlinx.coroutines.delay import java.util.Locale -import kotlin.math.min +import kotlin.math.max class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), FlexibleAdapter.OnItemClickListener, @@ -54,7 +55,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), private lateinit var adapter: LibraryCategoryAdapter - private lateinit var spinner: Spinner + // private lateinit var spinner: AutoCompleteTextView private var lastClickPosition = -1 @@ -64,13 +65,16 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), private var lastItemPosition:Int? = null private var lastItem:IFlexible<*>? = null + private var lastHeaderPos = 0 + private lateinit var customTitleSpinner: LinearLayout + private lateinit var titlePopupMenu:PopupMenu /** * Recycler view of the list of manga. */ private lateinit var recycler: RecyclerView - override fun contentView():View = recycler_layout + override fun contentView():View = recycler override fun getTitle(): String? { return when { @@ -97,22 +101,18 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), bottom_sheet.lastCategory = category bottom_sheet.updateTitle() - val categortPosition = presenter.categories.indexOf(category) - if (spinner.selectedItemPosition != categortPosition) { + //val categortPosition = presenter.categories.indexOf(category) + customTitleSpinner.category_title.text = category?.name ?: "" + /*if (spinner.selectedItemPosition != categortPosition) { updateScroll = true spinner.setSelection(categortPosition, true) - } + }*/ } } } override fun onViewCreated(view: View) { super.onViewCreated(view) - val config = resources?.configuration - val phoneLandscape = (config?.orientation == Configuration.ORIENTATION_LANDSCAPE && - (config.screenLayout.and(Configuration.SCREENLAYOUT_SIZE_MASK)) < - Configuration.SCREENLAYOUT_SIZE_LARGE) - // pad the recycler if the filter bottom sheet is visible if (!phoneLandscape) { val height = view.context.resources.getDimensionPixelSize(R.dimen.rounder_radius) + 4.dpToPx @@ -128,7 +128,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), override fun layoutView(view: View) { adapter = LibraryCategoryAdapter(this) recycler = - (recycler_layout.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply { + (library_layout.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply { spanCount = if (libraryLayout == 0) 1 else mangaPerRow manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() { override fun getSpanSize(position: Int): Int { @@ -141,27 +141,42 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), recycler.setHasFixedSize(true) recycler.adapter = adapter - recycler_layout.addView(recycler, 0) + library_layout.addView(recycler, 0) adapter.fastScroller = fast_scroller recycler.addOnScrollListener(scrollListener) - spinner = ReSpinner(view.context) + /* val dropdown = library_layout.inflate(R.layout.expanded_dropdown_menu) as + TextInputLayout // ReSpinner(view .context) + spinner = dropdown.filled_exposed_dropdown*/ val tv = TypedValue() activity!!.theme.resolveAttribute(R.attr.actionBarTintColor, tv, true) - spinner.backgroundTintList = ContextCompat.getColorStateList( + /*spinner.backgroundTintList = ContextCompat.getColorStateList( view.context, tv.resourceId ) - (activity as MainActivity).supportActionBar?.customView = spinner + (spinner.parent.parent as ViewGroup).removeView(spinner.parent as View) + (activity as MainActivity).supportActionBar?.customView = spinner.parent as View*/ + customTitleSpinner = library_layout.inflate(R.layout.spinner_title) as LinearLayout (activity as MainActivity).supportActionBar?.setDisplayShowCustomEnabled(false) spinnerAdapter = SpinnerAdapter( view.context, R.layout.library_spinner_textview, arrayOf(resources!!.getString(R.string.label_library)) ) - spinnerAdapter?.setDropDownViewResource(R.layout.library_spinner_entry_text) - spinner.adapter = spinnerAdapter + customTitleSpinner.category_title.text = view.resources.getString(R.string.label_library) + + titlePopupMenu = PopupMenu(view.context, customTitleSpinner, Gravity.END or Gravity.CENTER) + customTitleSpinner.setOnTouchListener(titlePopupMenu.dragToOpenListener) + + titlePopupMenu.setOnMenuItemClickListener { item -> + scrollToHeader(item.itemId) + true + } + (activity as MainActivity).supportActionBar?.customView = customTitleSpinner + //spinnerAdapter?.setDropDownViewResource(R.layout.library_spinner_entry_text) + //spinner.setAdapter(spinnerAdapter) + // spinner.adapter = spinnerAdapter } override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { @@ -184,7 +199,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), } override fun onNextLibraryUpdate(mangaMap: List, freshStart: Boolean) { - val recyclerLayout = recycler_layout ?: return + val recyclerLayout = view ?: return destroyActionModeIfNeeded() if (mangaMap.isNotEmpty()) { empty_view?.hide() @@ -194,27 +209,31 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), adapter.setItems(mangaMap) - spinner.onItemSelectedListener = null + //spinner.onItemSelectedListener = null val categoryNames = presenter.categories.map { it.name }.toTypedArray() - spinnerAdapter = SpinnerAdapter(spinner.context, R.layout.library_spinner_textview, + spinnerAdapter = SpinnerAdapter(recyclerLayout.context, R.layout.library_spinner_textview, if (categoryNames.isNotEmpty()) categoryNames - else arrayOf(spinner.context.getString(R.string.label_library)) + else arrayOf(recyclerLayout.context.getString(R.string.label_library)) ) - spinnerAdapter?.setDropDownViewResource(R.layout.library_spinner_entry_text) - spinner.adapter = spinnerAdapter + //spinnerAdapter?.setDropDownViewResource(R.layout.library_spinner_entry_text) + //spinner.setAdapter(spinnerAdapter) val isCurrentController = router?.backstack?.lastOrNull()?.controller() == this (activity as AppCompatActivity).supportActionBar - ?.setDisplayShowCustomEnabled(isCurrentController && categoryNames.size > 1) + ?.setDisplayShowCustomEnabled(isCurrentController && presenter.categories.size > 1) if (isCurrentController) setTitle() - spinner.setSelection(min(presenter.categories.size - 1, activeCategory + 1)) + //spinner.setSelection(min(presenter.categories.size - 1, activeCategory)) + customTitleSpinner.category_title.text = + presenter.categories[clamp(activeCategory, + 0, + presenter.categories.size - 1)].name updateScroll = false if (!freshStart) { justStarted = false - if (recyclerLayout.alpha == 0f) - recyclerLayout.animate().alpha(1f).setDuration(500).start() + if (contentView().alpha == 0f) + contentView().animate().alpha(1f).setDuration(500).start() } else if (justStarted) { @@ -230,21 +249,39 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), activeCategory, 0, presenter.categories.size - 1 )) bottom_sheet.updateTitle() - spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos -> + titlePopupMenu.menu.clear() + presenter.categories.forEach { category -> + titlePopupMenu.menu.add(0, category.order, max(0, category.order), category.name) + } + customTitleSpinner.setOnClickListener { + + titlePopupMenu.show() + } + /*spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos -> if (updateScroll) { updateScroll = false return@IgnoreFirstSpinnerListener } scrollToHeader(presenter.categories[pos].order) - } + }*/ } - private fun scrollToHeader(pos: Int) { + private fun scrollToHeader(pos: Int, offset: Float? = null) { val headerPosition = adapter.indexOf(pos) if (headerPosition > -1) { (recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( - headerPosition, if (headerPosition == 0) 0 else (-30).dpToPx + headerPosition, offset?.toInt() ?: if (headerPosition == 0) 0 else (-30).dpToPx ) + lastHeaderPos = pos + if (offset != null && preferences.libraryLayout().getOrDefault() == 2) { + launchUI { + delay(100) + if (pos == lastHeaderPos) + (recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset( + headerPosition, offset.toInt() + ) + } + } } } @@ -523,4 +560,21 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle), val items = adapter.getSectionItemPositions(header) return items.all { adapter.isSelected(it) } } + + override fun showCategories(position: Int, view: View) { + if (presenter.categories.size <= 1) return + val header = adapter.getSectionHeader(position) as? LibraryHeaderItem ?: return + if (presenter.categories.size <= 1) return + val category = header.category + val popupMenu = PopupMenu(view.context, view) + presenter.categories.forEach { + if (it.id != category.id) + popupMenu.menu.add(0, it.order, it.order, it.name) + } + popupMenu.setOnMenuItemClickListener { + scrollToHeader(it.itemId) + true + } + popupMenu.show() + } } \ No newline at end of file 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 b789c6a83a..857ff8d443 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 @@ -169,9 +169,6 @@ class LibraryPresenter( return@f false if (filterUnread == STATE_REALLY_EXCLUDE && item.manga.unread > 0) return@f false - if (filterMangaType == Manga.TYPE_MANGA && - item.manga.mangaType() == Manga.TYPE_MANHWA) - return@f false if ((filterMangaType == Manga.TYPE_MANHWA) && item.manga.mangaType() == Manga.TYPE_MANGA) return@f false @@ -351,6 +348,7 @@ class LibraryPresenter( category.isFirst = (category.id ?: 0 <= 0 || (category.order == 0 && categories.none { it.id == 0 })) } + if (category.isLast == null) category.isLast = categories.lastOrNull()?.id == category.id return category } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/filter/SortFilterBottomSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/filter/SortFilterBottomSheet.kt index 3076dda265..f7f9f8f098 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/filter/SortFilterBottomSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/filter/SortFilterBottomSheet.kt @@ -13,7 +13,6 @@ import android.widget.LinearLayout import android.widget.Spinner import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.widget.PopupMenu -import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.core.content.ContextCompat import com.f2prateek.rx.preferences.Preference import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -44,6 +43,7 @@ import kotlinx.coroutines.withContext import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import kotlin.math.max import kotlin.math.min import kotlin.math.roundToInt @@ -80,11 +80,11 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A private val filterItems:MutableList by lazy { val list = mutableListOf() - if (Injekt.get().getCategories().executeAsBlocking().isNotEmpty()) - list.add(categories) list.add(downloaded) list.add(unread) list.add(completed) + if (Injekt.get().getCategories().executeAsBlocking().isNotEmpty()) + list.add(categories) if (Injekt.get().hasLoggedServices()) list.add(tracked) list @@ -108,10 +108,11 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A clearButton = clear_button filter_layout.removeView(clearButton) sheetBehavior = BottomSheetBehavior.from(this) + val phoneLandscape = (isLandscape() && !isTablet()) + sheetBehavior?.isHideable = !phoneLandscape top_bar.setOnClickListener { if (sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED) { sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED - //topbar.animate().alpha(0f).setDuration(100).start() } else { sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED } @@ -121,25 +122,34 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A updateTitle() val shadow2:View = (pagerView.parent as ViewGroup).findViewById(R.id.shadow2) val shadow:View = (pagerView.parent as ViewGroup).findViewById(R.id.shadow) - val fastScroller:View? = (pagerView.parent as ViewGroup).findViewById(R.id.fast_scroller) - val coordLayout:View = (pagerView.parent as ViewGroup).findViewById(R.id.snackbar_layout) - val phoneLandscape = (isLandscape() && !isTablet()) - if (phoneLandscape) + val snackbarLayout:View = (pagerView.parent as ViewGroup).findViewById(R.id.snackbar_layout) + if (phoneLandscape) { shadow.alpha = 0f + sheetBehavior?.peekHeight = 0 + } sheetBehavior?.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onSlide(bottomSheet: View, progress: Float) { - top_bar.alpha = 1 - progress - shadow2.alpha = (1 - progress) * 0.25f + top_bar.alpha = 1 - max(0f, progress) + shadow2.alpha = (1 - max(0f, progress)) * 0.25f if (phoneLandscape) shadow.alpha = progress - updateRootPadding(progress) + else + shadow.alpha = 1 + min(0f, progress) + //if (progress >= 0) + updateRootPadding(progress) } override fun onStateChanged(p0: View, state: Int) { if (state == BottomSheetBehavior.STATE_COLLAPSED) { - reSortViews() + if (phoneLandscape) + reSortViews() if (phoneLandscape) shadow.alpha = 0f + else + shadow.alpha = 1f + pager?.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0) + snackbarLayout.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0) + preferences.hideFiltersAtStart().set(false) } else setMainSortText() if (state == BottomSheetBehavior.STATE_EXPANDED) { @@ -147,37 +157,50 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A if (phoneLandscape) shadow.alpha = 1f } - top_bar.isClickable = state == BottomSheetBehavior.STATE_COLLAPSED - top_bar.isFocusable = state == BottomSheetBehavior.STATE_COLLAPSED + if (state == BottomSheetBehavior.STATE_HIDDEN) { + reSortViews() + shadow.alpha = 0f + pager?.updatePaddingRelative(bottom = 0) + snackbarLayout.updatePaddingRelative(bottom = 0) + preferences.hideFiltersAtStart().set(true) + } + //top_bar.isClickable = state == BottomSheetBehavior.STATE_COLLAPSED + //top_bar.isFocusable = state == BottomSheetBehavior.STATE_COLLAPSED } }) + if (preferences.hideFiltersAtStart().getOrDefault()) { + sheetBehavior?.state = BottomSheetBehavior.STATE_HIDDEN + shadow.alpha = 0f + } + else { + pager?.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0) + snackbarLayout.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0) + } if (phoneLandscape && shadow2.visibility != View.GONE) { shadow2.gone() } - if (phoneLandscape) - sheetBehavior?.peekHeight = 0 - top_bar.viewTreeObserver.addOnGlobalLayoutListener { - val peekingHeight = if (phoneLandscape) 0 + /*top_bar.viewTreeObserver.addOnGlobalLayoutListener { + /*val peekingHeight = if (phoneLandscape) 0 else if (!title.text.isNullOrBlank()) top_bar.height else if (peekHeight != 0) -1 else 0 if (peekingHeight > -1 && (peekHeight == 0 || peekingHeight > 0)) { sheetBehavior?.peekHeight = peekingHeight peekHeight = peekingHeight - } + }*/ if (sheetBehavior?.state == BottomSheetBehavior.STATE_COLLAPSED) { val height = context.resources.getDimensionPixelSize(R.dimen.rounder_radius) fastScroller?.updateLayoutParams { bottomMargin = if (phoneLandscape) 0 else (top_bar.height - height) } - pager?.setPadding(0, 0, 0, if (phoneLandscape) 0 else + pager?.updatePaddingRelative(bottom = if (phoneLandscape) 0 else (top_bar.height - height)) - coordLayout.setPadding(0, 0, 0, peekingHeight) + coordLayout.updatePaddingRelative(bottom = sheetBehavior?.peekHeight ?: 0) } else { updateRootPadding() } - } + }*/ createTags() sorting_layout.visibility = if (preferences.libraryAsSingleList().getOrDefault()) View.GONE @@ -210,7 +233,7 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A override fun onRestoreInstanceState(state: Parcelable?) { if (state is Bundle) // implicit null check { - this.peekHeight = state.getInt("peek") + /*this.peekHeight = state.getInt("peek") this.startingTitle = state.getString("title") ?: "" val sheet = BottomSheetBehavior.from(this) if (isLandscape() && !isTablet()) @@ -222,9 +245,10 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A top_bar.alpha = if (sheet.state == BottomSheetBehavior.STATE_COLLAPSED) 1f else 0f + */ + super.onRestoreInstanceState(state.getParcelable("superState")) } - else - super.onRestoreInstanceState(state) + else super.onRestoreInstanceState(state) } private fun isLandscape(): Boolean { @@ -288,7 +312,10 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A val percent = (trueProgress * 100).roundToInt() val value = (percent * (maxHeight - minHeight) / 100) + minHeight val height = context.resources.getDimensionPixelSize(R.dimen.rounder_radius) - pager?.setPadding(0, 0, 0, value - height) + if (trueProgress >= 0) + pager?.updatePaddingRelative(bottom = value - height) + else + pager?.updatePaddingRelative(bottom = (minHeight * (1 + trueProgress)).toInt()) } fun sorting(trueSort:Boolean = false): Int { @@ -338,13 +365,13 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A } filter = preferences.filterMangaType().getOrDefault() if (filter > 0) { - filters.add(if (filter == 1) R.string.manga_only else R.string.manhwa_only) + filters.add(R.string.manhwa_only) } return filters } - fun createTags() { + private fun createTags() { categories = inflate(R.layout.filter_buttons) as FilterTagGroup categories.setup(this, R.string.action_hide_categories) @@ -361,9 +388,7 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A tracked = inflate(R.layout.filter_buttons) as FilterTagGroup tracked.setup(this, R.string.action_filter_tracked, R.string.action_filter_not_tracked) - filterItems.forEach { - filter_layout.addView(it) - } + reSortViews() checkForManhwa() } @@ -376,9 +401,7 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A launchUI { val mangaType = inflate(R.layout.filter_buttons) as FilterTagGroup mangaType.setup( - this@SortFilterBottomSheet, - R.string.manga, - R.string.manhwa + this@SortFilterBottomSheet, R.string.manhwa ) this@SortFilterBottomSheet.mangaType = mangaType filter_layout.addView(mangaType) @@ -680,7 +703,7 @@ class SortFilterBottomSheet @JvmOverloads constructor(context: Context, attrs: A onGroupClicked(action) } - fun reSortViews() { + private fun reSortViews() { filter_layout.removeAllViews() if (filterItems.any { it.isActivated }) filter_layout.addView(clearButton) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index c2f03cfd51..29bc294cfb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -168,8 +168,15 @@ open class MainActivity : BaseActivity(), DownloadServiceListener { updateRecentsIcon() } } - R.id.nav_library, R.id.nav_catalogues, - R.id.nav_settings -> router.popToRoot() + R.id.nav_library -> { + if (router.backstack.size > 1) router.popToRoot() + else { + val controller = router.getControllerWithTag(id.toString()) as? + LibraryController + controller?.showFiltersBottomSheet() + } + } + R.id.nav_catalogues, R.id.nav_settings -> router.popToRoot() } } true diff --git a/app/src/main/res/drawable/bottom_nav_item_selector.xml b/app/src/main/res/drawable/bottom_nav_item_selector.xml index e4e0225719..2345ab46ea 100644 --- a/app/src/main/res/drawable/bottom_nav_item_selector.xml +++ b/app/src/main/res/drawable/bottom_nav_item_selector.xml @@ -6,5 +6,5 @@ android:color="?attr/tabBarIconColor" /> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/draggable_pill.xml b/app/src/main/res/drawable/draggable_pill.xml index 8e07f2fd57..8f56150d01 100644 --- a/app/src/main/res/drawable/draggable_pill.xml +++ b/app/src/main/res/drawable/draggable_pill.xml @@ -3,7 +3,7 @@ android:shape="rectangle"> + android:width="50dp"/> \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_drop_down_white_24dp.xml b/app/src/main/res/drawable/ic_arrow_drop_down_white_24dp.xml new file mode 100644 index 0000000000..69fde7f2a7 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_drop_down_white_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/catalogue_grid_item.xml b/app/src/main/res/layout/catalogue_grid_item.xml index ee5b3ab71a..b2fd5a8f35 100644 --- a/app/src/main/res/layout/catalogue_grid_item.xml +++ b/app/src/main/res/layout/catalogue_grid_item.xml @@ -13,7 +13,6 @@ android:layout_height="wrap_content" android:layout_gravity="bottom" android:background="@drawable/library_compact_grid_selector" - android:minHeight="200dp" android:orientation="vertical"> @@ -190,8 +191,6 @@ android:id="@+id/top_bar" android:layout_width="match_parent" android:layout_height="wrap_content" - tools:visibility="gone" - android:background="@drawable/bg_bottom_sheet_primary" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> @@ -203,7 +202,7 @@ android:layout_height="wrap_content" android:layout_marginTop="5dp" android:src="@drawable/draggable_pill" - android:alpha="0.15" + android:alpha="0.25" android:contentDescription="@string/drag_handle" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" @@ -214,6 +213,7 @@ android:layout_width="wrap_content" android:layout_height="0dp" android:layout_marginStart="24dp" + android:visibility="gone" android:src="@drawable/ic_sort_white_24dp" app:layout_constraintBottom_toBottomOf="@+id/title" android:contentDescription="@string/sorting_mode" @@ -228,6 +228,7 @@ android:layout_marginTop="15dp" android:layout_marginEnd="8dp" android:layout_marginBottom="15dp" + android:visibility="gone" android:textAlignment="textStart" android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" android:textColor="?attr/actionBarTintColor" diff --git a/app/src/main/res/layout/filter_buttons.xml b/app/src/main/res/layout/filter_buttons.xml index a76ca56d31..2d364b720c 100644 --- a/app/src/main/res/layout/filter_buttons.xml +++ b/app/src/main/res/layout/filter_buttons.xml @@ -3,8 +3,7 @@ android:orientation="horizontal" android:layout_width="wrap_content" xmlns:tools="http://schemas.android.com/tools" android:background="@drawable/round_textview_border" - android:layout_marginStart="5dp" - android:layout_marginEnd="5dp" + android:layout_margin="5dp" android:layout_height="32dp"> + android:drawableEnd="@drawable/ic_arrow_drop_down_white_24dp" + tools:text="Title dfdsfsfsfsfsfdsfsfsfs" /> @@ -76,27 +78,27 @@ android:id="@+id/category_sort" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginEnd="10dp" + android:layout_marginEnd="2dp" android:clickable="true" android:drawableEnd="@drawable/ic_sort_white_24dp" android:drawablePadding="6dp" - android:layout_marginBottom="4dp" android:drawableTint="@color/gray_button" android:ellipsize="none" android:focusable="true" android:gravity="center|end" android:textAlignment="textEnd" - android:maxLines="3" + android:maxLines="2" android:padding="6dp" android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" android:textColor="?android:attr/textColorPrimary" android:textSize="12sp" android:textStyle="normal" app:layout_constrainedWidth="true" - app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintBottom_toBottomOf="@id/category_title" + app:layout_constraintTop_toTopOf="@id/category_title" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toEndOf="@id/space" - app:layout_constraintWidth_min="80dp" + app:layout_constraintWidth_min="100dp" tools:text="Drag and Drop" /> \ No newline at end of file diff --git a/app/src/main/res/layout/library_list_controller.xml b/app/src/main/res/layout/library_list_controller.xml index cd80a2b7f2..92cfa2d938 100644 --- a/app/src/main/res/layout/library_list_controller.xml +++ b/app/src/main/res/layout/library_list_controller.xml @@ -6,13 +6,6 @@ android:id="@+id/library_layout" android:layout_height="match_parent"> - - - - diff --git a/app/src/main/res/layout/spinner_title.xml b/app/src/main/res/layout/spinner_title.xml new file mode 100644 index 0000000000..4a33b2dcc4 --- /dev/null +++ b/app/src/main/res/layout/spinner_title.xml @@ -0,0 +1,33 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/unread_download_badge.xml b/app/src/main/res/layout/unread_download_badge.xml index da7d29cc5a..ad454a380b 100644 --- a/app/src/main/res/layout/unread_download_badge.xml +++ b/app/src/main/res/layout/unread_download_badge.xml @@ -21,7 +21,7 @@ style="@style/TextAppearance.Regular.Caption.Light" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@color/pale_green" + android:background="@color/pale_red" android:gravity="center" android:maxLines="1" android:paddingStart="5dp" diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index bd5f166fb2..8d02361646 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -14,10 +14,10 @@ #707070 @color/md_grey_800 #3399FF - #212121 #212121 @color/md_white_1000_38 @color/colorAccent + @color/md_white_1000_76 @color/md_white_1000 @color/md_white_1000_70 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index bc94325892..0db3d4d539 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -35,6 +35,7 @@ #B3FFFFFF @color/material_red_accent_700 @color/md_white_1000 + @color/md_white_1000_50 @color/colorAccent #212121 @@ -82,5 +83,6 @@ #009688 - #99CC99 + @color/material_green_800 + @color/material_red_300 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 665b2caf30..d996763229 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -95,7 +95,7 @@ Add to home screen Display mode Display - Comfortable + Comfy Grid Compact Grid List Download badges diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 11721c49c5..5b9efd8bfb 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -195,6 +195,10 @@ ?attr/selectable_list_drawable + +