Restored "spinner" in library list mode

Added Rudimentary search to recent updates, might expand on it more later
This commit is contained in:
Jay 2020-03-07 21:41:52 -08:00
parent b7e66fa404
commit 489cef7962
11 changed files with 168 additions and 20 deletions

View File

@ -2,8 +2,12 @@ package eu.kanade.tachiyomi.ui.base
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable import androidx.appcompat.graphics.drawable.DrawerArrowDrawable
import androidx.appcompat.widget.PopupMenu
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.main_activity.view.* import kotlinx.android.synthetic.main.main_activity.view.*
class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null): Toolbar class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null): Toolbar
@ -30,4 +34,20 @@ class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: Attribut
super.setTitle(null) super.setTitle(null)
} }
} }
fun showSpinner(): PopupMenu {
val popupMenu = PopupMenu(context, title_layout, Gravity.CENTER)
dropdown.visible()
title_layout.setOnTouchListener(popupMenu.dragToOpenListener)
title_layout.setOnClickListener {
popupMenu.show()
}
return popupMenu
}
fun removeSpinner() {
dropdown.gone()
title_layout.setOnTouchListener(null)
title_layout.setOnClickListener(null)
}
} }

View File

@ -100,7 +100,7 @@ class CategoryHolder(view: View, val adapter: CategoryAdapter) : BaseFlexibleVie
reorder.setOnTouchListener { _, _ -> true} reorder.setOnTouchListener { _, _ -> true}
} }
edit_text.clearFocus() edit_text.clearFocus()
edit_button.drawable.mutate().setTint(ContextCompat.getColor(itemView.context, R edit_button.drawable?.mutate()?.setTint(ContextCompat.getColor(itemView.context, R
.color.gray_button)) .color.gray_button))
reorder.setImageDrawable(regularDrawable) reorder.setImageDrawable(regularDrawable)
} }

View File

@ -27,6 +27,7 @@ import eu.kanade.tachiyomi.data.database.models.LibraryManga
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.main.SpinnerTitleInterface
import eu.kanade.tachiyomi.ui.main.SwipeGestureInterface import eu.kanade.tachiyomi.ui.main.SwipeGestureInterface
import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.launchUI import eu.kanade.tachiyomi.util.system.launchUI
@ -49,6 +50,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
FlexibleAdapter.OnItemMoveListener, FlexibleAdapter.OnItemMoveListener,
LibraryCategoryAdapter.LibraryListener, LibraryCategoryAdapter.LibraryListener,
SpinnerTitleInterface,
SwipeGestureInterface { SwipeGestureInterface {
private lateinit var adapter: LibraryCategoryAdapter private lateinit var adapter: LibraryCategoryAdapter
@ -108,7 +110,6 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
override fun onViewCreated(view: View) { override fun onViewCreated(view: View) {
super.onViewCreated(view) super.onViewCreated(view)
// pad the recycler if the filter bottom sheet is visible // pad the recycler if the filter bottom sheet is visible
if (!phoneLandscape) { if (!phoneLandscape) {
val height = view.context.resources.getDimensionPixelSize(R.dimen.rounder_radius) + 4.dpToPx val height = view.context.resources.getDimensionPixelSize(R.dimen.rounder_radius) + 4.dpToPx
@ -166,6 +167,13 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) { override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeStarted(handler, type) super.onChangeStarted(handler, type)
if (type.isEnter) {
if (presenter.categories.size > 1) {
activity?.toolbar?.showSpinner()
} else {
activity?.toolbar?.removeSpinner()
}
}
/*if (type.isEnter) { /*if (type.isEnter) {
(activity as MainActivity).supportActionBar (activity as MainActivity).supportActionBar
?.setDisplayShowCustomEnabled(router?.backstack?.lastOrNull()?.controller() == ?.setDisplayShowCustomEnabled(router?.backstack?.lastOrNull()?.controller() ==
@ -228,9 +236,23 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
} }
adapter.isLongPressDragEnabled = canDrag() adapter.isLongPressDragEnabled = canDrag()
val popupMenu = if (presenter.categories.size > 1) {
activity?.toolbar?.showSpinner()
}
else {
activity?.toolbar?.removeSpinner()
null
}
titlePopupMenu.menu.clear() titlePopupMenu.menu.clear()
presenter.categories.forEach { category -> presenter.categories.forEach { category ->
titlePopupMenu.menu.add(0, category.order, max(0, category.order), category.name) titlePopupMenu.menu.add(0, category.order, max(0, category.order), category.name)
popupMenu?.menu?.add(0, category.order, max(0, category.order), category.name)
}
popupMenu?.setOnMenuItemClickListener { item ->
scrollToHeader(item.itemId)
true
} }
customTitleSpinner.setOnClickListener { customTitleSpinner.setOnClickListener {
@ -591,4 +613,6 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
scrollToHeader (newOffset, true) scrollToHeader (newOffset, true)
} }
} }
override fun popUpMenu(): PopupMenu = titlePopupMenu
} }

View File

@ -20,6 +20,7 @@ import android.view.WindowManager
import android.webkit.WebView import android.webkit.WebView
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable import androidx.appcompat.graphics.drawable.DrawerArrowDrawable
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import androidx.core.view.GestureDetectorCompat import androidx.core.view.GestureDetectorCompat
@ -619,6 +620,8 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
}*/ }*/
} }
if (to !is SpinnerTitleInterface) toolbar.removeSpinner()
if (to !is DialogController) { if (to !is DialogController) {
navigationView.visibility = if (router.backstackSize == 0 || navigationView.visibility = if (router.backstackSize == 0 ||
(router.backstackSize <= 1 && !isPush)) (router.backstackSize <= 1 && !isPush))
@ -736,6 +739,10 @@ interface BottomNavBarInterface {
interface RootSearchInterface interface RootSearchInterface
interface SpinnerTitleInterface {
fun popUpMenu(): PopupMenu
}
interface SwipeGestureInterface { interface SwipeGestureInterface {
fun onSwipeRight(x: Float, y: Float) fun onSwipeRight(x: Float, y: Float)
fun onSwipeLeft(x: Float, y: Float) fun onSwipeLeft(x: Float, y: Float)

View File

@ -40,6 +40,11 @@ class RecentChapterItem(val chapter: Chapter, val manga: Manga, header: DateItem
holder.bind(this) holder.bind(this)
} }
fun filter(text: String): Boolean {
return chapter.name.contains(text, false) ||
manga.currentTitle().contains(text, false)
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other is RecentChapterItem) { if (other is RecentChapterItem) {

View File

@ -7,12 +7,28 @@ class RecentChaptersAdapter(val controller: RecentChaptersController) :
FlexibleAdapter<IFlexible<*>>(null, controller, true) { FlexibleAdapter<IFlexible<*>>(null, controller, true) {
val coverClickListener: OnCoverClickListener = controller val coverClickListener: OnCoverClickListener = controller
var recents = emptyList<RecentChapterItem>()
init { init {
setDisplayHeadersAtStartUp(true) setDisplayHeadersAtStartUp(true)
//setStickyHeaders(true) //setStickyHeaders(true)
} }
fun setItems(recents: List<RecentChapterItem>) {
this.recents = recents
performFilter()
}
fun performFilter() {
val s = getFilter(String::class.java)
if (s.isNullOrBlank()) {
updateDataSet(recents)
}
else {
updateDataSet(recents.filter { it.filter(s) })
}
}
interface OnCoverClickListener { interface OnCoverClickListener {
fun onCoverClick(position: Int) fun onCoverClick(position: Int)
} }

View File

@ -8,13 +8,13 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.jakewharton.rxbinding.support.v4.widget.refreshes import com.jakewharton.rxbinding.support.v4.widget.refreshes
import com.jakewharton.rxbinding.support.v7.widget.scrollStateChanges import com.jakewharton.rxbinding.support.v7.widget.scrollStateChanges
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter import eu.davidea.flexibleadapter.SelectableAdapter
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
@ -23,12 +23,14 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.main.RootSearchInterface
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController import eu.kanade.tachiyomi.ui.recently_read.RecentlyReadController
import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
import eu.kanade.tachiyomi.util.view.scrollViewWith import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.util.view.snack
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.recent_chapters_controller.* import kotlinx.android.synthetic.main.recent_chapters_controller.*
@ -47,6 +49,7 @@ class RecentChaptersController : NucleusController<RecentChaptersPresenter>(),
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
FlexibleAdapter.OnUpdateListener, FlexibleAdapter.OnUpdateListener,
ConfirmDeleteChaptersDialog.Listener, ConfirmDeleteChaptersDialog.Listener,
RootSearchInterface,
RecentChaptersAdapter.OnCoverClickListener { RecentChaptersAdapter.OnCoverClickListener {
init { init {
@ -63,6 +66,8 @@ class RecentChaptersController : NucleusController<RecentChaptersPresenter>(),
var adapter: RecentChaptersAdapter? = null var adapter: RecentChaptersAdapter? = null
private set private set
private var query = ""
override fun getTitle(): String? { override fun getTitle(): String? {
return resources?.getString(R.string.label_recent_updates) return resources?.getString(R.string.label_recent_updates)
} }
@ -191,9 +196,9 @@ class RecentChaptersController : NucleusController<RecentChaptersPresenter>(),
* Populate adapter with chapters * Populate adapter with chapters
* @param chapters list of [Any] * @param chapters list of [Any]
*/ */
fun onNextRecentChapters(chapters: List<IFlexible<*>>) { fun onNextRecentChapters(chapters: List<RecentChapterItem>) {
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
adapter?.updateDataSet(chapters) adapter?.setItems(chapters)
} }
override fun onUpdateEmptyView(size: Int) { override fun onUpdateEmptyView(size: Int) {
@ -344,6 +349,34 @@ class RecentChaptersController : NucleusController<RecentChaptersPresenter>(),
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
inflater.inflate(R.menu.recent_updates, menu) inflater.inflate(R.menu.recent_updates, menu)
val searchItem = menu.findItem(R.id.action_search)
val searchView = searchItem.actionView as SearchView
searchView.queryHint = resources?.getString(R.string.action_search)
if (query.isNotEmpty()) {
searchItem.expandActionView()
searchView.setQuery(query, true)
searchView.clearFocus()
}
setOnQueryTextChangeListener(searchView) {
if (query != it) {
query = it ?: return@setOnQueryTextChangeListener false
adapter?.setFilter(query)
adapter?.performFilter()
}
true
}
// Fixes problem with the overflow icon showing up in lieu of search
searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener {
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
return true
}
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
activity?.invalidateOptionsMenu()
return true
}
})
} }
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {

View File

@ -136,10 +136,10 @@ class RecentlyReadController(bundle: Bundle? = null) : BaseController(bundle),
override fun onUpdateEmptyView(size: Int) { override fun onUpdateEmptyView(size: Int) {
if (size > 0) { if (size > 0) {
// empty_view?.hide() empty_view?.hide()
} else { } else {
// empty_view.show(R.drawable.ic_history_white_128dp, R.string empty_view.show(R.drawable.ic_history_white_128dp, R.string
//.information_no_recent_manga) .information_no_recent_manga)
} }
} }

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content" android:id="@+id/main_content"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -35,19 +36,38 @@
android:layout_height="?attr/actionBarSize" android:layout_height="?attr/actionBarSize"
android:background="?android:attr/colorBackground"> android:background="?android:attr/colorBackground">
<LinearLayout
android:id="@+id/title_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:clickable="true"
android:focusable="true"
android:orientation="horizontal"
tools:background="?colorPrimary">
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/toolbar_title" android:id="@+id/toolbar_title"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title" style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:ellipsize="end" android:ellipsize="end"
android:gravity="start" android:gravity="start"
android:maxLines="1" android:maxLines="1"
android:text="@string/label_library"
android:textColor="?actionBarTintColor" android:textColor="?actionBarTintColor"
android:textSize="20sp" android:textSize="20sp"
app:fontFamily="@font/roboto_medium" /> tools:text="Title Text" />
<ImageView
android:id="@+id/dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="4dp"
android:background="@drawable/round_ripple"
android:src="@drawable/ic_arrow_drop_down_white_24dp"
android:tint="?actionBarTintColor" />
</LinearLayout>
</eu.kanade.tachiyomi.ui.base.CenteredToolbar> </eu.kanade.tachiyomi.ui.base.CenteredToolbar>
<com.google.android.material.tabs.TabLayout <com.google.android.material.tabs.TabLayout

View File

@ -1,6 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frame_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler" android:id="@+id/recycler"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -10,3 +16,12 @@
tools:listitem="@layout/recently_read_item"> tools:listitem="@layout/recently_read_item">
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
<eu.kanade.tachiyomi.widget.EmptyView
android:id="@+id/empty_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>

View File

@ -2,6 +2,14 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_search"
android:icon="@drawable/ic_search_white_24dp"
android:title="@string/action_search"
android:visible="false"
app:actionViewClass="androidx.appcompat.widget.SearchView"
app:showAsAction="ifRoom|collapseActionView" />
<item <item
android:id="@+id/action_recents" android:id="@+id/action_recents"
android:icon="@drawable/ic_history_black_24dp" android:icon="@drawable/ic_history_black_24dp"