Restored Select all functionality for single list and pager mode

Mat white theme is now the default theme
This commit is contained in:
Jay 2020-02-22 15:20:11 -08:00
parent 5339eccb3f
commit bfec83440c
12 changed files with 116 additions and 23 deletions

View File

@ -55,7 +55,7 @@ class PreferencesHelper(val context: Context) {
fun clear() = prefs.edit().clear().apply() fun clear() = prefs.edit().clear().apply()
fun theme() = prefs.getInt(Keys.theme, 5) fun theme() = prefs.getInt(Keys.theme, 9)
fun rotation() = rxPrefs.getInteger(Keys.rotation, 1) fun rotation() = rxPrefs.getInteger(Keys.rotation, 1)

View File

@ -67,6 +67,12 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
else false } else false }
} }
fun getHeaderPositions(): List<Int> {
return currentItems.mapIndexedNotNull { index, it ->
if (it is LibraryHeaderItem) index
else null }
}
/** /**
* Returns the position in the adapter for the given manga. * Returns the position in the adapter for the given manga.
* *
@ -173,5 +179,7 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
fun canDrag(): Boolean fun canDrag(): Boolean
fun updateCategory(catId: Int): Boolean fun updateCategory(catId: Int): Boolean
fun sortCategory(catId: Int, sortBy: Int) fun sortCategory(catId: Int, sortBy: Int)
fun selectAll(position: Int)
fun allSelected(position: Int): Boolean
} }
} }

View File

@ -389,9 +389,9 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
controller.invalidateActionMode() controller.invalidateActionMode()
} }
override fun updateCategory(catId: Int): Boolean { // unused for this view
return true override fun updateCategory(catId: Int): Boolean = true
}
override fun sortCategory(catId: Int, sortBy: Int) { } override fun sortCategory(catId: Int, sortBy: Int) { }
override fun selectAll(position: Int) { }
override fun allSelected(position: Int): Boolean = false
} }

View File

@ -535,6 +535,8 @@ open class LibraryController(
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
mode.menuInflater.inflate(R.menu.library_selection, menu) mode.menuInflater.inflate(R.menu.library_selection, menu)
val selectItem = menu.findItem(R.id.action_select_all)
selectItem.isVisible = !preferences.libraryAsSingleList().getOrDefault()
return true return true
} }
@ -568,11 +570,11 @@ open class LibraryController(
.negativeButton(android.R.string.no) .negativeButton(android.R.string.no)
.show() .show()
} }
/*R.id.action_select_all -> { R.id.action_select_all -> {
adapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let { pagerAdapter?.categories?.getOrNull(library_pager.currentItem)?.id?.let {
selectAllRelay.call(it) selectAllRelay.call(it)
} }
}*/ }
R.id.action_migrate -> { R.id.action_migrate -> {
router.pushController( router.pushController(
if (preferences.skipPreMigration().getOrDefault()) { if (preferences.skipPreMigration().getOrDefault()) {

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.library
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.View import android.view.View
import android.widget.ImageView
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.view.menu.MenuBuilder
@ -10,6 +11,7 @@ import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder import eu.davidea.viewholders.FlexibleViewHolder
@ -76,10 +78,12 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
private val sortText: TextView = view.findViewById(R.id.category_sort) private val sortText: TextView = view.findViewById(R.id.category_sort)
private val updateButton: MaterialButton = view.findViewById(R.id.update_button) private val updateButton: MaterialButton = view.findViewById(R.id.update_button)
private val catProgress: ProgressBar = view.findViewById(R.id.cat_progress) private val catProgress: ProgressBar = view.findViewById(R.id.cat_progress)
private val checkboxImage: ImageView = view.findViewById(R.id.checkbox)
init { init {
updateButton.setOnClickListener { addCategoryToUpdate() } updateButton.setOnClickListener { addCategoryToUpdate() }
sortText.setOnClickListener { showCatSortOptions() } sortText.setOnClickListener { showCatSortOptions() }
checkboxImage.setOnClickListener { selectAll() }
} }
fun bind(category: Category) { fun bind(category: Category) {
@ -97,15 +101,24 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
) )
when { when {
adapter.mode == SelectableAdapter.Mode.MULTI -> {
checkboxImage.visible()
catProgress.gone()
updateButton.invisible()
setSelection()
}
category.id == -1 -> { category.id == -1 -> {
checkboxImage.gone()
catProgress.gone() catProgress.gone()
updateButton.invisible() updateButton.invisible()
} }
LibraryUpdateService.categoryInQueue(category.id) -> { LibraryUpdateService.categoryInQueue(category.id) -> {
checkboxImage.gone()
catProgress.visible() catProgress.visible()
updateButton.invisible() updateButton.invisible()
} }
else -> { else -> {
checkboxImage.gone()
catProgress.gone() catProgress.gone()
updateButton.visible() updateButton.visible()
} }
@ -195,5 +208,24 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
} }
adapter.libraryListener.sortCategory(category.id!!, modType) adapter.libraryListener.sortCategory(category.id!!, modType)
} }
private fun selectAll() {
adapter.libraryListener.selectAll(adapterPosition)
}
fun setSelection() {
val allSelected = adapter.libraryListener.allSelected(adapterPosition)
val drawable =
ContextCompat.getDrawable(contentView.context,
if (allSelected) R.drawable.ic_check_circle_white_24dp else
R.drawable.ic_radio_button_unchecked_white_24dp)
val tintedDrawable = drawable?.mutate()
tintedDrawable?.setTint(ContextCompat.getColor(contentView.context,
if (allSelected) R.color.colorAccent
else R.color.gray_button))
checkboxImage.setImageDrawable(tintedDrawable)
}
} }
} }

View File

@ -177,6 +177,7 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
override fun onNextLibraryUpdate(mangaMap: List<LibraryItem>, freshStart: Boolean) { override fun onNextLibraryUpdate(mangaMap: List<LibraryItem>, freshStart: Boolean) {
val recyclerLayout = recycler_layout ?: return val recyclerLayout = recycler_layout ?: return
destroyActionModeIfNeeded()
if (mangaMap.isNotEmpty()) { if (mangaMap.isNotEmpty()) {
empty_view?.hide() empty_view?.hide()
} else { } else {
@ -193,18 +194,22 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
spinner.setSelection(min(presenter.categories.size - 1, activeCategory + 1)) spinner.setSelection(min(presenter.categories.size - 1, activeCategory + 1))
updateScroll = false
if (!freshStart) { if (!freshStart) {
justStarted = false justStarted = false
if (recyclerLayout.alpha == 0f) if (recyclerLayout.alpha == 0f)
recyclerLayout.animate().alpha(1f).setDuration(500).start() recyclerLayout.animate().alpha(1f).setDuration(500).start()
}else { } else if (justStarted) {
val position = if (freshStart) adapter.indexOf(activeCategory) else null val position = if (freshStart) adapter.indexOf(activeCategory) else null
if (position != null) if (position != null)
(recycler.layoutManager as LinearLayoutManager) (recycler.layoutManager as LinearLayoutManager)
.scrollToPositionWithOffset(position, (-30).dpToPx) .scrollToPositionWithOffset(position, (-30).dpToPx)
} }
else {
updateScroll = true
}
adapter.isLongPressDragEnabled = canDrag() adapter.isLongPressDragEnabled = canDrag()
tabsVisibilityRelay.call(false) tabsVisibilityRelay.call(false)
@ -212,7 +217,6 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
activeCategory, 0, presenter.categories.size - 1 activeCategory, 0, presenter.categories.size - 1
)] )]
bottom_sheet.updateTitle() bottom_sheet.updateTitle()
updateScroll = false
spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos -> spinner.onItemSelectedListener = IgnoreFirstSpinnerListener { pos ->
if (updateScroll) { if (updateScroll) {
updateScroll = false updateScroll = false
@ -288,6 +292,14 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
} }
} }
} }
updateHeaders()
}
fun updateHeaders() {
val headerPositions = adapter.getHeaderPositions()
headerPositions.forEach {
adapter.notifyItemChanged(it)
}
} }
override fun startReading(position: Int) { override fun startReading(position: Int) {
@ -375,18 +387,12 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
else super.onUpdateManga(manga) else super.onUpdateManga(manga)
} }
/** private fun setSelection(position: Int, selected: Boolean = true) {
* Tells the presenter to set the selection for the given position.
*
* @param position the position to toggle.
*/
private fun setSelection(position: Int) {
val item = adapter.getItem(position) as? LibraryItem ?: return val item = adapter.getItem(position) as? LibraryItem ?: return
setSelection(item.manga, true) setSelection(item.manga, selected)
invalidateActionMode() invalidateActionMode()
} }
override fun onItemMove(fromPosition: Int, toPosition: Int) { override fun onItemMove(fromPosition: Int, toPosition: Int) {
if (lastItemPosition == toPosition) if (lastItemPosition == toPosition)
lastItemPosition = null lastItemPosition = null
@ -480,4 +486,18 @@ class LibraryListController(bundle: Bundle? = null) : LibraryController(bundle),
override fun sortCategory(catId: Int, sortBy: Int) { override fun sortCategory(catId: Int, sortBy: Int) {
presenter.sortCategory(catId, sortBy) presenter.sortCategory(catId, sortBy)
} }
override fun selectAll(position: Int) {
val header = adapter.getSectionHeader(position) ?: return
val items = adapter.getSectionItemPositions(header)
val allSelected = allSelected(position)
for (i in items)
setSelection(i, !allSelected)
}
override fun allSelected(position: Int): Boolean {
val header = adapter.getSectionHeader(position) ?: return false
val items = adapter.getSectionItemPositions(header)
return items.all { adapter.isSelected(it) }
}
} }

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.library package eu.kanade.tachiyomi.ui.library
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
@ -469,6 +470,9 @@ class LibraryPresenter(
if (libraryMap.containsKey(0)) if (libraryMap.containsKey(0))
categories.add(0, createDefaultCategory()) categories.add(0, createDefaultCategory())
if (categories.size == 1 && showCategories)
categories.first().name = context.getString(R.string.label_library)
this.allCategories = categories this.allCategories = categories
this.categories = if (!showCategories) arrayListOf(categoryAll) this.categories = if (!showCategories) arrayListOf(categoryAll)
else categories else categories

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
</vector>

View File

@ -32,6 +32,7 @@
android:clipToPadding="false" android:clipToPadding="false"
android:paddingStart="20dp" android:paddingStart="20dp"
android:paddingTop="10dp" android:paddingTop="10dp"
android:paddingBottom="18dp"
android:paddingEnd="20dp" android:paddingEnd="20dp"
android:scrollbars="none"> android:scrollbars="none">
@ -63,7 +64,7 @@
android:id="@+id/side_layout" android:id="@+id/side_layout"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="0dp"
android:paddingStart="23dp" android:paddingStart="23dp"
android:paddingEnd="20dp" android:paddingEnd="20dp"
android:baselineAligned="true" android:baselineAligned="true"
@ -189,7 +190,7 @@
android:id="@+id/top_bar" android:id="@+id/top_bar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:visibility="visible" tools:visibility="gone"
android:background="@drawable/bg_bottom_sheet_primary" android:background="@drawable/bg_bottom_sheet_primary"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@ -31,7 +31,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:background="@drawable/square_ripple"
android:clickable="true" android:clickable="true"
android:drawableEnd="@drawable/ic_sort_white_24dp" android:drawableEnd="@drawable/ic_sort_white_24dp"
android:drawablePadding="6dp" android:drawablePadding="6dp"
@ -51,7 +50,7 @@
app:layout_constraintHorizontal_bias="1.0" app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toEndOf="@id/space" app:layout_constraintStart_toEndOf="@id/space"
app:layout_constraintWidth_min="20dp" app:layout_constraintWidth_min="20dp"
tools:text="Drag wddf Drop" /> tools:text="Drag and Drop" />
<Space <Space
android:id="@+id/space" android:id="@+id/space"
@ -91,4 +90,21 @@
app:layout_constraintStart_toEndOf="@+id/category_title" app:layout_constraintStart_toEndOf="@+id/category_title"
app:layout_constraintTop_toTopOf="@+id/category_title" /> app:layout_constraintTop_toTopOf="@+id/category_title" />
<ImageView
android:id="@+id/checkbox"
android:padding="10dp"
android:visibility="gone"
tools:visibility="visible"
android:layout_width="wrap_content"
android:contentDescription="@string/action_select_all"
android:clickable="true"
android:focusable="true"
android:layout_height="wrap_content"
android:src="@drawable/ic_check_circle_white_24dp"
android:layout_marginStart="2dp"
app:layout_constraintBottom_toBottomOf="@+id/category_title"
app:layout_constraintStart_toEndOf="@+id/category_title"
app:layout_constraintTop_toTopOf="@+id/category_title"
/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -200,7 +200,7 @@
<string name="pref_auto_update_manga_sync">Sync chapters after reading</string> <string name="pref_auto_update_manga_sync">Sync chapters after reading</string>
<string name="pref_remove_articles">Sort by ignoring articles</string> <string name="pref_remove_articles">Sort by ignoring articles</string>
<string name="pref_library_single_list">Show library as a single list</string> <string name="pref_library_single_list">Show library as a single list</string>
<string name="pref_library_single_list_summary">Show all categories under a single <string name="pref_library_single_list_summary">Show all categories under a single,
sectioned list</string> sectioned list</string>
<string name="pref_remove_articles_summary">When sorting alphabetically, sort ignoring <string name="pref_remove_articles_summary">When sorting alphabetically, sort ignoring
articles (a, an, the) at the start of manga titles</string> articles (a, an, the) at the start of manga titles</string>